@scelar/nodepod 1.0.2 → 1.0.3

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 (70) hide show
  1. package/dist/__tests__/bench/integration.bench.d.ts +1 -0
  2. package/dist/__tests__/bench/memory-volume.bench.d.ts +1 -0
  3. package/dist/__tests__/bench/polyfills.bench.d.ts +1 -0
  4. package/dist/__tests__/bench/script-engine.bench.d.ts +1 -0
  5. package/dist/__tests__/bench/shell.bench.d.ts +1 -0
  6. package/dist/__tests__/bench/syntax-transforms.bench.d.ts +1 -0
  7. package/dist/__tests__/bench/version-resolver.bench.d.ts +1 -0
  8. package/dist/__tests__/buffer.test.d.ts +1 -0
  9. package/dist/__tests__/byte-encoding.test.d.ts +1 -0
  10. package/dist/__tests__/digest.test.d.ts +1 -0
  11. package/dist/__tests__/events.test.d.ts +1 -0
  12. package/dist/__tests__/memory-volume.test.d.ts +1 -0
  13. package/dist/__tests__/path.test.d.ts +1 -0
  14. package/dist/__tests__/process.test.d.ts +1 -0
  15. package/dist/__tests__/script-engine.test.d.ts +1 -0
  16. package/dist/__tests__/shell-builtins.test.d.ts +1 -0
  17. package/dist/__tests__/shell-interpreter.test.d.ts +1 -0
  18. package/dist/__tests__/shell-parser.test.d.ts +1 -0
  19. package/dist/__tests__/stream.test.d.ts +1 -0
  20. package/dist/__tests__/syntax-transforms.test.d.ts +1 -0
  21. package/dist/__tests__/version-resolver.test.d.ts +1 -0
  22. package/dist/{child_process-Dopvyd-E.js → child_process-D6oDN2MX.js} +4 -4
  23. package/dist/{child_process-Dopvyd-E.js.map → child_process-D6oDN2MX.js.map} +1 -1
  24. package/dist/{child_process-B38qoN6R.cjs → child_process-hmVqFcF7.cjs} +5 -5
  25. package/dist/{child_process-B38qoN6R.cjs.map → child_process-hmVqFcF7.cjs.map} +1 -1
  26. package/dist/{index--Qr8LVpQ.js → index-Ale2oba_.js} +240 -136
  27. package/dist/index-Ale2oba_.js.map +1 -0
  28. package/dist/{index-cnitc68U.cjs → index-BO1i013L.cjs} +236 -191
  29. package/dist/index-BO1i013L.cjs.map +1 -0
  30. package/dist/index.cjs +1 -1
  31. package/dist/index.mjs +1 -1
  32. package/dist/script-engine.d.ts +2 -0
  33. package/dist/syntax-transforms.d.ts +1 -0
  34. package/package.json +97 -95
  35. package/src/__tests__/bench/integration.bench.ts +117 -0
  36. package/src/__tests__/bench/memory-volume.bench.ts +115 -0
  37. package/src/__tests__/bench/polyfills.bench.ts +147 -0
  38. package/src/__tests__/bench/script-engine.bench.ts +104 -0
  39. package/src/__tests__/bench/shell.bench.ts +101 -0
  40. package/src/__tests__/bench/syntax-transforms.bench.ts +82 -0
  41. package/src/__tests__/bench/version-resolver.bench.ts +95 -0
  42. package/src/__tests__/buffer.test.ts +273 -0
  43. package/src/__tests__/byte-encoding.test.ts +98 -0
  44. package/src/__tests__/digest.test.ts +44 -0
  45. package/src/__tests__/events.test.ts +245 -0
  46. package/src/__tests__/memory-volume.test.ts +443 -0
  47. package/src/__tests__/path.test.ts +181 -0
  48. package/src/__tests__/process.test.ts +129 -0
  49. package/src/__tests__/script-engine.test.ts +229 -0
  50. package/src/__tests__/shell-builtins.test.ts +357 -0
  51. package/src/__tests__/shell-interpreter.test.ts +157 -0
  52. package/src/__tests__/shell-parser.test.ts +204 -0
  53. package/src/__tests__/stream.test.ts +142 -0
  54. package/src/__tests__/syntax-transforms.test.ts +158 -0
  55. package/src/__tests__/version-resolver.test.ts +184 -0
  56. package/src/constants/cdn-urls.ts +18 -18
  57. package/src/helpers/byte-encoding.ts +51 -39
  58. package/src/memory-volume.ts +962 -941
  59. package/src/module-transformer.ts +368 -368
  60. package/src/packages/installer.ts +396 -396
  61. package/src/polyfills/buffer.ts +633 -628
  62. package/src/polyfills/esbuild.ts +854 -854
  63. package/src/polyfills/events.ts +282 -276
  64. package/src/polyfills/process.ts +695 -690
  65. package/src/polyfills/readline.ts +692 -692
  66. package/src/polyfills/tty.ts +71 -71
  67. package/src/script-engine.ts +3396 -3375
  68. package/src/syntax-transforms.ts +543 -561
  69. package/dist/index--Qr8LVpQ.js.map +0 -1
  70. package/dist/index-cnitc68U.cjs.map +0 -1
