@nimbus-sh/worker 0.2.1 → 0.2.2
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/dist/loaders/generated-workers.d.ts +2 -2
- package/dist/loaders/generated-workers.d.ts.map +1 -1
- package/dist/loaders/generated-workers.js +3 -3
- package/dist/runtime/facet-loader-host.d.ts +3 -2
- package/dist/runtime/facet-loader-host.d.ts.map +1 -1
- package/dist/runtime/facet-loader-host.js +1 -0
- package/dist/runtime/ruby-repl.js +1 -1
- package/dist/runtime/ruby-resident.d.ts +20 -0
- package/dist/runtime/ruby-resident.d.ts.map +1 -0
- package/dist/runtime/ruby-resident.js +278 -0
- package/dist/session/init.d.ts +16 -7
- package/dist/session/init.d.ts.map +1 -1
- package/dist/session/init.js +181 -208
- package/dist/session/nimbus-session.d.ts +11 -1
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +13 -57
- package/dist/session/programmatic.d.ts +1 -1
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +1 -1
- package/dist/session/routes.js +1 -1
- package/package.json +2 -2
- package/scripts/bundle-facet-workers.mjs +4 -3
- package/scripts/bundle-runtime.mjs +276 -44
- package/dist/npm/tarball-stream.d.ts +0 -93
- package/dist/npm/tarball-stream.d.ts.map +0 -1
- package/dist/npm/tarball-stream.js +0 -235
- package/dist/npm/tarball.d.ts +0 -34
- package/dist/npm/tarball.d.ts.map +0 -1
- package/dist/npm/tarball.js +0 -97
- package/dist/runtime/clang-runner.d.ts +0 -37
- package/dist/runtime/clang-runner.d.ts.map +0 -1
- package/dist/runtime/clang-runner.js +0 -865
- package/dist/runtime/ruby-gems.d.ts +0 -30
- package/dist/runtime/ruby-gems.d.ts.map +0 -1
- package/dist/runtime/ruby-gems.js +0 -636
- package/dist/runtime/ruby-runner.d.ts +0 -75
- package/dist/runtime/ruby-runner.d.ts.map +0 -1
- package/dist/runtime/ruby-runner.js +0 -1577
|
@@ -30,12 +30,12 @@ import { NpmInstaller } from '../npm/installer.js';
|
|
|
30
30
|
// (was getEsbuildWasmBytes; cached) to fetchEsbuildWasmBytes (no
|
|
31
31
|
// supervisor cache; goes through env.ASSETS on demand).
|
|
32
32
|
import { setCtxExports } from './ctx-exports.js';
|
|
33
|
-
import { NIMBUS_VERSION,
|
|
33
|
+
import { NIMBUS_VERSION, DEFAULT_MOUNT_POINTS, CF_COMPAT_DATE } from '@nimbus-sh/core/constants.js';
|
|
34
|
+
import { seedBaseFilesystem } from '@nimbus-sh/core/workspace';
|
|
34
35
|
import { seedProject } from '@nimbus-sh/core/vfs/seed-project.js';
|
|
35
36
|
import { BASE_PATH_HEADER } from '../_shared/session-router.js';
|
|
36
37
|
import { ATTACH_BOOTSTRAP_JTI_KEY_PREFIX, SESSION_DESTROYED_KEY } from './keys.js';
|
|
37
38
|
import { appendScrollback } from './state-store.js';
|
|
38
|
-
import { dec } from '@nimbus-sh/core/_shared/bytes.js';
|
|
39
39
|
import { notifyTerminalEvent, wireProcessLogSocketBroadcast } from '../runtime/process-logs-api.js';
|
|
40
40
|
// S3: tryEnableReplicas + getReplicaState extracted to ./nimbus-session-replica.ts.
|
|
41
41
|
import { wireReplicasOnConstruct as _w12WireReplicasOnConstruct, getReplicaState as _w12GetReplicaState, } from './replica-routes.js';
|
|
@@ -1359,64 +1359,20 @@ export class NimbusSession extends CloudflareDurableObject {
|
|
|
1359
1359
|
fs.mkdir(dir, { recursive: true });
|
|
1360
1360
|
}
|
|
1361
1361
|
}
|
|
1362
|
+
/**
|
|
1363
|
+
* The starter content a fresh Nimbus session shows a user: the banner, the
|
|
1364
|
+
* sample files, and the Vite starter app.
|
|
1365
|
+
*
|
|
1366
|
+
* The base the OS boots on — the mount directories, /etc/passwd, /etc/group,
|
|
1367
|
+
* /etc/profile, ~/.nimbusrc — comes from the workspace's own seed, which
|
|
1368
|
+
* this calls rather than restates. Both are idempotent, so the workspace
|
|
1369
|
+
* re-running it when it composes the shell costs a handful of existence
|
|
1370
|
+
* checks and changes nothing.
|
|
1371
|
+
*/
|
|
1362
1372
|
seedFilesystem() {
|
|
1373
|
+
seedBaseFilesystem(this.sqliteFs, DEFAULT_MOUNT_POINTS);
|
|
1363
1374
|
const fs = this.sqliteFs.as(CRED_SESSION_USER);
|
|
1364
1375
|
const rootFs = this.sqliteFs.as(CRED_KERNEL);
|
|
1365
|
-
const dirs = [
|
|
1366
|
-
'bin', 'home', 'home/user', 'home/user/.config',
|
|
1367
|
-
'tmp', 'var', 'var/log', 'usr', 'usr/bin', 'usr/lib',
|
|
1368
|
-
'usr/lib/node_modules', 'usr/share', 'usr/share/pkg',
|
|
1369
|
-
'usr/share/pkg/node_modules', 'opt',
|
|
1370
|
-
'home/user/projects',
|
|
1371
|
-
];
|
|
1372
|
-
for (const dir of dirs) {
|
|
1373
|
-
if (!fs.exists(dir))
|
|
1374
|
-
fs.mkdir(dir, { recursive: true });
|
|
1375
|
-
}
|
|
1376
|
-
this.ensureGlobalPrefixDirs('usr/local');
|
|
1377
|
-
if (!rootFs.exists('etc')) {
|
|
1378
|
-
rootFs.mkdir('etc', { mode: 0o755 });
|
|
1379
|
-
}
|
|
1380
|
-
else {
|
|
1381
|
-
const etc = rootFs.stat('etc');
|
|
1382
|
-
if (etc.uid !== 0 || etc.gid !== 0)
|
|
1383
|
-
rootFs.chown('etc', 0, 0);
|
|
1384
|
-
if ((etc.mode & 0o7777) !== 0o755)
|
|
1385
|
-
rootFs.chmod('etc', 0o755);
|
|
1386
|
-
}
|
|
1387
|
-
if (!rootFs.exists('etc/hostname')) {
|
|
1388
|
-
rootFs.writeFile('etc/hostname', DEFAULT_HOSTNAME + '\n');
|
|
1389
|
-
rootFs.chown('etc/hostname', CRED_SESSION_USER.uid, CRED_SESSION_USER.gid);
|
|
1390
|
-
}
|
|
1391
|
-
if (!rootFs.exists('etc/os-release')) {
|
|
1392
|
-
rootFs.writeFile('etc/os-release', `NAME="Nimbus"\nVERSION="${NIMBUS_VERSION}"\nID=nimbus\n` +
|
|
1393
|
-
'PRETTY_NAME="Nimbus — Cloud Dev Environment"\n');
|
|
1394
|
-
rootFs.chown('etc/os-release', CRED_SESSION_USER.uid, CRED_SESSION_USER.gid);
|
|
1395
|
-
}
|
|
1396
|
-
const seedRootAccountFile = (path, content) => {
|
|
1397
|
-
if (!rootFs.exists(path))
|
|
1398
|
-
rootFs.writeFile(path, content, { mode: 0o644 });
|
|
1399
|
-
const stat = rootFs.stat(path);
|
|
1400
|
-
if (stat.uid !== 0 || stat.gid !== 0)
|
|
1401
|
-
rootFs.chown(path, 0, 0);
|
|
1402
|
-
if ((stat.mode & 0o7777) !== 0o644)
|
|
1403
|
-
rootFs.chmod(path, 0o644);
|
|
1404
|
-
};
|
|
1405
|
-
seedRootAccountFile('etc/passwd', 'root:x:0:0:root:/root:/bin/sh\n' +
|
|
1406
|
-
'user:x:1000:1000:Nimbus User:/home/user:/bin/sh\n');
|
|
1407
|
-
seedRootAccountFile('etc/group', 'root:x:0:\n' +
|
|
1408
|
-
'user:x:1000:user\n');
|
|
1409
|
-
const defaultProfile = `export PATH=${DEFAULT_PATH}\nexport EDITOR=nano\n`;
|
|
1410
|
-
if (!rootFs.exists('etc/profile')) {
|
|
1411
|
-
rootFs.writeFile('etc/profile', defaultProfile);
|
|
1412
|
-
rootFs.chown('etc/profile', CRED_SESSION_USER.uid, CRED_SESSION_USER.gid);
|
|
1413
|
-
}
|
|
1414
|
-
else if (dec.decode(rootFs.readFile('etc/profile')) === 'export PATH=/usr/bin:/bin\nexport EDITOR=nano\n') {
|
|
1415
|
-
rootFs.writeFile('etc/profile', defaultProfile);
|
|
1416
|
-
}
|
|
1417
|
-
if (!fs.exists('home/user/.nimbusrc')) {
|
|
1418
|
-
fs.writeFile('home/user/.nimbusrc', '# Nimbus shell config\nalias ll="ls -la"\nalias la="ls -a"\nalias l="ls -1"\n');
|
|
1419
|
-
}
|
|
1420
1376
|
{
|
|
1421
1377
|
// [BANNER ALIGNMENT FIX] Always re-render the motd so existing
|
|
1422
1378
|
// sessions whose VFS has the pre-fix mis-aligned banner get the
|
|
@@ -94,7 +94,7 @@ export interface ProgrammaticHost {
|
|
|
94
94
|
_w9WireProcessLogPersist?(): void;
|
|
95
95
|
ensureSqliteFs(): void;
|
|
96
96
|
ensureFacetManager(): void;
|
|
97
|
-
initSession(ws: WebSocket): void
|
|
97
|
+
initSession(ws: WebSocket): Promise<void>;
|
|
98
98
|
}
|
|
99
99
|
export interface ProgrammaticReadyOptions {
|
|
100
100
|
preinstall?: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"programmatic.d.ts","sourceRoot":"","sources":["../../src/session/programmatic.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"programmatic.d.ts","sourceRoot":"","sources":["../../src/session/programmatic.ts"],"names":[],"mappings":"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"}
|
|
@@ -79,7 +79,7 @@ function runtimeDeps(self) {
|
|
|
79
79
|
}
|
|
80
80
|
export async function ensureProgrammaticReady(self, options = {}) {
|
|
81
81
|
if (!self.shell) {
|
|
82
|
-
self.initSession(makeHeadlessWebSocket());
|
|
82
|
+
await self.initSession(makeHeadlessWebSocket());
|
|
83
83
|
// Programmatic boot owns no real terminal socket. Mark the session
|
|
84
84
|
// drained so a later browser /ws can warm-join instead of 409ing.
|
|
85
85
|
self._b4Phase = 'drained';
|
package/dist/session/routes.js
CHANGED
|
@@ -398,7 +398,7 @@ export async function handleFetch(self, request) {
|
|
|
398
398
|
}
|
|
399
399
|
// Cold init path — first ever /ws (or post-DO-eviction).
|
|
400
400
|
try {
|
|
401
|
-
self.initSession(server);
|
|
401
|
+
await self.initSession(server);
|
|
402
402
|
}
|
|
403
403
|
catch (err) {
|
|
404
404
|
console.error('initSession error:', err?.message, err?.stack);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nimbus-sh/worker",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Nimbus runtime package for Cloudflare Workers, re-exported publicly through @nimbus-sh/sdk/worker.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
86
|
"@ai-sdk/openai-compatible": "^2.0.41",
|
|
87
|
-
"@nimbus-sh/core": "^0.
|
|
87
|
+
"@nimbus-sh/core": "^0.3.0",
|
|
88
88
|
"@renovatebot/pep440": "^5.0.0",
|
|
89
89
|
"ai": "^6.0.182",
|
|
90
90
|
"clean-git-ref": "^2.0.1",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
* into a self-contained source string at build time.
|
|
12
12
|
*
|
|
13
13
|
* For the npm install facet we need the streaming tar parser
|
|
14
|
-
* (src/
|
|
14
|
+
* (@nimbus-sh/core src/_shared/tarball-stream.ts) available as a
|
|
15
|
+
* top-level named export
|
|
15
16
|
* the user function can call. We esbuild-bundle that source file into
|
|
16
17
|
* a self-contained ES module string, and NimbusFacetPool's `preamble`
|
|
17
18
|
* option splices it into the generated module between the
|
|
@@ -261,7 +262,7 @@ async function bundleBashRunner() {
|
|
|
261
262
|
async function main() {
|
|
262
263
|
// 1. Tar-parser preamble (existing W2.5/W4 hot-path helpers).
|
|
263
264
|
const tarStripped = await bundleAsPreamble(
|
|
264
|
-
join(
|
|
265
|
+
join(coreRoot, 'src', '_shared', 'tarball-stream.ts'),
|
|
265
266
|
'tar-stream',
|
|
266
267
|
);
|
|
267
268
|
|
|
@@ -289,7 +290,7 @@ async function main() {
|
|
|
289
290
|
' * generated-workers.ts — AUTO-GENERATED. DO NOT EDIT.',
|
|
290
291
|
' *',
|
|
291
292
|
' * Produced by scripts/bundle-facet-workers.mjs from:',
|
|
292
|
-
' * - src/
|
|
293
|
+
' * - @nimbus-sh/core src/_shared/tarball-stream.ts (streaming tar primitives)',
|
|
293
294
|
' * - @nimbus-sh/core src/_shared/w7-frame.ts (W7 streaming bulk-write encoder)',
|
|
294
295
|
' *',
|
|
295
296
|
' * Consumed by src/loaders/loader-pool.ts callers via the `preamble`',
|
|
@@ -7,6 +7,13 @@
|
|
|
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 --npm-package <dir> (local; no R2)
|
|
11
|
+
*
|
|
12
|
+
* `--npm-package` is the SECOND publisher for the same artifacts: it stages
|
|
13
|
+
* exactly what the R2 path stages, composes the same manifest bytes, and lays
|
|
14
|
+
* the blobs out under the same content-addressed keys — into a directory that
|
|
15
|
+
* `npm publish` takes, for the embedders who have npm and no bucket. It reads
|
|
16
|
+
* nothing from Cloudflare and writes nothing to it. See §--npm-package below.
|
|
10
17
|
*
|
|
11
18
|
* Per `2026-05-10-true-os/plan.md` §2.4:
|
|
12
19
|
* - Blobs are content-addressed under `blobs/<name>-<version>/<sha256>/<file>`.
|
|
@@ -45,10 +52,6 @@ import { tmpdir } from 'node:os';
|
|
|
45
52
|
import { basename, dirname, join } from 'node:path';
|
|
46
53
|
|
|
47
54
|
const ACCOUNT = process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
48
|
-
if (!ACCOUNT) {
|
|
49
|
-
console.error('ERROR: CLOUDFLARE_ACCOUNT_ID env var required');
|
|
50
|
-
process.exit(1);
|
|
51
|
-
}
|
|
52
55
|
// Resolve the wrangler bin from either the package-local or the
|
|
53
56
|
// repo-root node_modules (this script runs from packages/worker but
|
|
54
57
|
// the bin is hoisted to the workspace root).
|
|
@@ -62,6 +65,7 @@ const PYODIDE_WORKERD_ADAPTER = JSON.parse(
|
|
|
62
65
|
|
|
63
66
|
const USAGE =
|
|
64
67
|
'usage: bundle-runtime.mjs <name> <version> [--bucket <bucket>]\n' +
|
|
68
|
+
' bundle-runtime.mjs <name> <version> --npm-package <dir>\n' +
|
|
65
69
|
' bundle-runtime.mjs --pin-catalog [--bucket <bucket>]';
|
|
66
70
|
|
|
67
71
|
/** The bucket the deployed Worker's NIMBUS_RUNTIME_CACHE binding points at.
|
|
@@ -74,12 +78,25 @@ const rawArgs = process.argv.slice(2);
|
|
|
74
78
|
const positionalArgs = [];
|
|
75
79
|
let BUCKET = process.env.NIMBUS_RUNTIME_BUCKET || PRODUCTION_BUCKET;
|
|
76
80
|
let PIN_ONLY = false;
|
|
81
|
+
let NPM_OUT_DIR = null;
|
|
77
82
|
for (let i = 0; i < rawArgs.length; i++) {
|
|
78
83
|
const arg = rawArgs[i];
|
|
79
84
|
if (arg === '--pin-catalog') {
|
|
80
85
|
PIN_ONLY = true;
|
|
81
86
|
continue;
|
|
82
87
|
}
|
|
88
|
+
if (arg === '--npm-package') {
|
|
89
|
+
NPM_OUT_DIR = rawArgs[++i];
|
|
90
|
+
if (!NPM_OUT_DIR) {
|
|
91
|
+
console.error(USAGE);
|
|
92
|
+
process.exit(2);
|
|
93
|
+
}
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (arg.startsWith('--npm-package=')) {
|
|
97
|
+
NPM_OUT_DIR = arg.slice('--npm-package='.length);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
83
100
|
if (arg === '--bucket') {
|
|
84
101
|
const value = rawArgs[++i];
|
|
85
102
|
if (!value) {
|
|
@@ -96,6 +113,12 @@ for (let i = 0; i < rawArgs.length; i++) {
|
|
|
96
113
|
positionalArgs.push(arg);
|
|
97
114
|
}
|
|
98
115
|
|
|
116
|
+
// Every mode but `--npm-package` reads or writes R2 through wrangler.
|
|
117
|
+
if (!NPM_OUT_DIR && !ACCOUNT) {
|
|
118
|
+
console.error('ERROR: CLOUDFLARE_ACCOUNT_ID env var required');
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
|
|
99
122
|
// `--pin-catalog` regenerates the build-time root of trust from the catalog
|
|
100
123
|
// already in R2. Read-only: it publishes nothing, so it is safe to run at any
|
|
101
124
|
// time, including while another ingest is in flight against a different bucket.
|
|
@@ -127,6 +150,15 @@ const SPECS = {
|
|
|
127
150
|
license: 'Apache-2.0-with-LLVM-exception',
|
|
128
151
|
wasi_namespace: 'wasi_unstable',
|
|
129
152
|
upstream_base: 'https://raw.githubusercontent.com/binji/wasm-clang/master',
|
|
153
|
+
npm: {
|
|
154
|
+
name: '@nimbus-sh/runtime-clang',
|
|
155
|
+
summary: 'clang 8.0.1 and wasm-ld for wasm32-wasi, with a wasi-libc sysroot',
|
|
156
|
+
// npm demands semver and this runtime's Nimbus version is a channel
|
|
157
|
+
// name, so the compiler's own version is what the package carries. The
|
|
158
|
+
// two namespaces stay separate: the manifest still says `binji-2020`,
|
|
159
|
+
// and that is what the install root under ~/.nimbus/runtimes is named.
|
|
160
|
+
version: '8.0.1',
|
|
161
|
+
},
|
|
130
162
|
files: [
|
|
131
163
|
{ src: 'clang', vfs: 'bin/clang', mode: 'exec', runner: 'clang-runner', binName: 'clang' },
|
|
132
164
|
{ src: 'lld', vfs: 'bin/wasm-ld', mode: 'exec', runner: 'clang-runner', binName: 'wasm-ld', kind: 'linker' },
|
|
@@ -154,6 +186,10 @@ const SPECS = {
|
|
|
154
186
|
license: 'Ruby+BSD-2-Clause',
|
|
155
187
|
wasi_namespace: 'wasi_snapshot_preview1',
|
|
156
188
|
upstream_base: 'https://registry.npmjs.org/@ruby/3.3-wasm-wasi/-/3.3-wasm-wasi-2.9.3-2.9.4.tgz',
|
|
189
|
+
npm: {
|
|
190
|
+
name: '@nimbus-sh/runtime-ruby',
|
|
191
|
+
summary: 'Ruby 3.3.4 (ruby.wasm) for wasm32-wasi, with its stdlib packed in',
|
|
192
|
+
},
|
|
157
193
|
tarball_extract: 'package/dist', // strip this prefix from src paths inside the tarball
|
|
158
194
|
files: [
|
|
159
195
|
// The Ruby wasm — includes Ruby 3.3.x interpreter + stdlib packed
|
|
@@ -194,6 +230,10 @@ const SPECS = {
|
|
|
194
230
|
license: 'GPL-3.0-or-later AND GPL-2.0-only',
|
|
195
231
|
wasi_namespace: 'wasi_snapshot_preview1',
|
|
196
232
|
local_base: '../wasm/bash',
|
|
233
|
+
npm: {
|
|
234
|
+
name: '@nimbus-sh/runtime-bash',
|
|
235
|
+
summary: 'GNU bash 5.2.37 and BusyBox 1.37.0, cross-compiled to wasm32-wasi',
|
|
236
|
+
},
|
|
197
237
|
files: [
|
|
198
238
|
{ src: 'bash.async.wasm', vfs: 'share/bash/bash.async.wasm' },
|
|
199
239
|
{ src: 'coreutils/busybox.wasm', vfs: 'share/bash/coreutils/busybox.wasm' },
|
|
@@ -271,6 +311,10 @@ const SPECS = {
|
|
|
271
311
|
license: 'PSF-2.0',
|
|
272
312
|
wasi_namespace: 'wasi_snapshot_preview1',
|
|
273
313
|
local_base: '../wasm/python',
|
|
314
|
+
npm: {
|
|
315
|
+
name: '@nimbus-sh/runtime-cpython',
|
|
316
|
+
summary: 'CPython 3.13.14, cross-compiled to wasm32-wasi, with its stdlib',
|
|
317
|
+
},
|
|
274
318
|
files: [
|
|
275
319
|
{ src: 'python.wasm', vfs: 'share/cpython/python.wasm' },
|
|
276
320
|
// The same interpreter with numpy and markupsafe's C speedups linked in,
|
|
@@ -383,6 +427,19 @@ if (!spec) {
|
|
|
383
427
|
console.error(`known: ${Object.keys(SPECS).join(', ')}`);
|
|
384
428
|
process.exit(2);
|
|
385
429
|
}
|
|
430
|
+
// Checked before anything is staged: which runtimes we publish to npm is a
|
|
431
|
+
// decision, and a spec that has not made it should cost nothing to find out.
|
|
432
|
+
if (NPM_OUT_DIR) {
|
|
433
|
+
if (!spec.npm) {
|
|
434
|
+
console.error(`ERROR: ${key} declares no npm package in its spec.`);
|
|
435
|
+
console.error(' Add an `npm: { name, summary }` entry to publish it that way.');
|
|
436
|
+
process.exit(2);
|
|
437
|
+
}
|
|
438
|
+
if (spec.ingest_only) {
|
|
439
|
+
console.error(`ERROR: ${key} is ingest_only — it has no manifest to publish.`);
|
|
440
|
+
process.exit(2);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
386
443
|
|
|
387
444
|
const workDir = join(tmpdir(), `bundle-runtime-${RUNTIME}-${VERSION}`);
|
|
388
445
|
rmSync(workDir, { recursive: true, force: true });
|
|
@@ -390,8 +447,12 @@ mkdirSync(workDir, { recursive: true });
|
|
|
390
447
|
|
|
391
448
|
console.log(`[bundle-runtime] ${RUNTIME} ${VERSION}`);
|
|
392
449
|
console.log(`[bundle-runtime] work dir: ${workDir}`);
|
|
393
|
-
|
|
394
|
-
console.log(`[bundle-runtime]
|
|
450
|
+
if (NPM_OUT_DIR) {
|
|
451
|
+
console.log(`[bundle-runtime] target: ${NPM_OUT_DIR} (npm package; R2 is not read or written)`);
|
|
452
|
+
} else {
|
|
453
|
+
console.log(`[bundle-runtime] bucket: ${BUCKET}`);
|
|
454
|
+
console.log(`[bundle-runtime] account: ${ACCOUNT}`);
|
|
455
|
+
}
|
|
395
456
|
|
|
396
457
|
// ── 0. Optional repackage step (sysroot-prep wave) ──────────────────
|
|
397
458
|
// Runs BEFORE the fetch loop. Produces one or more local files inside
|
|
@@ -480,6 +541,19 @@ if (!spec.ingest_only) {
|
|
|
480
541
|
console.log(`[bundle-runtime] LICENSE → ${licenseBytes.length} bytes sha256=${licenseSha256.slice(0, 16)}…`);
|
|
481
542
|
}
|
|
482
543
|
|
|
544
|
+
const totalMb = (downloaded.reduce((a, f) => a + f.size, 0) / 1024 / 1024).toFixed(2);
|
|
545
|
+
|
|
546
|
+
// ── --npm-package: the same artifacts, published through npm ────────
|
|
547
|
+
// Everything above this line is the staging the R2 path performs, and
|
|
548
|
+
// everything below it is Cloudflare. A runtime package is the staged blobs
|
|
549
|
+
// under their content-addressed keys plus the manifest that names them, which
|
|
550
|
+
// is the R2 bucket's shape for one runtime, in a directory `npm publish`
|
|
551
|
+
// takes. Nothing here reads or writes R2.
|
|
552
|
+
if (NPM_OUT_DIR) {
|
|
553
|
+
writeNpmPackage(NPM_OUT_DIR, composeManifest(downloaded, packageRuntimeArtifacts), downloaded);
|
|
554
|
+
process.exit(0);
|
|
555
|
+
}
|
|
556
|
+
|
|
483
557
|
// ── 2. Upload each file as a content-addressed blob (deduped) ──────
|
|
484
558
|
// Content path: blobs/<name>-<version>/<sha256>/<src-name>. Multiple
|
|
485
559
|
// manifest entries pointing at identical content share one R2 upload.
|
|
@@ -497,8 +571,6 @@ for (const f of downloaded) {
|
|
|
497
571
|
// ── 3 + 4. Manifest + catalog. Skipped in ingest_only mode (the swap
|
|
498
572
|
// wave composes those at manifest-compose time; this prep pass only
|
|
499
573
|
// stages the upstream blobs).
|
|
500
|
-
const totalMb = (downloaded.reduce((a, f) => a + f.size, 0) / 1024 / 1024).toFixed(2);
|
|
501
|
-
|
|
502
574
|
if (spec.ingest_only) {
|
|
503
575
|
console.log(`\n[bundle-runtime] DONE (ingest_only)`);
|
|
504
576
|
console.log(`[bundle-runtime] uploaded ${downloaded.length} file(s) (${totalMb} MiB) for ${RUNTIME}@${VERSION}`);
|
|
@@ -507,43 +579,8 @@ if (spec.ingest_only) {
|
|
|
507
579
|
console.log(`[bundle-runtime] catalog: UNCHANGED (swap wave will flip default)`);
|
|
508
580
|
} else {
|
|
509
581
|
// ── 3. Write the per-version manifest ────────────────────────────
|
|
510
|
-
const runtimeArtifacts = downloaded
|
|
511
|
-
.filter((f) => f.transformMetadata)
|
|
512
|
-
.map((f) => ({
|
|
513
|
-
path: f.vfs,
|
|
514
|
-
kind: f.transformMetadata.kind,
|
|
515
|
-
id: f.transformMetadata.id,
|
|
516
|
-
source_sha256: f.transformMetadata.source_sha256,
|
|
517
|
-
sha256: f.sha256,
|
|
518
|
-
}));
|
|
519
|
-
runtimeArtifacts.push(...packageRuntimeArtifacts);
|
|
520
|
-
|
|
521
|
-
const manifest = {
|
|
522
|
-
name: RUNTIME,
|
|
523
|
-
version: VERSION,
|
|
524
|
-
license: spec.license,
|
|
525
|
-
wasi_namespace: spec.wasi_namespace || null,
|
|
526
|
-
files: downloaded.map((f) => ({
|
|
527
|
-
path: f.vfs,
|
|
528
|
-
content: f.r2Key,
|
|
529
|
-
sha256: f.sha256,
|
|
530
|
-
size: f.size,
|
|
531
|
-
...(f.mode ? { mode: f.mode } : {}),
|
|
532
|
-
})),
|
|
533
|
-
entrypoints: spec.files
|
|
534
|
-
.filter((f) => f.runner)
|
|
535
|
-
.map((f) => ({
|
|
536
|
-
binName: f.binName,
|
|
537
|
-
runner: f.runner,
|
|
538
|
-
args: [],
|
|
539
|
-
...(f.kind ? { kind: f.kind } : {}),
|
|
540
|
-
})),
|
|
541
|
-
...(runtimeArtifacts.length ? { runtime_artifacts: runtimeArtifacts } : {}),
|
|
542
|
-
};
|
|
543
|
-
|
|
544
582
|
const manifestLocal = join(workDir, 'manifest.json');
|
|
545
|
-
|
|
546
|
-
writeFileSync(manifestLocal, manifestText);
|
|
583
|
+
writeFileSync(manifestLocal, manifestText(composeManifest(downloaded, packageRuntimeArtifacts)));
|
|
547
584
|
// Digest of the exact bytes uploaded below. The catalog carries it so the
|
|
548
585
|
// supervisor can verify a manifest the same way a manifest lets it verify
|
|
549
586
|
// a blob — see the trust-model note in src/runtime/runtime-catalog.ts.
|
|
@@ -788,6 +825,201 @@ function pinCatalogFromR2() {
|
|
|
788
825
|
}
|
|
789
826
|
}
|
|
790
827
|
|
|
828
|
+
// ── The manifest ─────────────────────────────────────────────────────
|
|
829
|
+
//
|
|
830
|
+
// What a runtime IS: the files it is made of, the digest of each, and the
|
|
831
|
+
// commands they answer. Both publishers compose it here so an embedder who
|
|
832
|
+
// installed the npm package and a session that ran `nimbus install` are
|
|
833
|
+
// holding the same description of the same runtime, byte for byte.
|
|
834
|
+
|
|
835
|
+
function composeManifest(downloaded, packageRuntimeArtifacts) {
|
|
836
|
+
const runtimeArtifacts = downloaded
|
|
837
|
+
.filter((f) => f.transformMetadata)
|
|
838
|
+
.map((f) => ({
|
|
839
|
+
path: f.vfs,
|
|
840
|
+
kind: f.transformMetadata.kind,
|
|
841
|
+
id: f.transformMetadata.id,
|
|
842
|
+
source_sha256: f.transformMetadata.source_sha256,
|
|
843
|
+
sha256: f.sha256,
|
|
844
|
+
}));
|
|
845
|
+
runtimeArtifacts.push(...packageRuntimeArtifacts);
|
|
846
|
+
|
|
847
|
+
return {
|
|
848
|
+
name: RUNTIME,
|
|
849
|
+
version: VERSION,
|
|
850
|
+
license: spec.license,
|
|
851
|
+
wasi_namespace: spec.wasi_namespace || null,
|
|
852
|
+
files: downloaded.map((f) => ({
|
|
853
|
+
path: f.vfs,
|
|
854
|
+
content: f.r2Key,
|
|
855
|
+
sha256: f.sha256,
|
|
856
|
+
size: f.size,
|
|
857
|
+
...(f.mode ? { mode: f.mode } : {}),
|
|
858
|
+
})),
|
|
859
|
+
entrypoints: spec.files
|
|
860
|
+
.filter((f) => f.runner)
|
|
861
|
+
.map((f) => ({
|
|
862
|
+
binName: f.binName,
|
|
863
|
+
runner: f.runner,
|
|
864
|
+
args: [],
|
|
865
|
+
...(f.kind ? { kind: f.kind } : {}),
|
|
866
|
+
})),
|
|
867
|
+
...(runtimeArtifacts.length ? { runtime_artifacts: runtimeArtifacts } : {}),
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
function manifestText(manifest) {
|
|
872
|
+
return JSON.stringify(manifest, null, 2);
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// ── --npm-package ────────────────────────────────────────────────────
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* Write the runtime as a directory `npm publish` accepts.
|
|
879
|
+
*
|
|
880
|
+
* The blobs keep the keys the manifest already names — `blobs/<name>-<version>/
|
|
881
|
+
* <sha256>/<file>`, the R2 object keys — so the manifest needs no npm-specific
|
|
882
|
+
* rewrite and comes out byte-identical to the one in the bucket. That is the
|
|
883
|
+
* point rather than a coincidence: `content` is documented as the publisher's
|
|
884
|
+
* key for a blob, and for this publisher a path inside its own tarball IS that
|
|
885
|
+
* key. There is one manifest format and one layout, and `readBlob` below is
|
|
886
|
+
* the whole of what distinguishes the two publishers.
|
|
887
|
+
*/
|
|
888
|
+
function writeNpmPackage(outDir, manifest, downloaded) {
|
|
889
|
+
rmSync(outDir, { recursive: true, force: true });
|
|
890
|
+
mkdirSync(outDir, { recursive: true });
|
|
891
|
+
|
|
892
|
+
const written = new Set();
|
|
893
|
+
let unpackedBytes = 0;
|
|
894
|
+
for (const f of downloaded) {
|
|
895
|
+
if (written.has(f.r2Key)) continue;
|
|
896
|
+
written.add(f.r2Key);
|
|
897
|
+
unpackedBytes += f.size;
|
|
898
|
+
const dest = join(outDir, f.r2Key);
|
|
899
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
900
|
+
writeFileSync(dest, f.bytes);
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
writeFileSync(join(outDir, 'manifest.json'), manifestText(manifest));
|
|
904
|
+
writeFileSync(join(outDir, 'LICENSE'), spec.license_text);
|
|
905
|
+
writeFileSync(join(outDir, 'index.js'), runtimePackageEntry());
|
|
906
|
+
writeFileSync(join(outDir, 'index.d.ts'), runtimePackageTypes());
|
|
907
|
+
writeFileSync(join(outDir, 'README.md'), runtimePackageReadme());
|
|
908
|
+
const npmVersion = spec.npm.version ?? VERSION;
|
|
909
|
+
writeFileSync(join(outDir, 'package.json'), `${JSON.stringify({
|
|
910
|
+
name: spec.npm.name,
|
|
911
|
+
version: npmVersion,
|
|
912
|
+
description: `${spec.npm.summary}, as a Nimbus runtime package.`,
|
|
913
|
+
keywords: ['nimbus', 'wasm', 'wasi', 'runtime', RUNTIME],
|
|
914
|
+
homepage: 'https://github.com/AshishKumar4/Nimbus',
|
|
915
|
+
// No `directory`: the package is built from the runtime spec and the wasm
|
|
916
|
+
// build tree, and has no source directory of its own to point at.
|
|
917
|
+
repository: { type: 'git', url: 'git+https://github.com/AshishKumar4/Nimbus.git' },
|
|
918
|
+
bugs: 'https://github.com/AshishKumar4/Nimbus/issues',
|
|
919
|
+
license: spec.license,
|
|
920
|
+
type: 'module',
|
|
921
|
+
main: './index.js',
|
|
922
|
+
types: './index.d.ts',
|
|
923
|
+
exports: {
|
|
924
|
+
'.': { types: './index.d.ts', import: './index.js' },
|
|
925
|
+
'./manifest.json': './manifest.json',
|
|
926
|
+
'./package.json': './package.json',
|
|
927
|
+
},
|
|
928
|
+
files: ['index.js', 'index.d.ts', 'manifest.json', 'blobs', 'LICENSE', 'README.md'],
|
|
929
|
+
// The runtime is inert without the half that installs and runs it, and
|
|
930
|
+
// `index.d.ts` types itself against that package's exports.
|
|
931
|
+
peerDependencies: { '@nimbus-sh/core': '>=0.2.0' },
|
|
932
|
+
publishConfig: { access: 'public' },
|
|
933
|
+
}, null, 2)}\n`);
|
|
934
|
+
|
|
935
|
+
console.log(`\n[bundle-runtime] DONE (npm package)`);
|
|
936
|
+
console.log(`[bundle-runtime] ${spec.npm.name}@${npmVersion} → ${outDir}`);
|
|
937
|
+
console.log(`[bundle-runtime] ${written.size} blobs, ${(unpackedBytes / 1024 / 1024).toFixed(2)} MiB unpacked`);
|
|
938
|
+
console.log(`[bundle-runtime] publish with: npm publish ${outDir}`);
|
|
939
|
+
console.log(`[bundle-runtime] R2: UNTOUCHED (nothing was read from or written to Cloudflare)`);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* The package entry point, identical in every runtime package.
|
|
944
|
+
*
|
|
945
|
+
* It is the `RuntimePackage` port from `@nimbus-sh/core`: a manifest, and the
|
|
946
|
+
* bytes it names. Core verifies every blob against the manifest before it
|
|
947
|
+
* reaches a filesystem, so this side neither hashes nor validates — it reads.
|
|
948
|
+
*/
|
|
949
|
+
function runtimePackageEntry() {
|
|
950
|
+
return `/**
|
|
951
|
+
* A Nimbus runtime package: a manifest, and the content-addressed blobs it
|
|
952
|
+
* names. Pass the default export to \`NimbusWorkspace.create({ runtimes })\`
|
|
953
|
+
* and the runtime installs into the workspace filesystem, digest-verified,
|
|
954
|
+
* at the same path \`nimbus install\` uses on Cloudflare.
|
|
955
|
+
*
|
|
956
|
+
* Generated by packages/worker/scripts/bundle-runtime.mjs. Do not edit.
|
|
957
|
+
*/
|
|
958
|
+
|
|
959
|
+
import { readFileSync } from 'node:fs';
|
|
960
|
+
|
|
961
|
+
const root = new URL('./', import.meta.url);
|
|
962
|
+
|
|
963
|
+
export const manifest = JSON.parse(readFileSync(new URL('manifest.json', root), 'utf8'));
|
|
964
|
+
|
|
965
|
+
/** The bytes of one manifest file entry, by the publisher key it carries. */
|
|
966
|
+
export function readBlob(file) {
|
|
967
|
+
// Copied rather than handed over: readFileSync returns a pooled Buffer for
|
|
968
|
+
// small files, whose backing ArrayBuffer holds other files' bytes too.
|
|
969
|
+
return new Uint8Array(readFileSync(new URL(file.content, root)));
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
export default { manifest, readBlob };
|
|
973
|
+
`;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
function runtimePackageTypes() {
|
|
977
|
+
return `import type { ManifestFile, RuntimeManifest, RuntimePackage } from '@nimbus-sh/core';
|
|
978
|
+
|
|
979
|
+
export declare const manifest: RuntimeManifest;
|
|
980
|
+
export declare function readBlob(file: ManifestFile): Uint8Array;
|
|
981
|
+
|
|
982
|
+
declare const runtimePackage: RuntimePackage;
|
|
983
|
+
export default runtimePackage;
|
|
984
|
+
`;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
function runtimePackageReadme() {
|
|
988
|
+
return `# ${spec.npm.name}
|
|
989
|
+
|
|
990
|
+
${spec.npm.summary}, packaged for [Nimbus](https://github.com/AshishKumar4/Nimbus).
|
|
991
|
+
|
|
992
|
+
This package is data: the runtime's wasm and support files, content-addressed,
|
|
993
|
+
plus the manifest that describes them. It does nothing on its own —
|
|
994
|
+
[\`@nimbus-sh/core\`](https://www.npmjs.com/package/@nimbus-sh/core) installs it
|
|
995
|
+
into a workspace filesystem and runs it.
|
|
996
|
+
|
|
997
|
+
\`\`\`bash
|
|
998
|
+
npm install @nimbus-sh/core ${spec.npm.name}
|
|
999
|
+
\`\`\`
|
|
1000
|
+
|
|
1001
|
+
\`\`\`js
|
|
1002
|
+
import { NimbusWorkspace, localFacetHost } from '@nimbus-sh/core';
|
|
1003
|
+
import ${RUNTIME} from '${spec.npm.name}';
|
|
1004
|
+
|
|
1005
|
+
const workspace = await NimbusWorkspace.create({
|
|
1006
|
+
sql, // your SQLite, through the SqlDatabase port
|
|
1007
|
+
facets: localFacetHost(),
|
|
1008
|
+
runtimes: [${RUNTIME}],
|
|
1009
|
+
});
|
|
1010
|
+
\`\`\`
|
|
1011
|
+
|
|
1012
|
+
Every file is verified against the manifest's SHA-256 before it reaches the
|
|
1013
|
+
filesystem. The same bytes are served to Cloudflare deployments from R2 by
|
|
1014
|
+
\`nimbus install ${RUNTIME}\`, under the same manifest.
|
|
1015
|
+
|
|
1016
|
+
## Licence
|
|
1017
|
+
|
|
1018
|
+
${spec.license}. See the bundled \`LICENSE\` for the notice and where to find
|
|
1019
|
+
the full text and corresponding source.
|
|
1020
|
+
`;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
791
1023
|
// ── Runtime transforms ───────────────────────────────────────────────
|
|
792
1024
|
|
|
793
1025
|
function runtimeBlobKey(src, sha256) {
|