almostnode 0.1.0
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/LICENSE +21 -0
- package/README.md +731 -0
- package/dist/__sw__.js +394 -0
- package/dist/ai-chatbot-demo-entry.d.ts +6 -0
- package/dist/ai-chatbot-demo-entry.d.ts.map +1 -0
- package/dist/ai-chatbot-demo.d.ts +42 -0
- package/dist/ai-chatbot-demo.d.ts.map +1 -0
- package/dist/assets/runtime-worker-D9x_Ddwz.js +60543 -0
- package/dist/assets/runtime-worker-D9x_Ddwz.js.map +1 -0
- package/dist/convex-app-demo-entry.d.ts +6 -0
- package/dist/convex-app-demo-entry.d.ts.map +1 -0
- package/dist/convex-app-demo.d.ts +68 -0
- package/dist/convex-app-demo.d.ts.map +1 -0
- package/dist/cors-proxy.d.ts +46 -0
- package/dist/cors-proxy.d.ts.map +1 -0
- package/dist/create-runtime.d.ts +42 -0
- package/dist/create-runtime.d.ts.map +1 -0
- package/dist/demo.d.ts +6 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/dev-server.d.ts +97 -0
- package/dist/dev-server.d.ts.map +1 -0
- package/dist/frameworks/next-dev-server.d.ts +202 -0
- package/dist/frameworks/next-dev-server.d.ts.map +1 -0
- package/dist/frameworks/vite-dev-server.d.ts +85 -0
- package/dist/frameworks/vite-dev-server.d.ts.map +1 -0
- package/dist/index.cjs +14965 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +14867 -0
- package/dist/index.mjs.map +1 -0
- package/dist/next-demo.d.ts +49 -0
- package/dist/next-demo.d.ts.map +1 -0
- package/dist/npm/index.d.ts +71 -0
- package/dist/npm/index.d.ts.map +1 -0
- package/dist/npm/registry.d.ts +66 -0
- package/dist/npm/registry.d.ts.map +1 -0
- package/dist/npm/resolver.d.ts +52 -0
- package/dist/npm/resolver.d.ts.map +1 -0
- package/dist/npm/tarball.d.ts +29 -0
- package/dist/npm/tarball.d.ts.map +1 -0
- package/dist/runtime-interface.d.ts +90 -0
- package/dist/runtime-interface.d.ts.map +1 -0
- package/dist/runtime.d.ts +103 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/sandbox-helpers.d.ts +43 -0
- package/dist/sandbox-helpers.d.ts.map +1 -0
- package/dist/sandbox-runtime.d.ts +65 -0
- package/dist/sandbox-runtime.d.ts.map +1 -0
- package/dist/server-bridge.d.ts +89 -0
- package/dist/server-bridge.d.ts.map +1 -0
- package/dist/shims/assert.d.ts +51 -0
- package/dist/shims/assert.d.ts.map +1 -0
- package/dist/shims/async_hooks.d.ts +37 -0
- package/dist/shims/async_hooks.d.ts.map +1 -0
- package/dist/shims/buffer.d.ts +20 -0
- package/dist/shims/buffer.d.ts.map +1 -0
- package/dist/shims/child_process-browser.d.ts +92 -0
- package/dist/shims/child_process-browser.d.ts.map +1 -0
- package/dist/shims/child_process.d.ts +93 -0
- package/dist/shims/child_process.d.ts.map +1 -0
- package/dist/shims/chokidar.d.ts +55 -0
- package/dist/shims/chokidar.d.ts.map +1 -0
- package/dist/shims/cluster.d.ts +52 -0
- package/dist/shims/cluster.d.ts.map +1 -0
- package/dist/shims/crypto.d.ts +122 -0
- package/dist/shims/crypto.d.ts.map +1 -0
- package/dist/shims/dgram.d.ts +34 -0
- package/dist/shims/dgram.d.ts.map +1 -0
- package/dist/shims/diagnostics_channel.d.ts +80 -0
- package/dist/shims/diagnostics_channel.d.ts.map +1 -0
- package/dist/shims/dns.d.ts +87 -0
- package/dist/shims/dns.d.ts.map +1 -0
- package/dist/shims/domain.d.ts +25 -0
- package/dist/shims/domain.d.ts.map +1 -0
- package/dist/shims/esbuild.d.ts +105 -0
- package/dist/shims/esbuild.d.ts.map +1 -0
- package/dist/shims/events.d.ts +37 -0
- package/dist/shims/events.d.ts.map +1 -0
- package/dist/shims/fs.d.ts +115 -0
- package/dist/shims/fs.d.ts.map +1 -0
- package/dist/shims/fsevents.d.ts +67 -0
- package/dist/shims/fsevents.d.ts.map +1 -0
- package/dist/shims/http.d.ts +217 -0
- package/dist/shims/http.d.ts.map +1 -0
- package/dist/shims/http2.d.ts +81 -0
- package/dist/shims/http2.d.ts.map +1 -0
- package/dist/shims/https.d.ts +36 -0
- package/dist/shims/https.d.ts.map +1 -0
- package/dist/shims/inspector.d.ts +25 -0
- package/dist/shims/inspector.d.ts.map +1 -0
- package/dist/shims/module.d.ts +22 -0
- package/dist/shims/module.d.ts.map +1 -0
- package/dist/shims/net.d.ts +100 -0
- package/dist/shims/net.d.ts.map +1 -0
- package/dist/shims/os.d.ts +159 -0
- package/dist/shims/os.d.ts.map +1 -0
- package/dist/shims/path.d.ts +72 -0
- package/dist/shims/path.d.ts.map +1 -0
- package/dist/shims/perf_hooks.d.ts +50 -0
- package/dist/shims/perf_hooks.d.ts.map +1 -0
- package/dist/shims/process.d.ts +93 -0
- package/dist/shims/process.d.ts.map +1 -0
- package/dist/shims/querystring.d.ts +23 -0
- package/dist/shims/querystring.d.ts.map +1 -0
- package/dist/shims/readdirp.d.ts +52 -0
- package/dist/shims/readdirp.d.ts.map +1 -0
- package/dist/shims/readline.d.ts +62 -0
- package/dist/shims/readline.d.ts.map +1 -0
- package/dist/shims/rollup.d.ts +34 -0
- package/dist/shims/rollup.d.ts.map +1 -0
- package/dist/shims/sentry.d.ts +163 -0
- package/dist/shims/sentry.d.ts.map +1 -0
- package/dist/shims/stream.d.ts +181 -0
- package/dist/shims/stream.d.ts.map +1 -0
- package/dist/shims/tls.d.ts +53 -0
- package/dist/shims/tls.d.ts.map +1 -0
- package/dist/shims/tty.d.ts +30 -0
- package/dist/shims/tty.d.ts.map +1 -0
- package/dist/shims/url.d.ts +64 -0
- package/dist/shims/url.d.ts.map +1 -0
- package/dist/shims/util.d.ts +106 -0
- package/dist/shims/util.d.ts.map +1 -0
- package/dist/shims/v8.d.ts +73 -0
- package/dist/shims/v8.d.ts.map +1 -0
- package/dist/shims/vfs-adapter.d.ts +126 -0
- package/dist/shims/vfs-adapter.d.ts.map +1 -0
- package/dist/shims/vm.d.ts +45 -0
- package/dist/shims/vm.d.ts.map +1 -0
- package/dist/shims/worker_threads.d.ts +66 -0
- package/dist/shims/worker_threads.d.ts.map +1 -0
- package/dist/shims/ws.d.ts +66 -0
- package/dist/shims/ws.d.ts.map +1 -0
- package/dist/shims/zlib.d.ts +161 -0
- package/dist/shims/zlib.d.ts.map +1 -0
- package/dist/transform.d.ts +24 -0
- package/dist/transform.d.ts.map +1 -0
- package/dist/virtual-fs.d.ts +226 -0
- package/dist/virtual-fs.d.ts.map +1 -0
- package/dist/vite-demo.d.ts +35 -0
- package/dist/vite-demo.d.ts.map +1 -0
- package/dist/vite-sw.js +132 -0
- package/dist/worker/runtime-worker.d.ts +8 -0
- package/dist/worker/runtime-worker.d.ts.map +1 -0
- package/dist/worker-runtime.d.ts +50 -0
- package/dist/worker-runtime.d.ts.map +1 -0
- package/package.json +85 -0
- package/src/ai-chatbot-demo-entry.ts +244 -0
- package/src/ai-chatbot-demo.ts +509 -0
- package/src/convex-app-demo-entry.ts +1107 -0
- package/src/convex-app-demo.ts +1316 -0
- package/src/cors-proxy.ts +81 -0
- package/src/create-runtime.ts +147 -0
- package/src/demo.ts +304 -0
- package/src/dev-server.ts +274 -0
- package/src/frameworks/next-dev-server.ts +2224 -0
- package/src/frameworks/vite-dev-server.ts +702 -0
- package/src/index.ts +101 -0
- package/src/next-demo.ts +1784 -0
- package/src/npm/index.ts +347 -0
- package/src/npm/registry.ts +152 -0
- package/src/npm/resolver.ts +385 -0
- package/src/npm/tarball.ts +209 -0
- package/src/runtime-interface.ts +103 -0
- package/src/runtime.ts +1046 -0
- package/src/sandbox-helpers.ts +173 -0
- package/src/sandbox-runtime.ts +252 -0
- package/src/server-bridge.ts +426 -0
- package/src/shims/assert.ts +664 -0
- package/src/shims/async_hooks.ts +86 -0
- package/src/shims/buffer.ts +75 -0
- package/src/shims/child_process-browser.ts +217 -0
- package/src/shims/child_process.ts +463 -0
- package/src/shims/chokidar.ts +313 -0
- package/src/shims/cluster.ts +67 -0
- package/src/shims/crypto.ts +830 -0
- package/src/shims/dgram.ts +47 -0
- package/src/shims/diagnostics_channel.ts +196 -0
- package/src/shims/dns.ts +172 -0
- package/src/shims/domain.ts +58 -0
- package/src/shims/esbuild.ts +805 -0
- package/src/shims/events.ts +195 -0
- package/src/shims/fs.ts +803 -0
- package/src/shims/fsevents.ts +63 -0
- package/src/shims/http.ts +904 -0
- package/src/shims/http2.ts +96 -0
- package/src/shims/https.ts +86 -0
- package/src/shims/inspector.ts +30 -0
- package/src/shims/module.ts +82 -0
- package/src/shims/net.ts +359 -0
- package/src/shims/os.ts +195 -0
- package/src/shims/path.ts +199 -0
- package/src/shims/perf_hooks.ts +92 -0
- package/src/shims/process.ts +346 -0
- package/src/shims/querystring.ts +97 -0
- package/src/shims/readdirp.ts +228 -0
- package/src/shims/readline.ts +110 -0
- package/src/shims/rollup.ts +80 -0
- package/src/shims/sentry.ts +133 -0
- package/src/shims/stream.ts +1126 -0
- package/src/shims/tls.ts +95 -0
- package/src/shims/tty.ts +64 -0
- package/src/shims/url.ts +171 -0
- package/src/shims/util.ts +312 -0
- package/src/shims/v8.ts +113 -0
- package/src/shims/vfs-adapter.ts +402 -0
- package/src/shims/vm.ts +83 -0
- package/src/shims/worker_threads.ts +111 -0
- package/src/shims/ws.ts +382 -0
- package/src/shims/zlib.ts +289 -0
- package/src/transform.ts +313 -0
- package/src/types/external.d.ts +67 -0
- package/src/virtual-fs.ts +903 -0
- package/src/vite-demo.ts +577 -0
- package/src/worker/runtime-worker.ts +128 -0
- package/src/worker-runtime.ts +145 -0
package/src/shims/v8.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v8 shim - V8 engine internals are not available in browser
|
|
3
|
+
* Provides stubs for common usage patterns
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Heap statistics stub
|
|
7
|
+
export function getHeapStatistics() {
|
|
8
|
+
return {
|
|
9
|
+
total_heap_size: 0,
|
|
10
|
+
total_heap_size_executable: 0,
|
|
11
|
+
total_physical_size: 0,
|
|
12
|
+
total_available_size: 0,
|
|
13
|
+
used_heap_size: 0,
|
|
14
|
+
heap_size_limit: 0,
|
|
15
|
+
malloced_memory: 0,
|
|
16
|
+
peak_malloced_memory: 0,
|
|
17
|
+
does_zap_garbage: 0,
|
|
18
|
+
number_of_native_contexts: 0,
|
|
19
|
+
number_of_detached_contexts: 0,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getHeapSpaceStatistics() {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getHeapCodeStatistics() {
|
|
28
|
+
return {
|
|
29
|
+
code_and_metadata_size: 0,
|
|
30
|
+
bytecode_and_metadata_size: 0,
|
|
31
|
+
external_script_source_size: 0,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getHeapSnapshot() {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function writeHeapSnapshot() {
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function setFlagsFromString(_flags: string) {
|
|
44
|
+
// No-op
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function takeCoverage() {
|
|
48
|
+
// No-op
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function stopCoverage() {
|
|
52
|
+
// No-op
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Serialization (basic stubs)
|
|
56
|
+
export function serialize(value: unknown): Buffer {
|
|
57
|
+
const json = JSON.stringify(value);
|
|
58
|
+
return Buffer.from(json);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function deserialize(buffer: Buffer): unknown {
|
|
62
|
+
return JSON.parse(buffer.toString());
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export class Serializer {
|
|
66
|
+
writeHeader() {}
|
|
67
|
+
writeValue(_value: unknown) {}
|
|
68
|
+
releaseBuffer(): Buffer {
|
|
69
|
+
return Buffer.from('');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class Deserializer {
|
|
74
|
+
constructor(_buffer: Buffer) {}
|
|
75
|
+
readHeader(): boolean {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
readValue(): unknown {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export class DefaultSerializer extends Serializer {}
|
|
84
|
+
export class DefaultDeserializer extends Deserializer {}
|
|
85
|
+
|
|
86
|
+
// Promise hooks (stubs)
|
|
87
|
+
export function promiseHooks() {
|
|
88
|
+
return {
|
|
89
|
+
onInit: () => {},
|
|
90
|
+
onSettled: () => {},
|
|
91
|
+
onBefore: () => {},
|
|
92
|
+
onAfter: () => {},
|
|
93
|
+
createHook: () => ({ enable: () => {}, disable: () => {} }),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export default {
|
|
98
|
+
getHeapStatistics,
|
|
99
|
+
getHeapSpaceStatistics,
|
|
100
|
+
getHeapCodeStatistics,
|
|
101
|
+
getHeapSnapshot,
|
|
102
|
+
writeHeapSnapshot,
|
|
103
|
+
setFlagsFromString,
|
|
104
|
+
takeCoverage,
|
|
105
|
+
stopCoverage,
|
|
106
|
+
serialize,
|
|
107
|
+
deserialize,
|
|
108
|
+
Serializer,
|
|
109
|
+
Deserializer,
|
|
110
|
+
DefaultSerializer,
|
|
111
|
+
DefaultDeserializer,
|
|
112
|
+
promiseHooks,
|
|
113
|
+
};
|
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VirtualFS Adapter for just-bash
|
|
3
|
+
* Implements IFileSystem interface to bridge VirtualFS with just-bash
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
IFileSystem,
|
|
8
|
+
FsStat,
|
|
9
|
+
MkdirOptions,
|
|
10
|
+
RmOptions,
|
|
11
|
+
CpOptions,
|
|
12
|
+
BufferEncoding,
|
|
13
|
+
FileContent,
|
|
14
|
+
} from 'just-bash';
|
|
15
|
+
import type { VirtualFS } from '../virtual-fs';
|
|
16
|
+
import { createNodeError } from '../virtual-fs';
|
|
17
|
+
|
|
18
|
+
// Local types for just-bash interface compatibility
|
|
19
|
+
// These are not exported from just-bash main entry point
|
|
20
|
+
interface DirentEntry {
|
|
21
|
+
name: string;
|
|
22
|
+
isFile: boolean;
|
|
23
|
+
isDirectory: boolean;
|
|
24
|
+
isSymbolicLink: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface ReadFileOptions {
|
|
28
|
+
encoding?: BufferEncoding | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface WriteFileOptions {
|
|
32
|
+
encoding?: BufferEncoding;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class VirtualFSAdapter implements IFileSystem {
|
|
36
|
+
constructor(private vfs: VirtualFS) {}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Read the contents of a file as a string
|
|
40
|
+
*/
|
|
41
|
+
async readFile(
|
|
42
|
+
path: string,
|
|
43
|
+
options?: ReadFileOptions | BufferEncoding
|
|
44
|
+
): Promise<string> {
|
|
45
|
+
const encoding = typeof options === 'string' ? options : options?.encoding;
|
|
46
|
+
|
|
47
|
+
// VirtualFS only natively supports utf8/utf-8
|
|
48
|
+
// For other encodings, we need to handle the conversion ourselves
|
|
49
|
+
if (!encoding || encoding === 'utf8' || encoding === 'utf-8') {
|
|
50
|
+
return this.vfs.readFileSync(path, 'utf8');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// For binary/latin1 encoding, convert each byte to a character
|
|
54
|
+
if (encoding === 'binary' || encoding === 'latin1') {
|
|
55
|
+
const buffer = this.vfs.readFileSync(path);
|
|
56
|
+
return String.fromCharCode(...buffer);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// For other encodings, fall back to utf8
|
|
60
|
+
return this.vfs.readFileSync(path, 'utf8');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Read the contents of a file as a Uint8Array (binary)
|
|
65
|
+
*/
|
|
66
|
+
async readFileBuffer(path: string): Promise<Uint8Array> {
|
|
67
|
+
return this.vfs.readFileSync(path);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Write content to a file, creating it if it doesn't exist
|
|
72
|
+
*/
|
|
73
|
+
async writeFile(
|
|
74
|
+
path: string,
|
|
75
|
+
content: FileContent,
|
|
76
|
+
_options?: WriteFileOptions | BufferEncoding
|
|
77
|
+
): Promise<void> {
|
|
78
|
+
this.vfs.writeFileSync(path, content);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Append content to a file, creating it if it doesn't exist
|
|
83
|
+
*/
|
|
84
|
+
async appendFile(
|
|
85
|
+
path: string,
|
|
86
|
+
content: FileContent,
|
|
87
|
+
_options?: WriteFileOptions | BufferEncoding
|
|
88
|
+
): Promise<void> {
|
|
89
|
+
let existing = '';
|
|
90
|
+
try {
|
|
91
|
+
existing = this.vfs.readFileSync(path, 'utf8');
|
|
92
|
+
} catch {
|
|
93
|
+
// File doesn't exist, start with empty content
|
|
94
|
+
}
|
|
95
|
+
const newContent =
|
|
96
|
+
typeof content === 'string' ? content : new TextDecoder().decode(content);
|
|
97
|
+
this.vfs.writeFileSync(path, existing + newContent);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Check if a path exists
|
|
102
|
+
*/
|
|
103
|
+
async exists(path: string): Promise<boolean> {
|
|
104
|
+
return this.vfs.existsSync(path);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get file/directory information
|
|
109
|
+
*/
|
|
110
|
+
async stat(path: string): Promise<FsStat> {
|
|
111
|
+
const stats = this.vfs.statSync(path);
|
|
112
|
+
const isFile = stats.isFile();
|
|
113
|
+
const isDirectory = stats.isDirectory();
|
|
114
|
+
|
|
115
|
+
let size = 0;
|
|
116
|
+
if (isFile) {
|
|
117
|
+
try {
|
|
118
|
+
const content = this.vfs.readFileSync(path);
|
|
119
|
+
size = content.length;
|
|
120
|
+
} catch {
|
|
121
|
+
// Shouldn't happen, but default to 0
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
isFile,
|
|
127
|
+
isDirectory,
|
|
128
|
+
isSymbolicLink: false,
|
|
129
|
+
mode: isDirectory ? 0o755 : 0o644,
|
|
130
|
+
size,
|
|
131
|
+
mtime: new Date(),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Create a directory
|
|
137
|
+
*/
|
|
138
|
+
async mkdir(path: string, options?: MkdirOptions): Promise<void> {
|
|
139
|
+
this.vfs.mkdirSync(path, options);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Read directory contents
|
|
144
|
+
*/
|
|
145
|
+
async readdir(path: string): Promise<string[]> {
|
|
146
|
+
return this.vfs.readdirSync(path);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Read directory contents with file type information
|
|
151
|
+
*/
|
|
152
|
+
async readdirWithFileTypes(path: string): Promise<DirentEntry[]> {
|
|
153
|
+
const entries = this.vfs.readdirSync(path);
|
|
154
|
+
const result: DirentEntry[] = [];
|
|
155
|
+
|
|
156
|
+
for (const name of entries) {
|
|
157
|
+
const fullPath = path === '/' ? `/${name}` : `${path}/${name}`;
|
|
158
|
+
try {
|
|
159
|
+
const stats = this.vfs.statSync(fullPath);
|
|
160
|
+
result.push({
|
|
161
|
+
name,
|
|
162
|
+
isFile: stats.isFile(),
|
|
163
|
+
isDirectory: stats.isDirectory(),
|
|
164
|
+
isSymbolicLink: false,
|
|
165
|
+
});
|
|
166
|
+
} catch {
|
|
167
|
+
// Entry disappeared between readdir and stat, skip it
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Remove a file or directory
|
|
176
|
+
*/
|
|
177
|
+
async rm(path: string, options?: RmOptions): Promise<void> {
|
|
178
|
+
const exists = this.vfs.existsSync(path);
|
|
179
|
+
|
|
180
|
+
if (!exists) {
|
|
181
|
+
if (options?.force) {
|
|
182
|
+
return; // Force mode ignores missing files
|
|
183
|
+
}
|
|
184
|
+
throw createNodeError('ENOENT', 'rm', path);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const stats = this.vfs.statSync(path);
|
|
188
|
+
|
|
189
|
+
if (stats.isFile()) {
|
|
190
|
+
this.vfs.unlinkSync(path);
|
|
191
|
+
} else if (stats.isDirectory()) {
|
|
192
|
+
if (options?.recursive) {
|
|
193
|
+
await this.rmRecursive(path);
|
|
194
|
+
} else {
|
|
195
|
+
this.vfs.rmdirSync(path);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Recursively remove a directory and its contents
|
|
202
|
+
*/
|
|
203
|
+
private async rmRecursive(path: string): Promise<void> {
|
|
204
|
+
const entries = this.vfs.readdirSync(path);
|
|
205
|
+
|
|
206
|
+
for (const entry of entries) {
|
|
207
|
+
const fullPath = path === '/' ? `/${entry}` : `${path}/${entry}`;
|
|
208
|
+
const stats = this.vfs.statSync(fullPath);
|
|
209
|
+
|
|
210
|
+
if (stats.isDirectory()) {
|
|
211
|
+
await this.rmRecursive(fullPath);
|
|
212
|
+
} else {
|
|
213
|
+
this.vfs.unlinkSync(fullPath);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
this.vfs.rmdirSync(path);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Copy a file or directory
|
|
222
|
+
*/
|
|
223
|
+
async cp(src: string, dest: string, options?: CpOptions): Promise<void> {
|
|
224
|
+
const stats = this.vfs.statSync(src);
|
|
225
|
+
|
|
226
|
+
if (stats.isFile()) {
|
|
227
|
+
const content = this.vfs.readFileSync(src);
|
|
228
|
+
this.vfs.writeFileSync(dest, content);
|
|
229
|
+
} else if (stats.isDirectory()) {
|
|
230
|
+
if (!options?.recursive) {
|
|
231
|
+
throw new Error(
|
|
232
|
+
`EISDIR: illegal operation on a directory, cannot copy '${src}'`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
await this.cpRecursive(src, dest);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Recursively copy a directory
|
|
241
|
+
*/
|
|
242
|
+
private async cpRecursive(src: string, dest: string): Promise<void> {
|
|
243
|
+
// Create destination directory
|
|
244
|
+
this.vfs.mkdirSync(dest, { recursive: true });
|
|
245
|
+
|
|
246
|
+
const entries = this.vfs.readdirSync(src);
|
|
247
|
+
|
|
248
|
+
for (const entry of entries) {
|
|
249
|
+
const srcPath = src === '/' ? `/${entry}` : `${src}/${entry}`;
|
|
250
|
+
const destPath = dest === '/' ? `/${entry}` : `${dest}/${entry}`;
|
|
251
|
+
const stats = this.vfs.statSync(srcPath);
|
|
252
|
+
|
|
253
|
+
if (stats.isDirectory()) {
|
|
254
|
+
await this.cpRecursive(srcPath, destPath);
|
|
255
|
+
} else {
|
|
256
|
+
const content = this.vfs.readFileSync(srcPath);
|
|
257
|
+
this.vfs.writeFileSync(destPath, content);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Move/rename a file or directory
|
|
264
|
+
*/
|
|
265
|
+
async mv(src: string, dest: string): Promise<void> {
|
|
266
|
+
this.vfs.renameSync(src, dest);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Resolve a relative path against a base path
|
|
271
|
+
*/
|
|
272
|
+
resolvePath(base: string, path: string): string {
|
|
273
|
+
// If path is absolute, return it as-is (normalized)
|
|
274
|
+
if (path.startsWith('/')) {
|
|
275
|
+
return this.normalizePath(path);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Combine base and relative path
|
|
279
|
+
const combined = base.endsWith('/')
|
|
280
|
+
? `${base}${path}`
|
|
281
|
+
: `${base}/${path}`;
|
|
282
|
+
|
|
283
|
+
return this.normalizePath(combined);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Normalize a path (resolve . and .. segments)
|
|
288
|
+
*/
|
|
289
|
+
private normalizePath(path: string): string {
|
|
290
|
+
if (!path.startsWith('/')) {
|
|
291
|
+
path = '/' + path;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const parts = path.split('/').filter(Boolean);
|
|
295
|
+
const resolved: string[] = [];
|
|
296
|
+
|
|
297
|
+
for (const part of parts) {
|
|
298
|
+
if (part === '..') {
|
|
299
|
+
resolved.pop();
|
|
300
|
+
} else if (part !== '.') {
|
|
301
|
+
resolved.push(part);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return '/' + resolved.join('/');
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Get all paths in the filesystem
|
|
310
|
+
*/
|
|
311
|
+
getAllPaths(): string[] {
|
|
312
|
+
const paths: string[] = [];
|
|
313
|
+
this.collectPaths('/', paths);
|
|
314
|
+
return paths;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Recursively collect all paths
|
|
319
|
+
*/
|
|
320
|
+
private collectPaths(dir: string, paths: string[]): void {
|
|
321
|
+
try {
|
|
322
|
+
const entries = this.vfs.readdirSync(dir);
|
|
323
|
+
for (const entry of entries) {
|
|
324
|
+
const fullPath = dir === '/' ? `/${entry}` : `${dir}/${entry}`;
|
|
325
|
+
paths.push(fullPath);
|
|
326
|
+
try {
|
|
327
|
+
const stats = this.vfs.statSync(fullPath);
|
|
328
|
+
if (stats.isDirectory()) {
|
|
329
|
+
this.collectPaths(fullPath, paths);
|
|
330
|
+
}
|
|
331
|
+
} catch {
|
|
332
|
+
// Skip if stat fails
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
} catch {
|
|
336
|
+
// Directory doesn't exist or can't be read
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Change file/directory permissions (no-op - VFS doesn't track permissions)
|
|
342
|
+
*/
|
|
343
|
+
async chmod(_path: string, _mode: number): Promise<void> {
|
|
344
|
+
// VFS doesn't track permissions, but we verify the path exists
|
|
345
|
+
if (!this.vfs.existsSync(_path)) {
|
|
346
|
+
throw createNodeError('ENOENT', 'chmod', _path);
|
|
347
|
+
}
|
|
348
|
+
// No-op
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Create a symbolic link (not supported)
|
|
353
|
+
*/
|
|
354
|
+
async symlink(_target: string, _linkPath: string): Promise<void> {
|
|
355
|
+
throw new Error('Symbolic links are not supported in VirtualFS');
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Create a hard link (not supported)
|
|
360
|
+
*/
|
|
361
|
+
async link(_existingPath: string, _newPath: string): Promise<void> {
|
|
362
|
+
throw new Error('Hard links are not supported in VirtualFS');
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Read the target of a symbolic link (not supported)
|
|
367
|
+
*/
|
|
368
|
+
async readlink(_path: string): Promise<string> {
|
|
369
|
+
throw new Error('Symbolic links are not supported in VirtualFS');
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Get file/directory information without following symlinks
|
|
374
|
+
* Since VFS doesn't support symlinks, this is the same as stat
|
|
375
|
+
*/
|
|
376
|
+
async lstat(path: string): Promise<FsStat> {
|
|
377
|
+
return this.stat(path);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Resolve all symlinks in a path
|
|
382
|
+
* Since VFS doesn't support symlinks, just normalize and return
|
|
383
|
+
*/
|
|
384
|
+
async realpath(path: string): Promise<string> {
|
|
385
|
+
// Verify path exists
|
|
386
|
+
if (!this.vfs.existsSync(path)) {
|
|
387
|
+
throw createNodeError('ENOENT', 'realpath', path);
|
|
388
|
+
}
|
|
389
|
+
return this.normalizePath(path);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Set access and modification times (no-op - VFS doesn't track times)
|
|
394
|
+
*/
|
|
395
|
+
async utimes(path: string, _atime: Date, _mtime: Date): Promise<void> {
|
|
396
|
+
// VFS doesn't track times, but we verify the path exists
|
|
397
|
+
if (!this.vfs.existsSync(path)) {
|
|
398
|
+
throw createNodeError('ENOENT', 'utimes', path);
|
|
399
|
+
}
|
|
400
|
+
// No-op
|
|
401
|
+
}
|
|
402
|
+
}
|
package/src/shims/vm.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vm shim - Basic VM functionality using eval
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export class Script {
|
|
6
|
+
private code: string;
|
|
7
|
+
|
|
8
|
+
constructor(code: string, _options?: object) {
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
runInThisContext(_options?: object): unknown {
|
|
13
|
+
return eval(this.code);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
runInNewContext(contextObject?: object, _options?: object): unknown {
|
|
17
|
+
const keys = contextObject ? Object.keys(contextObject) : [];
|
|
18
|
+
const values = contextObject ? Object.values(contextObject) : [];
|
|
19
|
+
const fn = new Function(...keys, `return eval(${JSON.stringify(this.code)})`);
|
|
20
|
+
return fn(...values);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
runInContext(_context: object, _options?: object): unknown {
|
|
24
|
+
return this.runInNewContext(_context, _options);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
createCachedData(): Buffer {
|
|
28
|
+
return Buffer.from('');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function createContext(contextObject?: object, _options?: object): object {
|
|
33
|
+
return contextObject || {};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function isContext(_sandbox: object): boolean {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function runInThisContext(code: string, _options?: object): unknown {
|
|
41
|
+
return eval(code);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function runInNewContext(code: string, contextObject?: object, _options?: object): unknown {
|
|
45
|
+
const script = new Script(code);
|
|
46
|
+
return script.runInNewContext(contextObject);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function runInContext(code: string, context: object, _options?: object): unknown {
|
|
50
|
+
return runInNewContext(code, context);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function compileFunction(code: string, params?: string[], _options?: object): Function {
|
|
54
|
+
return new Function(...(params || []), code);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class Module {
|
|
58
|
+
constructor(_code: string, _options?: object) {}
|
|
59
|
+
link(_linker: unknown): Promise<void> { return Promise.resolve(); }
|
|
60
|
+
evaluate(_options?: object): Promise<unknown> { return Promise.resolve(); }
|
|
61
|
+
get status(): string { return 'unlinked'; }
|
|
62
|
+
get identifier(): string { return ''; }
|
|
63
|
+
get context(): object { return {}; }
|
|
64
|
+
get namespace(): object { return {}; }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export class SourceTextModule extends Module {}
|
|
68
|
+
export class SyntheticModule extends Module {
|
|
69
|
+
setExport(_name: string, _value: unknown): void {}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export default {
|
|
73
|
+
Script,
|
|
74
|
+
createContext,
|
|
75
|
+
isContext,
|
|
76
|
+
runInThisContext,
|
|
77
|
+
runInNewContext,
|
|
78
|
+
runInContext,
|
|
79
|
+
compileFunction,
|
|
80
|
+
Module,
|
|
81
|
+
SourceTextModule,
|
|
82
|
+
SyntheticModule,
|
|
83
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* worker_threads shim - Worker threads API
|
|
3
|
+
* Stub implementation for browser environment
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { EventEmitter } from './events';
|
|
7
|
+
|
|
8
|
+
export const isMainThread = true;
|
|
9
|
+
export const parentPort = null;
|
|
10
|
+
export const workerData = null;
|
|
11
|
+
export const threadId = 0;
|
|
12
|
+
|
|
13
|
+
export class Worker extends EventEmitter {
|
|
14
|
+
threadId = 0;
|
|
15
|
+
resourceLimits = {};
|
|
16
|
+
|
|
17
|
+
constructor(filename: string, options?: { workerData?: unknown }) {
|
|
18
|
+
super();
|
|
19
|
+
console.warn('Worker threads are not fully supported in browser environment');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
postMessage(value: unknown, transferList?: unknown[]): void {
|
|
23
|
+
// No-op
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
terminate(): Promise<number> {
|
|
27
|
+
return Promise.resolve(0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
ref(): void {}
|
|
31
|
+
unref(): void {}
|
|
32
|
+
|
|
33
|
+
getHeapSnapshot(): Promise<unknown> {
|
|
34
|
+
return Promise.resolve({});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class MessageChannel {
|
|
39
|
+
port1 = new MessagePort();
|
|
40
|
+
port2 = new MessagePort();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class MessagePort extends EventEmitter {
|
|
44
|
+
postMessage(value: unknown, transferList?: unknown[]): void {
|
|
45
|
+
// No-op
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
start(): void {}
|
|
49
|
+
close(): void {}
|
|
50
|
+
ref(): void {}
|
|
51
|
+
unref(): void {}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class BroadcastChannel extends EventEmitter {
|
|
55
|
+
name: string;
|
|
56
|
+
|
|
57
|
+
constructor(name: string) {
|
|
58
|
+
super();
|
|
59
|
+
this.name = name;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
postMessage(message: unknown): void {
|
|
63
|
+
// No-op in single-threaded environment
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
close(): void {}
|
|
67
|
+
ref(): void {}
|
|
68
|
+
unref(): void {}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function moveMessagePortToContext(
|
|
72
|
+
port: MessagePort,
|
|
73
|
+
contextifiedSandbox: unknown
|
|
74
|
+
): MessagePort {
|
|
75
|
+
return port;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function receiveMessageOnPort(port: MessagePort): { message: unknown } | undefined {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const SHARE_ENV = Symbol.for('nodejs.worker_threads.SHARE_ENV');
|
|
83
|
+
|
|
84
|
+
export function markAsUntransferable(object: unknown): void {
|
|
85
|
+
// No-op
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function getEnvironmentData(key: unknown): unknown {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function setEnvironmentData(key: unknown, value: unknown): void {
|
|
93
|
+
// No-op
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default {
|
|
97
|
+
isMainThread,
|
|
98
|
+
parentPort,
|
|
99
|
+
workerData,
|
|
100
|
+
threadId,
|
|
101
|
+
Worker,
|
|
102
|
+
MessageChannel,
|
|
103
|
+
MessagePort,
|
|
104
|
+
BroadcastChannel,
|
|
105
|
+
moveMessagePortToContext,
|
|
106
|
+
receiveMessageOnPort,
|
|
107
|
+
SHARE_ENV,
|
|
108
|
+
markAsUntransferable,
|
|
109
|
+
getEnvironmentData,
|
|
110
|
+
setEnvironmentData,
|
|
111
|
+
};
|