1+ const fs = require ( 'fs' ) ;
2+ const os = require ( 'os' ) ;
3+ const path = require ( 'path' ) ;
4+ const AdmZip = require ( 'adm-zip' ) ;
5+
6+ const VERSION = '4.0.0' ;
7+ const BIN_DIR = path . join ( __dirname , 'bin' ) ;
8+
9+ function getZipFilename ( currentSystem ) {
10+ return `protobuf-javascript-${ VERSION } -${ currentSystem } .zip` ;
11+ }
12+
13+ function getDownloadUrl ( currentSystem ) {
14+ return `https://github.com/protocolbuffers/protobuf-javascript/releases/download/v${ VERSION } /${ getZipFilename ( currentSystem ) } ` ;
15+ }
16+
17+ function unzip ( zipFile , destDir , binaryName ) {
18+ return new Promise ( ( resolve , reject ) => {
19+ const zip = new AdmZip ( zipFile ) ;
20+
21+ // Paths may be inconsistent between platforms. On MacOS and Windows,
22+ // the path seems to include the archive name while it doesn't on linux.
23+ // There's only one thing named protoc-gen-js(.exe), so just look for
24+ // that instead of trying to get the exact "entryName".
25+ const entries = zip . getEntries ( ) ;
26+ let found = false ;
27+ for ( const entry of entries ) {
28+ if ( entry . name === binaryName ) {
29+ zip . extractEntryTo ( entry , destDir , false , true ) ;
30+ found = true ;
31+ break ;
32+ }
33+ }
34+
35+ if ( found ) {
36+ resolve ( ) ;
37+ } else {
38+ reject ( new Error ( `Binary ${ binaryName } not found in zip file ${ zipFile } ` ) ) ;
39+ }
40+ } ) ;
41+ }
42+
43+ function getCurrentSystem ( ) {
44+ const platform = os . platform ( ) ;
45+ const arch = os . arch ( ) ;
46+
47+ if ( platform === 'darwin' ) {
48+ if ( arch === 'x64' ) {
49+ return 'osx-x86_64' ;
50+ }
51+ if ( arch === 'arm64' ) {
52+ return 'osx-aarch_64' ;
53+ }
54+ } else if ( platform === 'win32' && arch === 'x64' ) {
55+ return 'win64' ;
56+ } else if ( platform === 'linux' ) {
57+ if ( arch === 'x64' ) {
58+ return 'linux-x86_64' ;
59+ }
60+ if ( arch === 'arm64' ) {
61+ return 'linux-aarch_64' ;
62+ }
63+ if ( arch === 's390x' ) {
64+ return 'linux-s390_64' ;
65+ }
66+ }
67+
68+ console . error ( `Unsupported platform: ${ platform } ${ arch } ` ) ;
69+ process . exit ( 1 ) ;
70+ }
71+
72+ async function main ( ) {
73+ try {
74+ await fs . promises . mkdir ( BIN_DIR , { recursive : true } ) ;
75+ const currentSystem = getCurrentSystem ( ) ;
76+
77+
78+ const downloadUrl = getDownloadUrl ( currentSystem ) ;
79+ const zipFile = path . join ( __dirname , getZipFilename ( currentSystem ) ) ;
80+ const isWindows = os . platform ( ) === 'win32' ;
81+ const binaryName = isWindows ? 'protoc-gen-js.exe' : 'protoc-gen-js' ;
82+ const binaryPath = path . join ( BIN_DIR , binaryName ) ;
83+
84+ console . log ( `Downloading ${ downloadUrl } ` ) ;
85+ const response = await fetch ( downloadUrl ) ;
86+ if ( ! response . ok ) {
87+ throw new Error (
88+ `Failed to download: ${ response . status } ${ response . statusText } `
89+ ) ;
90+ }
91+ const buffer = await response . arrayBuffer ( ) ;
92+ await fs . promises . writeFile ( zipFile , Buffer . from ( buffer ) ) ;
93+
94+ console . log ( 'Unzipping...' ) ;
95+ await unzip ( zipFile , BIN_DIR , binaryName ) ;
96+
97+ await fs . promises . unlink ( zipFile ) ;
98+
99+ console . log ( `Making ${ binaryPath } executable...` ) ;
100+ if ( ! isWindows ) {
101+ await fs . promises . chmod ( binaryPath , 0o755 ) ;
102+ }
103+
104+ console . log ( 'Done!' ) ;
105+ } catch ( err ) {
106+ console . error ( `Failed to install protoc-gen-js: ${ err . message } ` ) ;
107+ process . exit ( 1 ) ;
108+ }
109+ }
110+
111+ main ( ) ;
0 commit comments