@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,104 @@
1
+ import { describe, bench } from "vitest";
2
+ import { MemoryVolume } from "../../memory-volume";
3
+ import { ScriptEngine } from "../../script-engine";
4
+
5
+ function createEngine(files?: Record<string, string>): ScriptEngine {
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 new ScriptEngine(vol, { cwd: "/project" });
16
+ }
17
+
18
+ describe("ScriptEngine - execute", () => {
19
+ bench("simple expression", () => {
20
+ const engine = createEngine();
21
+ engine.execute("module.exports = 1 + 1;", "/index.js");
22
+ });
23
+
24
+ bench("console.log", () => {
25
+ const engine = createEngine();
26
+ engine.execute('console.log("hello");', "/index.js");
27
+ });
28
+
29
+ bench("require('path')", () => {
30
+ const engine = createEngine();
31
+ engine.execute(
32
+ 'const path = require("path"); module.exports = path.join("/a", "b");',
33
+ "/index.js",
34
+ );
35
+ });
36
+
37
+ bench("require('events') + use", () => {
38
+ const engine = createEngine();
39
+ engine.execute(
40
+ 'const { EventEmitter } = require("events"); const ee = new EventEmitter(); ee.on("x", () => {}); ee.emit("x");',
41
+ "/index.js",
42
+ );
43
+ });
44
+ });
45
+
46
+ describe("ScriptEngine - module resolution", () => {
47
+ bench("require local file", () => {
48
+ const engine = createEngine({
49
+ "/project/lib.js": "module.exports = { value: 42 };",
50
+ "/project/index.js":
51
+ 'const lib = require("./lib"); module.exports = lib.value;',
52
+ });
53
+ engine.runFile("/project/index.js");
54
+ });
55
+
56
+ bench("require chain - 3 modules deep", () => {
57
+ const engine = createEngine({
58
+ "/project/a.js": "module.exports = { a: 1 };",
59
+ "/project/b.js":
60
+ 'const a = require("./a"); module.exports = { ...a, b: 2 };',
61
+ "/project/c.js":
62
+ 'const b = require("./b"); module.exports = { ...b, c: 3 };',
63
+ });
64
+ engine.runFile("/project/c.js");
65
+ });
66
+
67
+ bench("require with index.js resolution", () => {
68
+ const engine = createEngine({
69
+ "/project/mylib/index.js": "module.exports = { ok: true };",
70
+ "/project/index.js": 'module.exports = require("./mylib");',
71
+ });
72
+ engine.runFile("/project/index.js");
73
+ });
74
+
75
+ bench("require 10 builtins", () => {
76
+ const engine = createEngine();
77
+ engine.execute(
78
+ [
79
+ 'require("path");',
80
+ 'require("fs");',
81
+ 'require("events");',
82
+ 'require("util");',
83
+ 'require("os");',
84
+ 'require("url");',
85
+ 'require("querystring");',
86
+ 'require("buffer");',
87
+ 'require("stream");',
88
+ 'require("crypto");',
89
+ ].join("\n"),
90
+ "/index.js",
91
+ );
92
+ });
93
+ });
94
+
95
+ describe("ScriptEngine - cache", () => {
96
+ bench("execute + clearCache + re-execute", () => {
97
+ const engine = createEngine({
98
+ "/project/mod.js": "module.exports = Date.now();",
99
+ });
100
+ engine.runFile("/project/mod.js");
101
+ engine.clearCache();
102
+ engine.runFile("/project/mod.js");
103
+ });
104
+ });
@@ -0,0 +1,101 @@
1
+ import { describe, bench, beforeEach } from "vitest";
2
+ import { parse, expandVariables } from "../../shell/shell-parser";
3
+ import { NodepodShell } from "../../shell/shell-interpreter";
4
+ import { MemoryVolume } from "../../memory-volume";
5
+
6
+ const ENV = {
7
+ HOME: "/home/user",
8
+ PATH: "/usr/bin",
9
+ PWD: "/",
10
+ NODE_ENV: "production",
11
+ };
12
+
13
+ describe("Shell parser", () => {
14
+ bench("simple: echo hello", () => {
15
+ parse("echo hello", ENV, 0);
16
+ });
17
+
18
+ bench("pipe: ls | grep foo | wc -l", () => {
19
+ parse("ls | grep foo | wc -l", ENV, 0);
20
+ });
21
+
22
+ bench("compound: cd /tmp && ls -la && echo done", () => {
23
+ parse("cd /tmp && ls -la && echo done", ENV, 0);
24
+ });
25
+
26
+ bench("redirects: cat file.txt > output.txt 2>&1", () => {
27
+ parse("cat file.txt > output.txt 2>&1", ENV, 0);
28
+ });
29
+
30
+ bench("variable expansion: echo $HOME $PWD $NODE_ENV", () => {
31
+ parse("echo $HOME $PWD $NODE_ENV", ENV, 0);
32
+ });
33
+
34
+ bench("complex: VAR=hello echo ${VAR:-default} | cat && echo $?", () => {
35
+ parse("VAR=hello echo ${VAR:-default} | cat && echo $?", ENV, 0);
36
+ });
37
+
38
+ bench("quoted strings: echo 'hello world' \"$HOME/path\"", () => {
39
+ parse(`echo 'hello world' "$HOME/path"`, ENV, 0);
40
+ });
41
+ });
42
+
43
+ describe("Shell expandVariables", () => {
44
+ bench("simple $VAR", () => {
45
+ expandVariables("$HOME", ENV, 0);
46
+ });
47
+
48
+ bench("${VAR:-default}", () => {
49
+ expandVariables("${MISSING:-fallback}", ENV, 0);
50
+ });
51
+
52
+ bench("multiple vars in string", () => {
53
+ expandVariables("$HOME/.config/$NODE_ENV/settings", ENV, 0);
54
+ });
55
+ });
56
+
57
+ describe("Shell interpreter - builtins", () => {
58
+ let shell: NodepodShell;
59
+
60
+ beforeEach(() => {
61
+ const vol = new MemoryVolume();
62
+ vol.mkdirSync("/project/src", { recursive: true });
63
+ for (let i = 0; i < 20; i++) {
64
+ vol.writeFileSync(
65
+ `/project/src/file-${i}.ts`,
66
+ `export const x = ${i};`,
67
+ );
68
+ }
69
+ vol.writeFileSync(
70
+ "/project/readme.md",
71
+ "# Project\nThis is a readme.\nLine 3.\n",
72
+ );
73
+ shell = new NodepodShell(vol, { cwd: "/project", env: { ...ENV } });
74
+ });
75
+
76
+ bench("echo hello world", async () => {
77
+ await shell.exec("echo hello world");
78
+ });
79
+
80
+ bench("ls /project/src (20 files)", async () => {
81
+ await shell.exec("ls /project/src");
82
+ });
83
+
84
+ bench("cat readme.md", async () => {
85
+ await shell.exec("cat /project/readme.md");
86
+ });
87
+
88
+ bench("pwd", async () => {
89
+ await shell.exec("pwd");
90
+ });
91
+
92
+ bench("pipe: echo hello | cat", async () => {
93
+ await shell.exec("echo hello | cat");
94
+ });
95
+
96
+ bench("mkdir -p + echo redirect + rm", async () => {
97
+ await shell.exec(
98
+ "mkdir -p /tmp/bench && echo test > /tmp/bench/f.txt && rm /tmp/bench/f.txt",
99
+ );
100
+ });
101
+ });
@@ -0,0 +1,82 @@
1
+ import { describe, bench } from "vitest";
2
+ import { esmToCjs, hasTopLevelAwait, stripTopLevelAwait } from "../../syntax-transforms";
3
+
4
+ const SIMPLE_ESM = `
5
+ import { readFileSync } from 'fs';
6
+ import path from 'path';
7
+ export const data = readFileSync(path.join(__dirname, 'data.json'), 'utf8');
8
+ export default data;
9
+ `;
10
+
11
+ const COMPLEX_ESM = `
12
+ import express from 'express';
13
+ import { Router } from 'express';
14
+ import * as http from 'http';
15
+ import path, { join, resolve, dirname } from 'path';
16
+ import { readFileSync, writeFileSync } from 'fs';
17
+
18
+ export const app = express();
19
+ const router = Router();
20
+
21
+ router.get('/', (req, res) => {
22
+ res.json({ status: 'ok' });
23
+ });
24
+
25
+ app.use('/api', router);
26
+
27
+ export function startServer(port) {
28
+ return new Promise((resolve) => {
29
+ const server = http.createServer(app);
30
+ server.listen(port, () => resolve(server));
31
+ });
32
+ }
33
+
34
+ export default app;
35
+ `;
36
+
37
+ const LARGE_ESM =
38
+ Array.from(
39
+ { length: 20 },
40
+ (_, i) => `import mod${i} from './mod${i}';\nexport const val${i} = mod${i}.process();`,
41
+ ).join("\n") + "\nexport default { total: 20 };";
42
+
43
+ const TLA_SOURCE = `
44
+ import fs from 'fs';
45
+ const data = await fetch('/api');
46
+ const json = await data.json();
47
+ export default json;
48
+ `;
49
+
50
+ const PLAIN_CJS = 'const x = require("fs"); module.exports = x;';
51
+
52
+ describe("esmToCjs", () => {
53
+ bench("simple ESM (2 imports, 2 exports)", () => {
54
+ esmToCjs(SIMPLE_ESM);
55
+ });
56
+
57
+ bench("complex ESM (5 imports, mixed exports)", () => {
58
+ esmToCjs(COMPLEX_ESM);
59
+ });
60
+
61
+ bench("large ESM (20 imports, 20 exports)", () => {
62
+ esmToCjs(LARGE_ESM);
63
+ });
64
+
65
+ bench("passthrough - plain CJS", () => {
66
+ esmToCjs(PLAIN_CJS);
67
+ });
68
+ });
69
+
70
+ describe("Top-level await", () => {
71
+ bench("hasTopLevelAwait - with TLA", () => {
72
+ hasTopLevelAwait(TLA_SOURCE);
73
+ });
74
+
75
+ bench("hasTopLevelAwait - without TLA", () => {
76
+ hasTopLevelAwait(COMPLEX_ESM);
77
+ });
78
+
79
+ bench("stripTopLevelAwait", () => {
80
+ stripTopLevelAwait(TLA_SOURCE);
81
+ });
82
+ });
@@ -0,0 +1,95 @@
1
+ import { describe, bench } from "vitest";
2
+ import {
3
+ parseSemver,
4
+ compareSemver,
5
+ satisfiesRange,
6
+ pickBestMatch,
7
+ } from "../../packages/version-resolver";
8
+
9
+ const VERSIONS = [
10
+ "1.0.0", "1.0.1", "1.1.0", "1.2.0", "1.2.3",
11
+ "2.0.0", "2.0.1", "2.1.0", "2.3.4",
12
+ "3.0.0-alpha.1", "3.0.0-beta.1", "3.0.0", "3.1.0", "3.2.1",
13
+ "4.0.0", "4.1.0", "4.2.0", "4.3.0", "4.4.0", "4.5.0",
14
+ "5.0.0", "5.1.0", "5.2.0", "5.3.0", "5.4.0", "5.5.0",
15
+ ];
16
+
17
+ describe("parseSemver", () => {
18
+ bench("simple version", () => {
19
+ parseSemver("3.2.1");
20
+ });
21
+
22
+ bench("with prerelease", () => {
23
+ parseSemver("3.0.0-alpha.1");
24
+ });
25
+
26
+ bench("invalid (returns null)", () => {
27
+ parseSemver("not-a-version");
28
+ });
29
+ });
30
+
31
+ describe("compareSemver", () => {
32
+ bench("equal versions", () => {
33
+ compareSemver("1.2.3", "1.2.3");
34
+ });
35
+
36
+ bench("different major", () => {
37
+ compareSemver("1.2.3", "2.0.0");
38
+ });
39
+
40
+ bench("different patch", () => {
41
+ compareSemver("1.2.3", "1.2.4");
42
+ });
43
+
44
+ bench("with prerelease", () => {
45
+ compareSemver("3.0.0-alpha.1", "3.0.0-beta.1");
46
+ });
47
+ });
48
+
49
+ describe("satisfiesRange", () => {
50
+ bench("caret: ^1.2.0", () => {
51
+ satisfiesRange("1.5.0", "^1.2.0");
52
+ });
53
+
54
+ bench("tilde: ~1.2.0", () => {
55
+ satisfiesRange("1.2.5", "~1.2.0");
56
+ });
57
+
58
+ bench("compound: >=2.0.0 <4.0.0", () => {
59
+ satisfiesRange("3.1.0", ">=2.0.0 <4.0.0");
60
+ });
61
+
62
+ bench("OR union: ^1.0.0 || ^2.0.0", () => {
63
+ satisfiesRange("2.1.0", "^1.0.0 || ^2.0.0");
64
+ });
65
+
66
+ bench("x-range: 1.x", () => {
67
+ satisfiesRange("1.5.0", "1.x");
68
+ });
69
+
70
+ bench("wildcard: *", () => {
71
+ satisfiesRange("5.0.0", "*");
72
+ });
73
+
74
+ bench("exact: 1.2.3", () => {
75
+ satisfiesRange("1.2.3", "1.2.3");
76
+ });
77
+ });
78
+
79
+ describe("pickBestMatch", () => {
80
+ bench("^1.0.0 from 26 versions", () => {
81
+ pickBestMatch(VERSIONS, "^1.0.0");
82
+ });
83
+
84
+ bench(">=2.0.0 <5.0.0 from 26 versions", () => {
85
+ pickBestMatch(VERSIONS, ">=2.0.0 <5.0.0");
86
+ });
87
+
88
+ bench("* from 26 versions", () => {
89
+ pickBestMatch(VERSIONS, "*");
90
+ });
91
+
92
+ bench("no match: ^99.0.0", () => {
93
+ pickBestMatch(VERSIONS, "^99.0.0");
94
+ });
95
+ });
@@ -0,0 +1,273 @@
1
+ import { describe, it, expect } from "vitest";
2
+
3
+ import { Buffer } from "../polyfills/buffer";
4
+
5
+ describe("Buffer", () => {
6
+ describe("Buffer.from(string)", () => {
7
+ it("creates buffer from utf8 string", () => {
8
+ const buf = Buffer.from("hello");
9
+ expect(buf.toString()).toBe("hello");
10
+ expect(buf.length).toBe(5);
11
+ });
12
+
13
+ it("creates buffer from hex string", () => {
14
+ const buf = Buffer.from("48656c6c6f", "hex");
15
+ expect(buf.toString()).toBe("Hello");
16
+ });
17
+
18
+ it("creates buffer from base64 string", () => {
19
+ const buf = Buffer.from("SGVsbG8=", "base64");
20
+ expect(buf.toString()).toBe("Hello");
21
+ });
22
+
23
+ it("creates buffer from latin1 string", () => {
24
+ const buf = Buffer.from("hello", "latin1");
25
+ expect(buf.toString()).toBe("hello");
26
+ });
27
+
28
+ it("creates buffer from base64url", () => {
29
+ const buf = Buffer.from("SGVsbG8", "base64url");
30
+ expect(buf.toString()).toBe("Hello");
31
+ });
32
+ });
33
+
34
+ describe("Buffer.from(array/Uint8Array)", () => {
35
+ it("creates buffer from number array", () => {
36
+ const buf = Buffer.from([72, 101, 108, 108, 111]);
37
+ expect(buf.toString()).toBe("Hello");
38
+ });
39
+
40
+ it("creates buffer from Uint8Array", () => {
41
+ const arr = new Uint8Array([1, 2, 3]);
42
+ const buf = Buffer.from(arr);
43
+ expect(buf.length).toBe(3);
44
+ expect(buf[0]).toBe(1);
45
+ });
46
+ });
47
+
48
+ describe("Buffer.alloc", () => {
49
+ it("creates zero-filled buffer", () => {
50
+ const buf = Buffer.alloc(10);
51
+ expect(buf.length).toBe(10);
52
+ expect(buf.every((b: number) => b === 0)).toBe(true);
53
+ });
54
+
55
+ it("creates buffer filled with specified value", () => {
56
+ const buf = Buffer.alloc(5, 0xff);
57
+ expect(buf.every((b: number) => b === 255)).toBe(true);
58
+ });
59
+ });
60
+
61
+ describe("Buffer.concat", () => {
62
+ it("concatenates multiple buffers", () => {
63
+ const result = Buffer.concat([Buffer.from("hel"), Buffer.from("lo")]);
64
+ expect(result.toString()).toBe("hello");
65
+ });
66
+
67
+ it("handles empty array", () => {
68
+ const result = Buffer.concat([]);
69
+ expect(result.length).toBe(0);
70
+ });
71
+
72
+ it("handles single buffer", () => {
73
+ const buf = Buffer.from("only");
74
+ const result = Buffer.concat([buf]);
75
+ expect(result.toString()).toBe("only");
76
+ });
77
+ });
78
+
79
+ describe("toString", () => {
80
+ it("defaults to utf8", () => {
81
+ expect(Buffer.from("test").toString()).toBe("test");
82
+ });
83
+
84
+ it("encodes as hex", () => {
85
+ expect(Buffer.from("Hello").toString("hex")).toBe("48656c6c6f");
86
+ });
87
+
88
+ it("encodes as base64", () => {
89
+ expect(Buffer.from("Hello").toString("base64")).toBe("SGVsbG8=");
90
+ });
91
+
92
+ it("encodes as latin1", () => {
93
+ const buf = Buffer.from([0xe9]);
94
+ expect(buf.toString("latin1")).toBe("\xe9");
95
+ });
96
+ });
97
+
98
+ describe("slice / subarray", () => {
99
+ it("returns a sub-buffer", () => {
100
+ const buf = Buffer.from("hello");
101
+ expect(buf.slice(1, 3).toString()).toBe("el");
102
+ });
103
+
104
+ it("slice result is a Buffer-like", () => {
105
+ const buf = Buffer.from("test");
106
+ const sliced = buf.slice(0, 2);
107
+ expect(sliced).toBeInstanceOf(Uint8Array);
108
+ });
109
+ });
110
+
111
+ describe("compare / equals", () => {
112
+ it("returns 0 for equal buffers", () => {
113
+ expect(Buffer.from("abc").compare(Buffer.from("abc"))).toBe(0);
114
+ });
115
+
116
+ it("returns negative for lesser buffer", () => {
117
+ expect(Buffer.from("abc").compare(Buffer.from("abd"))).toBeLessThan(0);
118
+ });
119
+
120
+ it("returns positive for greater buffer", () => {
121
+ expect(Buffer.from("abd").compare(Buffer.from("abc"))).toBeGreaterThan(0);
122
+ });
123
+
124
+ it("equals returns true for same content", () => {
125
+ expect(Buffer.from("test").equals(Buffer.from("test"))).toBe(true);
126
+ });
127
+
128
+ it("equals returns false for different content", () => {
129
+ expect(Buffer.from("test").equals(Buffer.from("nope"))).toBe(false);
130
+ });
131
+ });
132
+
133
+ describe("indexOf", () => {
134
+ it("finds byte in buffer", () => {
135
+ const buf = Buffer.from([1, 2, 3, 4, 5]);
136
+ expect(buf.indexOf(3)).toBe(2);
137
+ });
138
+
139
+ it("returns -1 when not found", () => {
140
+ const buf = Buffer.from([1, 2, 3]);
141
+ expect(buf.indexOf(99)).toBe(-1);
142
+ });
143
+ });
144
+
145
+ describe("write", () => {
146
+ it("writes string into buffer at offset", () => {
147
+ const buf = Buffer.alloc(10);
148
+ buf.write("hi", 0);
149
+ expect(buf.slice(0, 2).toString()).toBe("hi");
150
+ });
151
+
152
+ it("returns number of bytes written", () => {
153
+ const buf = Buffer.alloc(10);
154
+ const written = buf.write("hello", 0);
155
+ expect(written).toBe(5);
156
+ });
157
+ });
158
+
159
+ describe("copy", () => {
160
+ it("copies bytes between buffers", () => {
161
+ const src = Buffer.from("hello");
162
+ const dst = Buffer.alloc(5);
163
+ src.copy(dst);
164
+ expect(dst.toString()).toBe("hello");
165
+ });
166
+ });
167
+
168
+ describe("integer read/write", () => {
169
+ it("readUInt8 / writeUInt8 round-trip", () => {
170
+ const buf = Buffer.alloc(1);
171
+ buf.writeUInt8(200, 0);
172
+ expect(buf.readUInt8(0)).toBe(200);
173
+ });
174
+
175
+ it("readUInt16BE / writeUInt16BE round-trip", () => {
176
+ const buf = Buffer.alloc(2);
177
+ buf.writeUInt16BE(0x1234, 0);
178
+ expect(buf.readUInt16BE(0)).toBe(0x1234);
179
+ });
180
+
181
+ it("readUInt32LE / writeUInt32LE round-trip", () => {
182
+ const buf = Buffer.alloc(4);
183
+ buf.writeUInt32LE(0xdeadbeef, 0);
184
+ expect(buf.readUInt32LE(0)).toBe(0xdeadbeef);
185
+ });
186
+
187
+ it("readInt8 handles signed values", () => {
188
+ const buf = Buffer.alloc(1);
189
+ buf.writeInt8(-42, 0);
190
+ expect(buf.readInt8(0)).toBe(-42);
191
+ });
192
+
193
+ it("readInt16BE handles negative values", () => {
194
+ const buf = Buffer.alloc(2);
195
+ buf.writeInt16BE(-1000, 0);
196
+ expect(buf.readInt16BE(0)).toBe(-1000);
197
+ });
198
+ });
199
+
200
+ describe("Float/Double read/write", () => {
201
+ it("readFloatLE / writeFloatLE round-trip", () => {
202
+ const buf = Buffer.alloc(4);
203
+ buf.writeFloatLE(3.14, 0);
204
+ expect(buf.readFloatLE(0)).toBeCloseTo(3.14, 2);
205
+ });
206
+
207
+ it("readDoubleLE / writeDoubleLE round-trip", () => {
208
+ const buf = Buffer.alloc(8);
209
+ buf.writeDoubleLE(Math.PI, 0);
210
+ expect(buf.readDoubleLE(0)).toBeCloseTo(Math.PI, 10);
211
+ });
212
+ });
213
+
214
+ describe("swap methods", () => {
215
+ it("swap16 swaps pairs of bytes", () => {
216
+ const buf = Buffer.from([0x01, 0x02, 0x03, 0x04]);
217
+ buf.swap16();
218
+ expect(Array.from(buf)).toEqual([0x02, 0x01, 0x04, 0x03]);
219
+ });
220
+
221
+ it("swap32 reverses 4-byte groups", () => {
222
+ const buf = Buffer.from([0x01, 0x02, 0x03, 0x04]);
223
+ buf.swap32();
224
+ expect(Array.from(buf)).toEqual([0x04, 0x03, 0x02, 0x01]);
225
+ });
226
+
227
+ it("swap16 throws on odd-length buffer", () => {
228
+ const buf = Buffer.from([1, 2, 3]);
229
+ expect(() => buf.swap16()).toThrow();
230
+ });
231
+ });
232
+
233
+ describe("static methods", () => {
234
+ it("isBuffer returns true for Buffer instances", () => {
235
+ expect(Buffer.isBuffer(Buffer.from("x"))).toBe(true);
236
+ });
237
+
238
+ it("isBuffer returns true for Uint8Array", () => {
239
+ expect(Buffer.isBuffer(new Uint8Array(1))).toBe(true);
240
+ });
241
+
242
+ it("isEncoding returns true for valid encodings", () => {
243
+ expect(Buffer.isEncoding("utf8")).toBe(true);
244
+ expect(Buffer.isEncoding("hex")).toBe(true);
245
+ expect(Buffer.isEncoding("base64")).toBe(true);
246
+ });
247
+
248
+ it("isEncoding returns false for invalid encoding", () => {
249
+ expect(Buffer.isEncoding("garbage")).toBe(false);
250
+ });
251
+
252
+ it("byteLength returns correct length for utf8", () => {
253
+ expect(Buffer.byteLength("hello", "utf8")).toBe(5);
254
+ });
255
+
256
+ it("byteLength returns correct length for hex", () => {
257
+ expect(Buffer.byteLength("aabb", "hex")).toBe(2);
258
+ });
259
+
260
+ it("byteLength returns correct length for base64", () => {
261
+ expect(Buffer.byteLength("SGVsbG8=", "base64")).toBe(5);
262
+ });
263
+ });
264
+
265
+ describe("toJSON", () => {
266
+ it('returns { type: "Buffer", data: [...] }', () => {
267
+ const buf = Buffer.from([1, 2, 3]);
268
+ const json = buf.toJSON();
269
+ expect(json.type).toBe("Buffer");
270
+ expect(json.data).toEqual([1, 2, 3]);
271
+ });
272
+ });
273
+ });