@nimbus-sh/worker 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +5 -0
- package/README.md +10 -0
- package/dist/_shared/session-router.d.ts +7 -0
- package/dist/_shared/session-router.d.ts.map +1 -1
- package/dist/_shared/session-router.js +7 -0
- package/dist/bindings/body.d.ts +6 -0
- package/dist/bindings/body.d.ts.map +1 -0
- package/dist/bindings/body.js +37 -0
- package/dist/bindings/kv.d.ts +0 -2
- package/dist/bindings/kv.d.ts.map +1 -1
- package/dist/bindings/kv.js +3 -42
- package/dist/bindings/r2.d.ts +0 -2
- package/dist/bindings/r2.d.ts.map +1 -1
- package/dist/bindings/r2.js +4 -44
- package/dist/esbuild-cli-artifact.generated.d.ts +18 -0
- package/dist/esbuild-cli-artifact.generated.d.ts.map +1 -0
- package/dist/esbuild-cli-artifact.generated.js +17 -0
- package/dist/facets/cirrus-real.d.ts.map +1 -1
- package/dist/facets/cirrus-real.js +9 -4
- package/dist/facets/compose.d.ts +11 -7
- package/dist/facets/compose.d.ts.map +1 -1
- package/dist/facets/compose.js +8 -38
- package/dist/facets/data-plan.d.ts +79 -0
- package/dist/facets/data-plan.d.ts.map +1 -0
- package/dist/facets/data-plan.js +477 -0
- package/dist/facets/esbuild-transform.d.ts +36 -10
- package/dist/facets/esbuild-transform.d.ts.map +1 -1
- package/dist/facets/esbuild-transform.js +216 -20
- package/dist/facets/exec-telemetry.d.ts +7 -3
- package/dist/facets/exec-telemetry.d.ts.map +1 -1
- package/dist/facets/manager.d.ts +179 -78
- package/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +1221 -649
- package/dist/facets/opencode-staging.d.ts +0 -2
- package/dist/facets/opencode-staging.d.ts.map +1 -1
- package/dist/facets/opencode-staging.js +5 -11
- package/dist/facets/process.d.ts +4 -0
- package/dist/facets/process.d.ts.map +1 -1
- package/dist/facets/process.js +3 -0
- package/dist/facets/read-profile.d.ts +149 -0
- package/dist/facets/read-profile.d.ts.map +1 -0
- package/dist/facets/read-profile.js +483 -0
- package/dist/facets/resident-identity.d.ts +0 -1
- package/dist/facets/resident-identity.d.ts.map +1 -1
- package/dist/facets/resident-identity.js +0 -3
- package/dist/facets/wasm-swap-registry.d.ts +34 -25
- package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
- package/dist/facets/wasm-swap-registry.js +62 -56
- package/dist/facets/ws-terminal.d.ts +4 -4
- package/dist/facets/ws-terminal.d.ts.map +1 -1
- package/dist/facets/ws-terminal.js +4 -5
- package/dist/git/commands.d.ts +16 -9
- package/dist/git/commands.d.ts.map +1 -1
- package/dist/git/commands.js +1818 -188
- package/dist/git/network-facet.d.ts +10 -2
- package/dist/git/network-facet.d.ts.map +1 -1
- package/dist/git/network-facet.js +62 -16
- package/dist/git/unified-diff.d.ts +74 -0
- package/dist/git/unified-diff.d.ts.map +1 -0
- package/dist/git/unified-diff.js +676 -0
- package/dist/git-bundle.generated.d.ts +7 -11
- package/dist/git-bundle.generated.d.ts.map +1 -1
- package/dist/git-bundle.generated.js +7 -11
- package/dist/hosted/commands.d.ts.map +1 -1
- package/dist/hosted/commands.js +62 -243
- package/dist/hosted/runtime.d.ts +19 -13
- package/dist/hosted/runtime.d.ts.map +1 -1
- package/dist/hosted/runtime.js +71 -14
- package/dist/hosted/services.d.ts +6 -7
- package/dist/hosted/services.d.ts.map +1 -1
- package/dist/hosted/services.js +10 -14
- package/dist/hosted/session.d.ts +165 -0
- package/dist/hosted/session.d.ts.map +1 -0
- package/dist/hosted/session.js +132 -0
- package/dist/loaders/generated-workers.d.ts +5 -2
- package/dist/loaders/generated-workers.d.ts.map +1 -1
- package/dist/loaders/generated-workers.js +6 -3
- package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
- package/dist/loaders/npm-resolve-preamble.js +0 -27
- package/dist/node-shims-artifact.generated.d.ts +13 -4
- package/dist/node-shims-artifact.generated.d.ts.map +1 -1
- package/dist/node-shims-artifact.generated.js +16 -7
- package/dist/npm/bin-links.d.ts +3 -1
- package/dist/npm/bin-links.d.ts.map +1 -1
- package/dist/npm/bin-links.js +32 -8
- package/dist/npm/cache.d.ts +5 -0
- package/dist/npm/cache.d.ts.map +1 -1
- package/dist/npm/cache.js +13 -1
- package/dist/npm/install-batch-facet.d.ts +2 -2
- package/dist/npm/install-batch-facet.js +3 -3
- package/dist/npm/installer.d.ts +17 -1
- package/dist/npm/installer.d.ts.map +1 -1
- package/dist/npm/installer.js +159 -20
- package/dist/npm/package-lock.d.ts +32 -0
- package/dist/npm/package-lock.d.ts.map +1 -0
- package/dist/npm/package-lock.js +65 -0
- package/dist/npm/pre-bundle-facet.d.ts +1 -30
- package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
- package/dist/npm/pre-bundle-facet.js +3 -5
- package/dist/npm/r2-cache.d.ts +2 -0
- package/dist/npm/r2-cache.d.ts.map +1 -1
- package/dist/npm/r2-cache.js +2 -0
- package/dist/npm/resolve-one-facet.d.ts.map +1 -1
- package/dist/npm/resolve-one-facet.js +14 -3
- package/dist/npm/resolver.d.ts +0 -7
- package/dist/npm/resolver.d.ts.map +1 -1
- package/dist/npm/resolver.js +0 -22
- package/dist/opencode-artifact.generated.js +2 -2
- package/dist/replica/routing.d.ts +2 -38
- package/dist/replica/routing.d.ts.map +1 -1
- package/dist/replica/routing.js +3 -55
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +15 -2
- package/dist/router/public-directory.d.ts +18 -0
- package/dist/router/public-directory.d.ts.map +1 -1
- package/dist/router/public-directory.js +1 -1
- package/dist/router/remote-api.d.ts +3 -1
- package/dist/router/remote-api.d.ts.map +1 -1
- package/dist/router/remote-api.js +42 -79
- package/dist/runtime/bash-repl.js +2 -2
- package/dist/runtime/bun-repl.d.ts.map +1 -1
- package/dist/runtime/bun-repl.js +2 -13
- package/dist/runtime/esbuild-wasm-bytes.d.ts +17 -5
- package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -1
- package/dist/runtime/esbuild-wasm-bytes.js +43 -94
- package/dist/runtime/git-bundle-artifact.d.ts +17 -0
- package/dist/runtime/git-bundle-artifact.d.ts.map +1 -0
- package/dist/runtime/git-bundle-artifact.js +25 -0
- package/dist/runtime/node-repl.d.ts.map +1 -1
- package/dist/runtime/node-repl.js +2 -13
- package/dist/runtime/node-shims-artifact.d.ts +22 -23
- package/dist/runtime/node-shims-artifact.d.ts.map +1 -1
- package/dist/runtime/node-shims-artifact.js +48 -78
- package/dist/runtime/node-shims.d.ts.map +1 -1
- package/dist/runtime/node-shims.js +1567 -864
- package/dist/runtime/opencode-artifact.d.ts.map +1 -1
- package/dist/runtime/opencode-artifact.js +17 -53
- package/dist/runtime/opencode-facet-runner.d.ts +3 -6
- package/dist/runtime/opencode-facet-runner.d.ts.map +1 -1
- package/dist/runtime/opencode-facet-runner.js +45 -10
- package/dist/runtime/opentui-wasm-bytes.d.ts.map +1 -1
- package/dist/runtime/opentui-wasm-bytes.js +16 -49
- package/dist/runtime/package-manager.d.ts +0 -2
- package/dist/runtime/package-manager.d.ts.map +1 -1
- package/dist/runtime/package-manager.js +0 -3
- package/dist/runtime/python-repl.d.ts.map +1 -1
- package/dist/runtime/python-repl.js +2 -2
- package/dist/runtime/repl-session.d.ts +10 -0
- package/dist/runtime/repl-session.d.ts.map +1 -1
- package/dist/runtime/repl-session.js +7 -0
- package/dist/runtime/ruby-repl.d.ts.map +1 -1
- package/dist/runtime/ruby-repl.js +2 -2
- package/dist/runtime/ruby-resident.d.ts.map +1 -1
- package/dist/runtime/ruby-resident.js +36 -35
- package/dist/runtime/runtime-catalog.d.ts +10 -3
- package/dist/runtime/runtime-catalog.d.ts.map +1 -1
- package/dist/runtime/runtime-catalog.js +125 -15
- package/dist/runtime/sqlite-wasm-bytes.d.ts +4 -4
- package/dist/runtime/sqlite-wasm-bytes.d.ts.map +1 -1
- package/dist/runtime/sqlite-wasm-bytes.js +21 -57
- package/dist/runtime/staged-source.d.ts +67 -0
- package/dist/runtime/staged-source.d.ts.map +1 -0
- package/dist/runtime/staged-source.js +113 -0
- package/dist/runtime/wasi/preamble.d.ts.map +1 -1
- package/dist/runtime/wasi/preamble.js +0 -24
- package/dist/runtime-catalog.generated.js +1 -1
- package/dist/session/agent.d.ts +14 -2
- package/dist/session/agent.d.ts.map +1 -1
- package/dist/session/agent.js +57 -19
- package/dist/session/ai.d.ts +0 -11
- package/dist/session/ai.d.ts.map +1 -1
- package/dist/session/ai.js +0 -4
- package/dist/session/fs-watch.d.ts +0 -11
- package/dist/session/fs-watch.d.ts.map +1 -1
- package/dist/session/fs-watch.js +0 -21
- package/dist/session/hibernation.d.ts +34 -11
- package/dist/session/hibernation.d.ts.map +1 -1
- package/dist/session/hibernation.js +46 -29
- package/dist/session/init-phases.d.ts +1 -2
- package/dist/session/init-phases.d.ts.map +1 -1
- package/dist/session/init-phases.js +1 -2
- package/dist/session/init.d.ts.map +1 -1
- package/dist/session/init.js +7 -20
- package/dist/session/keys.d.ts +0 -3
- package/dist/session/keys.d.ts.map +1 -1
- package/dist/session/keys.js +0 -3
- package/dist/session/legacy-reset.d.ts +11 -0
- package/dist/session/legacy-reset.d.ts.map +1 -0
- package/dist/session/legacy-reset.js +16 -0
- package/dist/session/nimbus-session.d.ts +41 -15
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +64 -70
- package/dist/session/npm-install-port.d.ts.map +1 -1
- package/dist/session/npm-install-port.js +1 -0
- package/dist/session/programmatic.d.ts +13 -18
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +53 -39
- package/dist/session/replica-routes.d.ts +2 -3
- package/dist/session/replica-routes.d.ts.map +1 -1
- package/dist/session/replica-routes.js +3 -10
- package/dist/session/routes.d.ts.map +1 -1
- package/dist/session/routes.js +7 -10
- package/dist/session/rpc.d.ts +104 -20
- package/dist/session/rpc.d.ts.map +1 -1
- package/dist/session/rpc.js +184 -37
- package/dist/session/start-real-vite.js +2 -2
- package/dist/session/state-store.d.ts +1 -17
- package/dist/session/state-store.d.ts.map +1 -1
- package/dist/session/state-store.js +3 -53
- package/dist/session/supervisor-op.d.ts +7 -0
- package/dist/session/supervisor-op.d.ts.map +1 -1
- package/dist/session/supervisor-op.js +6 -1
- package/dist/session/supervisor-rpc.d.ts +104 -15
- package/dist/session/supervisor-rpc.d.ts.map +1 -1
- package/dist/session/supervisor-rpc.js +188 -71
- package/dist/session/vite-command.d.ts.map +1 -1
- package/dist/session/vite-command.js +17 -14
- package/dist/session/ws.d.ts.map +1 -1
- package/dist/session/ws.js +20 -8
- package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
- package/dist/shell/npm-bin-entrypoints.js +30 -5
- package/dist/vfs/facet-resident-limits.d.ts +33 -0
- package/dist/vfs/facet-resident-limits.d.ts.map +1 -0
- package/dist/vfs/facet-resident-limits.js +33 -0
- package/dist/vfs/facet-resident-store.d.ts +2 -10
- package/dist/vfs/facet-resident-store.d.ts.map +1 -1
- package/dist/vfs/facet-resident-store.js +1594 -219
- package/dist/workspace-host.d.ts +2 -0
- package/dist/workspace-host.d.ts.map +1 -1
- package/dist/workspace-host.js +2 -0
- package/dist/wrangler/nimbus-wrangler.d.ts +0 -2
- package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -1
- package/dist/wrangler/nimbus-wrangler.js +5 -22
- package/package.json +8 -7
- package/public/_assets/opencode/1.16.2/index-attach.js +2 -2
- package/public/_assets/runtime/esbuild-cli-c4fda380d52befc1.js +6892 -0
- package/public/_assets/runtime/git-de3e60c9f3ff006a.js +103 -0
- package/public/_assets/runtime/{node-shims-7b4dd7a76d95d21e.js → node-shims-06565b121555c194.js} +2089 -861
- package/public/_assets/runtime/resident-store-6ffb1939c53d982f.js +2264 -0
- package/public/_assets/runtime/vfs-write-ledger-e501e8fc793bc2c1.js +889 -0
- package/scripts/build-opencode-attach-entry.mjs +51 -1
- package/scripts/bundle-facet-workers.mjs +114 -3
- package/scripts/bundle-git.mjs +88 -27
- package/scripts/bundle-node-shims.mjs +72 -46
- package/scripts/bundle-runtime.mjs +18 -421
- package/scripts/cf-git-patch.mjs +137 -0
- package/scripts/patch-install-deps.mjs +49 -96
- package/scripts/runtime-specs.mjs +435 -0
- package/vendor/git-http.generated.d.ts +82 -0
- package/vendor/git-upstream.generated.d.ts +4378 -0
- package/vendor/git.LICENSE +7 -0
- package/vendor/git.generated.d.mts +21 -0
- package/vendor/git.generated.mjs +103 -0
- package/dist/replica/suspension.d.ts +0 -36
- package/dist/replica/suspension.d.ts.map +0 -1
- package/dist/replica/suspension.js +0 -49
- package/dist/runtime/static-server.d.ts +0 -3
- package/dist/runtime/static-server.d.ts.map +0 -1
- package/dist/runtime/static-server.js +0 -133
- package/scripts/clean-dist.mjs +0 -7
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* node scripts/bundle-runtime.mjs clang binji-2020 [--bucket nimbus-runtime-cache]
|
|
8
8
|
* node scripts/bundle-runtime.mjs python 0.29.4 [--bucket nimbus-runtime-cache]
|
|
9
9
|
* node scripts/bundle-runtime.mjs --pin-catalog (read-only; publishes nothing)
|
|
10
|
-
* node scripts/bundle-runtime.mjs bash 5.2.37-
|
|
10
|
+
* node scripts/bundle-runtime.mjs bash 5.2.37-3 --npm-package <dir> (local; no R2)
|
|
11
11
|
*
|
|
12
12
|
* `--npm-package` is the SECOND publisher for the same artifacts: it stages
|
|
13
13
|
* exactly what the R2 path stages, composes the same manifest bytes, and lays
|
|
@@ -50,7 +50,7 @@ import { mkdirSync, readFileSync, writeFileSync, existsSync, rmSync, openSync, c
|
|
|
50
50
|
import { execFileSync, execSync, spawnSync } from 'node:child_process';
|
|
51
51
|
import { tmpdir } from 'node:os';
|
|
52
52
|
import { basename, dirname, join } from 'node:path';
|
|
53
|
-
import {
|
|
53
|
+
import { SPECS } from './runtime-specs.mjs';
|
|
54
54
|
|
|
55
55
|
const ACCOUNT = process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
56
56
|
// Resolve the wrangler bin from either the package-local or the
|
|
@@ -135,7 +135,7 @@ if (!NPM_OUT_DIR && !ACCOUNT) {
|
|
|
135
135
|
// time, including while another ingest is in flight against a different bucket.
|
|
136
136
|
if (PIN_ONLY) {
|
|
137
137
|
pinCatalogFromR2();
|
|
138
|
-
process.exit(
|
|
138
|
+
process.exit();
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
if (!positionalArgs[0] || !positionalArgs[1]) {
|
|
@@ -146,297 +146,6 @@ if (!positionalArgs[0] || !positionalArgs[1]) {
|
|
|
146
146
|
const RUNTIME = positionalArgs[0];
|
|
147
147
|
const VERSION = positionalArgs[1];
|
|
148
148
|
|
|
149
|
-
/**
|
|
150
|
-
* Static per-runtime spec. Each entry says where to fetch the upstream
|
|
151
|
-
* file from and how to map it into the per-user VFS at install time.
|
|
152
|
-
*
|
|
153
|
-
* For `clang binji-2020`:
|
|
154
|
-
* - VFS path `bin/clang` ← upstream `clang` (31.2 MB)
|
|
155
|
-
* - VFS path `bin/wasm-ld` ← upstream `lld` (19.5 MB)
|
|
156
|
-
* - VFS path `share/clang/sysroot.tar`← upstream `sysroot.tar` (9.3 MB)
|
|
157
|
-
* - VFS path `LICENSE` ← bundled APACHE-2.0 text
|
|
158
|
-
*/
|
|
159
|
-
const SPECS = {
|
|
160
|
-
'clang/binji-2020': {
|
|
161
|
-
license: 'Apache-2.0-with-LLVM-exception',
|
|
162
|
-
wasi_namespace: 'wasi_unstable',
|
|
163
|
-
upstream_base: 'https://raw.githubusercontent.com/binji/wasm-clang/master',
|
|
164
|
-
npm: {
|
|
165
|
-
name: '@nimbus-sh/runtime-clang',
|
|
166
|
-
summary: 'clang 8.0.1 and wasm-ld for wasm32-wasi, with a wasi-libc sysroot',
|
|
167
|
-
// npm demands semver and this runtime's Nimbus version is a channel
|
|
168
|
-
// name, so the compiler's own version is what the package carries. The
|
|
169
|
-
// two namespaces stay separate: the manifest still says `binji-2020`,
|
|
170
|
-
// and that is what the install root under ~/.nimbus/runtimes is named.
|
|
171
|
-
version: '8.0.1',
|
|
172
|
-
},
|
|
173
|
-
files: [
|
|
174
|
-
{ src: 'clang', vfs: 'bin/clang', mode: 'exec', runner: 'clang-runner', binName: 'clang' },
|
|
175
|
-
{ src: 'lld', vfs: 'bin/wasm-ld', mode: 'exec', runner: 'clang-runner', binName: 'wasm-ld', kind: 'linker' },
|
|
176
|
-
{ src: 'sysroot.tar', vfs: 'share/clang/sysroot.tar' },
|
|
177
|
-
],
|
|
178
|
-
// Bundled LICENSE text — Apache 2.0 with LLVM exception (full text below).
|
|
179
|
-
// Source: https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
|
180
|
-
license_text: APACHE_2_LLVM_LICENSE_TEXT(),
|
|
181
|
-
},
|
|
182
|
-
// ── Ruby (v1, 2026-05-11) ────────────────────────────────────────
|
|
183
|
-
// ruby.wasm 2.9.3-2.9.4 from npm @ruby/3.3-wasm-wasi (Ruby 3.3.x
|
|
184
|
-
// built on WASI). We bundle ONLY the `ruby+stdlib.wasm` artifact
|
|
185
|
-
// (34.3 MiB) — it's self-contained, stdlib is packed via wasi-vfs
|
|
186
|
-
// into the wasm. No separate stdlib zip transport needed (unlike
|
|
187
|
-
// Pyodide which ships python_stdlib.zip alongside the asm.js).
|
|
188
|
-
//
|
|
189
|
-
// Upstream channel: npm tarball — the script downloads the tarball
|
|
190
|
-
// (`upstream_base + '/' + src`) and extracts the wasm by file
|
|
191
|
-
// name via the `tarball_extract` flag. Each spec.files entry's
|
|
192
|
-
// `src` is interpreted as the path INSIDE the extracted tarball.
|
|
193
|
-
//
|
|
194
|
-
// See /workspace/.seal-internal/2026-05-11-ruby-v1/audit.md for
|
|
195
|
-
// the full artifact audit + import/export breakdown.
|
|
196
|
-
'ruby/3.3.4': {
|
|
197
|
-
license: 'Ruby+BSD-2-Clause',
|
|
198
|
-
wasi_namespace: 'wasi_snapshot_preview1',
|
|
199
|
-
upstream_base: 'https://registry.npmjs.org/@ruby/3.3-wasm-wasi/-/3.3-wasm-wasi-2.9.3-2.9.4.tgz',
|
|
200
|
-
npm: {
|
|
201
|
-
name: '@nimbus-sh/runtime-ruby',
|
|
202
|
-
summary: 'Ruby 3.3.4 (ruby.wasm) for wasm32-wasi, with its stdlib packed in',
|
|
203
|
-
},
|
|
204
|
-
tarball_extract: 'package/dist', // strip this prefix from src paths inside the tarball
|
|
205
|
-
files: [
|
|
206
|
-
// The Ruby wasm — includes Ruby 3.3.x interpreter + stdlib packed
|
|
207
|
-
// via wasi-vfs. ruby-runner instantiates this at child-facet
|
|
208
|
-
// module-init time and drives it via the Ruby ABI exports
|
|
209
|
-
// (`ruby-init`, `ruby-init-loadpath`, `rb-eval-string-protect`).
|
|
210
|
-
{ src: 'ruby+stdlib.wasm', vfs: 'share/ruby/ruby+stdlib.wasm' },
|
|
211
|
-
// User-facing bin entries. The shell registry dispatches `ruby`
|
|
212
|
-
// and `ruby3` to ruby-runner; this file is a marker, not exec.
|
|
213
|
-
{ src: 'BIN_MARKER', vfs: 'bin/ruby', mode: 'exec', runner: 'ruby-runner', binName: 'ruby' },
|
|
214
|
-
{ src: 'BIN_MARKER', vfs: 'bin/ruby3', mode: 'exec', runner: 'ruby-runner', binName: 'ruby3' },
|
|
215
|
-
],
|
|
216
|
-
synthetic_files: {
|
|
217
|
-
'BIN_MARKER': Buffer.from(
|
|
218
|
-
'# Nimbus ruby-runner launcher marker. The actual Ruby wasm\n' +
|
|
219
|
-
'# lives in share/ruby/. This file is here only so `which ruby`\n' +
|
|
220
|
-
'# and `ls bin/` find a regular file at the expected path. The\n' +
|
|
221
|
-
'# shell-registry dispatches `ruby` directly to the ruby-runner\n' +
|
|
222
|
-
'# factory; this file is not read or executed by Nimbus.\n',
|
|
223
|
-
'utf8',
|
|
224
|
-
),
|
|
225
|
-
},
|
|
226
|
-
license_text: RUBY_LICENSE_TEXT(),
|
|
227
|
-
},
|
|
228
|
-
// ── GNU bash (fork runtime, 2026-07-20) ──────────────────────────
|
|
229
|
-
// bash 5.2.37 cross-compiled to wasm32-wasi with the Nimbus process
|
|
230
|
-
// overlay (nimbus-proc.{h,c}: fork/exec/wait/pipe over nimbus_proc.*
|
|
231
|
-
// imports + asyncify-native setjmp) and asyncify-instrumented.
|
|
232
|
-
// There is NO upstream binary channel — the artifacts are built from
|
|
233
|
-
// source by packages/worker/wasm/bash/build-bash.sh (bash) and
|
|
234
|
-
// coreutils/build-busybox.sh (BusyBox 1.37.0, the plain-WASI multicall
|
|
235
|
-
// exec target providing ls/cat/cp/mv/rm/grep/sed/awk/find/... — see
|
|
236
|
-
// busybox.applets), then staged from the local build tree via
|
|
237
|
-
// `local_base`. The bash-runner aliases every applet name in
|
|
238
|
-
// busybox.applets onto the busybox module so bash's PATH lookup finds
|
|
239
|
-
// them in /bin and /usr/bin.
|
|
240
|
-
//
|
|
241
|
-
// The version is `<upstream>-<build>`: the build number advances with
|
|
242
|
-
// every rebuild, and the entrypoint names the runner contract the build
|
|
243
|
-
// was made for (BASH_RUNNER), so a deployment whose preamble predates it
|
|
244
|
-
// never binds it. 5.2.37 is build 1, published under `bash-runner`.
|
|
245
|
-
'bash/5.2.37-2': {
|
|
246
|
-
license: 'GPL-3.0-or-later AND GPL-2.0-only',
|
|
247
|
-
wasi_namespace: 'wasi_snapshot_preview1',
|
|
248
|
-
local_base: '../wasm/bash',
|
|
249
|
-
auxiliary_bins: 'coreutils/busybox.applets',
|
|
250
|
-
npm: {
|
|
251
|
-
name: '@nimbus-sh/runtime-bash',
|
|
252
|
-
summary: 'GNU bash 5.2.37 and BusyBox 1.37.0, cross-compiled to wasm32-wasi',
|
|
253
|
-
},
|
|
254
|
-
files: [
|
|
255
|
-
{ src: 'bash.async.wasm', vfs: 'share/bash/bash.async.wasm' },
|
|
256
|
-
{ src: 'coreutils/busybox.wasm', vfs: 'share/bash/coreutils/busybox.wasm' },
|
|
257
|
-
{ src: 'coreutils/busybox.applets', vfs: 'share/bash/coreutils/busybox.applets' },
|
|
258
|
-
{ src: 'BIN_MARKER', vfs: 'bin/bash', mode: 'exec', runner: BASH_RUNNER, binName: 'bash' },
|
|
259
|
-
],
|
|
260
|
-
synthetic_files: {
|
|
261
|
-
'BIN_MARKER': Buffer.from(
|
|
262
|
-
'# Nimbus bash-runner launcher marker. The real GNU bash wasm\n' +
|
|
263
|
-
'# lives in share/bash/. The shell registry dispatches `bash`\n' +
|
|
264
|
-
'# (and #!/bin/bash shebangs) to the bash-runner factory; this\n' +
|
|
265
|
-
'# file exists so `which bash` and `ls bin/` find a regular,\n' +
|
|
266
|
-
'# executable file at the expected path.\n',
|
|
267
|
-
'utf8',
|
|
268
|
-
),
|
|
269
|
-
},
|
|
270
|
-
license_text: GPL_3_LICENSE_NOTICE(),
|
|
271
|
-
},
|
|
272
|
-
'python/0.29.4': {
|
|
273
|
-
license: 'MPL-2.0',
|
|
274
|
-
wasi_namespace: null, // Pyodide is Emscripten, not WASI
|
|
275
|
-
upstream_base: 'https://cdn.jsdelivr.net/pyodide/v0.29.4/full',
|
|
276
|
-
files: [
|
|
277
|
-
// The wasm module Pyodide instantiates. Goes to share/ so the
|
|
278
|
-
// user-VFS layout matches binji-clang's convention (bin/ for
|
|
279
|
-
// exec entry, share/<name>/ for runtime-private blobs).
|
|
280
|
-
{ src: 'pyodide.asm.wasm', vfs: 'share/pyodide/pyodide.asm.wasm' },
|
|
281
|
-
// The Emscripten JS half. Runtime sync adapts it once for
|
|
282
|
-
// workerd and records that contract in manifest metadata; the
|
|
283
|
-
// Python runner consumes the resulting artifact without patching
|
|
284
|
-
// it during session boot.
|
|
285
|
-
{ src: 'pyodide.asm.js', vfs: 'share/pyodide/pyodide.asm.js', transform: 'pyodide-workerd-adapter' },
|
|
286
|
-
// Python 3.13 stdlib. Pyodide writes this into its Emscripten
|
|
287
|
-
// MEMFS at /lib/python313.zip and CPython imports from there
|
|
288
|
-
// via the ZipImporter on sys.path.
|
|
289
|
-
{ src: 'python_stdlib.zip', vfs: 'share/pyodide/python_stdlib.zip' },
|
|
290
|
-
// Lockfile — only used by pyodide.loadPackage / micropip (v3
|
|
291
|
-
// scope). We ship it so v3 doesn't need to re-bundle from
|
|
292
|
-
// scratch; v1 ignores its contents.
|
|
293
|
-
{ src: 'pyodide-lock.json', vfs: 'share/pyodide/pyodide-lock.json' },
|
|
294
|
-
// The user-facing "bin" — a tiny launcher marker. We don't
|
|
295
|
-
// actually exec this file; the python-runner factory pulls
|
|
296
|
-
// bytes from the share/ entries and ignores bin/python's
|
|
297
|
-
// content. The presence of the entry in entrypoints[] is what
|
|
298
|
-
// wires `python` into the shell registry.
|
|
299
|
-
{ src: 'BIN_MARKER', vfs: 'bin/python', mode: 'exec', runner: 'python-runner', binName: 'python' },
|
|
300
|
-
// Second entrypoint — `python3` is conventional on Linux.
|
|
301
|
-
{ src: 'BIN_MARKER', vfs: 'bin/python3', mode: 'exec', runner: 'python-runner', binName: 'python3' },
|
|
302
|
-
],
|
|
303
|
-
license_text: MPL_2_LICENSE_TEXT(),
|
|
304
|
-
/** Source 'BIN_MARKER' is synthesised, not fetched. */
|
|
305
|
-
synthetic_files: {
|
|
306
|
-
'BIN_MARKER': Buffer.from(
|
|
307
|
-
'# Nimbus python-runner launcher marker. The actual Pyodide\n' +
|
|
308
|
-
'# bootstrap lives in share/pyodide/. This file is here only so\n' +
|
|
309
|
-
'# `which python` and `ls bin/` find a regular file at the\n' +
|
|
310
|
-
'# expected path. The shell-registry dispatches `python`\n' +
|
|
311
|
-
'# directly to the python-runner factory; this file is not\n' +
|
|
312
|
-
'# read or executed by Nimbus.\n',
|
|
313
|
-
'utf8',
|
|
314
|
-
),
|
|
315
|
-
},
|
|
316
|
-
python_packages: ['numpy', 'markupsafe'],
|
|
317
|
-
},
|
|
318
|
-
|
|
319
|
-
// CPython 3.13 cross-built for wasm32-wasi by packages/worker/wasm/python/
|
|
320
|
-
// build-python.sh, with the C libraries the published wasm32-wasi artifacts
|
|
321
|
-
// leave out (zlib, bzip2, xz, sqlite, OpenSSL). Unlike the Pyodide entry
|
|
322
|
-
// above this is a real WASI module: it talks to runtime/wasi/preamble.ts, so
|
|
323
|
-
// it has no filesystem of its own to copy in and diff back out.
|
|
324
|
-
//
|
|
325
|
-
// Additive alongside python/0.29.4. Nothing reads these keys until
|
|
326
|
-
// session/init.ts routes `python` at the cpython-runner factory.
|
|
327
|
-
'cpython/3.13.14': {
|
|
328
|
-
license: 'PSF-2.0',
|
|
329
|
-
wasi_namespace: 'wasi_snapshot_preview1',
|
|
330
|
-
local_base: '../wasm/python',
|
|
331
|
-
npm: {
|
|
332
|
-
name: '@nimbus-sh/runtime-cpython',
|
|
333
|
-
summary: 'CPython 3.13.14, cross-compiled to wasm32-wasi, with its stdlib',
|
|
334
|
-
},
|
|
335
|
-
files: [
|
|
336
|
-
{ src: 'python.wasm', vfs: 'share/cpython/python.wasm' },
|
|
337
|
-
// The same interpreter with numpy and markupsafe's C speedups linked in,
|
|
338
|
-
// and their Python half. wasm32-wasi has no dlopen, so a compiled package
|
|
339
|
-
// is either in the binary or unavailable; the runner picks between the two
|
|
340
|
-
// from what the session installed. Both ship because the choice is made
|
|
341
|
-
// per invocation, inside the session, long after the install.
|
|
342
|
-
{ src: 'python-sci.wasm', vfs: 'share/cpython/python-sci.wasm' },
|
|
343
|
-
// Beside the stdlib zip on purpose: the runner puts it on sys.path and
|
|
344
|
-
// zipimport reads it out of the session filesystem, so it needs the same
|
|
345
|
-
// treatment as lib/python313.zip and no separate transport.
|
|
346
|
-
{ src: 'sci-packages.zip', vfs: 'lib/sci-packages.zip' },
|
|
347
|
-
// The stdlib, pyc-only. Read straight out of the session filesystem by
|
|
348
|
-
// zipimport, which is why it needs no separate transport.
|
|
349
|
-
// Laid out as a Python prefix, so nimbus_py_init can be handed the
|
|
350
|
-
// install root directly. Aliasing lib/ onto some other path would put
|
|
351
|
-
// entries in the guest's filesystem that the supervisor cannot serve,
|
|
352
|
-
// and a manifest entry nobody can fetch is an EIO waiting to happen.
|
|
353
|
-
{ src: 'python313.zip', vfs: 'lib/python313.zip' },
|
|
354
|
-
// OpenSSL has no default trust store to fall back on here: there is no
|
|
355
|
-
// /etc/ssl in the session, so ssl.create_default_context() would verify
|
|
356
|
-
// against nothing and every HTTPS fetch would fail. SSL_CERT_FILE points
|
|
357
|
-
// at this. Mozilla's bundle, as published by curl.se.
|
|
358
|
-
{ src: 'cacert.pem', vfs: 'etc/ssl/cert.pem' },
|
|
359
|
-
{ src: 'STDLIB_MARKER', vfs: 'lib/python3.13/os.py' },
|
|
360
|
-
{ src: 'BIN_MARKER', vfs: 'bin/python', mode: 'exec', runner: 'cpython-runner', binName: 'python' },
|
|
361
|
-
{ src: 'BIN_MARKER', vfs: 'bin/python3', mode: 'exec', runner: 'cpython-runner', binName: 'python3' },
|
|
362
|
-
],
|
|
363
|
-
license_text: PSF_LICENSE_NOTICE(),
|
|
364
|
-
/** Source 'BIN_MARKER' is synthesised, not fetched. */
|
|
365
|
-
synthetic_files: {
|
|
366
|
-
'STDLIB_MARKER': Buffer.from(
|
|
367
|
-
'# Nimbus stdlib marker. Every module is read from ../python313.zip;\n' +
|
|
368
|
-
'# this file exists so the prefix looks like a Python prefix.\n',
|
|
369
|
-
'utf8',
|
|
370
|
-
),
|
|
371
|
-
'BIN_MARKER': Buffer.from(
|
|
372
|
-
'# Nimbus cpython-runner launcher marker. The interpreter itself\n' +
|
|
373
|
-
'# lives in share/cpython/. This file exists so `which python` and\n' +
|
|
374
|
-
'# `ls bin/` find a regular, executable file at the expected path;\n' +
|
|
375
|
-
'# the shell registry dispatches `python` directly to the\n' +
|
|
376
|
-
'# cpython-runner factory and never reads this content.\n',
|
|
377
|
-
'utf8',
|
|
378
|
-
),
|
|
379
|
-
},
|
|
380
|
-
},
|
|
381
|
-
|
|
382
|
-
// 2026-05-11 sysroot-prep Phase 0 — R2 ingestion ONLY for the
|
|
383
|
-
// clang-sysroot-swap wave. This entry stages the upstream wasi-sdk-19
|
|
384
|
-
// sysroot in R2 (binji-shape: rootless `include/lib/share` layout) so
|
|
385
|
-
// when the swap wave dispatches, the blob is already present.
|
|
386
|
-
//
|
|
387
|
-
// `ingest_only: true` SUPPRESSES the manifest write AND the catalog
|
|
388
|
-
// auto-flip at the bottom of the script. The swap wave owns those
|
|
389
|
-
// operations (it composes a new manifest that inherits bin/clang,
|
|
390
|
-
// bin/wasm-ld from binji-2020 and references this
|
|
391
|
-
// prep'd sysroot.tar blob, then flips `clang.default`).
|
|
392
|
-
//
|
|
393
|
-
// `repackage` describes a download+extract+retar pre-step that
|
|
394
|
-
// produces a single local `sysroot.tar` file BEFORE the upload loop.
|
|
395
|
-
// The file's `src` value is used as both the cached download filename
|
|
396
|
-
// and (after repackage) the upload basename.
|
|
397
|
-
'clang/wasi-sdk-19': {
|
|
398
|
-
license: 'Apache-2.0-with-LLVM-exception',
|
|
399
|
-
ingest_only: true,
|
|
400
|
-
files: [
|
|
401
|
-
// The upload loop sees one logical "file" with src='sysroot.tar'.
|
|
402
|
-
// The repackage step below produces it from the upstream tarball
|
|
403
|
-
// and writes it to <workDir>/sysroot.tar before the upload loop
|
|
404
|
-
// runs. `vfs` mirrors the binji-2020 path for the swap wave's
|
|
405
|
-
// manifest composer (kept for documentation only; ignored in
|
|
406
|
-
// ingest_only mode since no manifest is written).
|
|
407
|
-
{ src: 'sysroot.tar', vfs: 'share/clang/sysroot.tar' },
|
|
408
|
-
],
|
|
409
|
-
// Build-time step: fetch the upstream wasi-sdk-19 sysroot tarball,
|
|
410
|
-
// extract, and re-tar in binji-2020 layout (rootless: include/, lib/,
|
|
411
|
-
// share/ as top-level entries, no `wasi-sysroot/` prefix). Runs
|
|
412
|
-
// BEFORE the existing fetch loop sees `sysroot.tar`.
|
|
413
|
-
repackage: {
|
|
414
|
-
upstream_url:
|
|
415
|
-
'https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sysroot-19.0.tar.gz',
|
|
416
|
-
// sha256 of the upstream .tar.gz, captured 2026-05-11.
|
|
417
|
-
// Falsification: bundle-runtime.mjs verifies this on every run.
|
|
418
|
-
upstream_sha256:
|
|
419
|
-
'd601c901a26d6cdb158e60c8a981caa189e87875abc23bb071c2c533a39fd143',
|
|
420
|
-
// Subdir inside the extracted tarball whose children become the
|
|
421
|
-
// top-level entries of the produced sysroot.tar.
|
|
422
|
-
strip_prefix: 'wasi-sysroot',
|
|
423
|
-
// Directories at strip_prefix to include in the produced sysroot.tar.
|
|
424
|
-
// Anything else under wasi-sysroot/ is dropped.
|
|
425
|
-
include_dirs: ['include', 'lib', 'share'],
|
|
426
|
-
// Expected sha256 of the *produced* sysroot.tar. Captured from a
|
|
427
|
-
// dry-run inspection at /tmp/sysroot-prep-work/ (see prep audit).
|
|
428
|
-
// Verified before upload; abort on mismatch.
|
|
429
|
-
output_sha256:
|
|
430
|
-
'82f30ed81d39072d54e3ba207305c26bfc29a7726e500230db3cad8abe828be3',
|
|
431
|
-
// Expected raw byte size of the produced sysroot.tar.
|
|
432
|
-
output_size: 11898880,
|
|
433
|
-
},
|
|
434
|
-
// license_text intentionally omitted — ingest_only mode skips the
|
|
435
|
-
// bundled LICENSE write. The swap wave composes a concat-license
|
|
436
|
-
// (binji + wasi-libc) at manifest time.
|
|
437
|
-
},
|
|
438
|
-
};
|
|
439
|
-
|
|
440
149
|
const key = `${RUNTIME}/${VERSION}`;
|
|
441
150
|
const spec = SPECS[key];
|
|
442
151
|
if (!spec) {
|
|
@@ -470,6 +179,8 @@ if (NPM_OUT_DIR) {
|
|
|
470
179
|
const workDir = join(tmpdir(), `bundle-runtime-${RUNTIME}-${VERSION}`);
|
|
471
180
|
rmSync(workDir, { recursive: true, force: true });
|
|
472
181
|
mkdirSync(workDir, { recursive: true });
|
|
182
|
+
// Scratch for this run only (every run starts it empty): removed however the run ends.
|
|
183
|
+
process.on('exit', () => rmSync(workDir, { recursive: true, force: true }));
|
|
473
184
|
|
|
474
185
|
console.log(`[bundle-runtime] ${RUNTIME} ${VERSION}`);
|
|
475
186
|
console.log(`[bundle-runtime] work dir: ${workDir}`);
|
|
@@ -819,6 +530,7 @@ function pinCatalogFromR2() {
|
|
|
819
530
|
const workDir = join(tmpdir(), `nimbus-catalog-pin-${process.pid}`);
|
|
820
531
|
mkdirSync(workDir, { recursive: true });
|
|
821
532
|
const local = join(workDir, 'catalog.json');
|
|
533
|
+
// Failures return rather than process.exit, so the finally removes the download either way.
|
|
822
534
|
try {
|
|
823
535
|
const result = spawnSync(
|
|
824
536
|
WRANGLER,
|
|
@@ -829,7 +541,8 @@ function pinCatalogFromR2() {
|
|
|
829
541
|
console.error(`ERROR: could not read catalog/v1.json from '${BUCKET}'; the pin is unchanged.`);
|
|
830
542
|
const detail = (result.stderr || '').trim();
|
|
831
543
|
if (detail) console.error(` ${detail.split('\n').slice(-3).join('\n ')}`);
|
|
832
|
-
process.
|
|
544
|
+
process.exitCode = 1;
|
|
545
|
+
return;
|
|
833
546
|
}
|
|
834
547
|
const bytes = readFileSync(local);
|
|
835
548
|
// A pin over bytes that are not the catalog would disable the cache on
|
|
@@ -839,11 +552,13 @@ function pinCatalogFromR2() {
|
|
|
839
552
|
parsed = JSON.parse(bytes.toString('utf8'));
|
|
840
553
|
} catch (e) {
|
|
841
554
|
console.error(`ERROR: catalog/v1.json is not valid JSON (${e.message}); refusing to pin it`);
|
|
842
|
-
process.
|
|
555
|
+
process.exitCode = 1;
|
|
556
|
+
return;
|
|
843
557
|
}
|
|
844
558
|
if (!parsed || typeof parsed.runtimes !== 'object' || parsed.runtimes === null) {
|
|
845
559
|
console.error('ERROR: catalog/v1.json has no runtimes object; refusing to pin it');
|
|
846
|
-
process.
|
|
560
|
+
process.exitCode = 1;
|
|
561
|
+
return;
|
|
847
562
|
}
|
|
848
563
|
console.log(`[bundle-runtime] catalog lists: ${Object.keys(parsed.runtimes).join(', ') || '(none)'}`);
|
|
849
564
|
writeCatalogPin(bytes);
|
|
@@ -955,17 +670,18 @@ function writeNpmPackage(outDir, manifest, downloaded) {
|
|
|
955
670
|
files: ['index.js', 'index.d.ts', 'manifest.json', 'blobs', 'LICENSE', 'README.md'],
|
|
956
671
|
// The runtime is inert without the half that installs and runs it, and
|
|
957
672
|
// `index.d.ts` types itself against that package's exports. The floor is
|
|
958
|
-
// the core release
|
|
959
|
-
//
|
|
960
|
-
|
|
961
|
-
peerDependencies: { '@nimbus-sh/core': '>=0.4.0' },
|
|
673
|
+
// the first core release that registers every runner this manifest names:
|
|
674
|
+
// an earlier core seeds the files and then has no command to run them.
|
|
675
|
+
peerDependencies: { '@nimbus-sh/core': spec.npm.core ?? '>=0.4.0' },
|
|
962
676
|
publishConfig: { access: 'public' },
|
|
963
677
|
}, null, 2)}\n`);
|
|
964
678
|
|
|
965
679
|
console.log(`\n[bundle-runtime] DONE (npm package)`);
|
|
966
680
|
console.log(`[bundle-runtime] ${spec.npm.name}@${npmVersion} → ${outDir}`);
|
|
967
681
|
console.log(`[bundle-runtime] ${written.size} blobs, ${(unpackedBytes / 1024 / 1024).toFixed(2)} MiB unpacked`);
|
|
968
|
-
|
|
682
|
+
// `--tag latest` because a rebuild (`5.2.37-2`) sorts below the build it
|
|
683
|
+
// replaces; see packages/core/scripts/check-runtime-packages.mjs.
|
|
684
|
+
console.log(`[bundle-runtime] publish with: cd ${outDir} && npm publish --tag latest --access public --auth-type=web`);
|
|
969
685
|
console.log(`[bundle-runtime] R2: UNTOUCHED (nothing was read from or written to Cloudflare)`);
|
|
970
686
|
}
|
|
971
687
|
|
|
@@ -1304,122 +1020,3 @@ function runRepackage(rep, workDir) {
|
|
|
1304
1020
|
process.exit(3);
|
|
1305
1021
|
}
|
|
1306
1022
|
}
|
|
1307
|
-
|
|
1308
|
-
// ── Bundled LICENSE text generator ────────────────────────────────
|
|
1309
|
-
function GPL_3_LICENSE_NOTICE() {
|
|
1310
|
-
return `GNU bash 5.2.37 — GPL-3.0-or-later
|
|
1311
|
-
Copyright (C) Free Software Foundation, Inc.
|
|
1312
|
-
|
|
1313
|
-
This runtime bundles GNU bash cross-compiled to wasm32-wasi. Full
|
|
1314
|
-
license text: https://www.gnu.org/licenses/gpl-3.0.txt
|
|
1315
|
-
Corresponding source: https://ftp.gnu.org/gnu/bash/bash-5.2.37.tar.gz
|
|
1316
|
-
plus the Nimbus build overlay (packages/worker/wasm/bash/ in the
|
|
1317
|
-
Nimbus repository: nimbus-proc.{h,c}, build-bash.sh, coreutils/).
|
|
1318
|
-
|
|
1319
|
-
BusyBox 1.37.0 — GPL-2.0-only
|
|
1320
|
-
Copyright (C) many authors, 1998-2015. See the source distribution.
|
|
1321
|
-
|
|
1322
|
-
The coreutils exec targets (ls, cat, grep, sed, awk, find, ...) are
|
|
1323
|
-
BusyBox cross-compiled to wasm32-wasi as one multicall binary. Full
|
|
1324
|
-
license text: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
|
1325
|
-
Corresponding source: https://busybox.net/downloads/busybox-1.37.0.tar.bz2
|
|
1326
|
-
plus the Nimbus build overlay (packages/worker/wasm/bash/coreutils/ in
|
|
1327
|
-
the Nimbus repository: build-busybox.sh, wasi-shim.c, overlay/).
|
|
1328
|
-
`;
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
|
-
function PSF_LICENSE_NOTICE() {
|
|
1332
|
-
return [
|
|
1333
|
-
'Python is distributed under the Python Software Foundation License',
|
|
1334
|
-
'Version 2. The full text is at https://docs.python.org/3/license.html',
|
|
1335
|
-
'and is included in the interpreter as Lib/LICENSE.txt.',
|
|
1336
|
-
'',
|
|
1337
|
-
'Copyright (c) 2001-2026 Python Software Foundation. All Rights Reserved.',
|
|
1338
|
-
'',
|
|
1339
|
-
'This build is CPython 3.13.14 cross-compiled for wasm32-wasi and',
|
|
1340
|
-
'statically linked against zlib (zlib licence), bzip2 (BSD-like), xz',
|
|
1341
|
-
'liblzma (0BSD), SQLite (public domain) and OpenSSL 3.5 (Apache-2.0).',
|
|
1342
|
-
'Each of those carries its own licence, reproduced by its upstream.',
|
|
1343
|
-
'',
|
|
1344
|
-
].join('\n');
|
|
1345
|
-
}
|
|
1346
|
-
|
|
1347
|
-
function MPL_2_LICENSE_TEXT() {
|
|
1348
|
-
// Mozilla Public License 2.0 — Pyodide is MPL-2.0-licensed. We
|
|
1349
|
-
// ship an abbreviated header pointing at the canonical text; the
|
|
1350
|
-
// LICENSE file lives next to the runtime install dir as a
|
|
1351
|
-
// disclosure to the user.
|
|
1352
|
-
return [
|
|
1353
|
-
'==============================================================================',
|
|
1354
|
-
'Pyodide is licensed under the Mozilla Public License Version 2.0:',
|
|
1355
|
-
'==============================================================================',
|
|
1356
|
-
'',
|
|
1357
|
-
'Copyright (c) 2018-present Pyodide contributors.',
|
|
1358
|
-
'',
|
|
1359
|
-
'Full license: https://www.mozilla.org/en-US/MPL/2.0/',
|
|
1360
|
-
'',
|
|
1361
|
-
'Pyodide source: https://github.com/pyodide/pyodide',
|
|
1362
|
-
'Release tarball: https://cdn.jsdelivr.net/pyodide/v0.29.4/full/',
|
|
1363
|
-
'',
|
|
1364
|
-
'Bundled in Nimbus for the `nimbus install python` runtime. Python',
|
|
1365
|
-
'itself is under the PSF License Agreement (https://docs.python.org/3/',
|
|
1366
|
-
'license.html); pyodide.asm.wasm contains CPython 3.13 + selected',
|
|
1367
|
-
'standard-library modules statically linked to wasm32-unknown-emscripten.',
|
|
1368
|
-
'',
|
|
1369
|
-
].join('\n');
|
|
1370
|
-
}
|
|
1371
|
-
|
|
1372
|
-
function APACHE_2_LLVM_LICENSE_TEXT() {
|
|
1373
|
-
// Apache 2.0 with LLVM exception — abbreviated header pointing at
|
|
1374
|
-
// the canonical upstream LICENSE.TXT. We don't redistribute the
|
|
1375
|
-
// entire license verbatim here; the LICENSE file in the runtime
|
|
1376
|
-
// install dir tells the user where to find the full text.
|
|
1377
|
-
return [
|
|
1378
|
-
'==============================================================================',
|
|
1379
|
-
'The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:',
|
|
1380
|
-
'==============================================================================',
|
|
1381
|
-
'',
|
|
1382
|
-
'Copyright (c) The LLVM Project authors.',
|
|
1383
|
-
'Copyright (c) Ben Smith (binji) and contributors to wasm-clang.',
|
|
1384
|
-
'',
|
|
1385
|
-
'Full license: https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT',
|
|
1386
|
-
'',
|
|
1387
|
-
'binji/wasm-clang source: https://github.com/binji/wasm-clang',
|
|
1388
|
-
'Original CppCon 2019 talk: https://www.youtube.com/watch?v=5N4b-rU-OAA',
|
|
1389
|
-
'',
|
|
1390
|
-
'This artifact is a frozen build of LLVM 8.0 from 2018-2020. It is bundled',
|
|
1391
|
-
'in Nimbus under the original LLVM Apache 2.0 + LLVM Exception license.',
|
|
1392
|
-
'See the canonical LICENSE.TXT for the full text including the WebAssembly',
|
|
1393
|
-
'runtime exception clauses.',
|
|
1394
|
-
'',
|
|
1395
|
-
].join('\n');
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
function RUBY_LICENSE_TEXT() {
|
|
1399
|
-
// Ruby is dual-licensed under the Ruby License + BSD-2-Clause.
|
|
1400
|
-
// ruby.wasm packaging adds MIT for the JS bindings (which we
|
|
1401
|
-
// re-implement, so we don't redistribute their JS — only the wasm).
|
|
1402
|
-
// The wasm itself carries: Ruby License + BSD-2-Clause for the
|
|
1403
|
-
// interpreter, plus various permissive licenses for bundled gems
|
|
1404
|
-
// and the C extensions in stdlib.
|
|
1405
|
-
return [
|
|
1406
|
-
'==============================================================================',
|
|
1407
|
-
'Ruby is dual-licensed under the Ruby License (2-clause variant) and BSD-2-Clause:',
|
|
1408
|
-
'==============================================================================',
|
|
1409
|
-
'',
|
|
1410
|
-
'Copyright (c) Yukihiro Matsumoto. All rights reserved.',
|
|
1411
|
-
'',
|
|
1412
|
-
'Ruby License full text: https://www.ruby-lang.org/en/about/license.txt',
|
|
1413
|
-
'BSD-2-Clause full text: https://opensource.org/license/bsd-2-clause/',
|
|
1414
|
-
'',
|
|
1415
|
-
'Ruby source: https://github.com/ruby/ruby',
|
|
1416
|
-
'ruby.wasm source: https://github.com/ruby/ruby.wasm',
|
|
1417
|
-
'Release tarball: https://registry.npmjs.org/@ruby/3.3-wasm-wasi/-/3.3-wasm-wasi-2.9.3-2.9.4.tgz',
|
|
1418
|
-
'',
|
|
1419
|
-
'Bundled in Nimbus for the `nimbus install ruby` runtime. ruby+stdlib.wasm',
|
|
1420
|
-
'contains Ruby 3.3.x + the standard library packed via wasi-vfs, compiled',
|
|
1421
|
-
'to wasm32-unknown-wasi. The full Ruby standard library license list is in',
|
|
1422
|
-
'the upstream LEGAL file: https://github.com/ruby/ruby/blob/master/LEGAL.',
|
|
1423
|
-
'',
|
|
1424
|
-
].join('\n');
|
|
1425
|
-
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The installed cf-git copies and whether each carries the tracked patch.
|
|
3
|
+
*
|
|
4
|
+
* `packages/worker/patches/@ashishkumar472+cf-git+1.0.5.patch` rewrites one
|
|
5
|
+
* file, `index.js`. Its `index <pre>..<post>` header names the git blob ids of
|
|
6
|
+
* that file before and after the patch, so a copy's state is exact: its
|
|
7
|
+
* index.js hashes to <post> (patched), to <pre> (pristine), or to neither
|
|
8
|
+
* (foreign: an older or newer revision of the patch, or a hand edit).
|
|
9
|
+
*
|
|
10
|
+
* patch-install-deps.mjs brings every copy to <post>; bundle-git.mjs refuses to
|
|
11
|
+
* bundle a copy that is not at <post>, so a store patched by an older revision
|
|
12
|
+
* can never regenerate the git bundle without the current fixes.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { createHash } from 'node:crypto';
|
|
16
|
+
import { existsSync, readdirSync, readFileSync, realpathSync } from 'node:fs';
|
|
17
|
+
import { spawnSync } from 'node:child_process';
|
|
18
|
+
import { dirname, join, resolve, sep } from 'node:path';
|
|
19
|
+
import { homedir } from 'node:os';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
21
|
+
|
|
22
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
|
|
24
|
+
export const CF_GIT_PATCH = resolve(__dirname, '..', 'patches', '@ashishkumar472+cf-git+1.0.5.patch');
|
|
25
|
+
/** Where bun's cache keeps the pristine package, below the cache directory. */
|
|
26
|
+
const CACHE_ENTRY = join('@ashishkumar472', 'cf-git@1.0.5@@@1');
|
|
27
|
+
|
|
28
|
+
/** The patch's pre- and post-image blob ids (abbreviated, as git writes them). */
|
|
29
|
+
export function patchImages(patch = CF_GIT_PATCH) {
|
|
30
|
+
if (!existsSync(patch)) throw new Error(`Missing tracked cf-git patch: ${patch}`);
|
|
31
|
+
const text = readFileSync(patch, 'utf8');
|
|
32
|
+
if ((text.match(/^diff --git /gm) ?? []).length !== 1 || !/^diff --git a\/index\.js b\/index\.js$/m.test(text)) {
|
|
33
|
+
throw new Error(`${patch}: expected a patch of index.js alone`);
|
|
34
|
+
}
|
|
35
|
+
const header = /^index ([0-9a-f]{7,40})\.\.([0-9a-f]{7,40})(?: \d+)?$/m.exec(text);
|
|
36
|
+
if (!header) throw new Error(`${patch}: no 'index <pre>..<post>' header to verify an install against`);
|
|
37
|
+
return { pre: header[1], post: header[2] };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** `git hash-object` of a file. */
|
|
41
|
+
export function blobId(file) {
|
|
42
|
+
const bytes = readFileSync(file);
|
|
43
|
+
return createHash('sha1').update(`blob ${bytes.length}\0`).update(bytes).digest('hex');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** 'patched' | 'pristine' | 'foreign' | 'missing', by index.js's blob id. */
|
|
47
|
+
export function cfGitState(dir, images = patchImages()) {
|
|
48
|
+
const file = join(dir, 'index.js');
|
|
49
|
+
if (!existsSync(file)) return 'missing';
|
|
50
|
+
const id = blobId(file);
|
|
51
|
+
if (id.startsWith(images.post)) return 'patched';
|
|
52
|
+
if (id.startsWith(images.pre)) return 'pristine';
|
|
53
|
+
return 'foreign';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** node_modules trees at the repo root and one level into packages/* and apps/*. */
|
|
57
|
+
export function findNodeModules(base, depth = 0) {
|
|
58
|
+
if (depth > 5 || !existsSync(base)) return [];
|
|
59
|
+
const out = [];
|
|
60
|
+
let entries;
|
|
61
|
+
try { entries = readdirSync(base, { withFileTypes: true }); }
|
|
62
|
+
catch { return []; }
|
|
63
|
+
for (const ent of entries) {
|
|
64
|
+
if (!ent.isDirectory()) continue;
|
|
65
|
+
if (ent.name === 'node_modules') {
|
|
66
|
+
out.push(join(base, ent.name));
|
|
67
|
+
} else if (ent.name === 'packages' || ent.name === 'apps') {
|
|
68
|
+
for (const sub of readdirSync(join(base, ent.name), { withFileTypes: true })) {
|
|
69
|
+
if (sub.isDirectory()) out.push(...findNodeModules(join(base, ent.name, sub.name), depth + 1));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Real directories of every installed @ashishkumar472/cf-git@1.0.5, however bun laid it out. */
|
|
77
|
+
export function findCfGitDirs(repoRoot) {
|
|
78
|
+
const dirs = new Set();
|
|
79
|
+
for (const nm of findNodeModules(repoRoot)) {
|
|
80
|
+
for (const packagePath of [
|
|
81
|
+
join(nm, 'isomorphic-git', 'package.json'),
|
|
82
|
+
join(nm, '@ashishkumar472', 'cf-git', 'package.json'),
|
|
83
|
+
join(nm, '.bun', '@ashishkumar472+cf-git@1.0.5', 'node_modules', '@ashishkumar472', 'cf-git', 'package.json'),
|
|
84
|
+
]) {
|
|
85
|
+
if (!existsSync(packagePath)) continue;
|
|
86
|
+
const pkg = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
87
|
+
if (pkg.name === '@ashishkumar472/cf-git' && pkg.version === '1.0.5') dirs.add(realpathSync(dirname(packagePath)));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return dirs;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** What to delete so `bun install` lays the copy out again: its store entry, else the package itself. */
|
|
94
|
+
export function storeEntry(dir) {
|
|
95
|
+
const marker = `${sep}node_modules${sep}.bun${sep}`;
|
|
96
|
+
const at = dir.lastIndexOf(marker);
|
|
97
|
+
if (at < 0) return dir;
|
|
98
|
+
return dir.slice(0, at + marker.length) + dir.slice(at + marker.length).split(sep)[0];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** The command that reinstalls `dir` from bun's cache, for a refusal to name. */
|
|
102
|
+
export function reinstallCommand(dir, repoRoot) {
|
|
103
|
+
return `rm -rf '${storeEntry(dir)}' && (cd '${repoRoot}' && bun install)`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Throw unless every installed copy carries exactly the tracked patch. `extra`
|
|
108
|
+
* names a copy found another way (the one a bundler resolves), checked too.
|
|
109
|
+
*/
|
|
110
|
+
export function assertCfGitPatched(repoRoot, extra = []) {
|
|
111
|
+
const images = patchImages();
|
|
112
|
+
const dirs = findCfGitDirs(repoRoot);
|
|
113
|
+
for (const dir of extra) dirs.add(realpathSync(dir));
|
|
114
|
+
if (dirs.size === 0) throw new Error('No @ashishkumar472/cf-git@1.0.5 installation found');
|
|
115
|
+
const wrong = [...dirs].map((dir) => [dir, cfGitState(dir, images)]).filter(([, state]) => state !== 'patched');
|
|
116
|
+
if (wrong.length === 0) return dirs;
|
|
117
|
+
throw new Error(
|
|
118
|
+
'cf-git is not patched with the tracked patch (packages/worker/patches/@ashishkumar472+cf-git+1.0.5.patch, '
|
|
119
|
+
+ `index.js ${images.pre}..${images.post}), so a bundle built now would lack its fixes:\n`
|
|
120
|
+
+ wrong.map(([dir, state]) => ` ${dir}: ${state}\n fix: ${reinstallCommand(dir, repoRoot)}`).join('\n'),
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** bun's cache directory: $BUN_INSTALL_CACHE_DIR, else what `bun pm cache` reports, else bun's default. */
|
|
125
|
+
function bunCacheDir() {
|
|
126
|
+
if (process.env.BUN_INSTALL_CACHE_DIR) return process.env.BUN_INSTALL_CACHE_DIR;
|
|
127
|
+
const reported = spawnSync('bun', ['pm', 'cache'], { encoding: 'utf8' });
|
|
128
|
+
if (reported.status === 0 && reported.stdout.trim()) return reported.stdout.trim();
|
|
129
|
+
return join(process.env.BUN_INSTALL || join(homedir(), '.bun'), 'install', 'cache');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** bun's cached, unpatched index.js for cf-git 1.0.5, or null when the cache holds no pristine copy. */
|
|
133
|
+
export function pristineIndexJs(images = patchImages()) {
|
|
134
|
+
const file = join(bunCacheDir(), CACHE_ENTRY, 'index.js');
|
|
135
|
+
if (!existsSync(file)) return null;
|
|
136
|
+
return blobId(file).startsWith(images.pre) ? file : null;
|
|
137
|
+
}
|