-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
442 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Editor configuration, see http://editorconfig.org | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
indent_style = space | ||
indent_size = 4 | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true | ||
|
||
[*.js] | ||
quote_type = double | ||
|
||
[*.md] | ||
max_line_length = off | ||
trim_trailing_whitespace = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
*.sh text eol=lf | ||
*.bash text eol=lf | ||
*.js text eol=lf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
name: publish | ||
|
||
on: | ||
release: | ||
types: [created] | ||
|
||
jobs: | ||
test: | ||
strategy: | ||
matrix: | ||
os: [macos-latest, ubuntu-latest, windows-latest] | ||
runs-on: ${{ matrix.os }} | ||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- uses: actions/setup-node@v2 | ||
with: | ||
node-version: 16 | ||
registry-url: https://registry.npmjs.org/ | ||
|
||
- run: node test | ||
|
||
publish: | ||
needs: [test] | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- uses: actions/setup-node@v2 | ||
with: | ||
node-version: 16 | ||
registry-url: https://registry.npmjs.org/ | ||
|
||
- env: | ||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} | ||
run: npm publish |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
name: test | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
|
||
pull_request: | ||
branches: [main] | ||
|
||
workflow_dispatch: | ||
|
||
jobs: | ||
test: | ||
strategy: | ||
matrix: | ||
os: [macos-latest, ubuntu-latest, windows-latest] | ||
runs-on: ${{ matrix.os }} | ||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- uses: actions/setup-node@v2 | ||
with: | ||
node-version: 16 | ||
registry-url: https://registry.npmjs.org/ | ||
|
||
- run: node test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
node_modules | ||
protoc-gen-js | ||
test | ||
tmp | ||
package-lock.json | ||
*.tgz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# protoc-gen-js-binary | ||
|
||
Downloads Google Protocol Buffers Javascript generator binary wrapped as npm package. | ||
By default, it will download the latest released version. | ||
If a specific version is required, add `"protoc-gen-js-binary": "x.x.x"` at the root of your package.json. | ||
|
||
## Install | ||
|
||
`npm i -D protoc-gen-js-binary` | ||
|
||
To force re-check for latest protoc-gen-js binary releases, simply run `npm ci`. | ||
Alternatively, you can manually invoke the install script `node node_modules/protoc-gen-js-binary/install`. | ||
If working in both Windows and WSL, you can invoke the install script to download binaries for both, | ||
however when switching OS you should run `npm ci`. | ||
|
||
## Usage | ||
|
||
Add `--plugin=protoc-gen-js=node_modules/protoc-gen-js-binary/protoc-gen-js` arg to `protoc` command | ||
|
||
```sh | ||
# download protoc and protoc-gen-js binaries | ||
npm install protoc-gen-js-binary protoc-binary | ||
|
||
# replace `input_dir`, `output_dir` and `my.proto` with actual values | ||
node_modules/.bin/protoc \ | ||
--plugin=protoc-gen-js=node_modules/protoc-gen-js-binary/protoc-gen-js \ | ||
--js_out=import_style=commonjs:input_dir \ | ||
-I=output_dir \ | ||
my.proto | ||
``` | ||
|
||
Alternatively, add the full path of `protoc-gen-js-binary` to PATH | ||
e.g. `/home/user/node_modules/protoc-gen-js-binary` | ||
|
||
## API | ||
|
||
### `binary` | ||
|
||
```js | ||
/* Returns the absolute path to local protoc-gen-js binary */ | ||
require("protoc-gen-js-binary").binary; | ||
``` | ||
|
||
### `version` | ||
|
||
```js | ||
/* Returns version of local protoc-gen-js binary */ | ||
require("protoc-gen-js-binary").version; | ||
``` | ||
|
||
## Supported versions | ||
|
||
See official [protocolbuffers/protobuf-javascript](https://github.com/protocolbuffers/protobuf-javascript/releases) download page. | ||
|
||
* osx-x86_64.zip | ||
* linux-x86_32.zip | ||
* linux-x86_64.zip | ||
* win32.zip | ||
* win64.zip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
const path = require("path"); | ||
|
||
const binaryZip = { | ||
"darwin-x64": "osx-x86_64.zip", | ||
"linux-x32": "linux-x86_32.zip", | ||
"linux-x64": "linux-x86_64.zip", | ||
"win32-x32": "win32.zip", | ||
"win32-x64": "win64.zip" | ||
}[process.platform + "-" + process.arch]; | ||
|
||
module.exports = Object.freeze({ | ||
binary: path.join(__dirname, "protoc-gen-js"), | ||
binaryZip, | ||
downloadUrlTemplate: `https://github.com/protocolbuffers/protobuf-javascript/releases/download/v{version}/protobuf-javascript-{version}-${binaryZip}`, | ||
latestReleaseUrl: "https://api.github.com/repos/protocolbuffers/protobuf-javascript/releases/latest", | ||
safeUnzip: Object.freeze({ | ||
MAX_FILES: 1_000, | ||
MAX_SIZE: 10_000_000, // 10 MB | ||
MAX_RATIO: 20 | ||
}) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
declare module "protoc-gen-js-binary" { | ||
/** Absolute path to local protoc-gen-js binary */ | ||
export const binary: string; | ||
|
||
/** Version of local protoc-gen-js binary */ | ||
export const version: string | ""; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/usr/bin/env node | ||
const fs = require("node:fs"); | ||
const evn = require("./env"); | ||
|
||
module.exports = Object.freeze({ | ||
/** Absolute path to local protoc-gen-js binary */ | ||
binary: evn.binary, | ||
|
||
/** Version of local protoc-gen-js binary, or empty string */ | ||
get version() { return getBinaryVersion(); }, | ||
}); | ||
|
||
function getBinaryVersion() { | ||
if (!fs.existsSync(evn.binary)) return ""; | ||
let ret; | ||
try { | ||
ret = require("./package.json")["protoc-gen-js-version"]; | ||
} catch (ex) { | ||
ret = ""; | ||
} | ||
return /[0-9.]/.test(ret) ? ret : ""; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
const fs = require("node:fs"); | ||
const path = require("node:path"); | ||
const https = require("node:https"); | ||
const extract = require("extract-zip"); | ||
const env = require("./env"); | ||
const index = require("./index"); | ||
|
||
const binaryZipRx = new RegExp(`\/protobuf-javascript-(.*)-${env.binaryZip}`); | ||
|
||
install(); | ||
|
||
function install() { | ||
let version = ""; | ||
let downloadUrl = ""; | ||
const tmpDir = path.join(__dirname, "tmp"); | ||
const tmpZipFile = path.join(tmpDir, "protoc-gen-js.zip"); | ||
const tmpBinFile = path.join(tmpDir, "bin", `protoc-gen-js${process.platform === "win32" ? ".exe" : ""}`); | ||
|
||
const validatePlatform = () => env.binaryZip | ||
|| Promise.reject(`${process.platform}-${process.arch} unsupported`); | ||
const checkBinaryVersion = () => getVersionInfo().then(bin => { | ||
version = bin.version; | ||
downloadUrl = bin.downloadUrl; | ||
if (bin.version === index.version) return Promise.reject("ERR_BIN_EEXIST"); | ||
}); | ||
const removeBinary = () => fs.promises.rm(env.binary, { recursive: true, force: true }); | ||
const removeTmpDir = () => fs.promises.rm(tmpDir, { recursive: true, force: true }); | ||
const cleanDir = () => Promise.all([removeBinary(), removeTmpDir()]); | ||
const createTmpDir = () => fs.promises.mkdir(tmpDir, { recursive: true }); | ||
const downloadZip = () => download(downloadUrl, tmpZipFile).then(() => fs.existsSync(tmpZipFile) | ||
|| Promise.reject(`binary "${env.binaryZip} not downloaded"`)); | ||
const deflateZip = () => unzip(tmpZipFile, tmpDir).then(() => fs.existsSync(tmpBinFile) | ||
|| Promise.reject(`binary "${tmpBinFile} not unzipped"`)); | ||
const moveBinary = () => fs.promises.rename(tmpBinFile, env.binary).then(() => fs.existsSync(env.binary) | ||
|| Promise.reject(`binary "${env.binary} not available"`)); | ||
const makeBinaryExecutable = () => fs.promises.access(env.binary, fs.constants.X_OK).catch(({ code }) => code === "EACCES" | ||
? fs.promises.chmod(env.binary, 0o775) | ||
: Promise.reject(`binary "${env.binary} not executable"`)); | ||
const storeBinaryVersion = () => fs.promises.writeFile( | ||
"package.json", | ||
JSON.stringify({ ...require("./package.json"), "protoc-gen-js-version": version }, null, 4), | ||
"utf8"); | ||
|
||
return Promise.resolve() | ||
.then(validatePlatform) | ||
.then(checkBinaryVersion) | ||
.then(cleanDir) | ||
.then(createTmpDir) | ||
.then(() => console.log(`downloading protoc-gen-js v${version} from ${downloadUrl}`)) | ||
.then(downloadZip) | ||
.then(deflateZip) | ||
.then(moveBinary) | ||
.then(makeBinaryExecutable) | ||
.then(storeBinaryVersion) | ||
.then(() => console.log(`downloaded protoc-gen-js v${version}`)) | ||
.catch(err => err === "ERR_BIN_EEXIST" | ||
? console.log(`latest protoc-gen-js v${version} already exists, skipping download`) | ||
: Promise.reject(err)) | ||
.finally(removeTmpDir); | ||
} | ||
|
||
async function unzip(zip, dir) { | ||
let fileCount = 0; | ||
let totalSize = 0; | ||
|
||
await extract(zip, { | ||
dir, | ||
onEntry: entry => { | ||
fileCount++; | ||
if (fileCount > env.safeUnzip.MAX_FILES) | ||
throw Error('Reached max. number of files'); | ||
|
||
let entrySize = entry.uncompressedSize; | ||
totalSize += entrySize; | ||
if (totalSize > env.safeUnzip.MAX_SIZE) | ||
throw Error('Reached max. size'); | ||
|
||
if (entry.compressedSize > 0) { | ||
let compressionRatio = entrySize / entry.compressedSize; | ||
if (compressionRatio > env.safeUnzip.MAX_RATIO) | ||
throw Error('Reached max. compression ratio'); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
async function getVersionInfo() { | ||
let version = getRequestedVersion(); | ||
let downloadUrl = ""; | ||
|
||
if (version) { | ||
downloadUrl = env.downloadUrlTemplate.replace(/\{version\}/g, version); | ||
} else { | ||
process.stdout.write(`querying latest protoc-gen-js version...`); | ||
downloadUrl = await getLatestReleaseLink().catch(e => { | ||
process.stdout.write('\n'); | ||
throw e; | ||
}); | ||
version = downloadUrl.match(binaryZipRx)[1]; | ||
process.stdout.write(`v${version} found\n`); | ||
} | ||
|
||
return { version, downloadUrl }; | ||
} | ||
|
||
function getRequestedVersion() { | ||
let dir = process.cwd(); | ||
let requestedVersion = undefined; | ||
while (!requestedVersion) { | ||
const packageJsonPath = path.join(dir, "package.json"); | ||
if (fs.existsSync(packageJsonPath)) | ||
requestedVersion = require(packageJsonPath)["protoc-gen-js-binary"]; | ||
if (requestedVersion || !dir.includes("node_modules")) | ||
break; | ||
dir = path.normalize(path.join(dir, "..")); | ||
} | ||
return requestedVersion || ""; | ||
} | ||
|
||
function getLatestReleaseLink() { | ||
return new Promise((resolve, reject) => https.get(env.latestReleaseUrl, { headers: { "User-Agent": `Nodejs/${process.version}` } }, response => { | ||
let data = ""; | ||
response.on("data", chunk => data += chunk); | ||
response.on("end", () => { | ||
const link = JSON.parse(data).assets.find(a => binaryZipRx.test(a.browser_download_url)); | ||
link | ||
? resolve(link.browser_download_url) | ||
: reject(`binary ${env.binaryZip} not available`); | ||
}); | ||
}).on("error", reject)); | ||
} | ||
|
||
function download(uri, filename) { | ||
return new Promise((resolve, reject) => https.get(uri, response => { | ||
if (response.statusCode === 200) | ||
response.pipe( | ||
fs.createWriteStream(filename) | ||
.on("error", reject) | ||
.on("close", resolve) | ||
); | ||
|
||
else if (response.headers.location) | ||
resolve(download(response.headers.location, filename)); | ||
|
||
else | ||
reject(Error(`${response.statusCode} ${response.statusMessage}`)); | ||
|
||
}).on("error", reject)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
{ | ||
"name": "protoc-gen-js-binary", | ||
"homepage": "https://github.com/vallyian/protoc-gen-js-binary#readme", | ||
"description": "Downloads latest Google Protocol Buffers Javascript generator binary wrapped as npm package", | ||
"keywords": [ | ||
"download", | ||
"latest", | ||
"google", | ||
"protocol", | ||
"buffers", | ||
"javascript", | ||
"generator", | ||
"protoc-gen-js", | ||
"binary" | ||
], | ||
"version": "1.0.0", | ||
"author": "[email protected]", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/vallyian/protoc-gen-js-binary.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/vallyian/protoc-gen-js-binary/issues" | ||
}, | ||
"engines": { | ||
"node": ">=14", | ||
"npm": ">=6" | ||
}, | ||
"main": "index.js", | ||
"types": "./index.d.ts", | ||
"scripts": { | ||
"postinstall": "node install" | ||
}, | ||
"dependencies": { | ||
"extract-zip": "latest" | ||
}, | ||
"files": [ | ||
"env.js", | ||
"index.d.ts", | ||
"index.js", | ||
"install.js" | ||
] | ||
} |
Oops, something went wrong.