@@ -0,0 +1,129 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { buildProcessEnv } from "../polyfills/process";
3
+
4
+ describe("process polyfill", () => {
5
+ describe("basic properties", () => {
6
+ it('has platform "linux"', () => {
7
+ const proc = buildProcessEnv();
8
+ expect(proc.platform).toBe("linux");
9
+ });
10
+
11
+ it('has arch "x64"', () => {
12
+ const proc = buildProcessEnv();
13
+ expect(proc.arch).toBe("x64");
14
+ });
15
+
16
+ it('has version string starting with "v"', () => {
17
+ const proc = buildProcessEnv();
18
+ expect(proc.version).toMatch(/^v\d+/);
19
+ });
20
+
21
+ it("has pid as a number", () => {
22
+ const proc = buildProcessEnv();
23
+ expect(typeof proc.pid).toBe("number");
24
+ });
25
+
26
+ it("has argv as an array", () => {
27
+ const proc = buildProcessEnv();
28
+ expect(Array.isArray(proc.argv)).toBe(true);
29
+ });
30
+ });
31
+
32
+ describe("cwd / chdir", () => {
33
+ it("cwd() returns initial cwd", () => {
34
+ const proc = buildProcessEnv({ cwd: "/mydir" });
35
+ expect(proc.cwd()).toBe("/mydir");
36
+ });
37
+
38
+ it("chdir changes cwd", () => {
39
+ const proc = buildProcessEnv({ cwd: "/" });
40
+ proc.chdir("/other");
41
+ expect(proc.cwd()).toBe("/other");
42
+ });
43
+ });
44
+
45
+ describe("env", () => {
46
+ it("includes default env vars", () => {
47
+ const proc = buildProcessEnv();
48
+ expect(proc.env.PATH).toBeDefined();
49
+ expect(proc.env.HOME).toBeDefined();
50
+ });
51
+
52
+ it("includes custom env vars passed in config", () => {
53
+ const proc = buildProcessEnv({ env: { MY_VAR: "hello" } });
54
+ expect(proc.env.MY_VAR).toBe("hello");
55
+ });
56
+
57
+ it("includes NAPI_RS_FORCE_WASM=1", () => {
58
+ const proc = buildProcessEnv();
59
+ expect(proc.env.NAPI_RS_FORCE_WASM).toBe("1");
60
+ });
61
+
62
+ it("is mutable", () => {
63
+ const proc = buildProcessEnv();
64
+ proc.env.CUSTOM = "value";
65
+ expect(proc.env.CUSTOM).toBe("value");
66
+ });
67
+ });
68
+
69
+ describe("hrtime", () => {
70
+ it("returns [seconds, nanoseconds] tuple", () => {
71
+ const proc = buildProcessEnv();
72
+ const hr = proc.hrtime();
73
+ expect(Array.isArray(hr)).toBe(true);
74
+ expect(hr.length).toBe(2);
75
+ expect(typeof hr[0]).toBe("number");
76
+ expect(typeof hr[1]).toBe("number");
77
+ });
78
+
79
+ it("hrtime.bigint() returns bigint", () => {
80
+ const proc = buildProcessEnv();
81
+ const result = proc.hrtime.bigint();
82
+ expect(typeof result).toBe("bigint");
83
+ });
84
+ });
85
+
86
+ describe("nextTick", () => {
87
+ it("schedules callback asynchronously", async () => {
88
+ const proc = buildProcessEnv();
89
+ let called = false;
90
+ proc.nextTick(() => {
91
+ called = true;
92
+ });
93
+ expect(called).toBe(false);
94
+ await new Promise((r) => setTimeout(r, 10));
95
+ expect(called).toBe(true);
96
+ });
97
+ });
98
+
99
+ describe("memoryUsage", () => {
100
+ it("returns object with expected shape", () => {
101
+ const proc = buildProcessEnv();
102
+ const mem = proc.memoryUsage();
103
+ expect(typeof mem.rss).toBe("number");
104
+ expect(typeof mem.heapTotal).toBe("number");
105
+ expect(typeof mem.heapUsed).toBe("number");
106
+ expect(typeof mem.external).toBe("number");
107
+ expect(typeof mem.arrayBuffers).toBe("number");
108
+ });
109
+ });
110
+
111
+ describe("stdout.write", () => {
112
+ it("calls onStdout callback when provided", () => {
113
+ const output: string[] = [];
114
+ const proc = buildProcessEnv({ onStdout: (text) => output.push(text) });
115
+ proc.stdout.write("test");
116
+ expect(output).toContain("test");
117
+ });
118
+ });
119
+
120
+ describe("kill / signals", () => {
121
+ it("kill emits signal on process", () => {
122
+ const proc = buildProcessEnv();
123
+ const fn = vi.fn();
124
+ proc.on("SIGTERM", fn);
125
+ proc.kill(proc.pid, "SIGTERM");
126
+ expect(fn).toHaveBeenCalled();
127
+ });
128
+ });
129
+ });
@@ -0,0 +1,229 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { ScriptEngine } from "../script-engine";
3
+ import { MemoryVolume } from "../memory-volume";
4
+
5
+ function createEngine(files?: Record<string, string>) {
6
+ const vol = new MemoryVolume();
7
+ vol.mkdirSync("/project", { recursive: true });
8
+ if (files) {
9
+ for (const [path, content] of Object.entries(files)) {
10
+ const dir = path.substring(0, path.lastIndexOf("/")) || "/";
11
+ if (dir !== "/") vol.mkdirSync(dir, { recursive: true });
12
+ vol.writeFileSync(path, content);
13
+ }
14
+ }
15
+ return { vol, engine: new ScriptEngine(vol, { cwd: "/project" }) };
16
+ }
17
+
18
+ describe("ScriptEngine", () => {
19
+ describe("execute()", () => {
20
+ it("runs basic JS and returns exports", () => {
21
+ const { engine } = createEngine();
22
+ const result = engine.execute("module.exports = 42;", "/index.js");
23
+ expect(result.exports).toBe(42);
24
+ });
25
+
26
+ it("module.exports = object", () => {
27
+ const { engine } = createEngine();
28
+ const result = engine.execute(
29
+ "module.exports = { x: 1 };",
30
+ "/index.js",
31
+ );
32
+ expect(result.exports).toEqual({ x: 1 });
33
+ });
34
+
35
+ it("exports.x = value shorthand", () => {
36
+ const { engine } = createEngine();
37
+ const result = engine.execute("exports.x = 1;", "/index.js");
38
+ expect((result.exports as any).x).toBe(1);
39
+ });
40
+
41
+ it("has access to __dirname and __filename", () => {
42
+ const { engine } = createEngine();
43
+ const result = engine.execute(
44
+ "module.exports = { dir: __dirname, file: __filename };",
45
+ "/project/test.js",
46
+ );
47
+ expect((result.exports as any).dir).toBe("/project");
48
+ expect((result.exports as any).file).toBe("/project/test.js");
49
+ });
50
+
51
+ it("has access to process object", () => {
52
+ const { engine } = createEngine();
53
+ const result = engine.execute(
54
+ "module.exports = process.platform;",
55
+ "/index.js",
56
+ );
57
+ expect(result.exports).toBe("linux");
58
+ });
59
+
60
+ it("handles syntax errors by throwing", () => {
61
+ const { engine } = createEngine();
62
+ expect(() => engine.execute("const {", "/bad.js")).toThrow();
63
+ });
64
+ });
65
+
66
+ describe("runFile()", () => {
67
+ it("reads file from volume and executes", () => {
68
+ const { engine } = createEngine({
69
+ "/project/app.js": 'module.exports = "hello";',
70
+ });
71
+ const result = engine.runFile("/project/app.js");
72
+ expect(result.exports).toBe("hello");
73
+ });
74
+
75
+ it("throws for nonexistent file", () => {
76
+ const { engine } = createEngine();
77
+ expect(() => engine.runFile("/nonexistent.js")).toThrow();
78
+ });
79
+ });
80
+
81
+ describe("require()", () => {
82
+ it("requires a local file with relative path", () => {
83
+ const { engine } = createEngine({
84
+ "/project/lib.js": "module.exports = 10;",
85
+ });
86
+ const result = engine.execute(
87
+ 'const lib = require("./lib"); module.exports = lib;',
88
+ "/project/index.js",
89
+ );
90
+ expect(result.exports).toBe(10);
91
+ });
92
+
93
+ it("requires chained files (A requires B requires C)", () => {
94
+ const { engine } = createEngine({
95
+ "/project/c.js": "module.exports = 3;",
96
+ "/project/b.js":
97
+ 'module.exports = require("./c") * 2;',
98
+ "/project/a.js":
99
+ 'module.exports = require("./b") + 1;',
100
+ });
101
+ const result = engine.runFile("/project/a.js");
102
+ expect(result.exports).toBe(7);
103
+ });
104
+
105
+ it("caches modules (same object returned on second require)", () => {
106
+ const { engine } = createEngine({
107
+ "/project/mod.js": "module.exports = { count: 0 };",
108
+ });
109
+ const result = engine.execute(
110
+ 'const a = require("./mod"); const b = require("./mod"); a.count++; module.exports = b.count;',
111
+ "/project/test.js",
112
+ );
113
+ expect(result.exports).toBe(1);
114
+ });
115
+
116
+ it("requires built-in modules: path", () => {
117
+ const { engine } = createEngine();
118
+ const result = engine.execute(
119
+ 'const p = require("path"); module.exports = p.join("/a", "b");',
120
+ "/index.js",
121
+ );
122
+ expect(result.exports).toBe("/a/b");
123
+ });
124
+
125
+ it("requires built-in modules: events", () => {
126
+ const { engine } = createEngine();
127
+ const result = engine.execute(
128
+ 'const EE = require("events"); module.exports = typeof EE;',
129
+ "/index.js",
130
+ );
131
+ expect(result.exports).toBe("function");
132
+ });
133
+
134
+ it("requires JSON files", () => {
135
+ const { engine } = createEngine({
136
+ "/project/data.json": '{"key": "value"}',
137
+ });
138
+ const result = engine.execute(
139
+ 'module.exports = require("./data.json");',
140
+ "/project/index.js",
141
+ );
142
+ expect(result.exports).toEqual({ key: "value" });
143
+ });
144
+
145
+ it("throws for missing module", () => {
146
+ const { engine } = createEngine();
147
+ expect(() =>
148
+ engine.execute('require("./nonexistent");', "/index.js"),
149
+ ).toThrow();
150
+ });
151
+ });
152
+
153
+ describe("ESM auto-conversion", () => {
154
+ it("auto-converts import/export to CJS when required", () => {
155
+ const { engine } = createEngine({
156
+ "/project/mod.js": "export const x = 42;",
157
+ });
158
+ const result = engine.execute(
159
+ 'const m = require("./mod"); module.exports = m.x;',
160
+ "/project/index.js",
161
+ );
162
+ expect(result.exports).toBe(42);
163
+ });
164
+
165
+ it("handles export function containing dynamic import() without corruption", () => {
166
+ const { engine } = createEngine({
167
+ "/project/plugin.js": [
168
+ 'import path from "path";',
169
+ "export function helper() { return 1; }",
170
+ "export function main() {",
171
+ " const loader = () => import('./other.js');",
172
+ " return { loader, val: path.join('a', 'b') };",
173
+ "}",
174
+ ].join("\n"),
175
+ });
176
+ const result = engine.execute(
177
+ 'const m = require("./plugin"); module.exports = m.main().val;',
178
+ "/project/index.js",
179
+ );
180
+ expect(result.exports).toBe("a/b");
181
+ });
182
+ });
183
+
184
+ describe("clearCache()", () => {
185
+ it("clears module cache so modules are re-evaluated", () => {
186
+ const { engine } = createEngine({
187
+ "/project/counter.js":
188
+ "let c = 0; module.exports = { inc() { return ++c; } };",
189
+ });
190
+ engine.execute(
191
+ 'module.exports = require("./counter").inc();',
192
+ "/project/a.js",
193
+ );
194
+ engine.clearCache();
195
+ const result = engine.execute(
196
+ 'module.exports = require("./counter").inc();',
197
+ "/project/b.js",
198
+ );
199
+ // c resets to 0 after cache clear
200
+ expect(result.exports).toBe(1);
201
+ });
202
+ });
203
+
204
+ describe("createREPL()", () => {
205
+ it("evaluates expressions", () => {
206
+ const { engine } = createEngine();
207
+ const repl = engine.createREPL();
208
+ expect(repl.eval("1 + 1")).toBe(2);
209
+ });
210
+
211
+ it("evaluates variable declarations across calls", () => {
212
+ const { engine } = createEngine();
213
+ const repl = engine.createREPL();
214
+ repl.eval("var x = 10");
215
+ expect(repl.eval("x")).toBe(10);
216
+ });
217
+ });
218
+
219
+ describe("shebang handling", () => {
220
+ it("strips shebang line", () => {
221
+ const { engine } = createEngine({
222
+ "/project/script.js":
223
+ "#!/usr/bin/env node\nmodule.exports = 42;",
224
+ });
225
+ const result = engine.runFile("/project/script.js");
226
+ expect(result.exports).toBe(42);
227
+ });
228
+ });
229
+ });