@scelar/nodepod 1.0.2 → 1.0.4
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/__sw__.js +642 -642
- package/dist/__tests__/bench/integration.bench.d.ts +1 -0
- package/dist/__tests__/bench/memory-volume.bench.d.ts +1 -0
- package/dist/__tests__/bench/polyfills.bench.d.ts +1 -0
- package/dist/__tests__/bench/script-engine.bench.d.ts +1 -0
- package/dist/__tests__/bench/shell.bench.d.ts +1 -0
- package/dist/__tests__/bench/syntax-transforms.bench.d.ts +1 -0
- package/dist/__tests__/bench/version-resolver.bench.d.ts +1 -0
- package/dist/__tests__/buffer.test.d.ts +1 -0
- package/dist/__tests__/byte-encoding.test.d.ts +1 -0
- package/dist/__tests__/digest.test.d.ts +1 -0
- package/dist/__tests__/events.test.d.ts +1 -0
- package/dist/__tests__/memory-volume.test.d.ts +1 -0
- package/dist/__tests__/path.test.d.ts +1 -0
- package/dist/__tests__/process.test.d.ts +1 -0
- package/dist/__tests__/script-engine.test.d.ts +1 -0
- package/dist/__tests__/shell-builtins.test.d.ts +1 -0
- package/dist/__tests__/shell-interpreter.test.d.ts +1 -0
- package/dist/__tests__/shell-parser.test.d.ts +1 -0
- package/dist/__tests__/stream.test.d.ts +1 -0
- package/dist/__tests__/syntax-transforms.test.d.ts +1 -0
- package/dist/__tests__/version-resolver.test.d.ts +1 -0
- package/dist/{child_process-Dopvyd-E.js → child_process-53fMkug_.js} +4 -4
- package/dist/child_process-53fMkug_.js.map +1 -0
- package/dist/{child_process-B38qoN6R.cjs → child_process-lxSKECHq.cjs} +5 -5
- package/dist/child_process-lxSKECHq.cjs.map +1 -0
- package/dist/{index--Qr8LVpQ.js → index-B8lyh_ti.js} +1316 -559
- package/dist/index-B8lyh_ti.js.map +1 -0
- package/dist/{index-cnitc68U.cjs → index-C-TQIrdG.cjs} +1422 -612
- package/dist/index-C-TQIrdG.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/memory-volume.d.ts +1 -1
- package/dist/polyfills/wasi.d.ts +45 -4
- package/dist/script-engine.d.ts +2 -0
- package/dist/sdk/nodepod.d.ts +4 -3
- package/dist/sdk/types.d.ts +6 -0
- package/dist/syntax-transforms.d.ts +1 -0
- package/dist/threading/process-manager.d.ts +1 -1
- package/dist/threading/worker-protocol.d.ts +1 -1
- package/package.json +5 -3
- package/src/__tests__/bench/integration.bench.ts +117 -0
- package/src/__tests__/bench/memory-volume.bench.ts +115 -0
- package/src/__tests__/bench/polyfills.bench.ts +147 -0
- package/src/__tests__/bench/script-engine.bench.ts +104 -0
- package/src/__tests__/bench/shell.bench.ts +101 -0
- package/src/__tests__/bench/syntax-transforms.bench.ts +82 -0
- package/src/__tests__/bench/version-resolver.bench.ts +95 -0
- package/src/__tests__/buffer.test.ts +273 -0
- package/src/__tests__/byte-encoding.test.ts +98 -0
- package/src/__tests__/digest.test.ts +44 -0
- package/src/__tests__/events.test.ts +245 -0
- package/src/__tests__/memory-volume.test.ts +443 -0
- package/src/__tests__/path.test.ts +181 -0
- package/src/__tests__/process.test.ts +129 -0
- package/src/__tests__/script-engine.test.ts +229 -0
- package/src/__tests__/shell-builtins.test.ts +357 -0
- package/src/__tests__/shell-interpreter.test.ts +157 -0
- package/src/__tests__/shell-parser.test.ts +204 -0
- package/src/__tests__/stream.test.ts +142 -0
- package/src/__tests__/syntax-transforms.test.ts +158 -0
- package/src/__tests__/version-resolver.test.ts +184 -0
- package/src/constants/cdn-urls.ts +18 -18
- package/src/helpers/byte-encoding.ts +51 -39
- package/src/index.ts +192 -192
- package/src/memory-volume.ts +968 -941
- package/src/module-transformer.ts +368 -368
- package/src/packages/installer.ts +396 -396
- package/src/packages/version-resolver.ts +12 -2
- package/src/polyfills/buffer.ts +633 -628
- package/src/polyfills/child_process.ts +2288 -2288
- package/src/polyfills/esbuild.ts +854 -854
- package/src/polyfills/events.ts +282 -276
- package/src/polyfills/fs.ts +2888 -2888
- package/src/polyfills/http.ts +1450 -1449
- package/src/polyfills/process.ts +721 -690
- package/src/polyfills/readline.ts +692 -692
- package/src/polyfills/stream.ts +1620 -1620
- package/src/polyfills/tty.ts +71 -71
- package/src/polyfills/wasi.ts +1284 -22
- package/src/request-proxy.ts +716 -716
- package/src/script-engine.ts +465 -146
- package/src/sdk/nodepod.ts +525 -509
- package/src/sdk/types.ts +7 -0
- package/src/syntax-transforms.ts +543 -561
- package/src/threading/offload-worker.ts +383 -383
- package/src/threading/offload.ts +271 -271
- package/src/threading/process-manager.ts +956 -956
- package/src/threading/process-worker-entry.ts +858 -854
- package/src/threading/worker-protocol.ts +1 -1
- package/dist/child_process-B38qoN6R.cjs.map +0 -1
- package/dist/child_process-Dopvyd-E.js.map +0 -1
- package/dist/index--Qr8LVpQ.js.map +0 -1
- package/dist/index-cnitc68U.cjs.map +0 -1
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
// Pinned CDN versions and URLs
|
|
2
|
-
|
|
3
|
-
export const PINNED_ESBUILD_WASM = '0.20.0';
|
|
4
|
-
export const PINNED_ROLLUP_BROWSER = '4.9.0';
|
|
5
|
-
export const PINNED_BROTLI_WASM = '3.0.1';
|
|
6
|
-
export const PINNED_LIGHTNINGCSS_WASM = '1.31.1';
|
|
7
|
-
|
|
8
|
-
export const CDN_ESBUILD_ESM = `https://esm.sh/esbuild-wasm@${PINNED_ESBUILD_WASM}`;
|
|
9
|
-
export const CDN_ESBUILD_BINARY = `https://esm.sh/esbuild-wasm@${PINNED_ESBUILD_WASM}/esbuild.wasm`;
|
|
10
|
-
export const CDN_ESBUILD_BROWSER = `https://esm.sh/esbuild-wasm@${PINNED_ESBUILD_WASM}/esm/browser.min.js`;
|
|
11
|
-
export const CDN_ROLLUP_BROWSER = `https://esm.sh/@rollup/browser@${PINNED_ROLLUP_BROWSER}`;
|
|
12
|
-
export const CDN_BROTLI_WASM = `https://esm.sh/brotli-wasm@${PINNED_BROTLI_WASM}`;
|
|
13
|
-
export const CDN_LIGHTNINGCSS_WASM = `https://esm.sh/lightningcss-wasm@${PINNED_LIGHTNINGCSS_WASM}`;
|
|
14
|
-
|
|
15
|
-
// new Function hides import() from bundler static analysis so CDN URLs work at runtime
|
|
16
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
17
|
-
const _dynamicImport = new Function("url", "return import(url)") as (url: string) => Promise<any>;
|
|
18
|
-
export { _dynamicImport as cdnImport };
|
|
1
|
+
// Pinned CDN versions and URLs
|
|
2
|
+
|
|
3
|
+
export const PINNED_ESBUILD_WASM = '0.20.0';
|
|
4
|
+
export const PINNED_ROLLUP_BROWSER = '4.9.0';
|
|
5
|
+
export const PINNED_BROTLI_WASM = '3.0.1';
|
|
6
|
+
export const PINNED_LIGHTNINGCSS_WASM = '1.31.1';
|
|
7
|
+
|
|
8
|
+
export const CDN_ESBUILD_ESM = `https://esm.sh/esbuild-wasm@${PINNED_ESBUILD_WASM}`;
|
|
9
|
+
export const CDN_ESBUILD_BINARY = `https://esm.sh/esbuild-wasm@${PINNED_ESBUILD_WASM}/esbuild.wasm`;
|
|
10
|
+
export const CDN_ESBUILD_BROWSER = `https://esm.sh/esbuild-wasm@${PINNED_ESBUILD_WASM}/esm/browser.min.js`;
|
|
11
|
+
export const CDN_ROLLUP_BROWSER = `https://esm.sh/@rollup/browser@${PINNED_ROLLUP_BROWSER}`;
|
|
12
|
+
export const CDN_BROTLI_WASM = `https://esm.sh/brotli-wasm@${PINNED_BROTLI_WASM}`;
|
|
13
|
+
export const CDN_LIGHTNINGCSS_WASM = `https://esm.sh/lightningcss-wasm@${PINNED_LIGHTNINGCSS_WASM}`;
|
|
14
|
+
|
|
15
|
+
// new Function hides import() from bundler static analysis so CDN URLs work at runtime
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
17
|
+
const _dynamicImport = new Function("url", "return import(url)") as (url: string) => Promise<any>;
|
|
18
|
+
export { _dynamicImport as cdnImport };
|
|
@@ -1,39 +1,51 @@
|
|
|
1
|
-
// Chunked to avoid blowing the call stack on large buffers
|
|
2
|
-
const SEGMENT_SIZE = 8192;
|
|
3
|
-
|
|
4
|
-
export function bytesToBase64(data: Uint8Array): string {
|
|
5
|
-
const segments: string[] = [];
|
|
6
|
-
for (let offset = 0; offset < data.length; offset += SEGMENT_SIZE) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
// Chunked to avoid blowing the call stack on large buffers
|
|
2
|
+
const SEGMENT_SIZE = 8192;
|
|
3
|
+
|
|
4
|
+
export function bytesToBase64(data: Uint8Array): string {
|
|
5
|
+
const segments: string[] = [];
|
|
6
|
+
for (let offset = 0; offset < data.length; offset += SEGMENT_SIZE) {
|
|
7
|
+
const end = Math.min(offset + SEGMENT_SIZE, data.length);
|
|
8
|
+
let chunk = '';
|
|
9
|
+
for (let i = offset; i < end; i++) {
|
|
10
|
+
chunk += String.fromCharCode(data[i]);
|
|
11
|
+
}
|
|
12
|
+
segments.push(chunk);
|
|
13
|
+
}
|
|
14
|
+
return btoa(segments.join(''));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function base64ToBytes(encoded: string): Uint8Array {
|
|
18
|
+
const raw = atob(encoded);
|
|
19
|
+
const result = new Uint8Array(raw.length);
|
|
20
|
+
for (let i = 0; i < raw.length; i++) {
|
|
21
|
+
result[i] = raw.charCodeAt(i);
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Pre-computed hex lookup table
|
|
27
|
+
const HEX_TABLE: string[] = new Array(256);
|
|
28
|
+
for (let i = 0; i < 256; i++) {
|
|
29
|
+
HEX_TABLE[i] = (i < 16 ? '0' : '') + i.toString(16);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function bytesToHex(data: Uint8Array): string {
|
|
33
|
+
const chars = new Array(data.length);
|
|
34
|
+
for (let i = 0; i < data.length; i++) {
|
|
35
|
+
chars[i] = HEX_TABLE[data[i]];
|
|
36
|
+
}
|
|
37
|
+
return chars.join('');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function bytesToLatin1(data: Uint8Array): string {
|
|
41
|
+
const segments: string[] = [];
|
|
42
|
+
for (let offset = 0; offset < data.length; offset += SEGMENT_SIZE) {
|
|
43
|
+
const end = Math.min(offset + SEGMENT_SIZE, data.length);
|
|
44
|
+
let chunk = '';
|
|
45
|
+
for (let i = offset; i < end; i++) {
|
|
46
|
+
chunk += String.fromCharCode(data[i]);
|
|
47
|
+
}
|
|
48
|
+
segments.push(chunk);
|
|
49
|
+
}
|
|
50
|
+
return segments.join('');
|
|
51
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,192 +1,192 @@
|
|
|
1
|
-
// nodepod - browser-native Node.js runtime environment
|
|
2
|
-
|
|
3
|
-
export { MemoryVolume } from "./memory-volume";
|
|
4
|
-
export type {
|
|
5
|
-
VolumeNode,
|
|
6
|
-
FileStat,
|
|
7
|
-
FileWatchHandle,
|
|
8
|
-
WatchCallback,
|
|
9
|
-
WatchEventKind,
|
|
10
|
-
SystemError,
|
|
11
|
-
} from "./memory-volume";
|
|
12
|
-
export { ScriptEngine, executeCode } from "./script-engine";
|
|
13
|
-
export type { ModuleRecord, EngineOptions, ResolverFn } from "./script-engine";
|
|
14
|
-
export { spawnEngine, WorkerSandbox, IframeSandbox, spawnProcessWorkerEngine, ProcessWorkerAdapter } from "./engine-factory";
|
|
15
|
-
export type {
|
|
16
|
-
IScriptEngine,
|
|
17
|
-
ExecutionOutcome,
|
|
18
|
-
SpawnEngineConfig,
|
|
19
|
-
EngineConfig,
|
|
20
|
-
VolumeSnapshot,
|
|
21
|
-
} from "./engine-types";
|
|
22
|
-
export {
|
|
23
|
-
generateSandboxDeployment,
|
|
24
|
-
getSandboxPageHtml,
|
|
25
|
-
getSandboxHostingConfig,
|
|
26
|
-
SANDBOX_DEPLOYMENT_GUIDE,
|
|
27
|
-
} from "./isolation-helpers";
|
|
28
|
-
export { buildFileSystemBridge } from "./polyfills/fs";
|
|
29
|
-
export type { FsBridge } from "./polyfills/fs";
|
|
30
|
-
export { buildProcessEnv } from "./polyfills/process";
|
|
31
|
-
export type { ProcessObject, ProcessEnvVars } from "./polyfills/process";
|
|
32
|
-
export * as path from "./polyfills/path";
|
|
33
|
-
export * as http from "./polyfills/http";
|
|
34
|
-
export * as net from "./polyfills/net";
|
|
35
|
-
export * as events from "./polyfills/events";
|
|
36
|
-
export * as stream from "./polyfills/stream";
|
|
37
|
-
export * as url from "./polyfills/url";
|
|
38
|
-
export * as querystring from "./polyfills/querystring";
|
|
39
|
-
export * as util from "./polyfills/util";
|
|
40
|
-
export * as npm from "./packages/installer";
|
|
41
|
-
export { DependencyInstaller, install } from "./packages/installer";
|
|
42
|
-
export { RequestProxy, getProxyInstance, resetProxy } from "./request-proxy";
|
|
43
|
-
export type { ProxyOptions, ServiceWorkerConfig } from "./request-proxy";
|
|
44
|
-
export * as chokidar from "./polyfills/chokidar";
|
|
45
|
-
export * as ws from "./polyfills/ws";
|
|
46
|
-
export * as fsevents from "./polyfills/fsevents";
|
|
47
|
-
export * as readdirp from "./polyfills/readdirp";
|
|
48
|
-
export * as module from "./polyfills/module";
|
|
49
|
-
export * as perf_hooks from "./polyfills/perf_hooks";
|
|
50
|
-
export * as worker_threads from "./polyfills/worker_threads";
|
|
51
|
-
export * as esbuild from "./polyfills/esbuild";
|
|
52
|
-
export * as rollup from "./polyfills/rollup";
|
|
53
|
-
export * as assert from "./polyfills/assert";
|
|
54
|
-
|
|
55
|
-
import { MemoryVolume } from "./memory-volume";
|
|
56
|
-
import { ScriptEngine, EngineOptions } from "./script-engine";
|
|
57
|
-
import { DependencyInstaller } from "./packages/installer";
|
|
58
|
-
import { RequestProxy, getProxyInstance } from "./request-proxy";
|
|
59
|
-
// lazy-load child_process to avoid pulling in the shell at module load time
|
|
60
|
-
let _shellMod: typeof import("./polyfills/child_process") | null = null;
|
|
61
|
-
async function getShellMod() {
|
|
62
|
-
if (!_shellMod) _shellMod = await import("./polyfills/child_process");
|
|
63
|
-
return _shellMod;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface CommandResult {
|
|
67
|
-
stdout: string;
|
|
68
|
-
stderr: string;
|
|
69
|
-
exitCode: number;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export interface CommandOptions {
|
|
73
|
-
cwd?: string;
|
|
74
|
-
onStdout?: (data: string) => void;
|
|
75
|
-
onStderr?: (data: string) => void;
|
|
76
|
-
signal?: AbortSignal;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export interface WorkspaceConfig extends EngineOptions {
|
|
80
|
-
baseUrl?: string;
|
|
81
|
-
onServerReady?: (port: number, url: string) => void;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// create a fully-wired workspace (volume + engine + packages + proxy)
|
|
85
|
-
export function createWorkspace(config?: WorkspaceConfig): {
|
|
86
|
-
volume: MemoryVolume;
|
|
87
|
-
engine: ScriptEngine;
|
|
88
|
-
packages: DependencyInstaller;
|
|
89
|
-
proxy: RequestProxy;
|
|
90
|
-
execute: (code: string, filename?: string) => { exports: unknown };
|
|
91
|
-
runFile: (filename: string) => { exports: unknown };
|
|
92
|
-
run: (command: string, options?: CommandOptions) => Promise<CommandResult>;
|
|
93
|
-
sendInput: (data: string) => Promise<void>;
|
|
94
|
-
createREPL: () => { eval: (code: string) => unknown };
|
|
95
|
-
on: (event: string, listener: (...args: unknown[]) => void) => void;
|
|
96
|
-
} {
|
|
97
|
-
const volume = new MemoryVolume();
|
|
98
|
-
const engine = new ScriptEngine(volume, config);
|
|
99
|
-
const packages = new DependencyInstaller(volume);
|
|
100
|
-
const proxy = getProxyInstance({
|
|
101
|
-
baseUrl: config?.baseUrl,
|
|
102
|
-
onServerReady: config?.onServerReady,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// init shell lazily (SDK path uses Nodepod.boot() instead)
|
|
106
|
-
getShellMod().then((mod) => mod.initShellExec(volume, { cwd: config?.cwd }));
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
volume,
|
|
110
|
-
engine,
|
|
111
|
-
packages,
|
|
112
|
-
proxy,
|
|
113
|
-
execute: (code: string, filename?: string) =>
|
|
114
|
-
engine.execute(code, filename),
|
|
115
|
-
runFile: (filename: string) => engine.runFile(filename),
|
|
116
|
-
run: async (
|
|
117
|
-
command: string,
|
|
118
|
-
runOpts?: CommandOptions,
|
|
119
|
-
): Promise<CommandResult> => {
|
|
120
|
-
if (runOpts?.signal?.aborted) {
|
|
121
|
-
return { stdout: "", stderr: "", exitCode: 130 };
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const shell = await getShellMod();
|
|
125
|
-
const hasStreaming =
|
|
126
|
-
runOpts?.onStdout || runOpts?.onStderr || runOpts?.signal;
|
|
127
|
-
if (hasStreaming) {
|
|
128
|
-
shell.setStreamingCallbacks({
|
|
129
|
-
onStdout: runOpts?.onStdout,
|
|
130
|
-
onStderr: runOpts?.onStderr,
|
|
131
|
-
signal: runOpts?.signal,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return new Promise((resolve) => {
|
|
136
|
-
shell.exec(command, { cwd: runOpts?.cwd }, (error, stdout, stderr) => {
|
|
137
|
-
if (hasStreaming) shell.clearStreamingCallbacks();
|
|
138
|
-
resolve({
|
|
139
|
-
stdout: String(stdout),
|
|
140
|
-
stderr: String(stderr),
|
|
141
|
-
exitCode: error ? ((error as any).code ?? 1) : 0,
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
},
|
|
146
|
-
sendInput: async (data: string) => {
|
|
147
|
-
const shell = await getShellMod();
|
|
148
|
-
shell.sendStdin(data);
|
|
149
|
-
},
|
|
150
|
-
createREPL: () => engine.createREPL(),
|
|
151
|
-
on: (event: string, listener: (...args: unknown[]) => void) => {
|
|
152
|
-
proxy.on(event, listener);
|
|
153
|
-
},
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export default createWorkspace;
|
|
158
|
-
|
|
159
|
-
/* ---- SDK (clean public API) ---- */
|
|
160
|
-
|
|
161
|
-
export { Nodepod } from "./sdk/nodepod";
|
|
162
|
-
export { NodepodTerminal } from "./sdk/nodepod-terminal";
|
|
163
|
-
export { NodepodProcess } from "./sdk/nodepod-process";
|
|
164
|
-
export { NodepodFS } from "./sdk/nodepod-fs";
|
|
165
|
-
export type {
|
|
166
|
-
NodepodOptions,
|
|
167
|
-
TerminalOptions,
|
|
168
|
-
TerminalTheme,
|
|
169
|
-
StatResult,
|
|
170
|
-
Snapshot,
|
|
171
|
-
SpawnOptions,
|
|
172
|
-
} from "./sdk/types";
|
|
173
|
-
|
|
174
|
-
/* ---- Threading / Worker Infrastructure ---- */
|
|
175
|
-
|
|
176
|
-
export { ProcessManager } from "./threading/process-manager";
|
|
177
|
-
export { ProcessHandle } from "./threading/process-handle";
|
|
178
|
-
export type { ProcessState } from "./threading/process-handle";
|
|
179
|
-
export { VFSBridge } from "./threading/vfs-bridge";
|
|
180
|
-
export { WorkerVFS } from "./threading/worker-vfs";
|
|
181
|
-
export { SyncChannelController, SyncChannelWorker } from "./threading/sync-channel";
|
|
182
|
-
export { SharedVFSController, SharedVFSReader, isSharedArrayBufferAvailable } from "./threading/shared-vfs";
|
|
183
|
-
export { createProcessContext, getActiveContext, setActiveContext } from "./threading/process-context";
|
|
184
|
-
export type { ProcessContext, ProcessWriter, ProcessReader, OpenFileEntry } from "./threading/process-context";
|
|
185
|
-
export type {
|
|
186
|
-
VFSBinarySnapshot,
|
|
187
|
-
VFSSnapshotEntry,
|
|
188
|
-
SpawnConfig,
|
|
189
|
-
ProcessInfo,
|
|
190
|
-
MainToWorkerMessage,
|
|
191
|
-
WorkerToMainMessage,
|
|
192
|
-
} from "./threading/worker-protocol";
|
|
1
|
+
// nodepod - browser-native Node.js runtime environment
|
|
2
|
+
|
|
3
|
+
export { MemoryVolume } from "./memory-volume";
|
|
4
|
+
export type {
|
|
5
|
+
VolumeNode,
|
|
6
|
+
FileStat,
|
|
7
|
+
FileWatchHandle,
|
|
8
|
+
WatchCallback,
|
|
9
|
+
WatchEventKind,
|
|
10
|
+
SystemError,
|
|
11
|
+
} from "./memory-volume";
|
|
12
|
+
export { ScriptEngine, executeCode } from "./script-engine";
|
|
13
|
+
export type { ModuleRecord, EngineOptions, ResolverFn } from "./script-engine";
|
|
14
|
+
export { spawnEngine, WorkerSandbox, IframeSandbox, spawnProcessWorkerEngine, ProcessWorkerAdapter } from "./engine-factory";
|
|
15
|
+
export type {
|
|
16
|
+
IScriptEngine,
|
|
17
|
+
ExecutionOutcome,
|
|
18
|
+
SpawnEngineConfig,
|
|
19
|
+
EngineConfig,
|
|
20
|
+
VolumeSnapshot,
|
|
21
|
+
} from "./engine-types";
|
|
22
|
+
export {
|
|
23
|
+
generateSandboxDeployment,
|
|
24
|
+
getSandboxPageHtml,
|
|
25
|
+
getSandboxHostingConfig,
|
|
26
|
+
SANDBOX_DEPLOYMENT_GUIDE,
|
|
27
|
+
} from "./isolation-helpers";
|
|
28
|
+
export { buildFileSystemBridge } from "./polyfills/fs";
|
|
29
|
+
export type { FsBridge } from "./polyfills/fs";
|
|
30
|
+
export { buildProcessEnv } from "./polyfills/process";
|
|
31
|
+
export type { ProcessObject, ProcessEnvVars } from "./polyfills/process";
|
|
32
|
+
export * as path from "./polyfills/path";
|
|
33
|
+
export * as http from "./polyfills/http";
|
|
34
|
+
export * as net from "./polyfills/net";
|
|
35
|
+
export * as events from "./polyfills/events";
|
|
36
|
+
export * as stream from "./polyfills/stream";
|
|
37
|
+
export * as url from "./polyfills/url";
|
|
38
|
+
export * as querystring from "./polyfills/querystring";
|
|
39
|
+
export * as util from "./polyfills/util";
|
|
40
|
+
export * as npm from "./packages/installer";
|
|
41
|
+
export { DependencyInstaller, install } from "./packages/installer";
|
|
42
|
+
export { RequestProxy, getProxyInstance, resetProxy } from "./request-proxy";
|
|
43
|
+
export type { ProxyOptions, ServiceWorkerConfig } from "./request-proxy";
|
|
44
|
+
export * as chokidar from "./polyfills/chokidar";
|
|
45
|
+
export * as ws from "./polyfills/ws";
|
|
46
|
+
export * as fsevents from "./polyfills/fsevents";
|
|
47
|
+
export * as readdirp from "./polyfills/readdirp";
|
|
48
|
+
export * as module from "./polyfills/module";
|
|
49
|
+
export * as perf_hooks from "./polyfills/perf_hooks";
|
|
50
|
+
export * as worker_threads from "./polyfills/worker_threads";
|
|
51
|
+
export * as esbuild from "./polyfills/esbuild";
|
|
52
|
+
export * as rollup from "./polyfills/rollup";
|
|
53
|
+
export * as assert from "./polyfills/assert";
|
|
54
|
+
|
|
55
|
+
import { MemoryVolume } from "./memory-volume";
|
|
56
|
+
import { ScriptEngine, EngineOptions } from "./script-engine";
|
|
57
|
+
import { DependencyInstaller } from "./packages/installer";
|
|
58
|
+
import { RequestProxy, getProxyInstance } from "./request-proxy";
|
|
59
|
+
// lazy-load child_process to avoid pulling in the shell at module load time
|
|
60
|
+
let _shellMod: typeof import("./polyfills/child_process") | null = null;
|
|
61
|
+
async function getShellMod() {
|
|
62
|
+
if (!_shellMod) _shellMod = await import("./polyfills/child_process");
|
|
63
|
+
return _shellMod;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface CommandResult {
|
|
67
|
+
stdout: string;
|
|
68
|
+
stderr: string;
|
|
69
|
+
exitCode: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface CommandOptions {
|
|
73
|
+
cwd?: string;
|
|
74
|
+
onStdout?: (data: string) => void;
|
|
75
|
+
onStderr?: (data: string) => void;
|
|
76
|
+
signal?: AbortSignal;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface WorkspaceConfig extends EngineOptions {
|
|
80
|
+
baseUrl?: string;
|
|
81
|
+
onServerReady?: (port: number, url: string) => void;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// create a fully-wired workspace (volume + engine + packages + proxy)
|
|
85
|
+
export function createWorkspace(config?: WorkspaceConfig): {
|
|
86
|
+
volume: MemoryVolume;
|
|
87
|
+
engine: ScriptEngine;
|
|
88
|
+
packages: DependencyInstaller;
|
|
89
|
+
proxy: RequestProxy;
|
|
90
|
+
execute: (code: string, filename?: string) => { exports: unknown };
|
|
91
|
+
runFile: (filename: string) => { exports: unknown };
|
|
92
|
+
run: (command: string, options?: CommandOptions) => Promise<CommandResult>;
|
|
93
|
+
sendInput: (data: string) => Promise<void>;
|
|
94
|
+
createREPL: () => { eval: (code: string) => unknown };
|
|
95
|
+
on: (event: string, listener: (...args: unknown[]) => void) => void;
|
|
96
|
+
} {
|
|
97
|
+
const volume = new MemoryVolume();
|
|
98
|
+
const engine = new ScriptEngine(volume, config);
|
|
99
|
+
const packages = new DependencyInstaller(volume);
|
|
100
|
+
const proxy = getProxyInstance({
|
|
101
|
+
baseUrl: config?.baseUrl,
|
|
102
|
+
onServerReady: config?.onServerReady,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// init shell lazily (SDK path uses Nodepod.boot() instead)
|
|
106
|
+
getShellMod().then((mod) => mod.initShellExec(volume, { cwd: config?.cwd }));
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
volume,
|
|
110
|
+
engine,
|
|
111
|
+
packages,
|
|
112
|
+
proxy,
|
|
113
|
+
execute: (code: string, filename?: string) =>
|
|
114
|
+
engine.execute(code, filename),
|
|
115
|
+
runFile: (filename: string) => engine.runFile(filename),
|
|
116
|
+
run: async (
|
|
117
|
+
command: string,
|
|
118
|
+
runOpts?: CommandOptions,
|
|
119
|
+
): Promise<CommandResult> => {
|
|
120
|
+
if (runOpts?.signal?.aborted) {
|
|
121
|
+
return { stdout: "", stderr: "", exitCode: 130 };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const shell = await getShellMod();
|
|
125
|
+
const hasStreaming =
|
|
126
|
+
runOpts?.onStdout || runOpts?.onStderr || runOpts?.signal;
|
|
127
|
+
if (hasStreaming) {
|
|
128
|
+
shell.setStreamingCallbacks({
|
|
129
|
+
onStdout: runOpts?.onStdout,
|
|
130
|
+
onStderr: runOpts?.onStderr,
|
|
131
|
+
signal: runOpts?.signal,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return new Promise((resolve) => {
|
|
136
|
+
shell.exec(command, { cwd: runOpts?.cwd }, (error, stdout, stderr) => {
|
|
137
|
+
if (hasStreaming) shell.clearStreamingCallbacks();
|
|
138
|
+
resolve({
|
|
139
|
+
stdout: String(stdout),
|
|
140
|
+
stderr: String(stderr),
|
|
141
|
+
exitCode: error ? ((error as any).code ?? 1) : 0,
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
sendInput: async (data: string) => {
|
|
147
|
+
const shell = await getShellMod();
|
|
148
|
+
shell.sendStdin(data);
|
|
149
|
+
},
|
|
150
|
+
createREPL: () => engine.createREPL(),
|
|
151
|
+
on: (event: string, listener: (...args: unknown[]) => void) => {
|
|
152
|
+
proxy.on(event, listener);
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export default createWorkspace;
|
|
158
|
+
|
|
159
|
+
/* ---- SDK (clean public API) ---- */
|
|
160
|
+
|
|
161
|
+
export { Nodepod } from "./sdk/nodepod";
|
|
162
|
+
export { NodepodTerminal } from "./sdk/nodepod-terminal";
|
|
163
|
+
export { NodepodProcess } from "./sdk/nodepod-process";
|
|
164
|
+
export { NodepodFS } from "./sdk/nodepod-fs";
|
|
165
|
+
export type {
|
|
166
|
+
NodepodOptions,
|
|
167
|
+
TerminalOptions,
|
|
168
|
+
TerminalTheme,
|
|
169
|
+
StatResult,
|
|
170
|
+
Snapshot,
|
|
171
|
+
SpawnOptions,
|
|
172
|
+
} from "./sdk/types";
|
|
173
|
+
|
|
174
|
+
/* ---- Threading / Worker Infrastructure ---- */
|
|
175
|
+
|
|
176
|
+
export { ProcessManager } from "./threading/process-manager";
|
|
177
|
+
export { ProcessHandle } from "./threading/process-handle";
|
|
178
|
+
export type { ProcessState } from "./threading/process-handle";
|
|
179
|
+
export { VFSBridge } from "./threading/vfs-bridge";
|
|
180
|
+
export { WorkerVFS } from "./threading/worker-vfs";
|
|
181
|
+
export { SyncChannelController, SyncChannelWorker } from "./threading/sync-channel";
|
|
182
|
+
export { SharedVFSController, SharedVFSReader, isSharedArrayBufferAvailable } from "./threading/shared-vfs";
|
|
183
|
+
export { createProcessContext, getActiveContext, setActiveContext } from "./threading/process-context";
|
|
184
|
+
export type { ProcessContext, ProcessWriter, ProcessReader, OpenFileEntry } from "./threading/process-context";
|
|
185
|
+
export type {
|
|
186
|
+
VFSBinarySnapshot,
|
|
187
|
+
VFSSnapshotEntry,
|
|
188
|
+
SpawnConfig,
|
|
189
|
+
ProcessInfo,
|
|
190
|
+
MainToWorkerMessage,
|
|
191
|
+
WorkerToMainMessage,
|
|
192
|
+
} from "./threading/worker-protocol";
|