@nimbus-sh/worker 0.6.0 → 0.8.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/README.md +2 -2
- package/dist/cirrus-npm-cjs.generated.d.ts +1 -1
- package/dist/cirrus-npm-cjs.generated.js +1 -1
- package/dist/facets/cirrus-real.d.ts.map +1 -1
- package/dist/facets/cirrus-real.js +6 -5
- package/dist/facets/compose.d.ts +148 -0
- package/dist/facets/compose.d.ts.map +1 -0
- package/dist/facets/compose.js +146 -0
- package/dist/facets/durable-images.d.ts +9 -5
- package/dist/facets/durable-images.d.ts.map +1 -1
- package/dist/facets/durable-images.js +17 -7
- package/dist/facets/esbuild-bundle-pool.d.ts +49 -0
- package/dist/facets/esbuild-bundle-pool.d.ts.map +1 -0
- package/dist/facets/esbuild-bundle-pool.js +122 -0
- package/dist/facets/exec-telemetry.d.ts +8 -0
- package/dist/facets/exec-telemetry.d.ts.map +1 -1
- package/dist/facets/manager.d.ts +240 -109
- package/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +677 -342
- package/dist/facets/process.d.ts +20 -16
- package/dist/facets/process.d.ts.map +1 -1
- package/dist/facets/process.js +59 -28
- package/dist/facets/real-vite-fs-shim.js +2 -2
- package/dist/facets/real-vite-hmr.d.ts +3 -1
- package/dist/facets/real-vite-hmr.d.ts.map +1 -1
- package/dist/facets/real-vite-hmr.js +18 -8
- package/dist/facets/vite-dev-server.d.ts +25 -47
- package/dist/facets/vite-dev-server.d.ts.map +1 -1
- package/dist/facets/vite-dev-server.js +185 -219
- package/dist/facets/wasm-image-digest.d.ts +25 -0
- package/dist/facets/wasm-image-digest.d.ts.map +1 -0
- package/dist/facets/wasm-image-digest.js +25 -0
- package/dist/facets/wasm-swap-registry.d.ts +51 -92
- package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
- package/dist/facets/wasm-swap-registry.js +68 -227
- package/dist/facets/ws-terminal.d.ts +9 -31
- package/dist/facets/ws-terminal.d.ts.map +1 -1
- package/dist/facets/ws-terminal.js +58 -51
- package/dist/git/network-facet.d.ts.map +1 -1
- package/dist/git/network-facet.js +6 -5
- package/dist/hosted/commands.d.ts +12 -0
- package/dist/hosted/commands.d.ts.map +1 -0
- package/dist/hosted/commands.js +1658 -0
- package/dist/hosted/runtime.d.ts +114 -0
- package/dist/hosted/runtime.d.ts.map +1 -0
- package/dist/hosted/runtime.js +288 -0
- package/dist/hosted/services.d.ts +40 -0
- package/dist/hosted/services.d.ts.map +1 -0
- package/dist/hosted/services.js +512 -0
- package/dist/loaders/child-process/spawn-pool.d.ts +3 -2
- package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
- package/dist/loaders/child-process/spawn-pool.js +3 -2
- 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/loaders/npm-resolve-preamble.d.ts +3 -6
- package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
- package/dist/loaders/npm-resolve-preamble.js +34 -108
- package/dist/node-shims-artifact.generated.js +3 -3
- package/dist/npm/install-batch-facet.d.ts +3 -2
- package/dist/npm/install-batch-facet.d.ts.map +1 -1
- package/dist/npm/install-batch-facet.js +45 -15
- package/dist/npm/installer.d.ts +22 -17
- package/dist/npm/installer.d.ts.map +1 -1
- package/dist/npm/installer.js +209 -193
- package/dist/npm/pre-bundle-facet.d.ts +1 -1
- package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
- package/dist/npm/pre-bundle-facet.js +1 -1
- package/dist/npm/resolve-facet.d.ts +6 -0
- package/dist/npm/resolve-facet.d.ts.map +1 -1
- package/dist/npm/resolve-one-facet.d.ts +21 -20
- package/dist/npm/resolve-one-facet.d.ts.map +1 -1
- package/dist/npm/resolve-one-facet.js +85 -84
- package/dist/npm/semver.d.ts +59 -0
- package/dist/npm/semver.d.ts.map +1 -0
- package/dist/npm/semver.js +226 -0
- package/dist/router/remote-api.js +31 -1
- package/dist/runtime/bash-repl.d.ts +1 -1
- package/dist/runtime/bash-repl.d.ts.map +1 -1
- package/dist/runtime/bash-repl.js +38 -4
- package/dist/runtime/bun-runner.js +1 -1
- package/dist/runtime/html-entrypoint.d.ts +7 -0
- package/dist/runtime/html-entrypoint.d.ts.map +1 -1
- package/dist/runtime/html-entrypoint.js +18 -2
- package/dist/runtime/node-runner.d.ts +4 -1
- package/dist/runtime/node-runner.d.ts.map +1 -1
- package/dist/runtime/node-runner.js +9 -2
- package/dist/runtime/node-shims.d.ts.map +1 -1
- package/dist/runtime/node-shims.js +305 -29
- package/dist/runtime/opencode-facet-runner.js +16 -16
- package/dist/runtime/package-manager.d.ts +35 -122
- package/dist/runtime/package-manager.d.ts.map +1 -1
- package/dist/runtime/package-manager.js +61 -596
- package/dist/runtime/process-logs-api.d.ts +1 -1
- package/dist/runtime/process-logs-api.d.ts.map +1 -1
- package/dist/runtime/process-logs-api.js +1 -1
- package/dist/runtime/python-repl.d.ts +2 -1
- package/dist/runtime/python-repl.d.ts.map +1 -1
- package/dist/runtime/python-repl.js +82 -59
- package/dist/runtime/repl-session.d.ts +9 -47
- package/dist/runtime/repl-session.d.ts.map +1 -1
- package/dist/runtime/repl-session.js +105 -105
- package/dist/runtime/runtime-catalog.d.ts +13 -0
- package/dist/runtime/runtime-catalog.d.ts.map +1 -1
- package/dist/runtime/runtime-catalog.js +88 -0
- package/dist/session/agent.d.ts +1 -21
- package/dist/session/agent.d.ts.map +1 -1
- package/dist/session/ai.d.ts +5 -1
- package/dist/session/ai.d.ts.map +1 -1
- package/dist/session/ai.js +7 -0
- package/dist/session/helpers.d.ts +38 -0
- package/dist/session/helpers.d.ts.map +1 -1
- package/dist/session/helpers.js +76 -0
- package/dist/session/hibernation.d.ts +2 -1
- package/dist/session/hibernation.d.ts.map +1 -1
- package/dist/session/hibernation.js +7 -4
- package/dist/session/init-phases.d.ts +1 -1
- package/dist/session/init-phases.d.ts.map +1 -1
- package/dist/session/init-phases.js +2 -12
- package/dist/session/init.d.ts +15 -36
- package/dist/session/init.d.ts.map +1 -1
- package/dist/session/init.js +50 -2327
- package/dist/session/loopback.d.ts +2 -29
- package/dist/session/loopback.d.ts.map +1 -1
- package/dist/session/loopback.js +3 -27
- package/dist/session/nimbus-session.d.ts +77 -34
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +126 -514
- package/dist/session/npm-install-port.d.ts +18 -0
- package/dist/session/npm-install-port.d.ts.map +1 -0
- package/dist/session/npm-install-port.js +37 -0
- package/dist/session/port-capability.d.ts +44 -0
- package/dist/session/port-capability.d.ts.map +1 -1
- package/dist/session/port-capability.js +110 -0
- package/dist/session/programmatic.d.ts +36 -43
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +109 -115
- package/dist/session/routes.d.ts +30 -17
- package/dist/session/routes.d.ts.map +1 -1
- package/dist/session/routes.js +42 -131
- package/dist/session/rpc.d.ts +15 -15
- package/dist/session/rpc.d.ts.map +1 -1
- package/dist/session/rpc.js +98 -49
- package/dist/session/serving-port.d.ts +27 -0
- package/dist/session/serving-port.d.ts.map +1 -0
- package/dist/session/serving-port.js +27 -0
- package/dist/session/start-real-vite.d.ts +12 -0
- package/dist/session/start-real-vite.d.ts.map +1 -1
- package/dist/session/start-real-vite.js +4 -4
- package/dist/session/supervisor-op.d.ts +4 -4
- package/dist/session/supervisor-op.d.ts.map +1 -1
- package/dist/session/supervisor-op.js +24 -10
- package/dist/session/supervisor-rpc.d.ts +7 -7
- package/dist/session/supervisor-rpc.d.ts.map +1 -1
- package/dist/session/supervisor-rpc.js +4 -0
- package/dist/session/vite-command.d.ts +18 -0
- package/dist/session/vite-command.d.ts.map +1 -0
- package/dist/session/vite-command.js +609 -0
- package/dist/session/ws.d.ts +61 -0
- package/dist/session/ws.d.ts.map +1 -1
- package/dist/session/ws.js +122 -12
- package/dist/shell/npm-bin-entrypoints.d.ts +0 -35
- package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
- package/dist/shell/npm-bin-entrypoints.js +12 -85
- package/dist/workspace-host.d.ts +6 -0
- package/dist/workspace-host.d.ts.map +1 -0
- package/dist/workspace-host.js +5 -0
- package/dist/workspace.d.ts +2 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +1 -0
- package/package.json +34 -9
- package/public/_assets/runtime/{node-shims-9e1380d9ee430fcc.js → node-shims-8f8c64edd2a1f0f5.js} +305 -29
- package/public/index.html +1 -1
- package/scripts/bundle-facet-workers.mjs +1 -1
- package/scripts/bundle-npm-cjs.mjs +2 -2
- package/dist/facets/on-demand-bundle-gate.d.ts +0 -65
- package/dist/facets/on-demand-bundle-gate.d.ts.map +0 -1
- package/dist/facets/on-demand-bundle-gate.js +0 -125
- package/dist/npm/install-args.d.ts +0 -21
- package/dist/npm/install-args.d.ts.map +0 -1
- package/dist/npm/install-args.js +0 -70
- package/dist/npm/npm-log.d.ts +0 -31
- package/dist/npm/npm-log.d.ts.map +0 -1
- package/dist/npm/npm-log.js +0 -51
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
import { staticStdinReader } from "@nimbus-sh/core/shell/stdin-adapter.js";
|
|
2
|
+
import { composeFacetManager } from "../facets/compose.js";
|
|
3
|
+
import { FacetProcessManager, textBytes } from "../facets/process.js";
|
|
4
|
+
import { ChildProcessSpawnPool } from "../loaders/child-process/spawn-pool.js";
|
|
5
|
+
import { CRED_KERNEL, CRED_SESSION_USER } from "@nimbus-sh/core/runtime/os-contracts.js";
|
|
6
|
+
import { EsbuildBundlePool } from "../facets/esbuild-bundle-pool.js";
|
|
7
|
+
import { EsbuildService } from "@nimbus-sh/core/runtime/esbuild-service.js";
|
|
8
|
+
import { CF_COMPAT_DATE } from "@nimbus-sh/core/constants.js";
|
|
9
|
+
import { notifyTerminalEvent } from "../runtime/process-logs-api.js";
|
|
10
|
+
// The supervisor terminates a facet's outbound sockets so inbound frames
|
|
11
|
+
// arrive as supervisor replies (VFS coherence witness 3).
|
|
12
|
+
import { WebSocketRelay } from "../session/ws-relay.js";
|
|
13
|
+
// ── Pure helpers extracted to ./nimbus-session-helpers.ts (S1) ────────
|
|
14
|
+
//
|
|
15
|
+
// renderNoDevServerHtml, BUNDLER_BIN_PREFIXES, NIMBUS_UNSUPPORTED_BINS,
|
|
16
|
+
// WRANGLER_IGNORED_FLAGS{,_WITH_VALUE}, WRANGLER_UNSUPPORTED_CONFIG_FIELDS,
|
|
17
|
+
// filterWranglerFlags, detectUnsupportedWranglerConfig, _CP_FACET_DIRECT,
|
|
18
|
+
// _CP_PURE_BUILTIN, _classifyCommand, detectBundlerBin, checkNodeModulesGuard
|
|
19
|
+
// all live in the helpers module now.
|
|
20
|
+
//
|
|
21
|
+
// They are imported here (so call sites in this file work unchanged) and
|
|
22
|
+
// re-exported (so external callers importing them from
|
|
23
|
+
// `./nimbus-session.js` keep working — back-compat).
|
|
24
|
+
//
|
|
25
|
+
// (esbuild wasm bytes are fetched from env.ASSETS by
|
|
26
|
+
// src/esbuild-wasm-bytes.ts at pool-construction time; A'.5 dropped
|
|
27
|
+
// the supervisor-resident cache + the SUPERVISOR.getEsbuildWasm RPC.)
|
|
28
|
+
// Helpers needed by this class file's own logic (not just re-export).
|
|
29
|
+
import { _classifyCommand } from "../session/helpers.js";
|
|
30
|
+
import { z } from "zod/v4";
|
|
31
|
+
const CpFacetDirectPayloadSchema = z.object({
|
|
32
|
+
command: z.unknown().optional().transform((value) => value == null ? '' : String(value)),
|
|
33
|
+
args: z.array(z.unknown()).optional().transform((value) => (value || []).map((item) => String(item))),
|
|
34
|
+
env: z.record(z.string(), z.unknown()).optional().transform((value) => {
|
|
35
|
+
const out = {};
|
|
36
|
+
for (const [key, item] of Object.entries(value || {}))
|
|
37
|
+
out[key] = String(item);
|
|
38
|
+
return out;
|
|
39
|
+
}),
|
|
40
|
+
cwd: z.unknown().optional().transform((value) => value == null ? '/' : String(value)),
|
|
41
|
+
stdin: z.unknown().optional().transform((value) => value == null ? '' : String(value)),
|
|
42
|
+
processPid: z.number().int().positive(),
|
|
43
|
+
}).passthrough();
|
|
44
|
+
function normalizeCpCommandName(name) {
|
|
45
|
+
const text = String(name || '').trim();
|
|
46
|
+
if (!text.startsWith('/'))
|
|
47
|
+
return text;
|
|
48
|
+
const slash = text.lastIndexOf('/');
|
|
49
|
+
const base = slash >= 0 ? text.slice(slash + 1) : text;
|
|
50
|
+
const dir = text.slice(0, Math.max(0, text.length - base.length));
|
|
51
|
+
if (dir === '/bin/' || dir === '/usr/bin/' || dir === '/usr/local/bin/') {
|
|
52
|
+
return base;
|
|
53
|
+
}
|
|
54
|
+
return text;
|
|
55
|
+
}
|
|
56
|
+
export function ensureBundlePool(self, runtimeContext) {
|
|
57
|
+
if (!self.bundlePool)
|
|
58
|
+
self.bundlePool = new EsbuildBundlePool(runtimeContext.env, runtimeContext.ctx);
|
|
59
|
+
return self.bundlePool;
|
|
60
|
+
}
|
|
61
|
+
export function ensureFacetManager(self, runtimeContext) {
|
|
62
|
+
if (!self.facetManagerComposed) {
|
|
63
|
+
// The manager is composed over the filesystem, so the filesystem comes
|
|
64
|
+
// first. Cheap and idempotent; every caller already stood it up or is
|
|
65
|
+
// about to.
|
|
66
|
+
self.ensureSqliteFs();
|
|
67
|
+
self.facetManagerComposed = composeFacetManager({
|
|
68
|
+
ctx: runtimeContext.ctx,
|
|
69
|
+
env: runtimeContext.env,
|
|
70
|
+
processes: self.processes,
|
|
71
|
+
portRegistry: self.portRegistry,
|
|
72
|
+
vfs: self.sqliteFs,
|
|
73
|
+
...(self.esbuildService ? { esbuild: self.esbuildService } : {}),
|
|
74
|
+
hooks: {
|
|
75
|
+
onExternalExit: (pid, code, reason) => self._reportExternalExit(pid, code, reason),
|
|
76
|
+
requestLaunchTurn: (notBefore) => { void runtimeContext.requestLaunchTurn(notBefore); },
|
|
77
|
+
notify: (line) => runtimeContext.notify(line),
|
|
78
|
+
onSpawn: (pid, command, longRunning) => {
|
|
79
|
+
const attachedTty = self.processes.get(pid)?.attachedTty === true;
|
|
80
|
+
if (longRunning) {
|
|
81
|
+
try {
|
|
82
|
+
self.processes.openInput(pid);
|
|
83
|
+
}
|
|
84
|
+
catch { }
|
|
85
|
+
}
|
|
86
|
+
// Only surface long-running / user-visible spawns to keep
|
|
87
|
+
// the terminal uncluttered. Short `node <file>` evals also
|
|
88
|
+
// get a line because users want the pid for `logs`/`kill`.
|
|
89
|
+
if (!self.terminal)
|
|
90
|
+
return;
|
|
91
|
+
const label = longRunning ? 'started (long-running)' : 'started';
|
|
92
|
+
self.terminal.write(`\x1b[2m[facet ${label}: pid=${pid} cmd="${command}"]\x1b[0m\r\n`);
|
|
93
|
+
// Structured event so the tabs UI can auto-open a log tab
|
|
94
|
+
// for long-running processes (vite, wrangler dev, etc.).
|
|
95
|
+
notifyTerminalEvent(self.terminal, {
|
|
96
|
+
type: 'spawn', pid, command, longRunning, attachedTty,
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const composed = self.facetManagerComposed;
|
|
103
|
+
// W3.5 Fix B: share the session's lazy esbuildService with the
|
|
104
|
+
// FacetManager so the bundle's ESM→CJS pre-pass doesn't pay
|
|
105
|
+
// wasm-init twice. The session may construct it after the manager
|
|
106
|
+
// exists, so the share is re-offered on every call; FacetManager
|
|
107
|
+
// otherwise lazy-creates its own on first exec — same wasm bytes,
|
|
108
|
+
// same ~10ms init cost, just paid once per surface.
|
|
109
|
+
if (self.esbuildService) {
|
|
110
|
+
composed.manager.setEsbuildService(self.esbuildService);
|
|
111
|
+
}
|
|
112
|
+
return composed;
|
|
113
|
+
}
|
|
114
|
+
export function _ensureWebSocketRelay(self, runtimeContext) {
|
|
115
|
+
if (!self.webSocketRelay)
|
|
116
|
+
self.webSocketRelay = new WebSocketRelay();
|
|
117
|
+
return self.webSocketRelay;
|
|
118
|
+
}
|
|
119
|
+
export function _ensureFacetProcessManager(self, runtimeContext) {
|
|
120
|
+
if (self.facetProcessManager)
|
|
121
|
+
return self.facetProcessManager;
|
|
122
|
+
self.ensureSqliteFs();
|
|
123
|
+
self.ensureFacetManager();
|
|
124
|
+
// FacetProcessManager is statically imported at top-of-file (W8).
|
|
125
|
+
// No lazy-import: workerd doesn't ship CJS require, and the dynamic
|
|
126
|
+
// import would be async — making _ensureFacetProcessManager async
|
|
127
|
+
// would force every cp* RPC entry point to also be async on the
|
|
128
|
+
// promise-resolution path, which is fine but uglier. Compile-time
|
|
129
|
+
// tree-shaking handles unused-when-no-cp-RPC paths.
|
|
130
|
+
// Adapter for FacetManagerLike — wraps the existing FacetManager.exec
|
|
131
|
+
// with a streaming surface. Phase 1 simplification: facet-direct
|
|
132
|
+
// commands are dispatched through the shell registry the same way
|
|
133
|
+
// shell.execute does, but with the per-PID hooks routed.
|
|
134
|
+
const facetMgrAdapter = {
|
|
135
|
+
execStream: async (codeJson, opts, hooks) => {
|
|
136
|
+
// codeJson is a payload from FacetProcessManager._dispatch facet-direct
|
|
137
|
+
// path: {command, args, env, cwd, stdin}. We dispatch through the
|
|
138
|
+
// existing shell registry by resolving the command and invoking
|
|
139
|
+
// it with synthesized output streams that route to hooks.
|
|
140
|
+
let payload;
|
|
141
|
+
try {
|
|
142
|
+
const parsed = CpFacetDirectPayloadSchema.safeParse(JSON.parse(codeJson));
|
|
143
|
+
if (!parsed.success) {
|
|
144
|
+
hooks.onStderr(textBytes('child_process: facet dispatch requires a broker-assigned process pid\n'));
|
|
145
|
+
return 1;
|
|
146
|
+
}
|
|
147
|
+
payload = parsed.data;
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
hooks.onStderr(textBytes('child_process: invalid facet dispatch payload\n'));
|
|
151
|
+
return 1;
|
|
152
|
+
}
|
|
153
|
+
const registry = self._cpRegistry;
|
|
154
|
+
if (!registry) {
|
|
155
|
+
hooks.onStderr(textBytes('child_process: command registry unavailable\n'));
|
|
156
|
+
return 127;
|
|
157
|
+
}
|
|
158
|
+
const commandName = normalizeCpCommandName(payload.command);
|
|
159
|
+
const cmd = await registry.resolve(commandName);
|
|
160
|
+
if (!cmd) {
|
|
161
|
+
hooks.onStderr(textBytes(`${payload.command}: command not found\n`));
|
|
162
|
+
return 127;
|
|
163
|
+
}
|
|
164
|
+
// Synthesize a CommandContext for the internal shell substrate.
|
|
165
|
+
const stdoutStream = { write: (d) => hooks.onStdout(textBytes(String(d))) };
|
|
166
|
+
const stderrStream = { write: (d) => hooks.onStderr(textBytes(String(d))) };
|
|
167
|
+
const ac = new AbortController();
|
|
168
|
+
const cred = self.processes.cred(payload.processPid);
|
|
169
|
+
const ctx = {
|
|
170
|
+
pid: payload.processPid,
|
|
171
|
+
cred,
|
|
172
|
+
args: payload.args || [],
|
|
173
|
+
env: payload.env || {},
|
|
174
|
+
cwd: payload.cwd || '/home/user',
|
|
175
|
+
vfs: self.sqliteFs.as(cred),
|
|
176
|
+
stdout: stdoutStream,
|
|
177
|
+
stderr: stderrStream,
|
|
178
|
+
signal: ac.signal,
|
|
179
|
+
// For commands that need stdin we pass a tiny adapter.
|
|
180
|
+
stdin: staticStdinReader(payload.stdin || ''),
|
|
181
|
+
setUmask: (mask) => { self.processes.setUmask(payload.processPid, mask); },
|
|
182
|
+
runAs: async (targetCred, argv) => {
|
|
183
|
+
if (argv.length === 0)
|
|
184
|
+
return 0;
|
|
185
|
+
const child = self.processes.spawn(argv.join(' '), argv, payload.cwd, { parentPid: payload.processPid, cred: targetCred });
|
|
186
|
+
let exitCode = 1;
|
|
187
|
+
try {
|
|
188
|
+
exitCode = await cmdRegistryAdapter.runPureBuiltin(child.pid, argv[0], argv.slice(1), payload.env, payload.cwd, payload.stdin, hooks);
|
|
189
|
+
return exitCode;
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
self.processes.exit(child.pid, exitCode);
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
__nimbusCaptureOutput: true,
|
|
196
|
+
};
|
|
197
|
+
try {
|
|
198
|
+
const code = await cmd(ctx);
|
|
199
|
+
return typeof code === 'number' ? code : 0;
|
|
200
|
+
}
|
|
201
|
+
catch (e) {
|
|
202
|
+
hooks.onStderr(textBytes(`${payload.command}: ${e?.message || String(e)}\n`));
|
|
203
|
+
return 1;
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
abort: (facetName) => {
|
|
207
|
+
// Best-effort: relay to ctx.facets.abort, mirroring FacetManager.kill.
|
|
208
|
+
try {
|
|
209
|
+
runtimeContext.ctx.facets?.abort?.(facetName, new Error('SIGKILL'));
|
|
210
|
+
}
|
|
211
|
+
catch { }
|
|
212
|
+
return true;
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
// Adapter for CommandRegistryLike. The shared shell registry is
|
|
216
|
+
// attached to `this._cpRegistry` by the shell-init path (see
|
|
217
|
+
// construction near line 2058 — registry passed as ctor arg there).
|
|
218
|
+
const cmdRegistryAdapter = {
|
|
219
|
+
// Consult the live shell registry FIRST so dynamically-registered
|
|
220
|
+
// commands (registerUnixCommands / git / npm / wrangler etc.) are seen
|
|
221
|
+
// even if they're not in the static _CP_PURE_BUILTIN allow-list. Falls
|
|
222
|
+
// back to the static facet-direct table for known facet-only commands.
|
|
223
|
+
// Returns null
|
|
224
|
+
// (→ exit 127) for everything unknown.
|
|
225
|
+
resolve: (name) => {
|
|
226
|
+
const commandName = normalizeCpCommandName(name);
|
|
227
|
+
const registry = self._cpRegistry;
|
|
228
|
+
if (registry && typeof registry.has === 'function' && registry.has(commandName)) {
|
|
229
|
+
// Registered — classify by name. Reuse the static table so
|
|
230
|
+
// facet-direct commands (node/npm/git/...) keep their kind
|
|
231
|
+
// even when they ALSO happen to be registry entries.
|
|
232
|
+
return _classifyCommand(commandName) || { kind: 'pure-builtin' };
|
|
233
|
+
}
|
|
234
|
+
return _classifyCommand(commandName);
|
|
235
|
+
},
|
|
236
|
+
runPureBuiltin: async (pid, name, args, env, cwd, stdin, hooks) => {
|
|
237
|
+
const registry = self._cpRegistry;
|
|
238
|
+
if (!registry) {
|
|
239
|
+
hooks.onStderr(textBytes('cp: registry unavailable\n'));
|
|
240
|
+
return 127;
|
|
241
|
+
}
|
|
242
|
+
const commandName = normalizeCpCommandName(name);
|
|
243
|
+
const cmd = await registry.resolve(commandName);
|
|
244
|
+
if (!cmd) {
|
|
245
|
+
hooks.onStderr(textBytes(`${name}: command not found\n`));
|
|
246
|
+
return 127;
|
|
247
|
+
}
|
|
248
|
+
const cred = self.processes.cred(pid);
|
|
249
|
+
const ac = new AbortController();
|
|
250
|
+
const ctx = {
|
|
251
|
+
pid,
|
|
252
|
+
cred,
|
|
253
|
+
args, env, cwd,
|
|
254
|
+
vfs: self.sqliteFs.as(cred),
|
|
255
|
+
stdout: { write: (d) => hooks.onStdout(textBytes(String(d))) },
|
|
256
|
+
stderr: { write: (d) => hooks.onStderr(textBytes(String(d))) },
|
|
257
|
+
signal: ac.signal,
|
|
258
|
+
stdin: staticStdinReader(stdin),
|
|
259
|
+
setUmask: (mask) => { self.processes.setUmask(pid, mask); },
|
|
260
|
+
runAs: async (targetCred, argv) => {
|
|
261
|
+
if (argv.length === 0)
|
|
262
|
+
return 0;
|
|
263
|
+
const child = self.processes.spawn(argv.join(' '), argv, cwd, { parentPid: pid, cred: targetCred });
|
|
264
|
+
let exitCode = 1;
|
|
265
|
+
try {
|
|
266
|
+
exitCode = await cmdRegistryAdapter.runPureBuiltin(child.pid, argv[0], argv.slice(1), env, cwd, stdin, hooks);
|
|
267
|
+
return exitCode;
|
|
268
|
+
}
|
|
269
|
+
finally {
|
|
270
|
+
self.processes.exit(child.pid, exitCode);
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
try {
|
|
275
|
+
const code = await cmd(ctx);
|
|
276
|
+
return typeof code === 'number' ? code : 0;
|
|
277
|
+
}
|
|
278
|
+
catch (e) {
|
|
279
|
+
hooks.onStderr(textBytes(`${name}: ${e?.message || String(e)}\n`));
|
|
280
|
+
return 1;
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
// Construct the child-process Loader pool when the binding is available.
|
|
285
|
+
// Unit-test hosts without LOADER continue through direct dispatch.
|
|
286
|
+
let spawnPool;
|
|
287
|
+
try {
|
|
288
|
+
const envAny = runtimeContext.env;
|
|
289
|
+
if (envAny?.LOADER && typeof envAny.LOADER.get === 'function') {
|
|
290
|
+
spawnPool = new ChildProcessSpawnPool(runtimeContext.env, runtimeContext.ctx);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
spawnPool = undefined;
|
|
295
|
+
}
|
|
296
|
+
self.facetProcessManager = new FacetProcessManager({
|
|
297
|
+
facetMgr: facetMgrAdapter,
|
|
298
|
+
processes: self.processes,
|
|
299
|
+
vfsForProcess: (pid) => self.sqliteFs.as(self.processes.cred(pid)),
|
|
300
|
+
commandRegistry: cmdRegistryAdapter,
|
|
301
|
+
shellExecutor: {
|
|
302
|
+
execute: async (pid, commandLine, env, cwd, stdin, hooks) => {
|
|
303
|
+
if (!self.shell) {
|
|
304
|
+
hooks.onStderr(textBytes('sh: shell unavailable\n'));
|
|
305
|
+
return 127;
|
|
306
|
+
}
|
|
307
|
+
const cred = self.processes.cred(pid);
|
|
308
|
+
const setUmask = (mask) => { self.processes.setUmask(pid, mask); };
|
|
309
|
+
const runAs = async (_parent, targetCred, argv) => {
|
|
310
|
+
if (argv.length === 0)
|
|
311
|
+
return 0;
|
|
312
|
+
const child = self.processes.spawn(argv.join(' '), argv, cwd, { parentPid: pid, cred: targetCred });
|
|
313
|
+
let exitCode = 1;
|
|
314
|
+
try {
|
|
315
|
+
exitCode = await cmdRegistryAdapter.runPureBuiltin(child.pid, argv[0], argv.slice(1), env, cwd, stdin, hooks);
|
|
316
|
+
return exitCode;
|
|
317
|
+
}
|
|
318
|
+
finally {
|
|
319
|
+
self.processes.exit(child.pid, exitCode);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
const result = await self.shell.execute(String(commandLine), {
|
|
323
|
+
cwd: cwd || '/home/user',
|
|
324
|
+
env: { ...self.shell.env, ...(env || {}) },
|
|
325
|
+
onStdout: hooks.onStdout,
|
|
326
|
+
onStderr: hooks.onStderr,
|
|
327
|
+
stdin,
|
|
328
|
+
isolateShellState: true,
|
|
329
|
+
commandContext: { pid, cred, setUmask },
|
|
330
|
+
runAs,
|
|
331
|
+
});
|
|
332
|
+
return typeof result?.exitCode === 'number' ? result.exitCode : 0;
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
ctx: runtimeContext.ctx,
|
|
336
|
+
spawnPool,
|
|
337
|
+
});
|
|
338
|
+
return self.facetProcessManager;
|
|
339
|
+
}
|
|
340
|
+
export function ensureFetchProxy(self, runtimeContext, log) {
|
|
341
|
+
if (self.fetchProxyEntrypoint)
|
|
342
|
+
return self.fetchProxyEntrypoint;
|
|
343
|
+
try {
|
|
344
|
+
const env = runtimeContext.env;
|
|
345
|
+
if (!env?.LOADER?.load) {
|
|
346
|
+
log?.('LOADER.load not available — using global fetch');
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
// Buffered proxy: reads the entire response body into an ArrayBuffer
|
|
350
|
+
// and returns it in ONE message instead of forwarding a ReadableStream.
|
|
351
|
+
// In workerd local dev, streaming responses across a service-binding
|
|
352
|
+
// RPC fabric opens a separate loopback socket PER chunk (~16KB), which
|
|
353
|
+
// exhausts ephemeral ports for larger installs (npm registry packuments
|
|
354
|
+
// are 500KB-3MB, tarballs up to 5MB). Buffering to arrayBuffer means
|
|
355
|
+
// 1 stub call = 1 loopback connection, not N connections.
|
|
356
|
+
//
|
|
357
|
+
// 32MB cap prevents a malformed giant response from OOMing the proxy
|
|
358
|
+
// isolate. Packages with tarballs larger than 32MB will fail to install
|
|
359
|
+
// cleanly (returned as 413 → caller treats as failed fetch).
|
|
360
|
+
const proxyCode = [
|
|
361
|
+
'const MAX_BYTES = 32 * 1024 * 1024;',
|
|
362
|
+
'export default {',
|
|
363
|
+
' async fetch(request, workerEnv) {',
|
|
364
|
+
' try {',
|
|
365
|
+
' const body = await request.json();',
|
|
366
|
+
' const resp = await fetch(body.url, {',
|
|
367
|
+
' method: body.method || "GET",',
|
|
368
|
+
' headers: body.headers || {},',
|
|
369
|
+
' });',
|
|
370
|
+
' // Check advertised Content-Length before buffering',
|
|
371
|
+
' const clStr = resp.headers.get("content-length");',
|
|
372
|
+
' if (clStr) {',
|
|
373
|
+
' const cl = parseInt(clStr, 10);',
|
|
374
|
+
' if (cl > MAX_BYTES) {',
|
|
375
|
+
' return new Response(',
|
|
376
|
+
' JSON.stringify({ error: "response too large: " + cl + " bytes (cap " + MAX_BYTES + ")" }),',
|
|
377
|
+
' { status: 413, headers: { "Content-Type": "application/json" } }',
|
|
378
|
+
' );',
|
|
379
|
+
' }',
|
|
380
|
+
' }',
|
|
381
|
+
' // Buffer entire body — ONE message, not streamed chunks',
|
|
382
|
+
' const buf = await resp.arrayBuffer();',
|
|
383
|
+
' if (buf.byteLength > MAX_BYTES) {',
|
|
384
|
+
' return new Response(',
|
|
385
|
+
' JSON.stringify({ error: "response exceeded cap: " + buf.byteLength + " bytes" }),',
|
|
386
|
+
' { status: 413, headers: { "Content-Type": "application/json" } }',
|
|
387
|
+
' );',
|
|
388
|
+
' }',
|
|
389
|
+
' return new Response(buf, {',
|
|
390
|
+
' status: resp.status,',
|
|
391
|
+
' statusText: resp.statusText,',
|
|
392
|
+
' headers: Object.fromEntries(resp.headers.entries()),',
|
|
393
|
+
' });',
|
|
394
|
+
' } catch (e) {',
|
|
395
|
+
' return new Response(JSON.stringify({ error: e.message }), {',
|
|
396
|
+
' status: 502,',
|
|
397
|
+
' headers: { "Content-Type": "application/json" },',
|
|
398
|
+
' });',
|
|
399
|
+
' }',
|
|
400
|
+
' }',
|
|
401
|
+
'};',
|
|
402
|
+
].join('\n');
|
|
403
|
+
const worker = env.LOADER.load({
|
|
404
|
+
compatibilityDate: CF_COMPAT_DATE,
|
|
405
|
+
compatibilityFlags: ['nodejs_compat'],
|
|
406
|
+
mainModule: 'fetch-proxy.js',
|
|
407
|
+
modules: { 'fetch-proxy.js': proxyCode },
|
|
408
|
+
});
|
|
409
|
+
self.fetchProxyEntrypoint = worker.getEntrypoint();
|
|
410
|
+
log?.('Fetch proxy worker created (singleton)');
|
|
411
|
+
return self.fetchProxyEntrypoint;
|
|
412
|
+
}
|
|
413
|
+
catch (e) {
|
|
414
|
+
log?.(`Fetch proxy creation failed: ${e?.message}`);
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
export function buildFetchFn(self, runtimeContext, log) {
|
|
419
|
+
const entrypoint = self.ensureFetchProxy(log);
|
|
420
|
+
if (!entrypoint)
|
|
421
|
+
return undefined;
|
|
422
|
+
return async (url, init) => {
|
|
423
|
+
const headers = {};
|
|
424
|
+
if (init?.headers) {
|
|
425
|
+
if (init.headers instanceof Headers) {
|
|
426
|
+
init.headers.forEach((v, k) => { headers[k] = v; });
|
|
427
|
+
}
|
|
428
|
+
else if (typeof init.headers === 'object') {
|
|
429
|
+
Object.assign(headers, init.headers);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return entrypoint.fetch(new Request('http://fetch-proxy/do-fetch', {
|
|
433
|
+
method: 'POST',
|
|
434
|
+
body: JSON.stringify({ url, method: init?.method || 'GET', headers }),
|
|
435
|
+
}));
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
export async function ensureNpmInstaller(self, runtimeContext, onProgress) {
|
|
439
|
+
self.ensureSqliteFs();
|
|
440
|
+
if (!self.esbuildService) {
|
|
441
|
+
if (!self.sqliteFs)
|
|
442
|
+
throw new Error('Session VFS is not initialized');
|
|
443
|
+
self.esbuildService = new EsbuildService(self.sqliteFs.as(CRED_KERNEL));
|
|
444
|
+
}
|
|
445
|
+
// Lazy-load the installer (+ its ~216 KB resolver/facet/loader-pool
|
|
446
|
+
// subgraph) on first npm use so it stays out of the cold script-eval
|
|
447
|
+
// graph. The install command paths that call this are already async.
|
|
448
|
+
const { NpmInstaller } = await import('../npm/installer.js');
|
|
449
|
+
// ── Lazy fetch-proxy ────────────────────────────────────────────
|
|
450
|
+
// The fetch-proxy is a singleton dynamic worker (LOADER.load) that
|
|
451
|
+
// buffers registry responses to dodge wrangler-local-dev port
|
|
452
|
+
// exhaustion. It is only needed for the in-supervisor npm paths.
|
|
453
|
+
// When the resolver and install paths run in facets (default-on),
|
|
454
|
+
// they use bare globalThis.fetch and need no proxy.
|
|
455
|
+
//
|
|
456
|
+
// workerd has a per-DO cap on concurrent dynamic workers (~5-6
|
|
457
|
+
// empirically). A permanent live proxy worker eats one of those
|
|
458
|
+
// slots for the entire DO lifetime, so the proxy is built only when
|
|
459
|
+
// any facet path is disabled via its env flag.
|
|
460
|
+
const useFacetResolver = self._envFlagDefaultOn('NIMBUS_FACET_RESOLVER');
|
|
461
|
+
const useFacetInstall = self._envFlagDefaultOn('NIMBUS_FACET_NPM_INSTALL');
|
|
462
|
+
const useBatchFacet = self._envFlagDefaultOn('NIMBUS_FACET_NPM_INSTALL_BATCH');
|
|
463
|
+
const needProxy = !(useFacetResolver && useFacetInstall && useBatchFacet);
|
|
464
|
+
const fetchFn = needProxy ? self.buildFetchFn(onProgress) : undefined;
|
|
465
|
+
if (!needProxy) {
|
|
466
|
+
onProgress?.(`[npm] Lazy fetch-proxy: skipped (all facet paths default-on)`);
|
|
467
|
+
}
|
|
468
|
+
self.npmInstaller = new NpmInstaller(self.sqliteFs, runtimeContext.ctx.storage.sql, {
|
|
469
|
+
esbuild: self.esbuildService,
|
|
470
|
+
bundlePool: self.ensureBundlePool(),
|
|
471
|
+
ctx: runtimeContext.ctx,
|
|
472
|
+
env: runtimeContext.env,
|
|
473
|
+
onProgress,
|
|
474
|
+
fetchFn,
|
|
475
|
+
});
|
|
476
|
+
return self.npmInstaller;
|
|
477
|
+
}
|
|
478
|
+
export function _envFlagDefaultOn(self, runtimeContext, name) {
|
|
479
|
+
const raw = runtimeContext.env?.[name];
|
|
480
|
+
if (raw === undefined || raw === null)
|
|
481
|
+
return true;
|
|
482
|
+
const s = String(raw).toLowerCase();
|
|
483
|
+
if (s === '0' || s === '' || s === 'false' || s === 'off' || s === 'no')
|
|
484
|
+
return false;
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
export function ensureGlobalPrefixDirs(self, runtimeContext, prefix) {
|
|
488
|
+
const fs = self.sqliteFs.as(CRED_SESSION_USER);
|
|
489
|
+
const dirs = [
|
|
490
|
+
prefix,
|
|
491
|
+
`${prefix}/lib`,
|
|
492
|
+
`${prefix}/lib/node_modules`,
|
|
493
|
+
`${prefix}/bin`,
|
|
494
|
+
];
|
|
495
|
+
for (const dir of dirs) {
|
|
496
|
+
if (!fs.exists(dir))
|
|
497
|
+
fs.mkdir(dir, { recursive: true });
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
export function bindRuntimeServices(host, context) {
|
|
501
|
+
return {
|
|
502
|
+
ensureBundlePool: ensureBundlePool.bind(null, host, context),
|
|
503
|
+
ensureFacetManager: ensureFacetManager.bind(null, host, context),
|
|
504
|
+
_ensureWebSocketRelay: _ensureWebSocketRelay.bind(null, host, context),
|
|
505
|
+
_ensureFacetProcessManager: _ensureFacetProcessManager.bind(null, host, context),
|
|
506
|
+
ensureFetchProxy: ensureFetchProxy.bind(null, host, context),
|
|
507
|
+
buildFetchFn: buildFetchFn.bind(null, host, context),
|
|
508
|
+
ensureNpmInstaller: ensureNpmInstaller.bind(null, host, context),
|
|
509
|
+
_envFlagDefaultOn: _envFlagDefaultOn.bind(null, host, context),
|
|
510
|
+
ensureGlobalPrefixDirs: ensureGlobalPrefixDirs.bind(null, host, context),
|
|
511
|
+
};
|
|
512
|
+
}
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
* Each spawn receives its own lifecycle envelope while command semantics
|
|
7
7
|
* continue to flow through the existing supervisor RPC.
|
|
8
8
|
*/
|
|
9
|
+
/** The child ring takes bytes; the inline result is text, encoded at this edge. */
|
|
9
10
|
export interface SpawnPoolHooks {
|
|
10
|
-
onStdout(data:
|
|
11
|
-
onStderr(data:
|
|
11
|
+
onStdout(data: Uint8Array): void;
|
|
12
|
+
onStderr(data: Uint8Array): void;
|
|
12
13
|
}
|
|
13
14
|
export interface SpawnPoolReq {
|
|
14
15
|
command: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-pool.d.ts","sourceRoot":"","sources":["../../../src/loaders/child-process/spawn-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"spawn-pool.d.ts","sourceRoot":"","sources":["../../../src/loaders/child-process/spawn-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;CAClC;AAGD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,qBAAqB;IAChC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC;;;;;OAKG;IACH,OAAO,CAAC,KAAK,CAAuC;gBAExC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,kBAAkB;IAS7C;;;;;;;;OAQG;IACG,MAAM,CACV,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,cAAc,GAAG,cAAc,GAAG,cAAc,EACtD,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,MAAM,CAAC;CA8CnB"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { IsolatePool } from '@nimbus-sh/fabric/isolate-pool.js';
|
|
10
10
|
import { runSpawnInIsolate } from './spawn-facet.js';
|
|
11
|
+
const RESULT_ENCODER = new TextEncoder();
|
|
11
12
|
export class ChildProcessSpawnPool {
|
|
12
13
|
/**
|
|
13
14
|
* Shared single-slot pool. Serial dispatch keeps one dynamic-worker
|
|
@@ -79,9 +80,9 @@ export class ChildProcessSpawnPool {
|
|
|
79
80
|
this.chain = myTurn.catch(() => undefined);
|
|
80
81
|
result = await myTurn;
|
|
81
82
|
if (result.stdout)
|
|
82
|
-
hooks.onStdout(result.stdout);
|
|
83
|
+
hooks.onStdout(RESULT_ENCODER.encode(result.stdout));
|
|
83
84
|
if (result.stderr)
|
|
84
|
-
hooks.onStderr(result.stderr);
|
|
85
|
+
hooks.onStderr(RESULT_ENCODER.encode(result.stderr));
|
|
85
86
|
return typeof result.exitCode === 'number' ? result.exitCode : 1;
|
|
86
87
|
}
|
|
87
88
|
}
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* helpers by name.
|
|
12
12
|
*
|
|
13
13
|
* Tar-stream symbols: parseTarHeader, streamTarEntries,
|
|
14
|
-
* readableStreamToAsyncIterable, MAX_FILE_BYTES.
|
|
14
|
+
* streamPackageEntries, readableStreamToAsyncIterable, MAX_FILE_BYTES.
|
|
15
15
|
* W7-frame symbols: encodeWriteBatchStream, decodeWriteBatchStream,
|
|
16
16
|
* W7_MAGIC, W7_MAX_RECORD_BYTES.
|
|
17
17
|
*
|
|
18
|
-
* Tar size: 4.
|
|
18
|
+
* Tar size: 4.62 KiB
|
|
19
19
|
* W7 size: 28.97 KiB
|
|
20
20
|
*/
|
|
21
21
|
export declare const TAR_STREAM_PREAMBLE: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generated-workers.d.ts","sourceRoot":"","sources":["../../src/loaders/generated-workers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,mBAAmB,EAAE,
|
|
1
|
+
{"version":3,"file":"generated-workers.d.ts","sourceRoot":"","sources":["../../src/loaders/generated-workers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,mBAAmB,EAAE,MAAk1J,CAAC;AAEr3J,eAAO,MAAM,iBAAiB,EAAE,MAA4/7B,CAAC"}
|