@ricsam/isolate-daemon 0.1.7 → 0.1.9
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/callback-fs-handler.cjs +2 -4
- package/dist/cjs/callback-fs-handler.cjs.map +2 -2
- package/dist/cjs/connection.cjs +131 -9
- package/dist/cjs/connection.cjs.map +3 -3
- package/dist/cjs/daemon.cjs +2 -4
- package/dist/cjs/daemon.cjs.map +2 -2
- package/dist/cjs/index.cjs +4 -6
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/types.cjs +2 -4
- package/dist/cjs/types.cjs.map +1 -1
- package/dist/mjs/callback-fs-handler.mjs +1 -2
- package/dist/mjs/callback-fs-handler.mjs.map +2 -2
- package/dist/mjs/connection.mjs +130 -7
- package/dist/mjs/connection.mjs.map +3 -3
- package/dist/mjs/daemon.mjs +1 -2
- package/dist/mjs/daemon.mjs.map +2 -2
- package/dist/mjs/index.mjs +3 -4
- package/dist/mjs/index.mjs.map +2 -2
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/types.mjs +1 -2
- package/dist/mjs/types.mjs.map +1 -1
- package/dist/types/types.d.ts +21 -0
- package/package.json +1 -1
package/dist/cjs/daemon.cjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
(function(exports, require, module, __filename, __dirname) {
|
|
2
|
+
|
|
4
3
|
// packages/isolate-daemon/src/daemon.ts
|
|
5
4
|
var import__ = require("./index.cjs");
|
|
6
5
|
function parseArgs(args) {
|
|
@@ -92,6 +91,5 @@ main().catch((err) => {
|
|
|
92
91
|
console.error("Failed to start daemon:", err);
|
|
93
92
|
process.exit(1);
|
|
94
93
|
});
|
|
95
|
-
})
|
|
96
94
|
|
|
97
|
-
//# debugId=
|
|
95
|
+
//# debugId=9E325A09A251DFC164756E2164756E21
|
package/dist/cjs/daemon.cjs.map
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"#!/usr/bin/env node\n\n/**\n * CLI entry point for the isolate daemon.\n *\n * Usage:\n * isolate-daemon [options]\n *\n * Options:\n * --socket <path> Unix socket path (default: /tmp/isolate-daemon.sock)\n * --host <host> TCP host (default: 127.0.0.1)\n * --port <port> TCP port (default: 47891)\n * --max-isolates <n> Maximum isolates (default: 100)\n * --memory-limit <mb> Default memory limit (default: 128)\n */\n\nimport { startDaemon, type DaemonOptions } from \"./index.cjs\";\n\nfunction parseArgs(args: string[]): Partial<DaemonOptions> {\n const options: Partial<DaemonOptions> = {};\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n\n switch (arg) {\n case \"--socket\":\n i++;\n if (args[i]) {\n options.socketPath = args[i];\n }\n break;\n case \"--host\":\n i++;\n if (args[i]) {\n options.host = args[i];\n options.socketPath = undefined; // Use TCP instead\n }\n break;\n case \"--port\": {\n i++;\n const value = args[i];\n if (value !== undefined) {\n options.port = parseInt(value, 10);\n options.socketPath = undefined; // Use TCP instead\n }\n break;\n }\n case \"--max-isolates\": {\n i++;\n const value = args[i];\n if (value !== undefined) {\n options.maxIsolates = parseInt(value, 10);\n }\n break;\n }\n case \"--memory-limit\": {\n i++;\n const value = args[i];\n if (value !== undefined) {\n options.defaultMemoryLimitMB = parseInt(value, 10);\n }\n break;\n }\n case \"--help\":\n case \"-h\":\n console.log(`\nIsolate Daemon - Run isolated-vm runtimes accessible via IPC\n\nUsage:\n isolate-daemon [options]\n\nOptions:\n --socket <path> Unix socket path (default: /tmp/isolate-daemon.sock)\n --host <host> TCP host (default: 127.0.0.1, disables Unix socket)\n --port <port> TCP port (default: 47891, disables Unix socket)\n --max-isolates <n> Maximum isolates (default: 100)\n --memory-limit <mb> Default memory limit in MB (default: 128)\n --help, -h Show this help message\n`);\n process.exit(0);\n default:\n if (arg !== undefined && arg.startsWith(\"-\")) {\n console.error(`Unknown option: ${arg}`);\n process.exit(1);\n }\n }\n }\n\n return options;\n}\n\nasync function main() {\n const options = parseArgs(process.argv.slice(2));\n\n const daemon = await startDaemon(options);\n\n // Handle shutdown signals\n const shutdown = async () => {\n console.log(\"\\nShutting down...\");\n await daemon.close();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Log stats periodically\n setInterval(() => {\n const stats = daemon.getStats();\n console.log(\n `[stats] connections: ${stats.activeConnections}, isolates: ${stats.activeIsolates}, total requests: ${stats.totalRequestsProcessed}`\n );\n }, 60000);\n}\n\nmain().catch((err) => {\n console.error(\"Failed to start daemon:\", err);\n process.exit(1);\n});\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;AAgBgD,IAAhD;AAEA,SAAS,SAAS,CAAC,MAAwC;AAAA,EACzD,MAAM,UAAkC,CAAC;AAAA,EAEzC,SAAS,IAAI,EAAG,IAAI,KAAK,QAAQ,KAAK;AAAA,IACpC,MAAM,MAAM,KAAK;AAAA,IAEjB,QAAQ;AAAA,WACD;AAAA,QACH;AAAA,QACA,IAAI,KAAK,IAAI;AAAA,UACX,QAAQ,aAAa,KAAK;AAAA,QAC5B;AAAA,QACA;AAAA,WACG;AAAA,QACH;AAAA,QACA,IAAI,KAAK,IAAI;AAAA,UACX,QAAQ,OAAO,KAAK;AAAA,UACpB,QAAQ,aAAa;AAAA,QACvB;AAAA,QACA;AAAA,WACG,UAAU;AAAA,QACb;AAAA,QACA,MAAM,QAAQ,KAAK;AAAA,QACnB,IAAI,UAAU,WAAW;AAAA,UACvB,QAAQ,OAAO,SAAS,OAAO,EAAE;AAAA,UACjC,QAAQ,aAAa;AAAA,QACvB;AAAA,QACA;AAAA,MACF;AAAA,WACK,kBAAkB;AAAA,QACrB;AAAA,QACA,MAAM,QAAQ,KAAK;AAAA,QACnB,IAAI,UAAU,WAAW;AAAA,UACvB,QAAQ,cAAc,SAAS,OAAO,EAAE;AAAA,QAC1C;AAAA,QACA;AAAA,MACF;AAAA,WACK,kBAAkB;AAAA,QACrB;AAAA,QACA,MAAM,QAAQ,KAAK;AAAA,QACnB,IAAI,UAAU,WAAW;AAAA,UACvB,QAAQ,uBAAuB,SAAS,OAAO,EAAE;AAAA,QACnD;AAAA,QACA;AAAA,MACF;AAAA,WACK;AAAA,WACA;AAAA,QACH,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAanB;AAAA,QACO,QAAQ,KAAK,CAAC;AAAA;AAAA,QAEd,IAAI,QAAQ,aAAa,IAAI,WAAW,GAAG,GAAG;AAAA,UAC5C,QAAQ,MAAM,mBAAmB,KAAK;AAAA,UACtC,QAAQ,KAAK,CAAC;AAAA,QAChB;AAAA;AAAA,EAEN;AAAA,EAEA,OAAO;AAAA;AAGT,eAAe,IAAI,GAAG;AAAA,EACpB,MAAM,UAAU,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;AAAA,EAE/C,MAAM,SAAS,MAAM,qBAAY,OAAO;AAAA,EAGxC,MAAM,WAAW,YAAY;AAAA,IAC3B,QAAQ,IAAI;AAAA,iBAAoB;AAAA,IAChC,MAAM,OAAO,MAAM;AAAA,IACnB,QAAQ,KAAK,CAAC;AAAA;AAAA,EAGhB,QAAQ,GAAG,UAAU,QAAQ;AAAA,EAC7B,QAAQ,GAAG,WAAW,QAAQ;AAAA,EAG9B,YAAY,MAAM;AAAA,IAChB,MAAM,QAAQ,OAAO,SAAS;AAAA,IAC9B,QAAQ,IACN,wBAAwB,MAAM,gCAAgC,MAAM,mCAAmC,MAAM,wBAC/G;AAAA,KACC,KAAK;AAAA;AAGV,KAAK,EAAE,MAAM,CAAC,QAAQ;AAAA,EACpB,QAAQ,MAAM,2BAA2B,GAAG;AAAA,EAC5C,QAAQ,KAAK,CAAC;AAAA,CACf;",
|
|
8
|
+
"debugId": "9E325A09A251DFC164756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
(function(exports, require, module, __filename, __dirname) {var __defProp = Object.defineProperty;
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
3
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
@@ -33,8 +32,8 @@ __export(exports_src, {
|
|
|
33
32
|
startDaemon: () => startDaemon
|
|
34
33
|
});
|
|
35
34
|
module.exports = __toCommonJS(exports_src);
|
|
36
|
-
var import_node_net = require("net");
|
|
37
|
-
var import_promises = require("fs/promises");
|
|
35
|
+
var import_node_net = require("node:net");
|
|
36
|
+
var import_promises = require("node:fs/promises");
|
|
38
37
|
var import_connection = require("./connection.cjs");
|
|
39
38
|
var DEFAULT_OPTIONS = {
|
|
40
39
|
socketPath: "/tmp/isolate-daemon.sock",
|
|
@@ -129,6 +128,5 @@ function updateStats(state) {
|
|
|
129
128
|
state.stats.activeIsolates = state.isolates.size;
|
|
130
129
|
state.stats.activeConnections = state.connections.size;
|
|
131
130
|
}
|
|
132
|
-
})
|
|
133
131
|
|
|
134
|
-
//# debugId=
|
|
132
|
+
//# debugId=17BADF0A2CEBB48D64756E2164756E21
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * @ricsam/isolate-daemon\n *\n * Node.js daemon for running isolated-vm runtimes accessible via IPC.\n */\n\nimport { createServer, type Server } from \"node:net\";\nimport { unlink } from \"node:fs/promises\";\nimport { handleConnection } from \"./connection.cjs\";\nimport type {\n DaemonOptions,\n DaemonHandle,\n DaemonState,\n DaemonStats,\n} from \"./types.cjs\";\n\nexport type { DaemonOptions, DaemonHandle, DaemonStats };\n\nconst DEFAULT_OPTIONS: Required<DaemonOptions> = {\n socketPath: \"/tmp/isolate-daemon.sock\",\n host: \"127.0.0.1\",\n port: 47891,\n maxIsolates: 100,\n defaultMemoryLimitMB: 128,\n};\n\n/**\n * Start the isolate daemon.\n *\n * @param options - Daemon configuration options\n * @returns Handle to control the daemon\n */\nexport async function startDaemon(\n options: DaemonOptions = {}\n): Promise<DaemonHandle> {\n const resolvedOptions: Required<DaemonOptions> = {\n ...DEFAULT_OPTIONS,\n ...options,\n };\n\n const state: DaemonState = {\n isolates: new Map(),\n connections: new Map(),\n stats: {\n activeIsolates: 0,\n activeConnections: 0,\n totalIsolatesCreated: 0,\n totalRequestsProcessed: 0,\n },\n options: resolvedOptions,\n namespacedRuntimes: new Map(),\n };\n\n const server = createServer((socket) => {\n handleConnection(socket, state);\n updateStats(state);\n });\n\n // Try to remove existing socket file\n if (resolvedOptions.socketPath) {\n try {\n await unlink(resolvedOptions.socketPath);\n } catch {\n // Ignore if doesn't exist\n }\n }\n\n // Start listening\n await new Promise<void>((resolve, reject) => {\n server.on(\"error\", reject);\n\n if (resolvedOptions.socketPath) {\n server.listen(resolvedOptions.socketPath, () => {\n server.removeListener(\"error\", reject);\n resolve();\n });\n } else {\n server.listen(resolvedOptions.port, resolvedOptions.host, () => {\n server.removeListener(\"error\", reject);\n resolve();\n });\n }\n });\n\n const address = resolvedOptions.socketPath\n ? resolvedOptions.socketPath\n : `${resolvedOptions.host}:${resolvedOptions.port}`;\n\n console.log(`Isolate daemon listening on ${address}`);\n\n return {\n address,\n getStats: () => ({\n ...state.stats,\n activeIsolates: state.isolates.size,\n activeConnections: state.connections.size,\n }),\n close: async () => {\n // Close all connections\n for (const [socket] of state.connections) {\n socket.destroy();\n }\n\n // Dispose all isolates\n for (const [, instance] of state.isolates) {\n try {\n instance.runtime.dispose();\n } catch {\n // Ignore\n }\n }\n\n state.isolates.clear();\n state.connections.clear();\n state.namespacedRuntimes.clear();\n\n // Close server\n await closeServer(server);\n\n // Remove socket file\n if (resolvedOptions.socketPath) {\n try {\n await unlink(resolvedOptions.socketPath);\n } catch {\n // Ignore\n }\n }\n\n console.log(\"Isolate daemon stopped\");\n },\n };\n}\n\nfunction closeServer(server: Server): Promise<void> {\n return new Promise((resolve, reject) => {\n server.close((err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n}\n\nfunction updateStats(state: DaemonState): void {\n state.stats.activeIsolates = state.isolates.size;\n state.stats.activeConnections = state.connections.size;\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAM0C,IAA1C;AACuB,IAAvB;AACiC,IAAjC;AAUA,IAAM,kBAA2C;AAAA,EAC/C,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,sBAAsB;AACxB;AAQA,eAAsB,WAAW,CAC/B,UAAyB,CAAC,GACH;AAAA,EACvB,MAAM,kBAA2C;AAAA,OAC5C;AAAA,OACA;AAAA,EACL;AAAA,EAEA,MAAM,QAAqB;AAAA,IACzB,UAAU,IAAI;AAAA,IACd,aAAa,IAAI;AAAA,IACjB,OAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,mBAAmB;AAAA,MACnB,sBAAsB;AAAA,MACtB,wBAAwB;AAAA,IAC1B;AAAA,IACA,SAAS;AAAA,IACT,oBAAoB,IAAI;AAAA,EAC1B;AAAA,EAEA,MAAM,SAAS,6BAAa,CAAC,WAAW;AAAA,IACtC,mCAAiB,QAAQ,KAAK;AAAA,IAC9B,YAAY,KAAK;AAAA,GAClB;AAAA,EAGD,IAAI,gBAAgB,YAAY;AAAA,IAC9B,IAAI;AAAA,MACF,MAAM,uBAAO,gBAAgB,UAAU;AAAA,MACvC,MAAM;AAAA,EAGV;AAAA,EAGA,MAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAAA,IAC3C,OAAO,GAAG,SAAS,MAAM;AAAA,IAEzB,IAAI,gBAAgB,YAAY;AAAA,MAC9B,OAAO,OAAO,gBAAgB,YAAY,MAAM;AAAA,QAC9C,OAAO,eAAe,SAAS,MAAM;AAAA,QACrC,QAAQ;AAAA,OACT;AAAA,IACH,EAAO;AAAA,MACL,OAAO,OAAO,gBAAgB,MAAM,gBAAgB,MAAM,MAAM;AAAA,QAC9D,OAAO,eAAe,SAAS,MAAM;AAAA,QACrC,QAAQ;AAAA,OACT;AAAA;AAAA,GAEJ;AAAA,EAED,MAAM,UAAU,gBAAgB,aAC5B,gBAAgB,aAChB,GAAG,gBAAgB,QAAQ,gBAAgB;AAAA,EAE/C,QAAQ,IAAI,+BAA+B,SAAS;AAAA,EAEpD,OAAO;AAAA,IACL;AAAA,IACA,UAAU,OAAO;AAAA,SACZ,MAAM;AAAA,MACT,gBAAgB,MAAM,SAAS;AAAA,MAC/B,mBAAmB,MAAM,YAAY;AAAA,IACvC;AAAA,IACA,OAAO,YAAY;AAAA,MAEjB,YAAY,WAAW,MAAM,aAAa;AAAA,QACxC,OAAO,QAAQ;AAAA,MACjB;AAAA,MAGA,cAAc,aAAa,MAAM,UAAU;AAAA,QACzC,IAAI;AAAA,UACF,SAAS,QAAQ,QAAQ;AAAA,UACzB,MAAM;AAAA,MAGV;AAAA,MAEA,MAAM,SAAS,MAAM;AAAA,MACrB,MAAM,YAAY,MAAM;AAAA,MACxB,MAAM,mBAAmB,MAAM;AAAA,MAG/B,MAAM,YAAY,MAAM;AAAA,MAGxB,IAAI,gBAAgB,YAAY;AAAA,QAC9B,IAAI;AAAA,UACF,MAAM,uBAAO,gBAAgB,UAAU;AAAA,UACvC,MAAM;AAAA,MAGV;AAAA,MAEA,QAAQ,IAAI,wBAAwB;AAAA;AAAA,EAExC;AAAA;AAGF,SAAS,WAAW,CAAC,QAA+B;AAAA,EAClD,OAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAAA,IACtC,OAAO,MAAM,CAAC,QAAQ;AAAA,MACpB,IAAI,KAAK;AAAA,QACP,OAAO,GAAG;AAAA,MACZ,EAAO;AAAA,QACL,QAAQ;AAAA;AAAA,KAEX;AAAA,GACF;AAAA;AAGH,SAAS,WAAW,CAAC,OAA0B;AAAA,EAC7C,MAAM,MAAM,iBAAiB,MAAM,SAAS;AAAA,EAC5C,MAAM,MAAM,oBAAoB,MAAM,YAAY;AAAA;",
|
|
8
|
+
"debugId": "17BADF0A2CEBB48D64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/cjs/package.json
CHANGED
package/dist/cjs/types.cjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
(function(exports, require, module, __filename, __dirname) {var __defProp = Object.defineProperty;
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
3
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
@@ -21,6 +20,5 @@ var __toCommonJS = (from) => {
|
|
|
21
20
|
// packages/isolate-daemon/src/types.ts
|
|
22
21
|
var exports_types = {};
|
|
23
22
|
module.exports = __toCommonJS(exports_types);
|
|
24
|
-
})
|
|
25
23
|
|
|
26
|
-
//# debugId=
|
|
24
|
+
//# debugId=A80F84CE523F92D564756E2164756E21
|
package/dist/cjs/types.cjs.map
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @bun
|
|
2
1
|
// packages/isolate-daemon/src/callback-fs-handler.ts
|
|
3
2
|
function createCallbackFileSystemHandler(options) {
|
|
4
3
|
const { connection, callbackContext, invokeClientCallback, basePath = "" } = options;
|
|
@@ -311,4 +310,4 @@ export {
|
|
|
311
310
|
createCallbackFileSystemHandler
|
|
312
311
|
};
|
|
313
312
|
|
|
314
|
-
//# debugId=
|
|
313
|
+
//# debugId=40AFB3C807FDEBD864756E2164756E21
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * Callback-based FileSystemHandler adapter.\n *\n * Adapts simple client callbacks (readFile, writeFile, etc.) to the\n * FileSystemHandler interface used by @ricsam/isolate-fs.\n */\n\nimport type { FileSystemHandler } from \"@ricsam/isolate-fs\";\nimport type { ConnectionState, CallbackContext } from \"./types.mjs\";\n\ninterface InvokeClientCallback {\n (connection: ConnectionState, callbackId: number, args: unknown[]): Promise<unknown>;\n}\n\ninterface CallbackFsHandlerOptions {\n connection: ConnectionState;\n callbackContext: CallbackContext;\n invokeClientCallback: InvokeClientCallback;\n basePath?: string;\n}\n\n/**\n * Create a FileSystemHandler that invokes client callbacks.\n *\n * Maps WHATWG FileSystem API operations to simple POSIX-like callbacks.\n * Uses callbackContext for dynamic callback ID lookup to support runtime reuse.\n */\nexport function createCallbackFileSystemHandler(\n options: CallbackFsHandlerOptions\n): FileSystemHandler {\n const { connection, callbackContext, invokeClientCallback, basePath = \"\" } = options;\n\n const resolvePath = (path: string): string => {\n // Remove leading slash from the path\n const cleanPath = path.startsWith(\"/\") ? path.slice(1) : path;\n // Handle root case\n if (!basePath || basePath === \"/\") {\n return `/${cleanPath}`;\n }\n // Remove trailing slash from basePath\n const cleanBase = basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n return `${cleanBase}/${cleanPath}`;\n };\n\n // Helper to get current callback ID (supports runtime reuse)\n const getCallbackId = (name: keyof CallbackContext[\"fs\"]): number | undefined => {\n return callbackContext.fs[name];\n };\n\n // Helper to get current connection (supports runtime reuse)\n const getConnection = (): ConnectionState => {\n return callbackContext.connection || connection;\n };\n\n return {\n async getFileHandle(path: string, opts?: { create?: boolean }): Promise<void> {\n const fullPath = resolvePath(path);\n const conn = getConnection();\n\n if (opts?.create) {\n // Ensure file exists by writing empty content if it doesn't exist\n const writeFileId = getCallbackId(\"writeFile\");\n if (writeFileId !== undefined) {\n try {\n // Check if file exists first\n const statId = getCallbackId(\"stat\");\n if (statId !== undefined) {\n try {\n await invokeClientCallback(conn, statId, [fullPath]);\n // File exists, nothing to do\n return;\n } catch {\n // File doesn't exist, create it\n }\n }\n // Create empty file\n await invokeClientCallback(conn, writeFileId, [\n fullPath,\n new Uint8Array(0),\n ]);\n } catch (err) {\n const error = err as Error;\n throw new Error(`[NotFoundError]${error.message}`);\n }\n }\n return;\n }\n\n // Check file exists\n const statId = getCallbackId(\"stat\");\n if (statId !== undefined) {\n try {\n const result = (await invokeClientCallback(conn, statId, [\n fullPath,\n ])) as { isFile: boolean };\n if (!result.isFile) {\n throw new Error(`[TypeMismatchError]Not a file: ${fullPath}`);\n }\n } catch (err) {\n const error = err as Error;\n if (error.message.includes(\"TypeMismatchError\")) throw error;\n throw new Error(`[NotFoundError]File not found: ${fullPath}`);\n }\n }\n },\n\n async getDirectoryHandle(path: string, opts?: { create?: boolean }): Promise<void> {\n const fullPath = resolvePath(path);\n const conn = getConnection();\n\n if (opts?.create) {\n const mkdirId = getCallbackId(\"mkdir\");\n if (mkdirId !== undefined) {\n try {\n await invokeClientCallback(conn, mkdirId, [\n fullPath,\n { recursive: true },\n ]);\n } catch {\n // Ignore error if directory already exists\n }\n }\n return;\n }\n\n // Check directory exists\n const statId = getCallbackId(\"stat\");\n if (statId !== undefined) {\n try {\n const result = (await invokeClientCallback(conn, statId, [\n fullPath,\n ])) as { isDirectory: boolean };\n if (!result.isDirectory) {\n throw new Error(`[TypeMismatchError]Not a directory: ${fullPath}`);\n }\n } catch (err) {\n const error = err as Error;\n if (error.message.includes(\"TypeMismatchError\")) throw error;\n throw new Error(`[NotFoundError]Directory not found: ${fullPath}`);\n }\n }\n },\n\n async removeEntry(path: string, opts?: { recursive?: boolean }): Promise<void> {\n const fullPath = resolvePath(path);\n const conn = getConnection();\n\n // Check if it's a file or directory\n let isFile = true;\n const statId = getCallbackId(\"stat\");\n if (statId !== undefined) {\n try {\n const result = (await invokeClientCallback(conn, statId, [\n fullPath,\n ])) as { isFile: boolean; isDirectory: boolean };\n isFile = result.isFile;\n } catch {\n throw new Error(`[NotFoundError]Entry not found: ${fullPath}`);\n }\n }\n\n if (isFile) {\n const unlinkId = getCallbackId(\"unlink\");\n if (unlinkId === undefined) {\n throw new Error(`[NotAllowedError]File deletion not supported`);\n }\n await invokeClientCallback(conn, unlinkId, [fullPath]);\n } else {\n const rmdirId = getCallbackId(\"rmdir\");\n if (rmdirId === undefined) {\n throw new Error(`[NotAllowedError]Directory deletion not supported`);\n }\n // Note: recursive option may need special handling\n await invokeClientCallback(conn, rmdirId, [fullPath]);\n }\n },\n\n async readDirectory(\n path: string\n ): Promise<Array<{ name: string; kind: \"file\" | \"directory\" }>> {\n const fullPath = resolvePath(path);\n const conn = getConnection();\n\n const readdirId = getCallbackId(\"readdir\");\n if (readdirId === undefined) {\n throw new Error(`[NotAllowedError]Directory reading not supported`);\n }\n\n const entries = (await invokeClientCallback(conn, readdirId, [\n fullPath,\n ])) as string[];\n\n // We need to stat each entry to determine if it's a file or directory\n const result: Array<{ name: string; kind: \"file\" | \"directory\" }> = [];\n\n const statId = getCallbackId(\"stat\");\n for (const name of entries) {\n const entryPath = fullPath ? `${fullPath}/${name}` : name;\n let kind: \"file\" | \"directory\" = \"file\";\n\n if (statId !== undefined) {\n try {\n const stat = (await invokeClientCallback(conn, statId, [\n entryPath,\n ])) as { isFile: boolean; isDirectory: boolean };\n kind = stat.isDirectory ? \"directory\" : \"file\";\n } catch {\n // Default to file if stat fails\n }\n }\n\n result.push({ name, kind });\n }\n\n return result;\n },\n\n async readFile(\n path: string\n ): Promise<{ data: Uint8Array; size: number; lastModified: number; type: string }> {\n const fullPath = resolvePath(path);\n const conn = getConnection();\n\n const readFileId = getCallbackId(\"readFile\");\n if (readFileId === undefined) {\n throw new Error(`[NotAllowedError]File reading not supported`);\n }\n\n const data = (await invokeClientCallback(conn, readFileId, [\n fullPath,\n ])) as Uint8Array | ArrayBuffer | number[];\n\n // Convert to Uint8Array if needed\n let bytes: Uint8Array;\n if (data instanceof Uint8Array) {\n bytes = data;\n } else if (Array.isArray(data)) {\n bytes = new Uint8Array(data);\n } else if (data instanceof ArrayBuffer) {\n bytes = new Uint8Array(data);\n } else {\n bytes = new Uint8Array(0);\n }\n\n // Get metadata if stat is available\n let size = bytes.length;\n let lastModified = Date.now();\n\n const statId = getCallbackId(\"stat\");\n if (statId !== undefined) {\n try {\n const stat = (await invokeClientCallback(conn, statId, [\n fullPath,\n ])) as { size: number; lastModified?: number };\n size = stat.size;\n if (stat.lastModified) {\n lastModified = stat.lastModified;\n }\n } catch {\n // Use byte length as fallback\n }\n }\n\n // Determine MIME type from extension\n const ext = path.split(\".\").pop()?.toLowerCase() || \"\";\n const mimeTypes: Record<string, string> = {\n txt: \"text/plain\",\n html: \"text/html\",\n htm: \"text/html\",\n css: \"text/css\",\n js: \"text/javascript\",\n json: \"application/json\",\n xml: \"application/xml\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n svg: \"image/svg+xml\",\n pdf: \"application/pdf\",\n };\n const type = mimeTypes[ext] || \"application/octet-stream\";\n\n return { data: bytes, size, lastModified, type };\n },\n\n async writeFile(path: string, data: Uint8Array, position?: number): Promise<void> {\n const fullPath = resolvePath(path);\n const conn = getConnection();\n\n const writeFileId = getCallbackId(\"writeFile\");\n if (writeFileId === undefined) {\n throw new Error(`[NotAllowedError]File writing not supported`);\n }\n\n // Note: position parameter for partial writes may need special handling\n // Simple implementation overwrites entire file\n if (position !== undefined && position > 0) {\n // For positional writes, we need to read existing content and merge\n const readFileId = getCallbackId(\"readFile\");\n if (readFileId !== undefined) {\n try {\n const existing = (await invokeClientCallback(\n conn,\n readFileId,\n [fullPath]\n )) as Uint8Array | ArrayBuffer | number[];\n\n let existingBytes: Uint8Array;\n if (existing instanceof Uint8Array) {\n existingBytes = existing;\n } else if (Array.isArray(existing)) {\n existingBytes = new Uint8Array(existing);\n } else if (existing instanceof ArrayBuffer) {\n existingBytes = new Uint8Array(existing);\n } else {\n existingBytes = new Uint8Array(0);\n }\n\n // Create merged buffer\n const newSize = Math.max(existingBytes.length, position + data.length);\n const merged = new Uint8Array(newSize);\n merged.set(existingBytes);\n merged.set(data, position);\n\n await invokeClientCallback(conn, writeFileId, [\n fullPath,\n merged,\n ]);\n return;\n } catch {\n // File doesn't exist, create new one at position\n const newData = new Uint8Array(position + data.length);\n newData.set(data, position);\n await invokeClientCallback(conn, writeFileId, [\n fullPath,\n newData,\n ]);\n return;\n }\n }\n }\n\n await invokeClientCallback(conn, writeFileId, [fullPath, data]);\n },\n\n async truncateFile(path: string, size: number): Promise<void> {\n const fullPath = resolvePath(path);\n const conn = getConnection();\n\n const readFileId = getCallbackId(\"readFile\");\n const writeFileId = getCallbackId(\"writeFile\");\n if (readFileId === undefined || writeFileId === undefined) {\n throw new Error(`[NotAllowedError]File truncation not supported`);\n }\n\n // Read existing content\n const existing = (await invokeClientCallback(conn, readFileId, [\n fullPath,\n ])) as Uint8Array | ArrayBuffer | number[];\n\n let existingBytes: Uint8Array;\n if (existing instanceof Uint8Array) {\n existingBytes = existing;\n } else if (Array.isArray(existing)) {\n existingBytes = new Uint8Array(existing);\n } else if (existing instanceof ArrayBuffer) {\n existingBytes = new Uint8Array(existing);\n } else {\n existingBytes = new Uint8Array(0);\n }\n\n // Create truncated buffer\n const truncated = new Uint8Array(size);\n truncated.set(existingBytes.slice(0, size));\n\n await invokeClientCallback(conn, writeFileId, [fullPath, truncated]);\n },\n\n async getFileMetadata(\n path: string\n ): Promise<{ size: number; lastModified: number; type: string }> {\n const fullPath = resolvePath(path);\n const conn = getConnection();\n\n const statId = getCallbackId(\"stat\");\n if (statId === undefined) {\n throw new Error(`[NotAllowedError]File stat not supported`);\n }\n\n const stat = (await invokeClientCallback(conn, statId, [\n fullPath,\n ])) as { size: number; lastModified?: number; isFile: boolean };\n\n if (!stat.isFile) {\n throw new Error(`[TypeMismatchError]Not a file: ${fullPath}`);\n }\n\n // Determine MIME type from extension\n const ext = path.split(\".\").pop()?.toLowerCase() || \"\";\n const mimeTypes: Record<string, string> = {\n txt: \"text/plain\",\n html: \"text/html\",\n htm: \"text/html\",\n css: \"text/css\",\n js: \"text/javascript\",\n json: \"application/json\",\n xml: \"application/xml\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n svg: \"image/svg+xml\",\n pdf: \"application/pdf\",\n };\n const type = mimeTypes[ext] || \"application/octet-stream\";\n\n return {\n size: stat.size,\n lastModified: stat.lastModified ?? Date.now(),\n type,\n };\n },\n };\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "40AFB3C807FDEBD864756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/mjs/connection.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
// @bun
|
|
2
1
|
// packages/isolate-daemon/src/connection.ts
|
|
3
|
-
import { randomUUID } from "crypto";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
4
3
|
import ivm from "isolated-vm";
|
|
5
4
|
import {
|
|
6
5
|
createFrameParser,
|
|
@@ -35,7 +34,8 @@ function handleConnection(socket, state) {
|
|
|
35
34
|
nextCallbackId: 1,
|
|
36
35
|
nextStreamId: 1,
|
|
37
36
|
activeStreams: new Map,
|
|
38
|
-
streamReceivers: new Map
|
|
37
|
+
streamReceivers: new Map,
|
|
38
|
+
callbackStreamReceivers: new Map
|
|
39
39
|
};
|
|
40
40
|
state.connections.set(socket, connection);
|
|
41
41
|
const parser = createFrameParser();
|
|
@@ -196,6 +196,15 @@ async function handleMessage(message, connection, state) {
|
|
|
196
196
|
case MessageType.STREAM_ERROR:
|
|
197
197
|
handleStreamError(message, connection);
|
|
198
198
|
break;
|
|
199
|
+
case MessageType.CALLBACK_STREAM_START:
|
|
200
|
+
handleCallbackStreamStart(message, connection);
|
|
201
|
+
break;
|
|
202
|
+
case MessageType.CALLBACK_STREAM_CHUNK:
|
|
203
|
+
handleCallbackStreamChunk(message, connection);
|
|
204
|
+
break;
|
|
205
|
+
case MessageType.CALLBACK_STREAM_END:
|
|
206
|
+
handleCallbackStreamEnd(message, connection);
|
|
207
|
+
break;
|
|
199
208
|
default:
|
|
200
209
|
sendError(connection.socket, message.requestId ?? 0, ErrorCode.UNKNOWN_MESSAGE_TYPE, `Unknown message type: ${message.type}`);
|
|
201
210
|
}
|
|
@@ -387,7 +396,12 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
387
396
|
throw new Error("Fetch callback not available");
|
|
388
397
|
}
|
|
389
398
|
const serialized = await serializeRequest(request);
|
|
390
|
-
const result = await invokeClientCallback(conn, callbackId, [serialized]);
|
|
399
|
+
const result = await invokeClientCallback(conn, callbackId, [serialized], 60000);
|
|
400
|
+
if (result && typeof result === "object" && result.__streamingResponse) {
|
|
401
|
+
const response = result.response;
|
|
402
|
+
response.__isCallbackStream = true;
|
|
403
|
+
return response;
|
|
404
|
+
}
|
|
391
405
|
return deserializeResponse(result);
|
|
392
406
|
}
|
|
393
407
|
},
|
|
@@ -876,7 +890,7 @@ async function invokeClientCallback(connection, callbackId, args, timeout = 1e4)
|
|
|
876
890
|
}
|
|
877
891
|
var ISOLATE_MARSHAL_CODE = `
|
|
878
892
|
(function() {
|
|
879
|
-
// Marshal a value (JavaScript
|
|
893
|
+
// Marshal a value (JavaScript → Ref)
|
|
880
894
|
function marshalForHost(value, depth = 0) {
|
|
881
895
|
if (depth > 100) throw new Error('Maximum marshalling depth exceeded');
|
|
882
896
|
|
|
@@ -938,7 +952,7 @@ var ISOLATE_MARSHAL_CODE = `
|
|
|
938
952
|
return value;
|
|
939
953
|
}
|
|
940
954
|
|
|
941
|
-
// Unmarshal a value (Ref
|
|
955
|
+
// Unmarshal a value (Ref → JavaScript)
|
|
942
956
|
function unmarshalFromHost(value, depth = 0) {
|
|
943
957
|
if (depth > 100) throw new Error('Maximum unmarshalling depth exceeded');
|
|
944
958
|
|
|
@@ -1435,6 +1449,115 @@ function handleStreamError(message, connection) {
|
|
|
1435
1449
|
session.state = "closed";
|
|
1436
1450
|
connection.activeStreams.delete(message.streamId);
|
|
1437
1451
|
}
|
|
1452
|
+
const callbackReceiver = connection.callbackStreamReceivers.get(message.streamId);
|
|
1453
|
+
if (callbackReceiver && callbackReceiver.state === "active") {
|
|
1454
|
+
callbackReceiver.state = "errored";
|
|
1455
|
+
callbackReceiver.error = new Error(message.error);
|
|
1456
|
+
const resolvers = callbackReceiver.pullResolvers.splice(0);
|
|
1457
|
+
for (const resolver of resolvers) {
|
|
1458
|
+
resolver();
|
|
1459
|
+
}
|
|
1460
|
+
connection.callbackStreamReceivers.delete(message.streamId);
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
function handleCallbackStreamStart(message, connection) {
|
|
1464
|
+
const receiver = {
|
|
1465
|
+
streamId: message.streamId,
|
|
1466
|
+
requestId: message.requestId,
|
|
1467
|
+
metadata: message.metadata,
|
|
1468
|
+
controller: null,
|
|
1469
|
+
state: "active",
|
|
1470
|
+
pendingChunks: [],
|
|
1471
|
+
pullResolvers: [],
|
|
1472
|
+
controllerFinalized: false
|
|
1473
|
+
};
|
|
1474
|
+
const readableStream = new ReadableStream({
|
|
1475
|
+
start(controller) {
|
|
1476
|
+
receiver.controller = controller;
|
|
1477
|
+
},
|
|
1478
|
+
pull(_controller) {
|
|
1479
|
+
if (receiver.controllerFinalized) {
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
if (receiver.pendingChunks.length > 0) {
|
|
1483
|
+
const chunk = receiver.pendingChunks.shift();
|
|
1484
|
+
receiver.controller.enqueue(chunk);
|
|
1485
|
+
return Promise.resolve();
|
|
1486
|
+
}
|
|
1487
|
+
if (receiver.state === "closed") {
|
|
1488
|
+
if (!receiver.controllerFinalized) {
|
|
1489
|
+
receiver.controllerFinalized = true;
|
|
1490
|
+
receiver.controller.close();
|
|
1491
|
+
}
|
|
1492
|
+
return Promise.resolve();
|
|
1493
|
+
}
|
|
1494
|
+
if (receiver.state === "errored") {
|
|
1495
|
+
if (!receiver.controllerFinalized && receiver.error) {
|
|
1496
|
+
receiver.controllerFinalized = true;
|
|
1497
|
+
receiver.controller.error(receiver.error);
|
|
1498
|
+
}
|
|
1499
|
+
return Promise.resolve();
|
|
1500
|
+
}
|
|
1501
|
+
return new Promise((resolve) => {
|
|
1502
|
+
receiver.pullResolvers.push(resolve);
|
|
1503
|
+
});
|
|
1504
|
+
},
|
|
1505
|
+
cancel(_reason) {
|
|
1506
|
+
receiver.state = "closed";
|
|
1507
|
+
receiver.controllerFinalized = true;
|
|
1508
|
+
const resolvers = receiver.pullResolvers.splice(0);
|
|
1509
|
+
for (const resolver of resolvers) {
|
|
1510
|
+
resolver();
|
|
1511
|
+
}
|
|
1512
|
+
connection.callbackStreamReceivers.delete(message.streamId);
|
|
1513
|
+
return Promise.resolve();
|
|
1514
|
+
}
|
|
1515
|
+
});
|
|
1516
|
+
connection.callbackStreamReceivers.set(message.streamId, receiver);
|
|
1517
|
+
const pending = connection.pendingCallbacks.get(message.requestId);
|
|
1518
|
+
if (pending) {
|
|
1519
|
+
connection.pendingCallbacks.delete(message.requestId);
|
|
1520
|
+
if (pending.timeoutId) {
|
|
1521
|
+
clearTimeout(pending.timeoutId);
|
|
1522
|
+
}
|
|
1523
|
+
const response = new Response(readableStream, {
|
|
1524
|
+
status: message.metadata.status,
|
|
1525
|
+
statusText: message.metadata.statusText,
|
|
1526
|
+
headers: message.metadata.headers
|
|
1527
|
+
});
|
|
1528
|
+
pending.resolve({ __streamingResponse: true, response });
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
function handleCallbackStreamChunk(message, connection) {
|
|
1532
|
+
const receiver = connection.callbackStreamReceivers.get(message.streamId);
|
|
1533
|
+
if (receiver && receiver.state === "active") {
|
|
1534
|
+
if (receiver.pullResolvers.length > 0) {
|
|
1535
|
+
receiver.controller.enqueue(message.chunk);
|
|
1536
|
+
const resolver = receiver.pullResolvers.shift();
|
|
1537
|
+
resolver();
|
|
1538
|
+
} else {
|
|
1539
|
+
receiver.pendingChunks.push(message.chunk);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
function handleCallbackStreamEnd(message, connection) {
|
|
1544
|
+
const receiver = connection.callbackStreamReceivers.get(message.streamId);
|
|
1545
|
+
if (receiver) {
|
|
1546
|
+
receiver.state = "closed";
|
|
1547
|
+
while (receiver.pendingChunks.length > 0) {
|
|
1548
|
+
const chunk = receiver.pendingChunks.shift();
|
|
1549
|
+
receiver.controller.enqueue(chunk);
|
|
1550
|
+
}
|
|
1551
|
+
if (!receiver.controllerFinalized) {
|
|
1552
|
+
receiver.controllerFinalized = true;
|
|
1553
|
+
receiver.controller.close();
|
|
1554
|
+
}
|
|
1555
|
+
const resolvers = receiver.pullResolvers.splice(0);
|
|
1556
|
+
for (const resolver of resolvers) {
|
|
1557
|
+
resolver();
|
|
1558
|
+
}
|
|
1559
|
+
connection.callbackStreamReceivers.delete(message.streamId);
|
|
1560
|
+
}
|
|
1438
1561
|
}
|
|
1439
1562
|
function waitForCredit(session) {
|
|
1440
1563
|
return new Promise((resolve) => {
|
|
@@ -1662,4 +1785,4 @@ export {
|
|
|
1662
1785
|
handleConnection
|
|
1663
1786
|
};
|
|
1664
1787
|
|
|
1665
|
-
//# debugId=
|
|
1788
|
+
//# debugId=9E949C5B88C72B2F64756E2164756E21
|