@ricsam/isolate-runtime 0.0.1 → 0.1.2
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/README.md +49 -43
- package/dist/cjs/index.cjs +115 -0
- package/dist/cjs/index.cjs.map +10 -0
- package/dist/cjs/package.json +5 -0
- package/dist/mjs/index.mjs +71 -0
- package/dist/mjs/index.mjs.map +10 -0
- package/dist/mjs/package.json +5 -0
- package/dist/types/index.d.ts +65 -0
- package/package.json +57 -6
package/README.md
CHANGED
|
@@ -1,45 +1,51 @@
|
|
|
1
1
|
# @ricsam/isolate-runtime
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
3
|
+
Umbrella package that combines all APIs.
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import { createRuntime } from "@ricsam/isolate-runtime";
|
|
7
|
+
|
|
8
|
+
const runtime = await createRuntime({
|
|
9
|
+
// Memory limit in MB
|
|
10
|
+
memoryLimit: 128,
|
|
11
|
+
// Console API
|
|
12
|
+
console: {
|
|
13
|
+
onLog: (level, ...args) => console.log(`[${level}]`, ...args),
|
|
14
|
+
},
|
|
15
|
+
// Fetch API
|
|
16
|
+
fetch: {
|
|
17
|
+
onFetch: async (req) => fetch(req),
|
|
18
|
+
},
|
|
19
|
+
// File System API (optional)
|
|
20
|
+
fs: {
|
|
21
|
+
getDirectory: async (path) => createNodeFileSystemHandler(`./data${path}`),
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// The runtime includes:
|
|
26
|
+
// - runtime.isolate: The V8 isolate
|
|
27
|
+
// - runtime.context: The execution context
|
|
28
|
+
// - runtime.tick(): Process pending timers
|
|
29
|
+
// - runtime.dispose(): Clean up all resources
|
|
30
|
+
|
|
31
|
+
// Run code
|
|
32
|
+
await runtime.context.eval(`
|
|
33
|
+
console.log("Hello from sandbox!");
|
|
34
|
+
`, { promise: true });
|
|
35
|
+
|
|
36
|
+
// Process timers
|
|
37
|
+
await runtime.tick(100);
|
|
38
|
+
|
|
39
|
+
// Cleanup
|
|
40
|
+
runtime.dispose();
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**What's Included:**
|
|
44
|
+
- Core (Blob, File, streams, URL, TextEncoder/Decoder)
|
|
45
|
+
- Console
|
|
46
|
+
- Encoding (atob/btoa)
|
|
47
|
+
- Timers (setTimeout, setInterval)
|
|
48
|
+
- Path utilities
|
|
49
|
+
- Crypto (randomUUID, getRandomValues, subtle)
|
|
50
|
+
- Fetch API
|
|
51
|
+
- File System (if handler provided)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// @bun @bun-cjs
|
|
2
|
+
(function(exports, require, module, __filename, __dirname) {var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
9
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
10
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
11
|
+
for (let key of __getOwnPropNames(mod))
|
|
12
|
+
if (!__hasOwnProp.call(to, key))
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: () => mod[key],
|
|
15
|
+
enumerable: true
|
|
16
|
+
});
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
20
|
+
var __toCommonJS = (from) => {
|
|
21
|
+
var entry = __moduleCache.get(from), desc;
|
|
22
|
+
if (entry)
|
|
23
|
+
return entry;
|
|
24
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
25
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
26
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
27
|
+
get: () => from[key],
|
|
28
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
29
|
+
}));
|
|
30
|
+
__moduleCache.set(from, entry);
|
|
31
|
+
return entry;
|
|
32
|
+
};
|
|
33
|
+
var __export = (target, all) => {
|
|
34
|
+
for (var name in all)
|
|
35
|
+
__defProp(target, name, {
|
|
36
|
+
get: all[name],
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
set: (newValue) => all[name] = () => newValue
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// packages/runtime/src/index.ts
|
|
44
|
+
var exports_src = {};
|
|
45
|
+
__export(exports_src, {
|
|
46
|
+
setupTimers: () => import_isolate_timers2.setupTimers,
|
|
47
|
+
setupPath: () => import_isolate_path2.setupPath,
|
|
48
|
+
setupFs: () => import_isolate_fs2.setupFs,
|
|
49
|
+
setupFetch: () => import_isolate_fetch2.setupFetch,
|
|
50
|
+
setupEncoding: () => import_isolate_encoding2.setupEncoding,
|
|
51
|
+
setupCrypto: () => import_isolate_crypto2.setupCrypto,
|
|
52
|
+
setupCore: () => import_isolate_core2.setupCore,
|
|
53
|
+
setupConsole: () => import_isolate_console2.setupConsole,
|
|
54
|
+
createRuntime: () => createRuntime,
|
|
55
|
+
createNodeFileSystemHandler: () => import_isolate_fs2.createNodeFileSystemHandler
|
|
56
|
+
});
|
|
57
|
+
module.exports = __toCommonJS(exports_src);
|
|
58
|
+
var import_isolated_vm = __toESM(require("isolated-vm"));
|
|
59
|
+
var import_isolate_core = require("@ricsam/isolate-core");
|
|
60
|
+
var import_isolate_console = require("@ricsam/isolate-console");
|
|
61
|
+
var import_isolate_encoding = require("@ricsam/isolate-encoding");
|
|
62
|
+
var import_isolate_timers = require("@ricsam/isolate-timers");
|
|
63
|
+
var import_isolate_path = require("@ricsam/isolate-path");
|
|
64
|
+
var import_isolate_crypto = require("@ricsam/isolate-crypto");
|
|
65
|
+
var import_isolate_fetch = require("@ricsam/isolate-fetch");
|
|
66
|
+
var import_isolate_fs = require("@ricsam/isolate-fs");
|
|
67
|
+
var import_isolate_core2 = require("@ricsam/isolate-core");
|
|
68
|
+
var import_isolate_console2 = require("@ricsam/isolate-console");
|
|
69
|
+
var import_isolate_crypto2 = require("@ricsam/isolate-crypto");
|
|
70
|
+
var import_isolate_encoding2 = require("@ricsam/isolate-encoding");
|
|
71
|
+
var import_isolate_fetch2 = require("@ricsam/isolate-fetch");
|
|
72
|
+
var import_isolate_fs2 = require("@ricsam/isolate-fs");
|
|
73
|
+
var import_isolate_path2 = require("@ricsam/isolate-path");
|
|
74
|
+
var import_isolate_timers2 = require("@ricsam/isolate-timers");
|
|
75
|
+
async function createRuntime(options) {
|
|
76
|
+
const opts = options ?? {};
|
|
77
|
+
const isolate = new import_isolated_vm.default.Isolate({
|
|
78
|
+
memoryLimit: opts.memoryLimit
|
|
79
|
+
});
|
|
80
|
+
const context = await isolate.createContext();
|
|
81
|
+
const handles = {};
|
|
82
|
+
handles.core = await import_isolate_core.setupCore(context);
|
|
83
|
+
handles.console = await import_isolate_console.setupConsole(context, opts.console);
|
|
84
|
+
handles.encoding = await import_isolate_encoding.setupEncoding(context);
|
|
85
|
+
handles.timers = await import_isolate_timers.setupTimers(context);
|
|
86
|
+
handles.path = await import_isolate_path.setupPath(context);
|
|
87
|
+
handles.crypto = await import_isolate_crypto.setupCrypto(context);
|
|
88
|
+
handles.fetch = await import_isolate_fetch.setupFetch(context, opts.fetch);
|
|
89
|
+
if (opts.fs) {
|
|
90
|
+
handles.fs = await import_isolate_fs.setupFs(context, opts.fs);
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
isolate,
|
|
94
|
+
context,
|
|
95
|
+
fetch: handles.fetch,
|
|
96
|
+
async tick(ms) {
|
|
97
|
+
await handles.timers.tick(ms);
|
|
98
|
+
},
|
|
99
|
+
dispose() {
|
|
100
|
+
handles.fs?.dispose();
|
|
101
|
+
handles.fetch?.dispose();
|
|
102
|
+
handles.crypto?.dispose();
|
|
103
|
+
handles.path?.dispose();
|
|
104
|
+
handles.timers?.dispose();
|
|
105
|
+
handles.encoding?.dispose();
|
|
106
|
+
handles.console?.dispose();
|
|
107
|
+
handles.core?.dispose();
|
|
108
|
+
context.release();
|
|
109
|
+
isolate.dispose();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
//# debugId=4A635399139F1BA664756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import ivm from \"isolated-vm\";\nimport { setupCore } from \"@ricsam/isolate-core\";\nimport { setupConsole } from \"@ricsam/isolate-console\";\nimport { setupEncoding } from \"@ricsam/isolate-encoding\";\nimport { setupTimers } from \"@ricsam/isolate-timers\";\nimport { setupPath } from \"@ricsam/isolate-path\";\nimport { setupCrypto } from \"@ricsam/isolate-crypto\";\nimport { setupFetch } from \"@ricsam/isolate-fetch\";\nimport { setupFs } from \"@ricsam/isolate-fs\";\n\nimport type { ConsoleOptions, ConsoleHandle } from \"@ricsam/isolate-console\";\nimport type { FetchOptions, FetchHandle } from \"@ricsam/isolate-fetch\";\nimport type { FsOptions, FsHandle } from \"@ricsam/isolate-fs\";\nimport type { CoreHandle } from \"@ricsam/isolate-core\";\nimport type { EncodingHandle } from \"@ricsam/isolate-encoding\";\nimport type { TimersHandle } from \"@ricsam/isolate-timers\";\nimport type { PathHandle } from \"@ricsam/isolate-path\";\nimport type { CryptoHandle } from \"@ricsam/isolate-crypto\";\n\nexport interface RuntimeOptions {\n /** Isolate memory limit in MB */\n memoryLimit?: number;\n /** Console options */\n console?: ConsoleOptions;\n /** Fetch options */\n fetch?: FetchOptions;\n /** File system options (optional - fs only set up if provided) */\n fs?: FsOptions;\n}\n\nexport interface RuntimeHandle {\n /** The isolate instance */\n readonly isolate: ivm.Isolate;\n /** The context instance */\n readonly context: ivm.Context;\n /** The fetch handle for serve() and WebSocket dispatching */\n readonly fetch: FetchHandle;\n /** Process pending timers */\n tick(ms?: number): Promise<void>;\n /** Dispose all resources */\n dispose(): void;\n}\n\n/**\n * Create a fully configured isolated-vm runtime\n *\n * Sets up all WHATWG APIs: fetch, fs, console, crypto, encoding, timers\n *\n * @example\n * const runtime = await createRuntime({\n * console: {\n * onLog: (level, ...args) => console.log(`[${level}]`, ...args)\n * },\n * fetch: {\n * onFetch: async (request) => fetch(request)\n * }\n * });\n *\n * await runtime.context.eval(`\n * console.log(\"Hello from sandbox!\");\n * const response = await fetch(\"https://example.com\");\n * `);\n *\n * runtime.dispose();\n */\nexport async function createRuntime(\n options?: RuntimeOptions\n): Promise<RuntimeHandle> {\n const opts = options ?? {};\n\n // Create isolate with optional memory limit\n const isolate = new ivm.Isolate({\n memoryLimit: opts.memoryLimit,\n });\n const context = await isolate.createContext();\n\n // Store all handles for disposal\n const handles: {\n core?: CoreHandle;\n console?: ConsoleHandle;\n encoding?: EncodingHandle;\n timers?: TimersHandle;\n path?: PathHandle;\n crypto?: CryptoHandle;\n fetch?: FetchHandle;\n fs?: FsHandle;\n } = {};\n\n // Setup all APIs in order\n // Core must be first as it provides Blob, File, streams, URL, etc.\n handles.core = await setupCore(context);\n\n // Console\n handles.console = await setupConsole(context, opts.console);\n\n // Encoding (btoa/atob)\n handles.encoding = await setupEncoding(context);\n\n // Timers (setTimeout, setInterval)\n handles.timers = await setupTimers(context);\n\n // Path module\n handles.path = await setupPath(context);\n\n // Crypto (randomUUID, getRandomValues)\n handles.crypto = await setupCrypto(context);\n\n // Fetch API\n handles.fetch = await setupFetch(context, opts.fetch);\n\n // File system (only if handler provided)\n if (opts.fs) {\n handles.fs = await setupFs(context, opts.fs);\n }\n\n return {\n isolate,\n context,\n fetch: handles.fetch!,\n async tick(ms?: number) {\n await handles.timers!.tick(ms);\n },\n dispose() {\n // Dispose all handles\n handles.fs?.dispose();\n handles.fetch?.dispose();\n handles.crypto?.dispose();\n handles.path?.dispose();\n handles.timers?.dispose();\n handles.encoding?.dispose();\n handles.console?.dispose();\n handles.core?.dispose();\n\n // Release context and dispose isolate\n context.release();\n isolate.dispose();\n },\n };\n}\n\n// Re-export all package types and functions\nexport { setupCore } from \"@ricsam/isolate-core\";\nexport type { CoreHandle, SetupCoreOptions } from \"@ricsam/isolate-core\";\n\nexport { setupConsole } from \"@ricsam/isolate-console\";\nexport type { ConsoleHandle, ConsoleOptions } from \"@ricsam/isolate-console\";\n\nexport { setupCrypto } from \"@ricsam/isolate-crypto\";\nexport type { CryptoHandle } from \"@ricsam/isolate-crypto\";\n\nexport { setupEncoding } from \"@ricsam/isolate-encoding\";\nexport type { EncodingHandle } from \"@ricsam/isolate-encoding\";\n\nexport { setupFetch } from \"@ricsam/isolate-fetch\";\nexport type { FetchHandle, FetchOptions, WebSocketCommand, UpgradeRequest } from \"@ricsam/isolate-fetch\";\n\nexport { setupFs, createNodeFileSystemHandler } from \"@ricsam/isolate-fs\";\nexport type { FsHandle, FsOptions, FileSystemHandler, NodeFileSystemHandlerOptions } from \"@ricsam/isolate-fs\";\n\nexport { setupPath } from \"@ricsam/isolate-path\";\nexport type { PathHandle } from \"@ricsam/isolate-path\";\n\nexport { setupTimers } from \"@ricsam/isolate-timers\";\nexport type { TimersHandle } from \"@ricsam/isolate-timers\";\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAgB,IAAhB;AAC0B,IAA1B;AAC6B,IAA7B;AAC8B,IAA9B;AAC4B,IAA5B;AAC0B,IAA1B;AAC4B,IAA5B;AAC2B,IAA3B;AACwB,IAAxB;AAqI0B,IAA1B;AAG6B,IAA7B;AAG4B,IAA5B;AAG8B,IAA9B;AAG2B,IAA3B;AAGqD,IAArD;AAG0B,IAA1B;AAG4B,IAA5B;AAjGA,eAAsB,aAAa,CACjC,SACwB;AAAA,EACxB,MAAM,OAAO,WAAW,CAAC;AAAA,EAGzB,MAAM,UAAU,IAAI,2BAAI,QAAQ;AAAA,IAC9B,aAAa,KAAK;AAAA,EACpB,CAAC;AAAA,EACD,MAAM,UAAU,MAAM,QAAQ,cAAc;AAAA,EAG5C,MAAM,UASF,CAAC;AAAA,EAIL,QAAQ,OAAO,MAAM,8BAAU,OAAO;AAAA,EAGtC,QAAQ,UAAU,MAAM,oCAAa,SAAS,KAAK,OAAO;AAAA,EAG1D,QAAQ,WAAW,MAAM,sCAAc,OAAO;AAAA,EAG9C,QAAQ,SAAS,MAAM,kCAAY,OAAO;AAAA,EAG1C,QAAQ,OAAO,MAAM,8BAAU,OAAO;AAAA,EAGtC,QAAQ,SAAS,MAAM,kCAAY,OAAO;AAAA,EAG1C,QAAQ,QAAQ,MAAM,gCAAW,SAAS,KAAK,KAAK;AAAA,EAGpD,IAAI,KAAK,IAAI;AAAA,IACX,QAAQ,KAAK,MAAM,0BAAQ,SAAS,KAAK,EAAE;AAAA,EAC7C;AAAA,EAEA,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,QAAQ;AAAA,SACT,KAAI,CAAC,IAAa;AAAA,MACtB,MAAM,QAAQ,OAAQ,KAAK,EAAE;AAAA;AAAA,IAE/B,OAAO,GAAG;AAAA,MAER,QAAQ,IAAI,QAAQ;AAAA,MACpB,QAAQ,OAAO,QAAQ;AAAA,MACvB,QAAQ,QAAQ,QAAQ;AAAA,MACxB,QAAQ,MAAM,QAAQ;AAAA,MACtB,QAAQ,QAAQ,QAAQ;AAAA,MACxB,QAAQ,UAAU,QAAQ;AAAA,MAC1B,QAAQ,SAAS,QAAQ;AAAA,MACzB,QAAQ,MAAM,QAAQ;AAAA,MAGtB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA;AAAA,EAEpB;AAAA;",
|
|
8
|
+
"debugId": "4A635399139F1BA664756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/runtime/src/index.ts
|
|
3
|
+
import ivm from "isolated-vm";
|
|
4
|
+
import { setupCore } from "@ricsam/isolate-core";
|
|
5
|
+
import { setupConsole } from "@ricsam/isolate-console";
|
|
6
|
+
import { setupEncoding } from "@ricsam/isolate-encoding";
|
|
7
|
+
import { setupTimers } from "@ricsam/isolate-timers";
|
|
8
|
+
import { setupPath } from "@ricsam/isolate-path";
|
|
9
|
+
import { setupCrypto } from "@ricsam/isolate-crypto";
|
|
10
|
+
import { setupFetch } from "@ricsam/isolate-fetch";
|
|
11
|
+
import { setupFs } from "@ricsam/isolate-fs";
|
|
12
|
+
import { setupCore as setupCore2 } from "@ricsam/isolate-core";
|
|
13
|
+
import { setupConsole as setupConsole2 } from "@ricsam/isolate-console";
|
|
14
|
+
import { setupCrypto as setupCrypto2 } from "@ricsam/isolate-crypto";
|
|
15
|
+
import { setupEncoding as setupEncoding2 } from "@ricsam/isolate-encoding";
|
|
16
|
+
import { setupFetch as setupFetch2 } from "@ricsam/isolate-fetch";
|
|
17
|
+
import { setupFs as setupFs2, createNodeFileSystemHandler } from "@ricsam/isolate-fs";
|
|
18
|
+
import { setupPath as setupPath2 } from "@ricsam/isolate-path";
|
|
19
|
+
import { setupTimers as setupTimers2 } from "@ricsam/isolate-timers";
|
|
20
|
+
async function createRuntime(options) {
|
|
21
|
+
const opts = options ?? {};
|
|
22
|
+
const isolate = new ivm.Isolate({
|
|
23
|
+
memoryLimit: opts.memoryLimit
|
|
24
|
+
});
|
|
25
|
+
const context = await isolate.createContext();
|
|
26
|
+
const handles = {};
|
|
27
|
+
handles.core = await setupCore(context);
|
|
28
|
+
handles.console = await setupConsole(context, opts.console);
|
|
29
|
+
handles.encoding = await setupEncoding(context);
|
|
30
|
+
handles.timers = await setupTimers(context);
|
|
31
|
+
handles.path = await setupPath(context);
|
|
32
|
+
handles.crypto = await setupCrypto(context);
|
|
33
|
+
handles.fetch = await setupFetch(context, opts.fetch);
|
|
34
|
+
if (opts.fs) {
|
|
35
|
+
handles.fs = await setupFs(context, opts.fs);
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
isolate,
|
|
39
|
+
context,
|
|
40
|
+
fetch: handles.fetch,
|
|
41
|
+
async tick(ms) {
|
|
42
|
+
await handles.timers.tick(ms);
|
|
43
|
+
},
|
|
44
|
+
dispose() {
|
|
45
|
+
handles.fs?.dispose();
|
|
46
|
+
handles.fetch?.dispose();
|
|
47
|
+
handles.crypto?.dispose();
|
|
48
|
+
handles.path?.dispose();
|
|
49
|
+
handles.timers?.dispose();
|
|
50
|
+
handles.encoding?.dispose();
|
|
51
|
+
handles.console?.dispose();
|
|
52
|
+
handles.core?.dispose();
|
|
53
|
+
context.release();
|
|
54
|
+
isolate.dispose();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
setupTimers2 as setupTimers,
|
|
60
|
+
setupPath2 as setupPath,
|
|
61
|
+
setupFs2 as setupFs,
|
|
62
|
+
setupFetch2 as setupFetch,
|
|
63
|
+
setupEncoding2 as setupEncoding,
|
|
64
|
+
setupCrypto2 as setupCrypto,
|
|
65
|
+
setupCore2 as setupCore,
|
|
66
|
+
setupConsole2 as setupConsole,
|
|
67
|
+
createRuntime,
|
|
68
|
+
createNodeFileSystemHandler
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
//# debugId=FDBFD94222E0044364756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import ivm from \"isolated-vm\";\nimport { setupCore } from \"@ricsam/isolate-core\";\nimport { setupConsole } from \"@ricsam/isolate-console\";\nimport { setupEncoding } from \"@ricsam/isolate-encoding\";\nimport { setupTimers } from \"@ricsam/isolate-timers\";\nimport { setupPath } from \"@ricsam/isolate-path\";\nimport { setupCrypto } from \"@ricsam/isolate-crypto\";\nimport { setupFetch } from \"@ricsam/isolate-fetch\";\nimport { setupFs } from \"@ricsam/isolate-fs\";\n\nimport type { ConsoleOptions, ConsoleHandle } from \"@ricsam/isolate-console\";\nimport type { FetchOptions, FetchHandle } from \"@ricsam/isolate-fetch\";\nimport type { FsOptions, FsHandle } from \"@ricsam/isolate-fs\";\nimport type { CoreHandle } from \"@ricsam/isolate-core\";\nimport type { EncodingHandle } from \"@ricsam/isolate-encoding\";\nimport type { TimersHandle } from \"@ricsam/isolate-timers\";\nimport type { PathHandle } from \"@ricsam/isolate-path\";\nimport type { CryptoHandle } from \"@ricsam/isolate-crypto\";\n\nexport interface RuntimeOptions {\n /** Isolate memory limit in MB */\n memoryLimit?: number;\n /** Console options */\n console?: ConsoleOptions;\n /** Fetch options */\n fetch?: FetchOptions;\n /** File system options (optional - fs only set up if provided) */\n fs?: FsOptions;\n}\n\nexport interface RuntimeHandle {\n /** The isolate instance */\n readonly isolate: ivm.Isolate;\n /** The context instance */\n readonly context: ivm.Context;\n /** The fetch handle for serve() and WebSocket dispatching */\n readonly fetch: FetchHandle;\n /** Process pending timers */\n tick(ms?: number): Promise<void>;\n /** Dispose all resources */\n dispose(): void;\n}\n\n/**\n * Create a fully configured isolated-vm runtime\n *\n * Sets up all WHATWG APIs: fetch, fs, console, crypto, encoding, timers\n *\n * @example\n * const runtime = await createRuntime({\n * console: {\n * onLog: (level, ...args) => console.log(`[${level}]`, ...args)\n * },\n * fetch: {\n * onFetch: async (request) => fetch(request)\n * }\n * });\n *\n * await runtime.context.eval(`\n * console.log(\"Hello from sandbox!\");\n * const response = await fetch(\"https://example.com\");\n * `);\n *\n * runtime.dispose();\n */\nexport async function createRuntime(\n options?: RuntimeOptions\n): Promise<RuntimeHandle> {\n const opts = options ?? {};\n\n // Create isolate with optional memory limit\n const isolate = new ivm.Isolate({\n memoryLimit: opts.memoryLimit,\n });\n const context = await isolate.createContext();\n\n // Store all handles for disposal\n const handles: {\n core?: CoreHandle;\n console?: ConsoleHandle;\n encoding?: EncodingHandle;\n timers?: TimersHandle;\n path?: PathHandle;\n crypto?: CryptoHandle;\n fetch?: FetchHandle;\n fs?: FsHandle;\n } = {};\n\n // Setup all APIs in order\n // Core must be first as it provides Blob, File, streams, URL, etc.\n handles.core = await setupCore(context);\n\n // Console\n handles.console = await setupConsole(context, opts.console);\n\n // Encoding (btoa/atob)\n handles.encoding = await setupEncoding(context);\n\n // Timers (setTimeout, setInterval)\n handles.timers = await setupTimers(context);\n\n // Path module\n handles.path = await setupPath(context);\n\n // Crypto (randomUUID, getRandomValues)\n handles.crypto = await setupCrypto(context);\n\n // Fetch API\n handles.fetch = await setupFetch(context, opts.fetch);\n\n // File system (only if handler provided)\n if (opts.fs) {\n handles.fs = await setupFs(context, opts.fs);\n }\n\n return {\n isolate,\n context,\n fetch: handles.fetch!,\n async tick(ms?: number) {\n await handles.timers!.tick(ms);\n },\n dispose() {\n // Dispose all handles\n handles.fs?.dispose();\n handles.fetch?.dispose();\n handles.crypto?.dispose();\n handles.path?.dispose();\n handles.timers?.dispose();\n handles.encoding?.dispose();\n handles.console?.dispose();\n handles.core?.dispose();\n\n // Release context and dispose isolate\n context.release();\n isolate.dispose();\n },\n };\n}\n\n// Re-export all package types and functions\nexport { setupCore } from \"@ricsam/isolate-core\";\nexport type { CoreHandle, SetupCoreOptions } from \"@ricsam/isolate-core\";\n\nexport { setupConsole } from \"@ricsam/isolate-console\";\nexport type { ConsoleHandle, ConsoleOptions } from \"@ricsam/isolate-console\";\n\nexport { setupCrypto } from \"@ricsam/isolate-crypto\";\nexport type { CryptoHandle } from \"@ricsam/isolate-crypto\";\n\nexport { setupEncoding } from \"@ricsam/isolate-encoding\";\nexport type { EncodingHandle } from \"@ricsam/isolate-encoding\";\n\nexport { setupFetch } from \"@ricsam/isolate-fetch\";\nexport type { FetchHandle, FetchOptions, WebSocketCommand, UpgradeRequest } from \"@ricsam/isolate-fetch\";\n\nexport { setupFs, createNodeFileSystemHandler } from \"@ricsam/isolate-fs\";\nexport type { FsHandle, FsOptions, FileSystemHandler, NodeFileSystemHandlerOptions } from \"@ricsam/isolate-fs\";\n\nexport { setupPath } from \"@ricsam/isolate-path\";\nexport type { PathHandle } from \"@ricsam/isolate-path\";\n\nexport { setupTimers } from \"@ricsam/isolate-timers\";\nexport type { TimersHandle } from \"@ricsam/isolate-timers\";\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAqIA,sBAAS;AAGT,yBAAS;AAGT,wBAAS;AAGT,0BAAS;AAGT,uBAAS;AAGT,oBAAS;AAGT,sBAAS;AAGT,wBAAS;AAjGT,eAAsB,aAAa,CACjC,SACwB;AAAA,EACxB,MAAM,OAAO,WAAW,CAAC;AAAA,EAGzB,MAAM,UAAU,IAAI,IAAI,QAAQ;AAAA,IAC9B,aAAa,KAAK;AAAA,EACpB,CAAC;AAAA,EACD,MAAM,UAAU,MAAM,QAAQ,cAAc;AAAA,EAG5C,MAAM,UASF,CAAC;AAAA,EAIL,QAAQ,OAAO,MAAM,UAAU,OAAO;AAAA,EAGtC,QAAQ,UAAU,MAAM,aAAa,SAAS,KAAK,OAAO;AAAA,EAG1D,QAAQ,WAAW,MAAM,cAAc,OAAO;AAAA,EAG9C,QAAQ,SAAS,MAAM,YAAY,OAAO;AAAA,EAG1C,QAAQ,OAAO,MAAM,UAAU,OAAO;AAAA,EAGtC,QAAQ,SAAS,MAAM,YAAY,OAAO;AAAA,EAG1C,QAAQ,QAAQ,MAAM,WAAW,SAAS,KAAK,KAAK;AAAA,EAGpD,IAAI,KAAK,IAAI;AAAA,IACX,QAAQ,KAAK,MAAM,QAAQ,SAAS,KAAK,EAAE;AAAA,EAC7C;AAAA,EAEA,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,QAAQ;AAAA,SACT,KAAI,CAAC,IAAa;AAAA,MACtB,MAAM,QAAQ,OAAQ,KAAK,EAAE;AAAA;AAAA,IAE/B,OAAO,GAAG;AAAA,MAER,QAAQ,IAAI,QAAQ;AAAA,MACpB,QAAQ,OAAO,QAAQ;AAAA,MACvB,QAAQ,QAAQ,QAAQ;AAAA,MACxB,QAAQ,MAAM,QAAQ;AAAA,MACtB,QAAQ,QAAQ,QAAQ;AAAA,MACxB,QAAQ,UAAU,QAAQ;AAAA,MAC1B,QAAQ,SAAS,QAAQ;AAAA,MACzB,QAAQ,MAAM,QAAQ;AAAA,MAGtB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA;AAAA,EAEpB;AAAA;",
|
|
8
|
+
"debugId": "FDBFD94222E0044364756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import ivm from "isolated-vm";
|
|
2
|
+
import type { ConsoleOptions } from "@ricsam/isolate-console";
|
|
3
|
+
import type { FetchOptions, FetchHandle } from "@ricsam/isolate-fetch";
|
|
4
|
+
import type { FsOptions } from "@ricsam/isolate-fs";
|
|
5
|
+
export interface RuntimeOptions {
|
|
6
|
+
/** Isolate memory limit in MB */
|
|
7
|
+
memoryLimit?: number;
|
|
8
|
+
/** Console options */
|
|
9
|
+
console?: ConsoleOptions;
|
|
10
|
+
/** Fetch options */
|
|
11
|
+
fetch?: FetchOptions;
|
|
12
|
+
/** File system options (optional - fs only set up if provided) */
|
|
13
|
+
fs?: FsOptions;
|
|
14
|
+
}
|
|
15
|
+
export interface RuntimeHandle {
|
|
16
|
+
/** The isolate instance */
|
|
17
|
+
readonly isolate: ivm.Isolate;
|
|
18
|
+
/** The context instance */
|
|
19
|
+
readonly context: ivm.Context;
|
|
20
|
+
/** The fetch handle for serve() and WebSocket dispatching */
|
|
21
|
+
readonly fetch: FetchHandle;
|
|
22
|
+
/** Process pending timers */
|
|
23
|
+
tick(ms?: number): Promise<void>;
|
|
24
|
+
/** Dispose all resources */
|
|
25
|
+
dispose(): void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create a fully configured isolated-vm runtime
|
|
29
|
+
*
|
|
30
|
+
* Sets up all WHATWG APIs: fetch, fs, console, crypto, encoding, timers
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const runtime = await createRuntime({
|
|
34
|
+
* console: {
|
|
35
|
+
* onLog: (level, ...args) => console.log(`[${level}]`, ...args)
|
|
36
|
+
* },
|
|
37
|
+
* fetch: {
|
|
38
|
+
* onFetch: async (request) => fetch(request)
|
|
39
|
+
* }
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* await runtime.context.eval(`
|
|
43
|
+
* console.log("Hello from sandbox!");
|
|
44
|
+
* const response = await fetch("https://example.com");
|
|
45
|
+
* `);
|
|
46
|
+
*
|
|
47
|
+
* runtime.dispose();
|
|
48
|
+
*/
|
|
49
|
+
export declare function createRuntime(options?: RuntimeOptions): Promise<RuntimeHandle>;
|
|
50
|
+
export { setupCore } from "@ricsam/isolate-core";
|
|
51
|
+
export type { CoreHandle, SetupCoreOptions } from "@ricsam/isolate-core";
|
|
52
|
+
export { setupConsole } from "@ricsam/isolate-console";
|
|
53
|
+
export type { ConsoleHandle, ConsoleOptions } from "@ricsam/isolate-console";
|
|
54
|
+
export { setupCrypto } from "@ricsam/isolate-crypto";
|
|
55
|
+
export type { CryptoHandle } from "@ricsam/isolate-crypto";
|
|
56
|
+
export { setupEncoding } from "@ricsam/isolate-encoding";
|
|
57
|
+
export type { EncodingHandle } from "@ricsam/isolate-encoding";
|
|
58
|
+
export { setupFetch } from "@ricsam/isolate-fetch";
|
|
59
|
+
export type { FetchHandle, FetchOptions, WebSocketCommand, UpgradeRequest } from "@ricsam/isolate-fetch";
|
|
60
|
+
export { setupFs, createNodeFileSystemHandler } from "@ricsam/isolate-fs";
|
|
61
|
+
export type { FsHandle, FsOptions, FileSystemHandler, NodeFileSystemHandlerOptions } from "@ricsam/isolate-fs";
|
|
62
|
+
export { setupPath } from "@ricsam/isolate-path";
|
|
63
|
+
export type { PathHandle } from "@ricsam/isolate-path";
|
|
64
|
+
export { setupTimers } from "@ricsam/isolate-timers";
|
|
65
|
+
export type { TimersHandle } from "@ricsam/isolate-timers";
|
package/package.json
CHANGED
|
@@ -1,10 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ricsam/isolate-runtime",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"main": "./dist/cjs/index.cjs",
|
|
5
|
+
"types": "./dist/types/index.d.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/types/index.d.ts",
|
|
9
|
+
"require": "./dist/cjs/index.cjs",
|
|
10
|
+
"import": "./dist/mjs/index.mjs"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"test": "node --test --experimental-strip-types 'src/**/*.test.ts'",
|
|
16
|
+
"typecheck": "tsc --noEmit"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@ricsam/isolate-core": "*",
|
|
20
|
+
"@ricsam/isolate-console": "*",
|
|
21
|
+
"@ricsam/isolate-crypto": "*",
|
|
22
|
+
"@ricsam/isolate-encoding": "*",
|
|
23
|
+
"@ricsam/isolate-fetch": "*",
|
|
24
|
+
"@ricsam/isolate-fs": "*",
|
|
25
|
+
"@ricsam/isolate-timers": "*",
|
|
26
|
+
"isolated-vm": "^6"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"isolated-vm": "^6"
|
|
30
|
+
},
|
|
31
|
+
"author": "Richard Samuelsson",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/ricsam/isolate.git"
|
|
36
|
+
},
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/ricsam/isolate/issues"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://github.com/ricsam/isolate#readme",
|
|
5
41
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
42
|
+
"isolated-vm",
|
|
43
|
+
"sandbox",
|
|
44
|
+
"javascript",
|
|
45
|
+
"runtime",
|
|
46
|
+
"fetch",
|
|
47
|
+
"filesystem",
|
|
48
|
+
"streams",
|
|
49
|
+
"v8",
|
|
50
|
+
"isolate"
|
|
51
|
+
],
|
|
52
|
+
"description": "Complete isolated-vm V8 sandbox runtime with fetch, fs, and core bindings",
|
|
53
|
+
"module": "./dist/mjs/index.mjs",
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
},
|
|
57
|
+
"files": [
|
|
58
|
+
"dist",
|
|
59
|
+
"README.md"
|
|
9
60
|
]
|
|
10
|
-
}
|
|
61
|
+
}
|