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
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js child_process module shim
|
|
3
|
+
* Uses just-bash for command execution in browser with VirtualFS adapter
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Polyfill process for just-bash (it expects Node.js environment)
|
|
7
|
+
if (typeof globalThis.process === 'undefined') {
|
|
8
|
+
(globalThis as any).process = {
|
|
9
|
+
env: {
|
|
10
|
+
HOME: '/home/user',
|
|
11
|
+
USER: 'user',
|
|
12
|
+
PATH: '/usr/local/bin:/usr/bin:/bin',
|
|
13
|
+
NODE_ENV: 'development',
|
|
14
|
+
},
|
|
15
|
+
cwd: () => '/',
|
|
16
|
+
platform: 'linux',
|
|
17
|
+
version: 'v18.0.0',
|
|
18
|
+
versions: { node: '18.0.0' },
|
|
19
|
+
stdout: { write: () => {} },
|
|
20
|
+
stderr: { write: () => {} },
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
import { Bash, defineCommand } from 'just-bash';
|
|
25
|
+
import { EventEmitter } from './events';
|
|
26
|
+
import { Readable, Writable, Buffer } from './stream';
|
|
27
|
+
import type { VirtualFS } from '../virtual-fs';
|
|
28
|
+
import { VirtualFSAdapter } from './vfs-adapter';
|
|
29
|
+
import { Runtime } from '../runtime';
|
|
30
|
+
|
|
31
|
+
// Singleton bash instance - uses VFS adapter for two-way file sync
|
|
32
|
+
let bashInstance: Bash | null = null;
|
|
33
|
+
let vfsAdapter: VirtualFSAdapter | null = null;
|
|
34
|
+
let currentVfs: VirtualFS | null = null;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Initialize the child_process shim with a VirtualFS instance
|
|
38
|
+
* Creates a single Bash instance with VirtualFSAdapter for efficient file access
|
|
39
|
+
*/
|
|
40
|
+
export function initChildProcess(vfs: VirtualFS): void {
|
|
41
|
+
currentVfs = vfs;
|
|
42
|
+
vfsAdapter = new VirtualFSAdapter(vfs);
|
|
43
|
+
|
|
44
|
+
// Create custom 'node' command that runs JS files using the Runtime
|
|
45
|
+
const nodeCommand = defineCommand('node', async (args, ctx) => {
|
|
46
|
+
if (!currentVfs) {
|
|
47
|
+
return { stdout: '', stderr: 'VFS not initialized\n', exitCode: 1 };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const scriptPath = args[0];
|
|
51
|
+
if (!scriptPath) {
|
|
52
|
+
return { stdout: '', stderr: 'Usage: node <script.js> [args...]\n', exitCode: 1 };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Resolve the script path
|
|
56
|
+
const resolvedPath = scriptPath.startsWith('/')
|
|
57
|
+
? scriptPath
|
|
58
|
+
: `${ctx.cwd}/${scriptPath}`.replace(/\/+/g, '/');
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
// Check if file exists
|
|
62
|
+
if (!currentVfs.existsSync(resolvedPath)) {
|
|
63
|
+
return { stdout: '', stderr: `Error: Cannot find module '${resolvedPath}'\n`, exitCode: 1 };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let stdout = '';
|
|
67
|
+
let stderr = '';
|
|
68
|
+
|
|
69
|
+
// Create a runtime with the current environment
|
|
70
|
+
const runtime = new Runtime(currentVfs, {
|
|
71
|
+
cwd: ctx.cwd,
|
|
72
|
+
env: ctx.env,
|
|
73
|
+
onConsole: (method, consoleArgs) => {
|
|
74
|
+
const msg = consoleArgs.map(a => String(a)).join(' ') + '\n';
|
|
75
|
+
if (method === 'error') {
|
|
76
|
+
stderr += msg;
|
|
77
|
+
} else {
|
|
78
|
+
stdout += msg;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Set up process.argv for the script
|
|
84
|
+
const processShim = (globalThis as any).process || {};
|
|
85
|
+
const originalArgv = processShim.argv;
|
|
86
|
+
processShim.argv = ['node', resolvedPath, ...args.slice(1)];
|
|
87
|
+
(globalThis as any).process = processShim;
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
// Run the script
|
|
91
|
+
runtime.runFile(resolvedPath);
|
|
92
|
+
return { stdout, stderr, exitCode: 0 };
|
|
93
|
+
} finally {
|
|
94
|
+
// Restore original argv
|
|
95
|
+
processShim.argv = originalArgv;
|
|
96
|
+
}
|
|
97
|
+
} catch (error) {
|
|
98
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
99
|
+
return { stdout: '', stderr: `Error: ${errorMsg}\n`, exitCode: 1 };
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Create custom 'convex' command that runs the Convex CLI
|
|
104
|
+
const convexCommand = defineCommand('convex', async (args, ctx) => {
|
|
105
|
+
if (!currentVfs) {
|
|
106
|
+
return { stdout: '', stderr: 'VFS not initialized\n', exitCode: 1 };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Find the Convex CLI bundle
|
|
110
|
+
const cliBundlePath = '/node_modules/convex/dist/cli.bundle.cjs';
|
|
111
|
+
if (!currentVfs.existsSync(cliBundlePath)) {
|
|
112
|
+
return { stdout: '', stderr: 'Convex CLI not found. Run: npm install convex\n', exitCode: 1 };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let stdout = '';
|
|
116
|
+
let stderr = '';
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
// Create a runtime with the current environment
|
|
120
|
+
const runtime = new Runtime(currentVfs, {
|
|
121
|
+
cwd: ctx.cwd,
|
|
122
|
+
env: ctx.env,
|
|
123
|
+
onConsole: (method, consoleArgs) => {
|
|
124
|
+
const msg = consoleArgs.map(a => String(a)).join(' ') + '\n';
|
|
125
|
+
if (method === 'error') {
|
|
126
|
+
stderr += msg;
|
|
127
|
+
} else {
|
|
128
|
+
stdout += msg;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Set up process.argv for the CLI
|
|
134
|
+
const processShim = (globalThis as any).process || {};
|
|
135
|
+
const originalArgv = processShim.argv;
|
|
136
|
+
const originalEnv = { ...processShim.env };
|
|
137
|
+
|
|
138
|
+
processShim.argv = ['node', 'convex', ...args];
|
|
139
|
+
processShim.env = { ...processShim.env, ...ctx.env };
|
|
140
|
+
(globalThis as any).process = processShim;
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
// Run the CLI bundle
|
|
144
|
+
runtime.runFile(cliBundlePath);
|
|
145
|
+
return { stdout, stderr, exitCode: 0 };
|
|
146
|
+
} finally {
|
|
147
|
+
// Restore original state
|
|
148
|
+
processShim.argv = originalArgv;
|
|
149
|
+
processShim.env = originalEnv;
|
|
150
|
+
}
|
|
151
|
+
} catch (error) {
|
|
152
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
153
|
+
return { stdout, stderr: stderr + `Error: ${errorMsg}\n`, exitCode: 1 };
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
bashInstance = new Bash({
|
|
158
|
+
fs: vfsAdapter,
|
|
159
|
+
cwd: '/',
|
|
160
|
+
env: {
|
|
161
|
+
HOME: '/home/user',
|
|
162
|
+
USER: 'user',
|
|
163
|
+
PATH: '/usr/local/bin:/usr/bin:/bin:/node_modules/.bin',
|
|
164
|
+
NODE_ENV: 'development',
|
|
165
|
+
},
|
|
166
|
+
customCommands: [nodeCommand, convexCommand],
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface ExecOptions {
|
|
171
|
+
cwd?: string;
|
|
172
|
+
env?: Record<string, string>;
|
|
173
|
+
encoding?: BufferEncoding | 'buffer';
|
|
174
|
+
timeout?: number;
|
|
175
|
+
maxBuffer?: number;
|
|
176
|
+
shell?: string | boolean;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface ExecResult {
|
|
180
|
+
stdout: string | Buffer;
|
|
181
|
+
stderr: string | Buffer;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export type ExecCallback = (
|
|
185
|
+
error: Error | null,
|
|
186
|
+
stdout: string | Buffer,
|
|
187
|
+
stderr: string | Buffer
|
|
188
|
+
) => void;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Execute a command in a shell
|
|
192
|
+
*/
|
|
193
|
+
export function exec(
|
|
194
|
+
command: string,
|
|
195
|
+
optionsOrCallback?: ExecOptions | ExecCallback,
|
|
196
|
+
callback?: ExecCallback
|
|
197
|
+
): ChildProcess {
|
|
198
|
+
let options: ExecOptions = {};
|
|
199
|
+
let cb: ExecCallback | undefined;
|
|
200
|
+
|
|
201
|
+
if (typeof optionsOrCallback === 'function') {
|
|
202
|
+
cb = optionsOrCallback;
|
|
203
|
+
} else if (optionsOrCallback) {
|
|
204
|
+
options = optionsOrCallback;
|
|
205
|
+
cb = callback;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const child = new ChildProcess();
|
|
209
|
+
|
|
210
|
+
// Execute asynchronously
|
|
211
|
+
(async () => {
|
|
212
|
+
if (!bashInstance) {
|
|
213
|
+
const error = new Error('child_process not initialized');
|
|
214
|
+
child.emit('error', error);
|
|
215
|
+
if (cb) cb(error, '', '');
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
const result = await bashInstance!.exec(command, {
|
|
221
|
+
cwd: options.cwd,
|
|
222
|
+
env: options.env,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const stdout = result.stdout || '';
|
|
226
|
+
const stderr = result.stderr || '';
|
|
227
|
+
|
|
228
|
+
// Emit data events
|
|
229
|
+
if (stdout) {
|
|
230
|
+
child.stdout?.push(Buffer.from(stdout));
|
|
231
|
+
}
|
|
232
|
+
child.stdout?.push(null);
|
|
233
|
+
|
|
234
|
+
if (stderr) {
|
|
235
|
+
child.stderr?.push(Buffer.from(stderr));
|
|
236
|
+
}
|
|
237
|
+
child.stderr?.push(null);
|
|
238
|
+
|
|
239
|
+
// Emit close/exit
|
|
240
|
+
child.emit('close', result.exitCode, null);
|
|
241
|
+
child.emit('exit', result.exitCode, null);
|
|
242
|
+
|
|
243
|
+
if (cb) {
|
|
244
|
+
if (result.exitCode !== 0) {
|
|
245
|
+
const error = new Error(`Command failed: ${command}`);
|
|
246
|
+
(error as any).code = result.exitCode;
|
|
247
|
+
cb(error, stdout, stderr);
|
|
248
|
+
} else {
|
|
249
|
+
cb(null, stdout, stderr);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
} catch (error) {
|
|
253
|
+
child.emit('error', error);
|
|
254
|
+
if (cb) cb(error as Error, '', '');
|
|
255
|
+
}
|
|
256
|
+
})();
|
|
257
|
+
|
|
258
|
+
return child;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Execute a command synchronously
|
|
263
|
+
*/
|
|
264
|
+
export function execSync(
|
|
265
|
+
command: string,
|
|
266
|
+
options?: ExecOptions
|
|
267
|
+
): string | Buffer {
|
|
268
|
+
if (!bashInstance) {
|
|
269
|
+
throw new Error('child_process not initialized');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Note: just-bash exec is async, so we can't truly do sync execution
|
|
273
|
+
// This is a limitation of the browser environment
|
|
274
|
+
// For now, throw an error suggesting to use exec() instead
|
|
275
|
+
throw new Error(
|
|
276
|
+
'execSync is not supported in browser environment. Use exec() with async/await or callbacks instead.'
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export interface SpawnOptions {
|
|
281
|
+
cwd?: string;
|
|
282
|
+
env?: Record<string, string>;
|
|
283
|
+
shell?: boolean | string;
|
|
284
|
+
stdio?: 'pipe' | 'inherit' | 'ignore' | Array<'pipe' | 'inherit' | 'ignore'>;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Spawn a new process
|
|
289
|
+
*/
|
|
290
|
+
export function spawn(
|
|
291
|
+
command: string,
|
|
292
|
+
args?: string[] | SpawnOptions,
|
|
293
|
+
options?: SpawnOptions
|
|
294
|
+
): ChildProcess {
|
|
295
|
+
let spawnArgs: string[] = [];
|
|
296
|
+
let spawnOptions: SpawnOptions = {};
|
|
297
|
+
|
|
298
|
+
if (Array.isArray(args)) {
|
|
299
|
+
spawnArgs = args;
|
|
300
|
+
spawnOptions = options || {};
|
|
301
|
+
} else if (args) {
|
|
302
|
+
spawnOptions = args;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const child = new ChildProcess();
|
|
306
|
+
|
|
307
|
+
// Build the full command
|
|
308
|
+
const fullCommand = spawnArgs.length > 0
|
|
309
|
+
? `${command} ${spawnArgs.map(arg =>
|
|
310
|
+
arg.includes(' ') ? `"${arg}"` : arg
|
|
311
|
+
).join(' ')}`
|
|
312
|
+
: command;
|
|
313
|
+
|
|
314
|
+
// Execute asynchronously
|
|
315
|
+
(async () => {
|
|
316
|
+
if (!bashInstance) {
|
|
317
|
+
const error = new Error('child_process not initialized');
|
|
318
|
+
child.emit('error', error);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
try {
|
|
323
|
+
const result = await bashInstance!.exec(fullCommand, {
|
|
324
|
+
cwd: spawnOptions.cwd,
|
|
325
|
+
env: spawnOptions.env,
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
const stdout = result.stdout || '';
|
|
329
|
+
const stderr = result.stderr || '';
|
|
330
|
+
|
|
331
|
+
// Emit data events
|
|
332
|
+
if (stdout) {
|
|
333
|
+
child.stdout?.push(Buffer.from(stdout));
|
|
334
|
+
}
|
|
335
|
+
child.stdout?.push(null);
|
|
336
|
+
|
|
337
|
+
if (stderr) {
|
|
338
|
+
child.stderr?.push(Buffer.from(stderr));
|
|
339
|
+
}
|
|
340
|
+
child.stderr?.push(null);
|
|
341
|
+
|
|
342
|
+
// Emit close/exit
|
|
343
|
+
child.emit('close', result.exitCode, null);
|
|
344
|
+
child.emit('exit', result.exitCode, null);
|
|
345
|
+
} catch (error) {
|
|
346
|
+
child.emit('error', error);
|
|
347
|
+
}
|
|
348
|
+
})();
|
|
349
|
+
|
|
350
|
+
return child;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Spawn a new process synchronously
|
|
355
|
+
*/
|
|
356
|
+
export function spawnSync(
|
|
357
|
+
command: string,
|
|
358
|
+
args?: string[],
|
|
359
|
+
options?: SpawnOptions
|
|
360
|
+
): { stdout: Buffer; stderr: Buffer; status: number; error?: Error } {
|
|
361
|
+
throw new Error(
|
|
362
|
+
'spawnSync is not supported in browser environment. Use spawn() instead.'
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Execute a file
|
|
368
|
+
*/
|
|
369
|
+
export function execFile(
|
|
370
|
+
file: string,
|
|
371
|
+
args?: string[] | ExecOptions | ExecCallback,
|
|
372
|
+
options?: ExecOptions | ExecCallback,
|
|
373
|
+
callback?: ExecCallback
|
|
374
|
+
): ChildProcess {
|
|
375
|
+
let execArgs: string[] = [];
|
|
376
|
+
let execOptions: ExecOptions = {};
|
|
377
|
+
let cb: ExecCallback | undefined;
|
|
378
|
+
|
|
379
|
+
if (Array.isArray(args)) {
|
|
380
|
+
execArgs = args;
|
|
381
|
+
if (typeof options === 'function') {
|
|
382
|
+
cb = options;
|
|
383
|
+
} else if (options) {
|
|
384
|
+
execOptions = options;
|
|
385
|
+
cb = callback;
|
|
386
|
+
}
|
|
387
|
+
} else if (typeof args === 'function') {
|
|
388
|
+
cb = args;
|
|
389
|
+
} else if (args) {
|
|
390
|
+
execOptions = args;
|
|
391
|
+
cb = options as ExecCallback;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const command = execArgs.length > 0 ? `${file} ${execArgs.join(' ')}` : file;
|
|
395
|
+
return exec(command, execOptions, cb);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Fork is not supported in browser
|
|
400
|
+
*/
|
|
401
|
+
export function fork(): never {
|
|
402
|
+
throw new Error('fork is not supported in browser environment');
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* ChildProcess class
|
|
407
|
+
*/
|
|
408
|
+
export class ChildProcess extends EventEmitter {
|
|
409
|
+
pid: number;
|
|
410
|
+
connected: boolean = false;
|
|
411
|
+
killed: boolean = false;
|
|
412
|
+
exitCode: number | null = null;
|
|
413
|
+
signalCode: string | null = null;
|
|
414
|
+
spawnargs: string[] = [];
|
|
415
|
+
spawnfile: string = '';
|
|
416
|
+
|
|
417
|
+
stdin: Writable | null;
|
|
418
|
+
stdout: Readable | null;
|
|
419
|
+
stderr: Readable | null;
|
|
420
|
+
|
|
421
|
+
constructor() {
|
|
422
|
+
super();
|
|
423
|
+
this.pid = Math.floor(Math.random() * 10000) + 1000;
|
|
424
|
+
this.stdin = new Writable();
|
|
425
|
+
this.stdout = new Readable();
|
|
426
|
+
this.stderr = new Readable();
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
kill(signal?: string): boolean {
|
|
430
|
+
this.killed = true;
|
|
431
|
+
this.emit('exit', null, signal || 'SIGTERM');
|
|
432
|
+
return true;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
disconnect(): void {
|
|
436
|
+
this.connected = false;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
send(message: unknown, callback?: (error: Error | null) => void): boolean {
|
|
440
|
+
// IPC not supported
|
|
441
|
+
if (callback) callback(new Error('IPC not supported'));
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
ref(): this {
|
|
446
|
+
return this;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
unref(): this {
|
|
450
|
+
return this;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
export default {
|
|
455
|
+
exec,
|
|
456
|
+
execSync,
|
|
457
|
+
execFile,
|
|
458
|
+
spawn,
|
|
459
|
+
spawnSync,
|
|
460
|
+
fork,
|
|
461
|
+
ChildProcess,
|
|
462
|
+
initChildProcess,
|
|
463
|
+
};
|