@ricsam/isolate-test-utils 0.1.10 → 0.1.12
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/cjs/fetch-context.cjs +66 -0
- package/dist/cjs/fetch-context.cjs.map +10 -0
- package/dist/cjs/fs-context.cjs +73 -0
- package/dist/cjs/fs-context.cjs.map +10 -0
- package/dist/cjs/index.cjs +121 -0
- package/dist/cjs/index.cjs.map +10 -0
- package/{src/mock-fs.ts → dist/cjs/mock-fs.cjs} +63 -97
- package/dist/cjs/mock-fs.cjs.map +10 -0
- package/dist/cjs/native-input-test.cjs +347 -0
- package/dist/cjs/native-input-test.cjs.map +10 -0
- package/dist/cjs/package.json +5 -0
- package/dist/cjs/runtime-context.cjs +97 -0
- package/dist/cjs/runtime-context.cjs.map +10 -0
- package/dist/cjs/server.cjs +109 -0
- package/dist/cjs/server.cjs.map +10 -0
- package/dist/mjs/fetch-context.mjs +23 -0
- package/dist/mjs/fetch-context.mjs.map +10 -0
- package/dist/mjs/fs-context.mjs +30 -0
- package/dist/mjs/fs-context.mjs.map +10 -0
- package/dist/mjs/index.mjs +78 -0
- package/dist/mjs/index.mjs.map +10 -0
- package/dist/mjs/mock-fs.mjs +181 -0
- package/dist/mjs/mock-fs.mjs.map +10 -0
- package/{src/native-input-test.ts → dist/mjs/native-input-test.mjs} +60 -169
- package/dist/mjs/native-input-test.mjs.map +10 -0
- package/dist/mjs/package.json +5 -0
- package/dist/mjs/runtime-context.mjs +67 -0
- package/dist/mjs/runtime-context.mjs.map +10 -0
- package/dist/mjs/server.mjs +79 -0
- package/dist/mjs/server.mjs.map +10 -0
- package/dist/types/fetch-context.d.ts +7 -0
- package/dist/types/fs-context.d.ts +30 -0
- package/dist/types/index.d.ts +88 -0
- package/dist/types/mock-fs.d.ts +59 -0
- package/dist/types/native-input-test.d.ts +29 -0
- package/dist/types/runtime-context.d.ts +73 -0
- package/dist/types/server.d.ts +53 -0
- package/package.json +45 -18
- package/CHANGELOG.md +0 -119
- package/src/fetch-context.ts +0 -33
- package/src/fs-context.ts +0 -65
- package/src/index.test.ts +0 -472
- package/src/index.ts +0 -177
- package/src/runtime-context.ts +0 -148
- package/src/server.ts +0 -150
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
19
|
+
var __toCommonJS = (from) => {
|
|
20
|
+
var entry = __moduleCache.get(from), desc;
|
|
21
|
+
if (entry)
|
|
22
|
+
return entry;
|
|
23
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
24
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
25
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
26
|
+
get: () => from[key],
|
|
27
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
28
|
+
}));
|
|
29
|
+
__moduleCache.set(from, entry);
|
|
30
|
+
return entry;
|
|
31
|
+
};
|
|
32
|
+
var __export = (target, all) => {
|
|
33
|
+
for (var name in all)
|
|
34
|
+
__defProp(target, name, {
|
|
35
|
+
get: all[name],
|
|
36
|
+
enumerable: true,
|
|
37
|
+
configurable: true,
|
|
38
|
+
set: (newValue) => all[name] = () => newValue
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// packages/test-utils/src/fetch-context.ts
|
|
43
|
+
var exports_fetch_context = {};
|
|
44
|
+
__export(exports_fetch_context, {
|
|
45
|
+
createFetchTestContext: () => createFetchTestContext
|
|
46
|
+
});
|
|
47
|
+
module.exports = __toCommonJS(exports_fetch_context);
|
|
48
|
+
var import_isolated_vm = __toESM(require("isolated-vm"));
|
|
49
|
+
var import_isolate_fetch = require("@ricsam/isolate-fetch");
|
|
50
|
+
async function createFetchTestContext() {
|
|
51
|
+
const isolate = new import_isolated_vm.default.Isolate;
|
|
52
|
+
const context = await isolate.createContext();
|
|
53
|
+
import_isolate_fetch.clearAllInstanceState();
|
|
54
|
+
const fetchHandle = await import_isolate_fetch.setupFetch(context);
|
|
55
|
+
return {
|
|
56
|
+
isolate,
|
|
57
|
+
context,
|
|
58
|
+
dispose() {
|
|
59
|
+
fetchHandle.dispose();
|
|
60
|
+
context.release();
|
|
61
|
+
isolate.dispose();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//# debugId=3DD19E03E10A99CD64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/fetch-context.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type ivm from \"isolated-vm\";\nimport type { TestContext } from \"./index.cjs\";\nimport ivmModule from \"isolated-vm\";\nimport { setupFetch, clearAllInstanceState } from \"@ricsam/isolate-fetch\";\n\nexport interface FetchTestContext extends TestContext {\n // Context with fetch APIs set up\n}\n\n/**\n * Create a test context with fetch APIs set up (Headers, Request, Response, FormData, fetch)\n */\nexport async function createFetchTestContext(): Promise<FetchTestContext> {\n const isolate = new ivmModule.Isolate();\n const context = await isolate.createContext();\n\n clearAllInstanceState();\n\n const fetchHandle = await setupFetch(context);\n\n return {\n isolate,\n context,\n dispose() {\n fetchHandle.dispose();\n context.release();\n isolate.dispose();\n },\n };\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEsB,IAAtB;AACkD,IAAlD;AASA,eAAsB,sBAAsB,GAA8B;AAAA,EACxE,MAAM,UAAU,IAAI,2BAAU;AAAA,EAC9B,MAAM,UAAU,MAAM,QAAQ,cAAc;AAAA,EAE5C,2CAAsB;AAAA,EAEtB,MAAM,cAAc,MAAM,gCAAW,OAAO;AAAA,EAE5C,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,GAAG;AAAA,MACR,YAAY,QAAQ;AAAA,MACpB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA;AAAA,EAEpB;AAAA;",
|
|
8
|
+
"debugId": "3DD19E03E10A99CD64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
19
|
+
var __toCommonJS = (from) => {
|
|
20
|
+
var entry = __moduleCache.get(from), desc;
|
|
21
|
+
if (entry)
|
|
22
|
+
return entry;
|
|
23
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
24
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
25
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
26
|
+
get: () => from[key],
|
|
27
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
28
|
+
}));
|
|
29
|
+
__moduleCache.set(from, entry);
|
|
30
|
+
return entry;
|
|
31
|
+
};
|
|
32
|
+
var __export = (target, all) => {
|
|
33
|
+
for (var name in all)
|
|
34
|
+
__defProp(target, name, {
|
|
35
|
+
get: all[name],
|
|
36
|
+
enumerable: true,
|
|
37
|
+
configurable: true,
|
|
38
|
+
set: (newValue) => all[name] = () => newValue
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// packages/test-utils/src/fs-context.ts
|
|
43
|
+
var exports_fs_context = {};
|
|
44
|
+
__export(exports_fs_context, {
|
|
45
|
+
createFsTestContext: () => createFsTestContext
|
|
46
|
+
});
|
|
47
|
+
module.exports = __toCommonJS(exports_fs_context);
|
|
48
|
+
var import_mock_fs = require("./mock-fs.cjs");
|
|
49
|
+
var import_isolated_vm = __toESM(require("isolated-vm"));
|
|
50
|
+
var import_isolate_fs = require("@ricsam/isolate-fs");
|
|
51
|
+
var import_isolate_core = require("@ricsam/isolate-core");
|
|
52
|
+
var import_isolate_core2 = require("@ricsam/isolate-core");
|
|
53
|
+
async function createFsTestContext() {
|
|
54
|
+
const isolate = new import_isolated_vm.default.Isolate;
|
|
55
|
+
const context = await isolate.createContext();
|
|
56
|
+
import_isolate_core.clearAllInstanceState();
|
|
57
|
+
const mockFs = new import_mock_fs.MockFileSystem;
|
|
58
|
+
const coreHandle = await import_isolate_core2.setupCore(context);
|
|
59
|
+
const fsHandle = await import_isolate_fs.setupFs(context, { getDirectory: async () => mockFs });
|
|
60
|
+
return {
|
|
61
|
+
isolate,
|
|
62
|
+
context,
|
|
63
|
+
mockFs,
|
|
64
|
+
dispose() {
|
|
65
|
+
fsHandle.dispose();
|
|
66
|
+
coreHandle.dispose();
|
|
67
|
+
context.release();
|
|
68
|
+
isolate.dispose();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//# debugId=0F152B9CFB40E7B764756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/fs-context.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type ivm from \"isolated-vm\";\nimport { MockFileSystem } from \"./mock-fs.cjs\";\nimport ivmModule from \"isolated-vm\";\nimport { setupFs } from \"@ricsam/isolate-fs\";\nimport { clearAllInstanceState } from \"@ricsam/isolate-core\";\nimport { setupCore } from \"@ricsam/isolate-core\";\n\nexport interface FsTestContext {\n isolate: ivm.Isolate;\n context: ivm.Context;\n mockFs: MockFileSystem;\n dispose(): void;\n}\n\n/**\n * Create a test context with file system APIs set up using a mock file system.\n *\n * @example\n * const ctx = await createFsTestContext();\n *\n * // Set up initial files\n * ctx.mockFs.setFile(\"/test.txt\", \"Hello, World!\");\n *\n * // Use file system APIs in the isolate\n * const result = await ctx.context.eval(`\n * (async () => {\n * const root = await navigator.storage.getDirectory();\n * const fileHandle = await root.getFileHandle(\"test.txt\");\n * const file = await fileHandle.getFile();\n * return await file.text();\n * })()\n * `, { promise: true });\n *\n * ctx.dispose();\n */\nexport async function createFsTestContext(): Promise<FsTestContext> {\n const isolate = new ivmModule.Isolate();\n const context = await isolate.createContext();\n\n // Clear any previous instance state\n clearAllInstanceState();\n\n // Create mock file system\n const mockFs = new MockFileSystem();\n\n // Setup core APIs (required for Blob, File, streams)\n const coreHandle = await setupCore(context);\n\n // Setup file system APIs with mock handler\n const fsHandle = await setupFs(context, { getDirectory: async () => mockFs });\n\n return {\n isolate,\n context,\n mockFs,\n dispose() {\n fsHandle.dispose();\n coreHandle.dispose();\n context.release();\n isolate.dispose();\n },\n };\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAC+B,IAA/B;AACsB,IAAtB;AACwB,IAAxB;AACsC,IAAtC;AAC0B,IAA1B;AA8BA,eAAsB,mBAAmB,GAA2B;AAAA,EAClE,MAAM,UAAU,IAAI,2BAAU;AAAA,EAC9B,MAAM,UAAU,MAAM,QAAQ,cAAc;AAAA,EAG5C,0CAAsB;AAAA,EAGtB,MAAM,SAAS,IAAI;AAAA,EAGnB,MAAM,aAAa,MAAM,+BAAU,OAAO;AAAA,EAG1C,MAAM,WAAW,MAAM,0BAAQ,SAAS,EAAE,cAAc,YAAY,OAAO,CAAC;AAAA,EAE5E,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,GAAG;AAAA,MACR,SAAS,QAAQ;AAAA,MACjB,WAAW,QAAQ;AAAA,MACnB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA;AAAA,EAEpB;AAAA;",
|
|
8
|
+
"debugId": "0F152B9CFB40E7B764756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
19
|
+
var __toCommonJS = (from) => {
|
|
20
|
+
var entry = __moduleCache.get(from), desc;
|
|
21
|
+
if (entry)
|
|
22
|
+
return entry;
|
|
23
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
24
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
25
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
26
|
+
get: () => from[key],
|
|
27
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
28
|
+
}));
|
|
29
|
+
__moduleCache.set(from, entry);
|
|
30
|
+
return entry;
|
|
31
|
+
};
|
|
32
|
+
var __export = (target, all) => {
|
|
33
|
+
for (var name in all)
|
|
34
|
+
__defProp(target, name, {
|
|
35
|
+
get: all[name],
|
|
36
|
+
enumerable: true,
|
|
37
|
+
configurable: true,
|
|
38
|
+
set: (newValue) => all[name] = () => newValue
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// packages/test-utils/src/index.ts
|
|
43
|
+
var exports_src = {};
|
|
44
|
+
__export(exports_src, {
|
|
45
|
+
startIntegrationServer: () => import_server.startIntegrationServer,
|
|
46
|
+
runTestCode: () => import_native_input_test.runTestCode,
|
|
47
|
+
injectGlobals: () => injectGlobals,
|
|
48
|
+
evalCodeJsonAsync: () => evalCodeJsonAsync,
|
|
49
|
+
evalCodeJson: () => evalCodeJson,
|
|
50
|
+
evalCodeAsync: () => evalCodeAsync,
|
|
51
|
+
evalCode: () => evalCode,
|
|
52
|
+
createTestContext: () => createTestContext,
|
|
53
|
+
createRuntimeTestContext: () => import_runtime_context.createRuntimeTestContext,
|
|
54
|
+
createFsTestContext: () => import_fs_context.createFsTestContext,
|
|
55
|
+
createFetchTestContext: () => import_fetch_context.createFetchTestContext,
|
|
56
|
+
createCoreTestContext: () => createCoreTestContext,
|
|
57
|
+
MockFileSystem: () => import_mock_fs.MockFileSystem
|
|
58
|
+
});
|
|
59
|
+
module.exports = __toCommonJS(exports_src);
|
|
60
|
+
var import_isolated_vm = __toESM(require("isolated-vm"));
|
|
61
|
+
var import_isolate_core = require("@ricsam/isolate-core");
|
|
62
|
+
var import_mock_fs = require("./mock-fs.cjs");
|
|
63
|
+
var import_fs_context = require("./fs-context.cjs");
|
|
64
|
+
var import_runtime_context = require("./runtime-context.cjs");
|
|
65
|
+
var import_server = require("./server.cjs");
|
|
66
|
+
var import_native_input_test = require("./native-input-test.cjs");
|
|
67
|
+
var import_fetch_context = require("./fetch-context.cjs");
|
|
68
|
+
async function createTestContext() {
|
|
69
|
+
const isolate = new import_isolated_vm.default.Isolate;
|
|
70
|
+
const context = await isolate.createContext();
|
|
71
|
+
return {
|
|
72
|
+
isolate,
|
|
73
|
+
context,
|
|
74
|
+
dispose() {
|
|
75
|
+
context.release();
|
|
76
|
+
isolate.dispose();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async function createCoreTestContext() {
|
|
81
|
+
const isolate = new import_isolated_vm.default.Isolate;
|
|
82
|
+
const context = await isolate.createContext();
|
|
83
|
+
const coreHandle = await import_isolate_core.setupCore(context);
|
|
84
|
+
return {
|
|
85
|
+
isolate,
|
|
86
|
+
context,
|
|
87
|
+
dispose() {
|
|
88
|
+
coreHandle.dispose();
|
|
89
|
+
context.release();
|
|
90
|
+
isolate.dispose();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function evalCode(context, code) {
|
|
95
|
+
return context.evalSync(code);
|
|
96
|
+
}
|
|
97
|
+
async function evalCodeAsync(context, code) {
|
|
98
|
+
return await context.eval(code, { promise: true });
|
|
99
|
+
}
|
|
100
|
+
function evalCodeJson(context, code) {
|
|
101
|
+
const jsonString = context.evalSync(code);
|
|
102
|
+
return JSON.parse(jsonString);
|
|
103
|
+
}
|
|
104
|
+
async function evalCodeJsonAsync(context, code) {
|
|
105
|
+
const jsonString = await context.eval(code, { promise: true });
|
|
106
|
+
return JSON.parse(jsonString);
|
|
107
|
+
}
|
|
108
|
+
async function injectGlobals(context, values) {
|
|
109
|
+
const global = context.global;
|
|
110
|
+
for (const [key, value] of Object.entries(values)) {
|
|
111
|
+
if (typeof value === "function") {
|
|
112
|
+
global.setSync(key, new import_isolated_vm.default.Callback(value));
|
|
113
|
+
} else if (typeof value === "object" && value !== null) {
|
|
114
|
+
context.evalSync(`globalThis.${key} = ${JSON.stringify(value)}`);
|
|
115
|
+
} else {
|
|
116
|
+
global.setSync(key, value);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
//# debugId=927FD9D4B2821C8964756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type ivm from \"isolated-vm\";\nimport ivmModule from \"isolated-vm\";\nimport { setupCore } from \"@ricsam/isolate-core\";\nimport { MockFileSystem } from \"./mock-fs.cjs\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TestContext {\n isolate: ivm.Isolate;\n context: ivm.Context;\n dispose(): void;\n}\n\nexport interface TestResult<T> {\n result: T;\n logs: Array<{ level: string; args: unknown[] }>;\n}\n\n// ============================================================================\n// Context Creation\n// ============================================================================\n\n/**\n * Create a basic test context for isolated-vm tests.\n * This creates a bare context without any APIs set up.\n */\nexport async function createTestContext(): Promise<TestContext> {\n const isolate = new ivmModule.Isolate();\n const context = await isolate.createContext();\n\n return {\n isolate,\n context,\n dispose() {\n context.release();\n isolate.dispose();\n },\n };\n}\n\n/**\n * Create a test context with core APIs set up (Blob, File, URL, streams, etc.)\n */\nexport async function createCoreTestContext(): Promise<TestContext> {\n const isolate = new ivmModule.Isolate();\n const context = await isolate.createContext();\n const coreHandle = await setupCore(context);\n\n return {\n isolate,\n context,\n dispose() {\n coreHandle.dispose();\n context.release();\n isolate.dispose();\n },\n };\n}\n\n// ============================================================================\n// Code Evaluation Helpers\n// ============================================================================\n\n/**\n * Synchronously evaluate code and return typed result.\n * Use this for simple expressions that don't involve promises.\n *\n * @example\n * const result = evalCode<number>(ctx.context, \"1 + 1\");\n * // result === 2\n */\nexport function evalCode<T = unknown>(context: ivm.Context, code: string): T {\n return context.evalSync(code) as T;\n}\n\n/**\n * Asynchronously evaluate code that may return promises.\n * Automatically wraps code to handle promise resolution.\n *\n * @example\n * const result = await evalCodeAsync<string>(ctx.context, `\n * (async () => {\n * return \"hello\";\n * })()\n * `);\n */\nexport async function evalCodeAsync<T = unknown>(\n context: ivm.Context,\n code: string\n): Promise<T> {\n return (await context.eval(code, { promise: true })) as T;\n}\n\n/**\n * Evaluate code and return the result as JSON (for complex objects).\n * Useful when you need to extract structured data from the isolate.\n *\n * @example\n * const data = evalCodeJson<{ name: string }>(ctx.context, `\n * JSON.stringify({ name: \"test\" })\n * `);\n */\nexport function evalCodeJson<T = unknown>(context: ivm.Context, code: string): T {\n const jsonString = context.evalSync(code) as string;\n return JSON.parse(jsonString) as T;\n}\n\n/**\n * Evaluate async code and return the result as JSON (for complex objects).\n *\n * @example\n * const data = await evalCodeJsonAsync<{ status: number }>(ctx.context, `\n * (async () => {\n * const response = await fetch(\"...\");\n * return JSON.stringify({ status: response.status });\n * })()\n * `);\n */\nexport async function evalCodeJsonAsync<T = unknown>(\n context: ivm.Context,\n code: string\n): Promise<T> {\n const jsonString = (await context.eval(code, { promise: true })) as string;\n return JSON.parse(jsonString) as T;\n}\n\n/**\n * Inject values into the isolate's global scope before running code.\n *\n * @example\n * await injectGlobals(ctx.context, {\n * testInput: \"hello\",\n * testConfig: { debug: true }\n * });\n * const result = evalCode<string>(ctx.context, \"testInput\");\n */\nexport async function injectGlobals(\n context: ivm.Context,\n values: Record<string, unknown>\n): Promise<void> {\n const global = context.global;\n\n for (const [key, value] of Object.entries(values)) {\n if (typeof value === \"function\") {\n global.setSync(key, new ivmModule.Callback(value as (...args: unknown[]) => unknown));\n } else if (typeof value === \"object\" && value !== null) {\n // For objects, serialize as JSON and inject\n context.evalSync(`globalThis.${key} = ${JSON.stringify(value)}`);\n } else {\n // For primitives, set directly\n global.setSync(key, value);\n }\n }\n}\n\n// ============================================================================\n// Exports from other modules\n// ============================================================================\n\nexport { MockFileSystem } from \"./mock-fs.cjs\";\nexport { createFsTestContext } from \"./fs-context.cjs\";\nexport type { FsTestContext } from \"./fs-context.cjs\";\nexport { createRuntimeTestContext } from \"./runtime-context.cjs\";\nexport type { RuntimeTestContext } from \"./runtime-context.cjs\";\nexport { startIntegrationServer } from \"./server.cjs\";\nexport type { IntegrationServer } from \"./server.cjs\";\nexport { runTestCode } from \"./native-input-test.cjs\";\nexport type { TestRunner, TestRuntime } from \"./native-input-test.cjs\";\nexport { createFetchTestContext } from \"./fetch-context.cjs\";\nexport type { FetchTestContext } from \"./fetch-context.cjs\";\n\n// Re-export useful types\nexport type { FileSystemHandler } from \"@ricsam/isolate-fs\";\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACsB,IAAtB;AAC0B,IAA1B;AA+J+B,IAA/B;AACoC,IAApC;AAEyC,IAAzC;AAEuC,IAAvC;AAE4B,IAA5B;AAEuC,IAAvC;AA9IA,eAAsB,iBAAiB,GAAyB;AAAA,EAC9D,MAAM,UAAU,IAAI,2BAAU;AAAA,EAC9B,MAAM,UAAU,MAAM,QAAQ,cAAc;AAAA,EAE5C,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,GAAG;AAAA,MACR,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA;AAAA,EAEpB;AAAA;AAMF,eAAsB,qBAAqB,GAAyB;AAAA,EAClE,MAAM,UAAU,IAAI,2BAAU;AAAA,EAC9B,MAAM,UAAU,MAAM,QAAQ,cAAc;AAAA,EAC5C,MAAM,aAAa,MAAM,8BAAU,OAAO;AAAA,EAE1C,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,GAAG;AAAA,MACR,WAAW,QAAQ;AAAA,MACnB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA;AAAA,EAEpB;AAAA;AAeK,SAAS,QAAqB,CAAC,SAAsB,MAAiB;AAAA,EAC3E,OAAO,QAAQ,SAAS,IAAI;AAAA;AAc9B,eAAsB,aAA0B,CAC9C,SACA,MACY;AAAA,EACZ,OAAQ,MAAM,QAAQ,KAAK,MAAM,EAAE,SAAS,KAAK,CAAC;AAAA;AAY7C,SAAS,YAAyB,CAAC,SAAsB,MAAiB;AAAA,EAC/E,MAAM,aAAa,QAAQ,SAAS,IAAI;AAAA,EACxC,OAAO,KAAK,MAAM,UAAU;AAAA;AAc9B,eAAsB,iBAA8B,CAClD,SACA,MACY;AAAA,EACZ,MAAM,aAAc,MAAM,QAAQ,KAAK,MAAM,EAAE,SAAS,KAAK,CAAC;AAAA,EAC9D,OAAO,KAAK,MAAM,UAAU;AAAA;AAa9B,eAAsB,aAAa,CACjC,SACA,QACe;AAAA,EACf,MAAM,SAAS,QAAQ;AAAA,EAEvB,YAAY,KAAK,UAAU,OAAO,QAAQ,MAAM,GAAG;AAAA,IACjD,IAAI,OAAO,UAAU,YAAY;AAAA,MAC7B,OAAO,QAAQ,KAAK,IAAI,2BAAU,SAAS,KAAwC,CAAC;AAAA,IACxF,EAAO,SAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAAA,MAEtD,QAAQ,SAAS,cAAc,SAAS,KAAK,UAAU,KAAK,GAAG;AAAA,IACjE,EAAO;AAAA,MAEL,OAAO,QAAQ,KAAK,KAAK;AAAA;AAAA,EAE7B;AAAA;",
|
|
8
|
+
"debugId": "927FD9D4B2821C8964756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -1,20 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
6
|
+
var __toCommonJS = (from) => {
|
|
7
|
+
var entry = __moduleCache.get(from), desc;
|
|
8
|
+
if (entry)
|
|
9
|
+
return entry;
|
|
10
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
12
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
13
|
+
get: () => from[key],
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
}));
|
|
16
|
+
__moduleCache.set(from, entry);
|
|
17
|
+
return entry;
|
|
18
|
+
};
|
|
19
|
+
var __export = (target, all) => {
|
|
20
|
+
for (var name in all)
|
|
21
|
+
__defProp(target, name, {
|
|
22
|
+
get: all[name],
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
set: (newValue) => all[name] = () => newValue
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// packages/test-utils/src/mock-fs.ts
|
|
30
|
+
var exports_mock_fs = {};
|
|
31
|
+
__export(exports_mock_fs, {
|
|
32
|
+
MockFileSystem: () => MockFileSystem
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(exports_mock_fs);
|
|
35
|
+
|
|
36
|
+
class MockFileSystem {
|
|
37
|
+
files = new Map;
|
|
38
|
+
directories = new Set(["/"]);
|
|
39
|
+
async getFileHandle(path, options) {
|
|
18
40
|
const exists = this.files.has(path);
|
|
19
41
|
if (!exists && !options?.create) {
|
|
20
42
|
throw new Error("[NotFoundError]File not found: " + path);
|
|
@@ -26,15 +48,11 @@ export class MockFileSystem implements FileSystemHandler {
|
|
|
26
48
|
this.files.set(path, {
|
|
27
49
|
data: new Uint8Array(0),
|
|
28
50
|
lastModified: Date.now(),
|
|
29
|
-
type: ""
|
|
51
|
+
type: ""
|
|
30
52
|
});
|
|
31
53
|
}
|
|
32
54
|
}
|
|
33
|
-
|
|
34
|
-
async getDirectoryHandle(
|
|
35
|
-
path: string,
|
|
36
|
-
options?: { create?: boolean }
|
|
37
|
-
): Promise<void> {
|
|
55
|
+
async getDirectoryHandle(path, options) {
|
|
38
56
|
const exists = this.directories.has(path);
|
|
39
57
|
if (!exists && !options?.create) {
|
|
40
58
|
throw new Error("[NotFoundError]Directory not found: " + path);
|
|
@@ -46,26 +64,17 @@ export class MockFileSystem implements FileSystemHandler {
|
|
|
46
64
|
this.directories.add(path);
|
|
47
65
|
}
|
|
48
66
|
}
|
|
49
|
-
|
|
50
|
-
async removeEntry(
|
|
51
|
-
path: string,
|
|
52
|
-
options?: { recursive?: boolean }
|
|
53
|
-
): Promise<void> {
|
|
67
|
+
async removeEntry(path, options) {
|
|
54
68
|
if (this.files.has(path)) {
|
|
55
69
|
this.files.delete(path);
|
|
56
70
|
return;
|
|
57
71
|
}
|
|
58
|
-
|
|
59
72
|
if (this.directories.has(path)) {
|
|
60
73
|
const prefix = path === "/" ? "/" : path + "/";
|
|
61
|
-
const hasChildren =
|
|
62
|
-
[...this.files.keys()].some((p) => p.startsWith(prefix)) ||
|
|
63
|
-
[...this.directories].some((p) => p !== path && p.startsWith(prefix));
|
|
64
|
-
|
|
74
|
+
const hasChildren = [...this.files.keys()].some((p) => p.startsWith(prefix)) || [...this.directories].some((p) => p !== path && p.startsWith(prefix));
|
|
65
75
|
if (hasChildren && !options?.recursive) {
|
|
66
76
|
throw new Error("[InvalidModificationError]Directory not empty: " + path);
|
|
67
77
|
}
|
|
68
|
-
|
|
69
78
|
for (const p of this.files.keys()) {
|
|
70
79
|
if (p.startsWith(prefix)) {
|
|
71
80
|
this.files.delete(p);
|
|
@@ -78,21 +87,15 @@ export class MockFileSystem implements FileSystemHandler {
|
|
|
78
87
|
}
|
|
79
88
|
return;
|
|
80
89
|
}
|
|
81
|
-
|
|
82
90
|
throw new Error("[NotFoundError]Entry not found: " + path);
|
|
83
91
|
}
|
|
84
|
-
|
|
85
|
-
async readDirectory(
|
|
86
|
-
path: string
|
|
87
|
-
): Promise<Array<{ name: string; kind: "file" | "directory" }>> {
|
|
92
|
+
async readDirectory(path) {
|
|
88
93
|
if (!this.directories.has(path)) {
|
|
89
94
|
throw new Error("[NotFoundError]Directory not found: " + path);
|
|
90
95
|
}
|
|
91
|
-
|
|
92
96
|
const prefix = path === "/" ? "/" : path + "/";
|
|
93
|
-
const entries
|
|
94
|
-
const seen = new Set
|
|
95
|
-
|
|
97
|
+
const entries = [];
|
|
98
|
+
const seen = new Set;
|
|
96
99
|
for (const p of this.files.keys()) {
|
|
97
100
|
if (p.startsWith(prefix)) {
|
|
98
101
|
const rest = p.slice(prefix.length);
|
|
@@ -103,7 +106,6 @@ export class MockFileSystem implements FileSystemHandler {
|
|
|
103
106
|
}
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
|
-
|
|
107
109
|
for (const p of this.directories) {
|
|
108
110
|
if (p !== path && p.startsWith(prefix)) {
|
|
109
111
|
const rest = p.slice(prefix.length);
|
|
@@ -114,13 +116,9 @@ export class MockFileSystem implements FileSystemHandler {
|
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
|
-
|
|
118
119
|
return entries;
|
|
119
120
|
}
|
|
120
|
-
|
|
121
|
-
async readFile(
|
|
122
|
-
path: string
|
|
123
|
-
): Promise<{ data: Uint8Array; size: number; lastModified: number; type: string }> {
|
|
121
|
+
async readFile(path) {
|
|
124
122
|
const file = this.files.get(path);
|
|
125
123
|
if (!file) {
|
|
126
124
|
throw new Error("[NotFoundError]File not found: " + path);
|
|
@@ -129,20 +127,14 @@ export class MockFileSystem implements FileSystemHandler {
|
|
|
129
127
|
data: file.data,
|
|
130
128
|
size: file.data.length,
|
|
131
129
|
lastModified: file.lastModified,
|
|
132
|
-
type: file.type
|
|
130
|
+
type: file.type
|
|
133
131
|
};
|
|
134
132
|
}
|
|
135
|
-
|
|
136
|
-
async writeFile(
|
|
137
|
-
path: string,
|
|
138
|
-
data: Uint8Array,
|
|
139
|
-
position?: number
|
|
140
|
-
): Promise<void> {
|
|
133
|
+
async writeFile(path, data, position) {
|
|
141
134
|
const existing = this.files.get(path);
|
|
142
135
|
if (!existing) {
|
|
143
136
|
throw new Error("[NotFoundError]File not found: " + path);
|
|
144
137
|
}
|
|
145
|
-
|
|
146
138
|
if (position !== undefined && position > 0) {
|
|
147
139
|
const newSize = Math.max(existing.data.length, position + data.length);
|
|
148
140
|
const newData = new Uint8Array(newSize);
|
|
@@ -160,8 +152,7 @@ export class MockFileSystem implements FileSystemHandler {
|
|
|
160
152
|
}
|
|
161
153
|
existing.lastModified = Date.now();
|
|
162
154
|
}
|
|
163
|
-
|
|
164
|
-
async truncateFile(path: string, size: number): Promise<void> {
|
|
155
|
+
async truncateFile(path, size) {
|
|
165
156
|
const file = this.files.get(path);
|
|
166
157
|
if (!file) {
|
|
167
158
|
throw new Error("[NotFoundError]File not found: " + path);
|
|
@@ -175,10 +166,7 @@ export class MockFileSystem implements FileSystemHandler {
|
|
|
175
166
|
}
|
|
176
167
|
file.lastModified = Date.now();
|
|
177
168
|
}
|
|
178
|
-
|
|
179
|
-
async getFileMetadata(
|
|
180
|
-
path: string
|
|
181
|
-
): Promise<{ size: number; lastModified: number; type: string }> {
|
|
169
|
+
async getFileMetadata(path) {
|
|
182
170
|
const file = this.files.get(path);
|
|
183
171
|
if (!file) {
|
|
184
172
|
throw new Error("[NotFoundError]File not found: " + path);
|
|
@@ -186,56 +174,32 @@ export class MockFileSystem implements FileSystemHandler {
|
|
|
186
174
|
return {
|
|
187
175
|
size: file.data.length,
|
|
188
176
|
lastModified: file.lastModified,
|
|
189
|
-
type: file.type
|
|
177
|
+
type: file.type
|
|
190
178
|
};
|
|
191
179
|
}
|
|
192
|
-
|
|
193
|
-
// Test helper methods
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Reset the mock file system to its initial state (empty, with only root directory)
|
|
197
|
-
*/
|
|
198
|
-
reset(): void {
|
|
180
|
+
reset() {
|
|
199
181
|
this.files.clear();
|
|
200
182
|
this.directories.clear();
|
|
201
183
|
this.directories.add("/");
|
|
202
184
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
* Convenience method to set a file with string or binary content
|
|
206
|
-
*/
|
|
207
|
-
setFile(path: string, content: string | Uint8Array, type?: string): void {
|
|
208
|
-
const data =
|
|
209
|
-
typeof content === "string"
|
|
210
|
-
? new TextEncoder().encode(content)
|
|
211
|
-
: content;
|
|
185
|
+
setFile(path, content, type) {
|
|
186
|
+
const data = typeof content === "string" ? new TextEncoder().encode(content) : content;
|
|
212
187
|
this.files.set(path, {
|
|
213
188
|
data,
|
|
214
189
|
lastModified: Date.now(),
|
|
215
|
-
type: type ?? ""
|
|
190
|
+
type: type ?? ""
|
|
216
191
|
});
|
|
217
192
|
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Get file content as Uint8Array, or undefined if not found
|
|
221
|
-
*/
|
|
222
|
-
getFile(path: string): Uint8Array | undefined {
|
|
193
|
+
getFile(path) {
|
|
223
194
|
return this.files.get(path)?.data;
|
|
224
195
|
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Get file content as string, or undefined if not found
|
|
228
|
-
*/
|
|
229
|
-
getFileAsString(path: string): string | undefined {
|
|
196
|
+
getFileAsString(path) {
|
|
230
197
|
const data = this.getFile(path);
|
|
231
|
-
if (!data)
|
|
198
|
+
if (!data)
|
|
199
|
+
return;
|
|
232
200
|
return new TextDecoder().decode(data);
|
|
233
201
|
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Create a directory (and any necessary parent directories)
|
|
237
|
-
*/
|
|
238
|
-
createDirectory(path: string): void {
|
|
202
|
+
createDirectory(path) {
|
|
239
203
|
const parts = path.split("/").filter(Boolean);
|
|
240
204
|
let current = "";
|
|
241
205
|
for (const part of parts) {
|
|
@@ -244,3 +208,5 @@ export class MockFileSystem implements FileSystemHandler {
|
|
|
244
208
|
}
|
|
245
209
|
}
|
|
246
210
|
}
|
|
211
|
+
|
|
212
|
+
//# debugId=0DD8C7C4EEEFD3AA64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/mock-fs.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { FileSystemHandler } from \"@ricsam/isolate-fs\";\n\n/**\n * In-memory file system implementation for testing.\n * Implements the FileSystemHandler interface from @ricsam/isolate-fs.\n */\nexport class MockFileSystem implements FileSystemHandler {\n files = new Map<\n string,\n { data: Uint8Array; lastModified: number; type: string }\n >();\n directories = new Set<string>([\"/\"]);\n\n async getFileHandle(\n path: string,\n options?: { create?: boolean }\n ): Promise<void> {\n const exists = this.files.has(path);\n if (!exists && !options?.create) {\n throw new Error(\"[NotFoundError]File not found: \" + path);\n }\n if (this.directories.has(path)) {\n throw new Error(\"[TypeMismatchError]Path is a directory: \" + path);\n }\n if (!exists && options?.create) {\n this.files.set(path, {\n data: new Uint8Array(0),\n lastModified: Date.now(),\n type: \"\",\n });\n }\n }\n\n async getDirectoryHandle(\n path: string,\n options?: { create?: boolean }\n ): Promise<void> {\n const exists = this.directories.has(path);\n if (!exists && !options?.create) {\n throw new Error(\"[NotFoundError]Directory not found: \" + path);\n }\n if (this.files.has(path)) {\n throw new Error(\"[TypeMismatchError]Path is a file: \" + path);\n }\n if (!exists && options?.create) {\n this.directories.add(path);\n }\n }\n\n async removeEntry(\n path: string,\n options?: { recursive?: boolean }\n ): Promise<void> {\n if (this.files.has(path)) {\n this.files.delete(path);\n return;\n }\n\n if (this.directories.has(path)) {\n const prefix = path === \"/\" ? \"/\" : path + \"/\";\n const hasChildren =\n [...this.files.keys()].some((p) => p.startsWith(prefix)) ||\n [...this.directories].some((p) => p !== path && p.startsWith(prefix));\n\n if (hasChildren && !options?.recursive) {\n throw new Error(\"[InvalidModificationError]Directory not empty: \" + path);\n }\n\n for (const p of this.files.keys()) {\n if (p.startsWith(prefix)) {\n this.files.delete(p);\n }\n }\n for (const p of this.directories) {\n if (p.startsWith(prefix) || p === path) {\n this.directories.delete(p);\n }\n }\n return;\n }\n\n throw new Error(\"[NotFoundError]Entry not found: \" + path);\n }\n\n async readDirectory(\n path: string\n ): Promise<Array<{ name: string; kind: \"file\" | \"directory\" }>> {\n if (!this.directories.has(path)) {\n throw new Error(\"[NotFoundError]Directory not found: \" + path);\n }\n\n const prefix = path === \"/\" ? \"/\" : path + \"/\";\n const entries: Array<{ name: string; kind: \"file\" | \"directory\" }> = [];\n const seen = new Set<string>();\n\n for (const p of this.files.keys()) {\n if (p.startsWith(prefix)) {\n const rest = p.slice(prefix.length);\n const name = rest.split(\"/\")[0];\n if (name && !rest.includes(\"/\") && !seen.has(name)) {\n seen.add(name);\n entries.push({ name, kind: \"file\" });\n }\n }\n }\n\n for (const p of this.directories) {\n if (p !== path && p.startsWith(prefix)) {\n const rest = p.slice(prefix.length);\n const name = rest.split(\"/\")[0];\n if (name && !rest.includes(\"/\") && !seen.has(name)) {\n seen.add(name);\n entries.push({ name, kind: \"directory\" });\n }\n }\n }\n\n return entries;\n }\n\n async readFile(\n path: string\n ): Promise<{ data: Uint8Array; size: number; lastModified: number; type: string }> {\n const file = this.files.get(path);\n if (!file) {\n throw new Error(\"[NotFoundError]File not found: \" + path);\n }\n return {\n data: file.data,\n size: file.data.length,\n lastModified: file.lastModified,\n type: file.type,\n };\n }\n\n async writeFile(\n path: string,\n data: Uint8Array,\n position?: number\n ): Promise<void> {\n const existing = this.files.get(path);\n if (!existing) {\n throw new Error(\"[NotFoundError]File not found: \" + path);\n }\n\n if (position !== undefined && position > 0) {\n const newSize = Math.max(existing.data.length, position + data.length);\n const newData = new Uint8Array(newSize);\n newData.set(existing.data);\n newData.set(data, position);\n existing.data = newData;\n } else if (position === 0) {\n const newSize = Math.max(existing.data.length, data.length);\n const newData = new Uint8Array(newSize);\n newData.set(existing.data);\n newData.set(data, 0);\n existing.data = newData;\n } else {\n existing.data = data;\n }\n existing.lastModified = Date.now();\n }\n\n async truncateFile(path: string, size: number): Promise<void> {\n const file = this.files.get(path);\n if (!file) {\n throw new Error(\"[NotFoundError]File not found: \" + path);\n }\n if (size < file.data.length) {\n file.data = file.data.slice(0, size);\n } else if (size > file.data.length) {\n const newData = new Uint8Array(size);\n newData.set(file.data);\n file.data = newData;\n }\n file.lastModified = Date.now();\n }\n\n async getFileMetadata(\n path: string\n ): Promise<{ size: number; lastModified: number; type: string }> {\n const file = this.files.get(path);\n if (!file) {\n throw new Error(\"[NotFoundError]File not found: \" + path);\n }\n return {\n size: file.data.length,\n lastModified: file.lastModified,\n type: file.type,\n };\n }\n\n // Test helper methods\n\n /**\n * Reset the mock file system to its initial state (empty, with only root directory)\n */\n reset(): void {\n this.files.clear();\n this.directories.clear();\n this.directories.add(\"/\");\n }\n\n /**\n * Convenience method to set a file with string or binary content\n */\n setFile(path: string, content: string | Uint8Array, type?: string): void {\n const data =\n typeof content === \"string\"\n ? new TextEncoder().encode(content)\n : content;\n this.files.set(path, {\n data,\n lastModified: Date.now(),\n type: type ?? \"\",\n });\n }\n\n /**\n * Get file content as Uint8Array, or undefined if not found\n */\n getFile(path: string): Uint8Array | undefined {\n return this.files.get(path)?.data;\n }\n\n /**\n * Get file content as string, or undefined if not found\n */\n getFileAsString(path: string): string | undefined {\n const data = this.getFile(path);\n if (!data) return undefined;\n return new TextDecoder().decode(data);\n }\n\n /**\n * Create a directory (and any necessary parent directories)\n */\n createDirectory(path: string): void {\n const parts = path.split(\"/\").filter(Boolean);\n let current = \"\";\n for (const part of parts) {\n current += \"/\" + part;\n this.directories.add(current);\n }\n }\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "0DD8C7C4EEEFD3AA64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|