diff --git a/.github/workflows/tag_release.yml b/.github/workflows/tag_release.yml index 6ffcc7a3d..36fffbde9 100644 --- a/.github/workflows/tag_release.yml +++ b/.github/workflows/tag_release.yml @@ -46,3 +46,11 @@ jobs: GOHOSTOS: ${{ env.GOHOSTOS }} GOHOSTARCH: ${{ env.GOHOSTARCH }} GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }} + - name: Update npm packages to latest version + working-directory: ./npm/@fastly/cli + run: npm install && npm version "${{ github.ref_name }}" --allow-same-version + - name: Publish npm packages + working-directory: ./npm/@fastly + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: for dir in *; do (echo $dir && cd $dir && npm publish); done diff --git a/.gitignore b/.gitignore index 3ffdf34ed..5370bf679 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,6 @@ pkg/config/config.toml # Ignore commitlint tool commitlint.config.js callvis.svg + +# Ignore generated npm packages +npm/@fastly/cli-*/ diff --git a/RELEASE.md b/RELEASE.md index 62b2836de..b3ec2340b 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -12,6 +12,24 @@ 1. Copy/paste CHANGELOG into the [draft release](https://github.com/fastly/cli/releases). 1. Publish draft release. +## Creation of npm modules + +Each release of the Fastly CLI will trigger the creation of a new version of the `@fastly/cli` npm module, as well as multiple per-platform modules (e.g. `@fastly/cli-darwin-arm64`). The root module (`@fastly/cli`) depends on the platform-specific modules as `optionalDependencies` so that npm will only install the compatible platform-specific package. + +To see an example of the module layout, run... + +```sh +$ npm install @fastly/cli-darwin-arm64 --verbose +``` + +Next, run... + +```sh +$ ls node_modules/@fastly/cli-darwin-arm64 +``` + +You should see a `fastly` executable binary as well as an `index.js` shim which allows the package to be imported as a module by other JavaScript projects. + ## Footnotes 1. We utilize [semantic versioning](https://semver.org/) and only include relevant/significant changes within the CHANGELOG (be sure to document changes to the app config if `config_version` has changed, and if any breaking interface changes are made to the fastly.toml manifest those should be documented on https://fastly.com/documentation/developers). diff --git a/npm/@fastly/cli/LICENSE b/npm/@fastly/cli/LICENSE new file mode 120000 index 000000000..5853aaea5 --- /dev/null +++ b/npm/@fastly/cli/LICENSE @@ -0,0 +1 @@ +../../../LICENSE \ No newline at end of file diff --git a/npm/@fastly/cli/README.md b/npm/@fastly/cli/README.md new file mode 120000 index 000000000..8a33348c7 --- /dev/null +++ b/npm/@fastly/cli/README.md @@ -0,0 +1 @@ +../../../README.md \ No newline at end of file diff --git a/npm/@fastly/cli/fastly.js b/npm/@fastly/cli/fastly.js new file mode 100644 index 000000000..0e627d870 --- /dev/null +++ b/npm/@fastly/cli/fastly.js @@ -0,0 +1,22 @@ +#!/usr/bin/env node +import { execFileSync } from "node:child_process"; + +import { pkgForCurrentPlatform } from "./package-helpers.js"; + +const pkg = pkgForCurrentPlatform(); + +let location; +try { + // Check for the binary package from our "optionalDependencies". This + // package should have been installed alongside this package at install time. + location = (await import(pkg)).default; +} catch (e) { + throw new Error(`The package "${pkg}" could not be found, and is needed by @fastly/cli. + Either the package is missing or the platform/architecture you are using is not supported. + If you are installing @fastly/cli with npm, make sure that you don't specify the + "--no-optional" flag. The "optionalDependencies" package.json feature is used + by @fastly/cli to install the correct binary executable for your current platform. + If your platform is not supported, you can open an issue at https://github.com/fastly/cli/issues`); +} + +execFileSync(location, process.argv.slice(2), { stdio: "inherit" }); diff --git a/npm/@fastly/cli/index.js b/npm/@fastly/cli/index.js new file mode 100644 index 000000000..ab5876e73 --- /dev/null +++ b/npm/@fastly/cli/index.js @@ -0,0 +1,19 @@ +import { pkgForCurrentPlatform } from "./package-helpers.js"; + +const pkg = pkgForCurrentPlatform(); + +let location; +try { + // Check for the binary package from our "optionalDependencies". This + // package should have been installed alongside this package at install time. + location = (await import(pkg)).default; +} catch (e) { + throw new Error(`The package "${pkg}" could not be found, and is needed by @fastly/cli. + Either the package is missing or the platform/architecture you are using is not supported. + If you are installing @fastly/cli with npm, make sure that you don't specify the + "--no-optional" flag. The "optionalDependencies" package.json feature is used + by @fastly/cli to install the correct binary executable for your current platform. + If your platform is not supported, you can open an issue at https://github.com/fastly/cli/issues`); +} + +export default location; diff --git a/npm/@fastly/cli/package-helpers.js b/npm/@fastly/cli/package-helpers.js new file mode 100644 index 000000000..054bf89e7 --- /dev/null +++ b/npm/@fastly/cli/package-helpers.js @@ -0,0 +1,5 @@ +import { platform, arch } from "node:process"; + +export function pkgForCurrentPlatform() { + return `@fastly/cli-${platform}-${arch}`; +} diff --git a/npm/@fastly/cli/package-lock.json b/npm/@fastly/cli/package-lock.json new file mode 100644 index 000000000..b8120abbe --- /dev/null +++ b/npm/@fastly/cli/package-lock.json @@ -0,0 +1,545 @@ +{ + "name": "@fastly/cli", + "version": "10.12.3", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@fastly/cli", + "version": "10.12.3", + "license": "Apache-2.0", + "bin": { + "fastly": "fastly.js" + }, + "devDependencies": { + "decompress": "^4.2.1", + "decompress-targz": "^4.1.1" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dev": true, + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "dev": true, + "dependencies": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dev": true, + "dependencies": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dev": true, + "dependencies": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2/node_modules/file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dev": true, + "dependencies": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", + "dev": true, + "dependencies": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip/node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", + "dev": true, + "dependencies": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==", + "dev": true + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/make-dir/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "dev": true, + "dependencies": { + "commander": "^2.8.1" + }, + "bin": { + "seek-bunzip": "bin/seek-bunzip", + "seek-table": "bin/seek-bzip-table" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dev": true, + "dependencies": { + "is-natural-number": "^4.0.1" + } + }, + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dev": true, + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "dev": true + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/npm/@fastly/cli/package.json b/npm/@fastly/cli/package.json new file mode 100644 index 000000000..0498c7363 --- /dev/null +++ b/npm/@fastly/cli/package.json @@ -0,0 +1,30 @@ +{ + "name": "@fastly/cli", + "version": "10.12.3", + "description": "Build, deploy and configure Fastly services from your terminal", + "type": "module", + "scripts": { + "version": "node ./update.js $npm_package_version" + }, + "devDependencies": { + "decompress": "^4.2.1", + "decompress-targz": "^4.1.1" + }, + "main": "index.js", + "engines": { + "node": ">=16" + }, + "bin": { + "fastly": "./fastly.js" + }, + "optionalDependencies": {}, + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/fastly/cli.git" + }, + "bugs": { + "url": "https://github.com/fastly/cli/issues" + }, + "homepage": "https://github.com/fastly/cli#readme" +} diff --git a/npm/@fastly/cli/update.js b/npm/@fastly/cli/update.js new file mode 100644 index 000000000..0bbafce04 --- /dev/null +++ b/npm/@fastly/cli/update.js @@ -0,0 +1,180 @@ +#!/usr/bin/env node + +import { fileURLToPath } from "node:url"; +import { dirname, join, parse } from "node:path"; +import { mkdir, readFile, writeFile } from "node:fs/promises"; +import decompress from "decompress"; +import decompressTargz from "decompress-targz"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const input = process.argv.slice(2).at(0); +const tag = input ? `v${input}` : "dev"; + +let packages = [ + { + releaseAsset: `fastly_${tag}_darwin-arm64.tar.gz`, + binaryAsset: "fastly", + description: "The macOS (M-series) binary for the Fastly CLI", + os: "darwin", + cpu: "arm64", + }, + { + releaseAsset: `fastly_${tag}_darwin-amd64.tar.gz`, + binaryAsset: "fastly", + description: "The macOS (Intel) binary for the Fastly CLI", + os: "darwin", + cpu: "x64", + }, + { + releaseAsset: `fastly_${tag}_linux-arm64.tar.gz`, + binaryAsset: "fastly", + description: "The Linux (arm64) binary for the Fastly CLI", + os: "linux", + cpu: "arm64", + }, + { + releaseAsset: `fastly_${tag}_linux-amd64.tar.gz`, + binaryAsset: "fastly", + description: "The Linux (64-bit) binary for the Fastly CLI", + os: "linux", + cpu: "x64", + }, + { + releaseAsset: `fastly_${tag}_linux-386.tar.gz`, + binaryAsset: "fastly", + description: "The Linux (32-bit) binary for the Fastly CLI", + os: "linux", + cpu: "x32", + }, + { + releaseAsset: `fastly_${tag}_windows-arm64.tar.gz`, + binaryAsset: "fastly.exe", + description: "The Windows (arm64) binary for the Fastly CLI", + os: "win32", + cpu: "arm64", + }, + { + releaseAsset: `fastly_${tag}_windows-amd64.tar.gz`, + binaryAsset: "fastly.exe", + description: "The Windows (64-bit) binary for the Fastly CLI", + os: "win32", + cpu: "x64", + }, + { + releaseAsset: `fastly_${tag}_windows-386.tar.gz`, + binaryAsset: "fastly.exe", + description: "The Windows (32-bit) binary for the Fastly CLI", + os: "win32", + cpu: "x32", + }, +]; + +let response = await fetch( + `https://api.github.com/repos/fastly/cli/releases/tags/${tag}` +); +if (!response.ok) { + console.error( + `Response from https://api.github.com/repos/fastly/cli/releases/tags/${tag} was not ok`, + response + ); + console.error(await response.text()); + process.exit(1); +} +response = await response.json(); +const id = response.id; +let assets = await fetch( + `https://api.github.com/repos/fastly/cli/releases/${id}/assets` +); +if (!assets.ok) { + console.error( + `Response from https://api.github.com/repos/fastly/cli/releases/${id}/assets was not ok`, + assets + ); + console.error(await response.text()); + process.exit(1); +} +assets = await assets.json(); + +let generatedPackages = []; + +for (const info of packages) { + const packageName = `cli-${info.os}-${info.cpu}`; + const asset = assets.find((asset) => asset.name === info.releaseAsset); + if (!asset) { + console.error( + `Can't find an asset named ${info.releaseAsset} for the release https://github.com/fastly/cli/releases/tag/${tag}` + ); + process.exit(1); + } + const packageDirectory = join(__dirname, "../", packageName.split("/").pop()); + await mkdir(packageDirectory, { recursive: true }); + await writeFile( + join(packageDirectory, "package.json"), + packageJson(packageName, tag, info.description, info.os, info.cpu) + ); + await writeFile( + join(packageDirectory, "index.js"), + indexJs(info.binaryAsset) + ); + generatedPackages.push(packageName); + const browser_download_url = asset.browser_download_url; + const archive = await fetch(browser_download_url); + if (!archive.ok) { + console.error(`Response from ${browser_download_url} was not ok`, archive); + console.error(await response.text()); + process.exit(1); + } + let buf = await archive.arrayBuffer(); + + await decompress(Buffer.from(buf), packageDirectory, { + // Remove the leading directory from the extracted file. + strip: 1, + plugins: [decompressTargz()], + // Only extract the binary file and nothing else + filter: (file) => parse(file.path).base === info.binaryAsset, + }); +} + +// Generate `optionalDependencies` section in the root package.json +const rootPackageJsonPath = join(__dirname, "./package.json"); +let rootPackageJson = await readFile(rootPackageJsonPath, "utf8"); +rootPackageJson = JSON.parse(rootPackageJson); +rootPackageJson["optionalDependencies"] = generatedPackages.reduce( + (acc, packageName) => { + acc[`@fastly/${packageName}`] = `=${tag.substring(1)}`; + return acc; + }, + {} +); +await writeFile(rootPackageJsonPath, JSON.stringify(rootPackageJson, null, 4)); + +function indexJs(binaryAsset) { + return ` +import { fileURLToPath } from 'node:url' +import { dirname, join } from 'node:path' +const __dirname = dirname(fileURLToPath(import.meta.url)) +let location = join(__dirname, '${binaryAsset}') +export default location +`; +} +function packageJson(name, version, description, os, cpu) { + version = version.startsWith("v") ? version.replace("v", "") : version; + return JSON.stringify( + { + name: `@fastly/${name}`, + bin: { + [name]: "fastly", + }, + type: "module", + version, + main: "index.js", + description, + license: "Apache-2.0", + preferUnplugged: false, + os: [os], + cpu: [cpu], + }, + null, + 4 + ); +}