@scelar/nodepod 1.0.3 → 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.
Files changed (41) hide show
  1. package/dist/__sw__.js +642 -642
  2. package/dist/{child_process-D6oDN2MX.js → child_process-53fMkug_.js} +4 -4
  3. package/dist/child_process-53fMkug_.js.map +1 -0
  4. package/dist/{child_process-hmVqFcF7.cjs → child_process-lxSKECHq.cjs} +5 -5
  5. package/dist/child_process-lxSKECHq.cjs.map +1 -0
  6. package/dist/{index-Ale2oba_.js → index-B8lyh_ti.js} +1081 -428
  7. package/dist/index-B8lyh_ti.js.map +1 -0
  8. package/dist/{index-BO1i013L.cjs → index-C-TQIrdG.cjs} +1195 -430
  9. package/dist/index-C-TQIrdG.cjs.map +1 -0
  10. package/dist/index.cjs +1 -1
  11. package/dist/index.mjs +1 -1
  12. package/dist/memory-volume.d.ts +1 -1
  13. package/dist/polyfills/wasi.d.ts +45 -4
  14. package/dist/sdk/nodepod.d.ts +4 -3
  15. package/dist/sdk/types.d.ts +6 -0
  16. package/dist/threading/process-manager.d.ts +1 -1
  17. package/dist/threading/worker-protocol.d.ts +1 -1
  18. package/package.json +97 -97
  19. package/src/index.ts +192 -192
  20. package/src/memory-volume.ts +10 -4
  21. package/src/packages/version-resolver.ts +12 -2
  22. package/src/polyfills/child_process.ts +2288 -2288
  23. package/src/polyfills/fs.ts +2888 -2888
  24. package/src/polyfills/http.ts +1450 -1449
  25. package/src/polyfills/process.ts +27 -1
  26. package/src/polyfills/stream.ts +1620 -1620
  27. package/src/polyfills/wasi.ts +1284 -22
  28. package/src/request-proxy.ts +716 -716
  29. package/src/script-engine.ts +3694 -3396
  30. package/src/sdk/nodepod.ts +525 -509
  31. package/src/sdk/types.ts +7 -0
  32. package/src/syntax-transforms.ts +2 -2
  33. package/src/threading/offload-worker.ts +383 -383
  34. package/src/threading/offload.ts +271 -271
  35. package/src/threading/process-manager.ts +956 -956
  36. package/src/threading/process-worker-entry.ts +858 -854
  37. package/src/threading/worker-protocol.ts +1 -1
  38. package/dist/child_process-D6oDN2MX.js.map +0 -1
  39. package/dist/child_process-hmVqFcF7.cjs.map +0 -1
  40. package/dist/index-Ale2oba_.js.map +0 -1
  41. package/dist/index-BO1i013L.cjs.map +0 -1
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";
@@ -218,13 +218,19 @@ export class MemoryVolume {
218
218
 
219
219
  // ---- Snapshot serialization ----
220
220
 
221
- toSnapshot(): VolumeSnapshot {
221
+ toSnapshot(excludePrefixes?: string[]): VolumeSnapshot {
222
222
  const entries: VolumeEntry[] = [];
223
- this.collectEntries('/', this.tree, entries);
223
+ this.collectEntries('/', this.tree, entries, excludePrefixes);
224
224
  return { entries };
225
225
  }
226
226
 
227
- private collectEntries(currentPath: string, node: VolumeNode, result: VolumeEntry[]): void {
227
+ private collectEntries(currentPath: string, node: VolumeNode, result: VolumeEntry[], excludePrefixes?: string[]): void {
228
+ if (excludePrefixes) {
229
+ for (const prefix of excludePrefixes) {
230
+ if (currentPath === prefix || currentPath.startsWith(prefix + '/')) return;
231
+ }
232
+ }
233
+
228
234
  if (node.kind === 'file') {
229
235
  let data = '';
230
236
  if (node.content && node.content.length > 0) {
@@ -238,7 +244,7 @@ export class MemoryVolume {
238
244
  if (node.children) {
239
245
  for (const [name, child] of node.children) {
240
246
  const childPath = currentPath === '/' ? `/${name}` : `${currentPath}/${name}`;
241
- this.collectEntries(childPath, child, result);
247
+ this.collectEntries(childPath, child, result, excludePrefixes);
242
248
  }
243
249
  }
244
250
  }
@@ -375,8 +375,18 @@ async function walkDependency(
375
375
  Object.assign(edges, versionInfo.dependencies);
376
376
  }
377
377
 
378
- if (config.optionalDependencies && versionInfo.optionalDependencies) {
379
- Object.assign(edges, versionInfo.optionalDependencies);
378
+ if (versionInfo.optionalDependencies) {
379
+ if (config.optionalDependencies) {
380
+ Object.assign(edges, versionInfo.optionalDependencies);
381
+ } else {
382
+ // Always include wasm32-wasi optional deps — they're WASM alternatives
383
+ // to native bindings and are the only variant that can run in-browser
384
+ for (const [optName, optRange] of Object.entries(versionInfo.optionalDependencies)) {
385
+ if (optName.includes("wasm32-wasi")) {
386
+ edges[optName] = optRange as string;
387
+ }
388
+ }
389
+ }
380
390
  }
381
391
 
382
392
  const edgeList = Object.entries(edges);