Add NPM packaging and release workflow for CLI
keypair34 committed
Apr 23, 2026 at 06:28 UTC
02e2fffcb0e3f45788aba5a27ce0cd52a01b5c90
13 files changed
+651
.github/workflows/release-npm.yml
new
+221
@@ -0,0 +1,221 @@
1
+name: NPM Release
2
+
3
+on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ tag:
10
+ description: "Release tag (e.g. v0.2.0)"
11
+ required: true
12
+
13
+permissions:
14
+ id-token: write
15
+ contents: read
16
+
17
+env:
18
+ CARGO_TERM_COLOR: always
19
+ ONDE_APP_ID: ${{ secrets.ONDE_APP_ID }}
20
+ ONDE_APP_SECRET: ${{ secrets.ONDE_APP_SECRET }}
21
+ GRESIQ_API_KEY: ${{ secrets.GRESIQ_API_KEY }}
22
+ GRESIQ_API_SECRET: ${{ secrets.GRESIQ_API_SECRET }}
23
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
24
+
25
+jobs:
26
+ publish-npm-binaries:
27
+ name: Publish NPM platform packages
28
+ runs-on: ${{ matrix.build.OS }}
29
+ strategy:
30
+ fail-fast: false
31
+ matrix:
32
+ build:
33
+ - {
34
+ NAME: linux-x64-glibc,
35
+ OS: ubuntu-latest,
36
+ TARGET: x86_64-unknown-linux-gnu,
37
+ }
38
+ - {
39
+ NAME: linux-arm64-glibc,
40
+ OS: ubuntu-24.04-arm,
41
+ TARGET: aarch64-unknown-linux-gnu,
42
+ }
43
+ - {
44
+ NAME: win32-x64-msvc,
45
+ OS: windows-2022,
46
+ TARGET: x86_64-pc-windows-msvc,
47
+ }
48
+ - {
49
+ NAME: win32-arm64-msvc,
50
+ OS: windows-2022,
51
+ TARGET: aarch64-pc-windows-msvc,
52
+ }
53
+ - {
54
+ NAME: darwin-x64,
55
+ OS: macos-15-intel,
56
+ TARGET: x86_64-apple-darwin,
57
+ }
58
+ - {
59
+ NAME: darwin-arm64,
60
+ OS: macos-latest,
61
+ TARGET: aarch64-apple-darwin,
62
+ }
63
+
64
+ steps:
65
+ - name: Checkout
66
+ uses: actions/checkout@v6
67
+ with:
68
+ ref: ${{ github.event.inputs.tag || github.ref }}
69
+
70
+ - name: Set the release version
71
+ shell: bash
72
+ run: |
73
+ if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
74
+ release_version="${GITHUB_REF_NAME#v}"
75
+ else
76
+ release_version="${{ github.event.inputs.tag }}"
77
+ release_version="${release_version#v}"
78
+ fi
79
+ echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
80
+
81
+ - name: Read Rust toolchain
82
+ shell: bash
83
+ run: |
84
+ rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
85
+ if [ -z "$rust_toolchain" ]; then
86
+ echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
87
+ exit 1
88
+ fi
89
+ echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
90
+
91
+ - name: Install Rust toolchain
92
+ uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
93
+ with:
94
+ toolchain: ${{ env.RUST_TOOLCHAIN }}
95
+
96
+ - name: Install Rust target
97
+ shell: bash
98
+ run: |
99
+ rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
100
+ rustup target list --installed
101
+
102
+ - name: Setup Rust cache
103
+ uses: Swatinem/rust-cache@v2
104
+ with:
105
+ key: npm-${{ matrix.build.TARGET }}
106
+
107
+ - name: Build binary
108
+ shell: bash
109
+ run: cargo build --locked --release --target ${{ matrix.build.TARGET }}
110
+
111
+ - name: Install Node
112
+ uses: actions/setup-node@v6
113
+ with:
114
+ node-version-file: .nvmrc
115
+ registry-url: "https://registry.npmjs.org"
116
+
117
+ - name: Publish platform package to NPM
118
+ shell: bash
119
+ run: |
120
+ cd npm
121
+
122
+ # Binary name from Cargo.toml
123
+ cargo_bin="onde"
124
+
125
+ # Prefix used for optional dependency package names
126
+ node_pkg_prefix="cli"
127
+
128
+ # Derive OS and architecture from the build matrix name
129
+ # Matrix name format: <os>-<arch>[-<extra>]
130
+ node_os=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f1)
131
+ export node_os
132
+ node_arch=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f2)
133
+ export node_arch
134
+
135
+ # Set the version
136
+ export node_version="${{ env.RELEASE_VERSION }}"
137
+
138
+ # Build the platform package name; normalise win32 → windows
139
+ if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
140
+ export node_pkg="${node_pkg_prefix}-windows-${node_arch}"
141
+ else
142
+ export node_pkg="${node_pkg_prefix}-${node_os}-${node_arch}"
143
+ fi
144
+
145
+ # Create the package directory
146
+ mkdir -p "${node_pkg}/bin"
147
+
148
+ # Generate package.json + README for this platform slice
149
+ node ./scripts/render-platform-package.cjs \
150
+ "${node_pkg}" \
151
+ "${node_version}" \
152
+ "${node_os}" \
153
+ "${node_arch}"
154
+
155
+ # Windows binaries carry a .exe extension
156
+ if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
157
+ cargo_bin="${cargo_bin}.exe"
158
+ fi
159
+
160
+ cp "../target/${{ matrix.build.TARGET }}/release/${cargo_bin}" "${node_pkg}/bin"
161
+
162
+ cd "${node_pkg}"
163
+
164
+ npm_package_name="@ondeinference/${node_pkg}"
165
+ if npm view "${npm_package_name}@${node_version}" version >/dev/null 2>&1; then
166
+ echo "${npm_package_name}@${node_version} already exists on npm, skipping publish"
167
+ exit 0
168
+ fi
169
+
170
+ npm publish --access public --provenance
171
+
172
+ publish-npm-base:
173
+ name: Publish base NPM package (@ondeinference/cli)
174
+ needs: publish-npm-binaries
175
+ runs-on: ubuntu-latest
176
+
177
+ steps:
178
+ - name: Checkout
179
+ uses: actions/checkout@v6
180
+ with:
181
+ ref: ${{ github.event.inputs.tag || github.ref }}
182
+
183
+ - name: Set the release version
184
+ shell: bash
185
+ run: |
186
+ if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
187
+ release_version="${GITHUB_REF_NAME#v}"
188
+ else
189
+ release_version="${{ github.event.inputs.tag }}"
190
+ release_version="${release_version#v}"
191
+ fi
192
+ echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
193
+
194
+ - name: Install Node
195
+ uses: actions/setup-node@v6
196
+ with:
197
+ node-version-file: .nvmrc
198
+ registry-url: "https://registry.npmjs.org"
199
+
200
+ - name: Publish base package to NPM
201
+ shell: bash
202
+ run: |
203
+ cd npm/onde-cli
204
+
205
+ # Rewrite package.json with the correct release version and
206
+ # matching optionalDependency versions
207
+ node ../scripts/render-main-package.cjs \
208
+ "./package.json" \
209
+ "${{ env.RELEASE_VERSION }}"
210
+
211
+ npm_package_name="@ondeinference/cli"
212
+ npm_package_version="${{ env.RELEASE_VERSION }}"
213
+
214
+ if npm view "${npm_package_name}@${npm_package_version}" version >/dev/null 2>&1; then
215
+ echo "${npm_package_name}@${npm_package_version} already exists on npm, skipping publish"
216
+ exit 0
217
+ fi
218
+
219
+ npm install
220
+ npm run build
221
+ npm publish --access public --provenance
.nvmrc
new
+1
@@ -0,0 +1 @@
1
+20
npm/README.md.tmpl
new
+27
@@ -0,0 +1,27 @@
1
+<p align="center">
2
+ <img src="https://avatars.githubusercontent.com/u/218425892?s=200&v=4" alt="Onde Inference" width="96">
3
+</p>
4
+
5
+<h1 align="center">Onde CLI</h1>
6
+
7
+## `${node_pkg}`
8
+
9
+This is a platform-specific binary for [`@ondeinference/cli`](https://www.npmjs.com/package/@ondeinference/cli). You don't need to install it directly.
10
+
11
+Install the main package instead:
12
+
13
+```sh
14
+npm install -g @ondeinference/cli
15
+```
16
+
17
+npm pulls in the right binary for your OS and architecture.
18
+
19
+## Links
20
+
21
+- [Source code](https://github.com/ondeinference/onde-cli)
22
+- [Issues](https://github.com/ondeinference/onde-cli/issues)
23
+- [Website](https://ondeinference.com)
24
+
25
+## License
26
+
27
+[MIT OR Apache-2.0](https://github.com/ondeinference/onde-cli/blob/main/LICENSE)
npm/onde-cli/.gitignore
new
+2
@@ -0,0 +1,2 @@
1
+lib/
2
+node_modules/
npm/onde-cli/README.md
new
+79
@@ -0,0 +1,79 @@
1
+<p align="center">
2
+ <img src="https://raw.githubusercontent.com/ondeinference/onde/main/assets/onde-inference-logo.svg" alt="Onde Inference" width="80">
3
+</p>
4
+
5
+<h1 align="center">@ondeinference/cli</h1>
6
+
7
+<p align="center">
8
+ Manage your Onde Inference account from the terminal.
9
+</p>
10
+
11
+<p align="center">
12
+ <a href="https://www.npmjs.com/package/@ondeinference/cli"><img src="https://img.shields.io/npm/v/@ondeinference/cli?style=flat-square&labelColor=17211D&color=235843" alt="npm"></a>
13
+ <a href="https://crates.io/crates/onde-cli"><img src="https://img.shields.io/crates/v/onde-cli?style=flat-square&labelColor=17211D&color=235843" alt="crates.io"></a>
14
+ <a href="https://pypi.org/project/onde-cli/"><img src="https://img.shields.io/pypi/v/onde-cli?style=flat-square&labelColor=17211D&color=235843" alt="PyPI"></a>
15
+ <a href="https://ondeinference.com"><img src="https://img.shields.io/badge/ondeinference.com-235843?style=flat-square&labelColor=17211D" alt="Website"></a>
16
+</p>
17
+
18
+---
19
+
20
+## Install
21
+
22
+```sh
23
+npm install -g @ondeinference/cli
24
+```
25
+
26
+The right binary for your platform gets pulled in automatically. Works on macOS (Apple Silicon and Intel), Linux (x64 and arm64), and Windows (x64 and arm64).
27
+
28
+### Other ways to install
29
+
30
+| Method | Command |
31
+|---|---|
32
+| **Homebrew** | `brew install ondeinference/homebrew-tap/onde` |
33
+| **pip** | `pip install onde-cli` |
34
+| **uv** | `uv tool install onde-cli` |
35
+| **Cargo** | `cargo install onde-cli` |
36
+
37
+---
38
+
39
+## Usage
40
+
41
+```sh
42
+onde
43
+```
44
+
45
+Opens a TUI. Sign up or sign in from there, no browser needed.
46
+
47
+| Key | What it does |
48
+|---|---|
49
+| `Tab` | Move between fields |
50
+| `Enter` | Submit / sign out |
51
+| `Ctrl+L` | Sign in screen |
52
+| `Ctrl+N` | New account screen |
53
+| `Ctrl+C` | Quit |
54
+
55
+---
56
+
57
+## What's Onde?
58
+
59
+[Onde Inference](https://ondeinference.com) runs LLMs on the user's device. No server round-trips, no data leaving the hardware. It ships as a native SDK for each platform:
60
+
61
+<p align="center">
62
+ <a href="https://github.com/ondeinference/onde-swift">Swift</a> · <a href="https://pub.dev/packages/onde_inference">Flutter</a> · <a href="https://www.npmjs.com/package/@ondeinference/react-native">React Native</a> · <a href="https://crates.io/crates/onde">Rust</a>
63
+</p>
64
+
65
+This CLI handles the account side of things. The SDKs handle inference.
66
+
67
+---
68
+
69
+## Debug
70
+
71
+Logs go to `~/.cache/onde/debug.log`.
72
+
73
+## License
74
+
75
+Dual-licensed under [MIT](https://github.com/ondeinference/onde-cli/blob/main/LICENSE-MIT) and [Apache 2.0](https://github.com/ondeinference/onde-cli/blob/main/LICENSE-APACHE).
76
+
77
+<p align="center">
78
+ <sub>© 2026 <a href="https://ondeinference.com">Onde Inference</a> · <a href="https://apps.apple.com/se/developer/splitfire-ab/id1831430993">Splitfire AB</a></sub>
79
+</p>
\ No newline at end of file
npm/onde-cli/package-lock.json
new
+77
@@ -0,0 +1,77 @@
1
+{
2
+ "name": "@ondeinference/cli",
3
+ "version": "0.2.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "@ondeinference/cli",
9
+ "version": "0.2.0",
10
+ "license": "MIT OR Apache-2.0",
11
+ "bin": {
12
+ "onde": "lib/index.js"
13
+ },
14
+ "devDependencies": {
15
+ "@types/node": "^18.15.11",
16
+ "typescript": "^5.0.0"
17
+ },
18
+ "optionalDependencies": {
19
+ "@ondeinference/cli-darwin-arm64": "0.2.0",
20
+ "@ondeinference/cli-darwin-x64": "0.2.0",
21
+ "@ondeinference/cli-linux-arm64": "0.2.0",
22
+ "@ondeinference/cli-linux-x64": "0.2.0",
23
+ "@ondeinference/cli-windows-arm64": "0.2.0",
24
+ "@ondeinference/cli-windows-x64": "0.2.0"
25
+ }
26
+ },
27
+ "node_modules/@ondeinference/cli-darwin-arm64": {
28
+ "optional": true
29
+ },
30
+ "node_modules/@ondeinference/cli-darwin-x64": {
31
+ "optional": true
32
+ },
33
+ "node_modules/@ondeinference/cli-linux-arm64": {
34
+ "optional": true
35
+ },
36
+ "node_modules/@ondeinference/cli-linux-x64": {
37
+ "optional": true
38
+ },
39
+ "node_modules/@ondeinference/cli-windows-arm64": {
40
+ "optional": true
41
+ },
42
+ "node_modules/@ondeinference/cli-windows-x64": {
43
+ "optional": true
44
+ },
45
+ "node_modules/@types/node": {
46
+ "version": "18.19.130",
47
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
48
+ "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
49
+ "dev": true,
50
+ "license": "MIT",
51
+ "dependencies": {
52
+ "undici-types": "~5.26.4"
53
+ }
54
+ },
55
+ "node_modules/typescript": {
56
+ "version": "5.9.3",
57
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
58
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
59
+ "dev": true,
60
+ "license": "Apache-2.0",
61
+ "bin": {
62
+ "tsc": "bin/tsc",
63
+ "tsserver": "bin/tsserver"
64
+ },
65
+ "engines": {
66
+ "node": ">=14.17"
67
+ }
68
+ },
69
+ "node_modules/undici-types": {
70
+ "version": "5.26.5",
71
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
72
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
73
+ "dev": true,
74
+ "license": "MIT"
75
+ }
76
+ }
77
+}
npm/onde-cli/package.json
new
+45
@@ -0,0 +1,45 @@
1
+{
2
+ "name": "@ondeinference/cli",
3
+ "version": "0.2.0",
4
+ "keywords": [
5
+ "onde",
6
+ "cli",
7
+ "onde-cli",
8
+ "inference",
9
+ "llm",
10
+ "ai",
11
+ "on-device",
12
+ "developer",
13
+ "tools"
14
+ ],
15
+ "bin": {
16
+ "onde": "lib/index.js"
17
+ },
18
+ "files": [
19
+ "lib",
20
+ "README.md"
21
+ ],
22
+ "description": "A CLI for managing your Onde Inference account and models.",
23
+ "license": "MIT OR Apache-2.0",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/ondeinference/onde-cli.git"
27
+ },
28
+ "scripts": {
29
+ "typecheck": "tsc --noEmit",
30
+ "build": "tsc",
31
+ "dev": "npm run build && node lib/index.js"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^18.15.11",
35
+ "typescript": "^5.0.0"
36
+ },
37
+ "optionalDependencies": {
38
+ "@ondeinference/cli-darwin-arm64": "0.2.0",
39
+ "@ondeinference/cli-darwin-x64": "0.2.0",
40
+ "@ondeinference/cli-linux-arm64": "0.2.0",
41
+ "@ondeinference/cli-linux-x64": "0.2.0",
42
+ "@ondeinference/cli-windows-arm64": "0.2.0",
43
+ "@ondeinference/cli-windows-x64": "0.2.0"
44
+ }
45
+}
npm/onde-cli/src/index.ts
new
+41
@@ -0,0 +1,41 @@
1
+#!/usr/bin/env node
2
+
3
+import { spawnSync } from "child_process";
4
+
5
+/**
6
+ * Returns the executable path which is located inside node_modules
7
+ * The naming convention is cli-OS-ARCH
8
+ * If the platform is win32 or cygwin, executable will include a .exe extension.
9
+ * @see https://nodejs.org/api/os.html#osarch
10
+ * @see https://nodejs.org/api/os.html#osplatform
11
+ * @example "x/xx/node_modules/cli-darwin-arm64"
12
+ */
13
+function getExePath() {
14
+ const arch = process.arch;
15
+ let os = process.platform as string;
16
+ let extension = "";
17
+ if (["win32", "cygwin"].includes(process.platform)) {
18
+ os = "windows";
19
+ extension = ".exe";
20
+ }
21
+
22
+ try {
23
+ // Since the binary will be located inside node_modules, we can simply call require.resolve
24
+ return require.resolve(`@ondeinference/cli-${os}-${arch}/bin/onde${extension}`);
25
+ } catch (e) {
26
+ throw new Error(
27
+ `Couldn't find application binary inside node_modules for ${os}-${arch}`
28
+ );
29
+ }
30
+}
31
+
32
+/**
33
+ * Runs the application with args using nodejs spawn
34
+ */
35
+function run() {
36
+ const args = process.argv.slice(2);
37
+ const processResult = spawnSync(getExePath(), args, { stdio: "inherit" });
38
+ process.exit(processResult.status ?? 0);
39
+}
40
+
41
+run();
npm/onde-cli/tsconfig.json
new
+12
@@ -0,0 +1,12 @@
1
+{
2
+ "compilerOptions": {
3
+ "target": "es2016",
4
+ "module": "commonjs",
5
+ "esModuleInterop": true,
6
+ "baseUrl": "./",
7
+ "outDir": "lib",
8
+ "forceConsistentCasingInFileNames": true,
9
+ "strict": true,
10
+ "skipLibCheck": true
11
+ }
12
+}
npm/package-main.json.tmpl
new
+42
@@ -0,0 +1,42 @@
1
+{
2
+ "name": "@ondeinference/cli",
3
+ "version": "${release_version}",
4
+ "keywords": [
5
+ "onde",
6
+ "cli",
7
+ "onde-cli",
8
+ "inference",
9
+ "llm",
10
+ "ai",
11
+ "on-device",
12
+ "developer",
13
+ "tools"
14
+ ],
15
+ "bin": {
16
+ "onde": "lib/index.js"
17
+ },
18
+ "files": ["lib", "README.md"],
19
+ "description": "A CLI for managing your Onde Inference account and models.",
20
+ "license": "MIT OR Apache-2.0",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/ondeinference/onde-cli.git"
24
+ },
25
+ "scripts": {
26
+ "typecheck": "tsc --noEmit",
27
+ "build": "tsc",
28
+ "dev": "npm run build && node lib/index.js"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^18.15.11",
32
+ "typescript": "^5.0.0"
33
+ },
34
+ "optionalDependencies": {
35
+ "@ondeinference/cli-darwin-arm64": "${release_version}",
36
+ "@ondeinference/cli-darwin-x64": "${release_version}",
37
+ "@ondeinference/cli-linux-arm64": "${release_version}",
38
+ "@ondeinference/cli-linux-x64": "${release_version}",
39
+ "@ondeinference/cli-windows-arm64": "${release_version}",
40
+ "@ondeinference/cli-windows-x64": "${release_version}"
41
+ }
42
+}
npm/package.json.tmpl
new
+14
@@ -0,0 +1,14 @@
1
+{
2
+ "name": "@ondeinference/${node_pkg}",
3
+ "version": "${node_version}",
4
+ "description": "Platform binary for the Onde CLI.",
5
+ "license": "MIT OR Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/ondeinference/onde-cli.git"
9
+ },
10
+ "keywords": ["${node_pkg}","cli","binary","node","nodejs","npm","package","onde","inference","llm"],
11
+ "os": ["${node_os}"],
12
+ "cpu": ["${node_arch}"],
13
+ "files": ["bin"]
14
+}
npm/scripts/render-main-package.cjs
new
+34
@@ -0,0 +1,34 @@
1
+#!/usr/bin/env node
2
+
3
+const fs = require("fs");
4
+const path = require("path");
5
+
6
+const [outputPath, version] = process.argv.slice(2);
7
+
8
+if (!outputPath || !version) {
9
+ throw new Error("Usage: render-main-package.cjs <output-path> <version>");
10
+}
11
+
12
+const npmRoot = path.resolve(__dirname, "..");
13
+
14
+const vars = {
15
+ release_version: version,
16
+};
17
+
18
+/**
19
+ * Replace every `${key}` in the template with the corresponding value from vars.
20
+ */
21
+function interpolate(template, variables) {
22
+ return template.replace(/\$\{(\w+)\}/g, (match, key) => {
23
+ if (key in variables) return variables[key];
24
+ return match;
25
+ });
26
+}
27
+
28
+// Read and interpolate package-main.json.tmpl
29
+const template = fs.readFileSync(
30
+ path.join(npmRoot, "package-main.json.tmpl"),
31
+ "utf-8",
32
+);
33
+
34
+fs.writeFileSync(path.resolve(outputPath), interpolate(template, vars));
npm/scripts/render-platform-package.cjs
new
+56
@@ -0,0 +1,56 @@
1
+#!/usr/bin/env node
2
+
3
+const fs = require("fs");
4
+const path = require("path");
5
+
6
+const [packageName, version, operatingSystem, architecture] =
7
+ process.argv.slice(2);
8
+
9
+if (!packageName || !version || !operatingSystem || !architecture) {
10
+ throw new Error(
11
+ "Usage: render-platform-package.cjs <package-name> <version> <os> <arch>",
12
+ );
13
+}
14
+
15
+const npmRoot = path.resolve(__dirname, "..");
16
+const packageDirectory = path.resolve(npmRoot, packageName);
17
+
18
+fs.mkdirSync(packageDirectory, { recursive: true });
19
+
20
+// Variable map for template interpolation
21
+const vars = {
22
+ node_pkg: packageName,
23
+ node_version: version,
24
+ node_os: operatingSystem,
25
+ node_arch: architecture,
26
+};
27
+
28
+/**
29
+ * Replace every `${key}` in the template with the corresponding value from vars.
30
+ */
31
+function interpolate(template, variables) {
32
+ return template.replace(/\$\{(\w+)\}/g, (match, key) => {
33
+ if (key in variables) return variables[key];
34
+ return match;
35
+ });
36
+}
37
+
38
+// Read and interpolate package.json.tmpl
39
+const packageTemplate = fs.readFileSync(
40
+ path.join(npmRoot, "package.json.tmpl"),
41
+ "utf-8",
42
+);
43
+fs.writeFileSync(
44
+ path.join(packageDirectory, "package.json"),
45
+ interpolate(packageTemplate, vars),
46
+);
47
+
48
+// Read and interpolate README.md.tmpl
49
+const readmeTemplate = fs.readFileSync(
50
+ path.join(npmRoot, "README.md.tmpl"),
51
+ "utf-8",
52
+);
53
+fs.writeFileSync(
54
+ path.join(packageDirectory, "README.md"),
55
+ interpolate(readmeTemplate, vars),
56
+);