@seanhogg/builderforce-webcontainers-core 2026.10.2 → 2026.10.4
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/build.d.ts +42 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +65 -0
- package/dist/build.js.map +1 -0
- package/dist/buildHost.d.ts +31 -0
- package/dist/buildHost.d.ts.map +1 -0
- package/dist/buildHost.js +125 -0
- package/dist/buildHost.js.map +1 -0
- package/dist/buildHtml.d.ts +28 -0
- package/dist/buildHtml.d.ts.map +1 -0
- package/dist/buildHtml.js +74 -0
- package/dist/buildHtml.js.map +1 -0
- package/dist/bundler.d.ts +129 -0
- package/dist/bundler.d.ts.map +1 -0
- package/dist/bundler.js +79 -0
- package/dist/bundler.js.map +1 -0
- package/dist/check/acquire.d.ts +46 -0
- package/dist/check/acquire.d.ts.map +1 -0
- package/dist/check/acquire.js +179 -0
- package/dist/check/acquire.js.map +1 -0
- package/dist/check/compilerHost.d.ts +22 -0
- package/dist/check/compilerHost.d.ts.map +1 -0
- package/dist/check/compilerHost.js +128 -0
- package/dist/check/compilerHost.js.map +1 -0
- package/dist/check/diagnostics.d.ts +23 -0
- package/dist/check/diagnostics.d.ts.map +1 -0
- package/dist/check/diagnostics.js +28 -0
- package/dist/check/diagnostics.js.map +1 -0
- package/dist/check/index.d.ts +19 -0
- package/dist/check/index.d.ts.map +1 -0
- package/dist/check/index.js +13 -0
- package/dist/check/index.js.map +1 -0
- package/dist/check/projects.d.ts +26 -0
- package/dist/check/projects.d.ts.map +1 -0
- package/dist/check/projects.js +124 -0
- package/dist/check/projects.js.map +1 -0
- package/dist/check/shims.d.ts +29 -0
- package/dist/check/shims.d.ts.map +1 -0
- package/dist/check/shims.js +76 -0
- package/dist/check/shims.js.map +1 -0
- package/dist/check/typeStore.d.ts +57 -0
- package/dist/check/typeStore.d.ts.map +1 -0
- package/dist/check/typeStore.js +89 -0
- package/dist/check/typeStore.js.map +1 -0
- package/dist/check/typecheck.d.ts +29 -0
- package/dist/check/typecheck.d.ts.map +1 -0
- package/dist/check/typecheck.js +91 -0
- package/dist/check/typecheck.js.map +1 -0
- package/dist/compileComponent.d.ts +8 -0
- package/dist/compileComponent.d.ts.map +1 -0
- package/dist/compileComponent.js +22 -0
- package/dist/compileComponent.js.map +1 -0
- package/dist/compileScript.d.ts +19 -4
- package/dist/compileScript.d.ts.map +1 -1
- package/dist/compileScript.js +37 -12
- package/dist/compileScript.js.map +1 -1
- package/dist/components.d.ts +41 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +14 -0
- package/dist/components.js.map +1 -0
- package/dist/detectProject.d.ts +3 -0
- package/dist/detectProject.d.ts.map +1 -1
- package/dist/detectProject.js +16 -6
- package/dist/detectProject.js.map +1 -1
- package/dist/devServer.d.ts +5 -2
- package/dist/devServer.d.ts.map +1 -1
- package/dist/devServer.js +12 -8
- package/dist/devServer.js.map +1 -1
- package/dist/hash.d.ts +2 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +22 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +24 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/installer/bins.d.ts +24 -0
- package/dist/installer/bins.d.ts.map +1 -0
- package/dist/installer/bins.js +56 -0
- package/dist/installer/bins.js.map +1 -0
- package/dist/installer/index.d.ts +14 -0
- package/dist/installer/index.d.ts.map +1 -0
- package/dist/installer/index.js +9 -0
- package/dist/installer/index.js.map +1 -0
- package/dist/installer/install.d.ts +46 -0
- package/dist/installer/install.d.ts.map +1 -0
- package/dist/installer/install.js +245 -0
- package/dist/installer/install.js.map +1 -0
- package/dist/installer/lockfile.d.ts +49 -0
- package/dist/installer/lockfile.d.ts.map +1 -0
- package/dist/installer/lockfile.js +110 -0
- package/dist/installer/lockfile.js.map +1 -0
- package/dist/installer/registry.d.ts +84 -0
- package/dist/installer/registry.d.ts.map +1 -0
- package/dist/installer/registry.js +130 -0
- package/dist/installer/registry.js.map +1 -0
- package/dist/installer/semver.d.ts +38 -0
- package/dist/installer/semver.d.ts.map +1 -0
- package/dist/installer/semver.js +187 -0
- package/dist/installer/semver.js.map +1 -0
- package/dist/installer/spec.d.ts +30 -0
- package/dist/installer/spec.d.ts.map +1 -0
- package/dist/installer/spec.js +30 -0
- package/dist/installer/spec.js.map +1 -0
- package/dist/installer/tar.d.ts +17 -0
- package/dist/installer/tar.d.ts.map +1 -0
- package/dist/installer/tar.js +150 -0
- package/dist/installer/tar.js.map +1 -0
- package/dist/installer/tree.d.ts +48 -0
- package/dist/installer/tree.d.ts.map +1 -0
- package/dist/installer/tree.js +179 -0
- package/dist/installer/tree.js.map +1 -0
- package/dist/node/assert.d.ts +15 -0
- package/dist/node/assert.d.ts.map +1 -0
- package/dist/node/assert.js +137 -0
- package/dist/node/assert.js.map +1 -0
- package/dist/node/buffer.d.ts +84 -0
- package/dist/node/buffer.d.ts.map +1 -0
- package/dist/node/buffer.js +304 -0
- package/dist/node/buffer.js.map +1 -0
- package/dist/node/builtins.d.ts +25 -0
- package/dist/node/builtins.d.ts.map +1 -0
- package/dist/node/builtins.js +101 -0
- package/dist/node/builtins.js.map +1 -0
- package/dist/node/callable.d.ts +13 -0
- package/dist/node/callable.d.ts.map +1 -0
- package/dist/node/callable.js +26 -0
- package/dist/node/callable.js.map +1 -0
- package/dist/node/childProcess.d.ts +13 -0
- package/dist/node/childProcess.d.ts.map +1 -0
- package/dist/node/childProcess.js +143 -0
- package/dist/node/childProcess.js.map +1 -0
- package/dist/node/crypto.d.ts +3 -0
- package/dist/node/crypto.d.ts.map +1 -0
- package/dist/node/crypto.js +180 -0
- package/dist/node/crypto.js.map +1 -0
- package/dist/node/esm.d.ts +9 -0
- package/dist/node/esm.d.ts.map +1 -0
- package/dist/node/esm.js +202 -0
- package/dist/node/esm.js.map +1 -0
- package/dist/node/events.d.ts +40 -0
- package/dist/node/events.d.ts.map +1 -0
- package/dist/node/events.js +160 -0
- package/dist/node/events.js.map +1 -0
- package/dist/node/fs/index.d.ts +7 -0
- package/dist/node/fs/index.d.ts.map +1 -0
- package/dist/node/fs/index.js +270 -0
- package/dist/node/fs/index.js.map +1 -0
- package/dist/node/fs/stats.d.ts +93 -0
- package/dist/node/fs/stats.d.ts.map +1 -0
- package/dist/node/fs/stats.js +104 -0
- package/dist/node/fs/stats.js.map +1 -0
- package/dist/node/fs/sync.d.ts +98 -0
- package/dist/node/fs/sync.d.ts.map +1 -0
- package/dist/node/fs/sync.js +348 -0
- package/dist/node/fs/sync.js.map +1 -0
- package/dist/node/hashes.d.ts +15 -0
- package/dist/node/hashes.d.ts.map +1 -0
- package/dist/node/hashes.js +195 -0
- package/dist/node/hashes.js.map +1 -0
- package/dist/node/http/client.d.ts +35 -0
- package/dist/node/http/client.d.ts.map +1 -0
- package/dist/node/http/client.js +161 -0
- package/dist/node/http/client.js.map +1 -0
- package/dist/node/http/index.d.ts +5 -0
- package/dist/node/http/index.d.ts.map +1 -0
- package/dist/node/http/index.js +125 -0
- package/dist/node/http/index.js.map +1 -0
- package/dist/node/http/server.d.ts +135 -0
- package/dist/node/http/server.d.ts.map +1 -0
- package/dist/node/http/server.js +308 -0
- package/dist/node/http/server.js.map +1 -0
- package/dist/node/http/status.d.ts +3 -0
- package/dist/node/http/status.d.ts.map +1 -0
- package/dist/node/http/status.js +13 -0
- package/dist/node/http/status.js.map +1 -0
- package/dist/node/inspect.d.ts +22 -0
- package/dist/node/inspect.d.ts.map +1 -0
- package/dist/node/inspect.js +172 -0
- package/dist/node/inspect.js.map +1 -0
- package/dist/node/loader.d.ts +91 -0
- package/dist/node/loader.d.ts.map +1 -0
- package/dist/node/loader.js +265 -0
- package/dist/node/loader.js.map +1 -0
- package/dist/node/loop.d.ts +71 -0
- package/dist/node/loop.d.ts.map +1 -0
- package/dist/node/loop.js +189 -0
- package/dist/node/loop.js.map +1 -0
- package/dist/node/misc.d.ts +10 -0
- package/dist/node/misc.d.ts.map +1 -0
- package/dist/node/misc.js +256 -0
- package/dist/node/misc.js.map +1 -0
- package/dist/node/path.d.ts +14 -0
- package/dist/node/path.d.ts.map +1 -0
- package/dist/node/path.js +128 -0
- package/dist/node/path.js.map +1 -0
- package/dist/node/process.d.ts +31 -0
- package/dist/node/process.d.ts.map +1 -0
- package/dist/node/process.js +309 -0
- package/dist/node/process.js.map +1 -0
- package/dist/node/program.d.ts +19 -0
- package/dist/node/program.d.ts.map +1 -0
- package/dist/node/program.js +165 -0
- package/dist/node/program.js.map +1 -0
- package/dist/node/readline.d.ts +2 -0
- package/dist/node/readline.d.ts.map +1 -0
- package/dist/node/readline.js +155 -0
- package/dist/node/readline.js.map +1 -0
- package/dist/node/resolve.d.ts +45 -0
- package/dist/node/resolve.d.ts.map +1 -0
- package/dist/node/resolve.js +206 -0
- package/dist/node/resolve.js.map +1 -0
- package/dist/node/runtime.d.ts +40 -0
- package/dist/node/runtime.d.ts.map +1 -0
- package/dist/node/runtime.js +149 -0
- package/dist/node/runtime.js.map +1 -0
- package/dist/node/stream/index.d.ts +52 -0
- package/dist/node/stream/index.d.ts.map +1 -0
- package/dist/node/stream/index.js +184 -0
- package/dist/node/stream/index.js.map +1 -0
- package/dist/node/stream/readable.d.ts +83 -0
- package/dist/node/stream/readable.d.ts.map +1 -0
- package/dist/node/stream/readable.js +325 -0
- package/dist/node/stream/readable.js.map +1 -0
- package/dist/node/stream/writable.d.ts +80 -0
- package/dist/node/stream/writable.d.ts.map +1 -0
- package/dist/node/stream/writable.js +224 -0
- package/dist/node/stream/writable.js.map +1 -0
- package/dist/node/urlqs.d.ts +22 -0
- package/dist/node/urlqs.d.ts.map +1 -0
- package/dist/node/urlqs.js +165 -0
- package/dist/node/urlqs.js.map +1 -0
- package/dist/node/util.d.ts +37 -0
- package/dist/node/util.d.ts.map +1 -0
- package/dist/node/util.js +160 -0
- package/dist/node/util.js.map +1 -0
- package/dist/node/zlib.d.ts +2 -0
- package/dist/node/zlib.d.ts.map +1 -0
- package/dist/node/zlib.js +133 -0
- package/dist/node/zlib.js.map +1 -0
- package/dist/packageCdn.d.ts +40 -0
- package/dist/packageCdn.d.ts.map +1 -1
- package/dist/packageCdn.js +54 -7
- package/dist/packageCdn.js.map +1 -1
- package/dist/projectConfig.d.ts +6 -2
- package/dist/projectConfig.d.ts.map +1 -1
- package/dist/projectConfig.js +32 -8
- package/dist/projectConfig.js.map +1 -1
- package/dist/shell/builtins.d.ts +23 -0
- package/dist/shell/builtins.d.ts.map +1 -0
- package/dist/shell/builtins.js +131 -0
- package/dist/shell/builtins.js.map +1 -0
- package/dist/shell/context.d.ts +41 -0
- package/dist/shell/context.d.ts.map +1 -0
- package/dist/shell/context.js +65 -0
- package/dist/shell/context.js.map +1 -0
- package/dist/shell/devHandoff.d.ts +18 -0
- package/dist/shell/devHandoff.d.ts.map +1 -0
- package/dist/shell/devHandoff.js +36 -0
- package/dist/shell/devHandoff.js.map +1 -0
- package/dist/shell/exec.d.ts +67 -0
- package/dist/shell/exec.d.ts.map +1 -0
- package/dist/shell/exec.js +247 -0
- package/dist/shell/exec.js.map +1 -0
- package/dist/shell/expand.d.ts +28 -0
- package/dist/shell/expand.d.ts.map +1 -0
- package/dist/shell/expand.js +149 -0
- package/dist/shell/expand.js.map +1 -0
- package/dist/shell/fileCommands.d.ts +10 -0
- package/dist/shell/fileCommands.d.ts.map +1 -0
- package/dist/shell/fileCommands.js +208 -0
- package/dist/shell/fileCommands.js.map +1 -0
- package/dist/shell/lineEditor.d.ts +43 -0
- package/dist/shell/lineEditor.d.ts.map +1 -0
- package/dist/shell/lineEditor.js +234 -0
- package/dist/shell/lineEditor.js.map +1 -0
- package/dist/shell/npm.d.ts +6 -0
- package/dist/shell/npm.d.ts.map +1 -0
- package/dist/shell/npm.js +234 -0
- package/dist/shell/npm.js.map +1 -0
- package/dist/shell/parse.d.ts +73 -0
- package/dist/shell/parse.d.ts.map +1 -0
- package/dist/shell/parse.js +300 -0
- package/dist/shell/parse.js.map +1 -0
- package/dist/shell/program.d.ts +12 -0
- package/dist/shell/program.d.ts.map +1 -0
- package/dist/shell/program.js +219 -0
- package/dist/shell/program.js.map +1 -0
- package/dist/shell/textCommands.d.ts +15 -0
- package/dist/shell/textCommands.d.ts.map +1 -0
- package/dist/shell/textCommands.js +185 -0
- package/dist/shell/textCommands.js.map +1 -0
- package/dist/styleModules.d.ts +6 -0
- package/dist/styleModules.d.ts.map +1 -1
- package/dist/styleModules.js +14 -4
- package/dist/styleModules.js.map +1 -1
- package/dist/svelteCompiler.d.ts +28 -0
- package/dist/svelteCompiler.d.ts.map +1 -0
- package/dist/svelteCompiler.js +13 -0
- package/dist/svelteCompiler.js.map +1 -0
- package/dist/system/commands.d.ts +26 -0
- package/dist/system/commands.d.ts.map +1 -0
- package/dist/system/commands.js +53 -0
- package/dist/system/commands.js.map +1 -0
- package/dist/system/index.d.ts +23 -0
- package/dist/system/index.d.ts.map +1 -0
- package/dist/system/index.js +16 -0
- package/dist/system/index.js.map +1 -0
- package/dist/system/kernel.d.ts +54 -0
- package/dist/system/kernel.d.ts.map +1 -0
- package/dist/system/kernel.js +81 -0
- package/dist/system/kernel.js.map +1 -0
- package/dist/system/ports.d.ts +32 -0
- package/dist/system/ports.d.ts.map +1 -0
- package/dist/system/ports.js +57 -0
- package/dist/system/ports.js.map +1 -0
- package/dist/system/process.d.ts +32 -0
- package/dist/system/process.d.ts.map +1 -0
- package/dist/system/process.js +130 -0
- package/dist/system/process.js.map +1 -0
- package/dist/system/programs.d.ts +10 -0
- package/dist/system/programs.d.ts.map +1 -0
- package/dist/system/programs.js +22 -0
- package/dist/system/programs.js.map +1 -0
- package/dist/system/terminal.d.ts +45 -0
- package/dist/system/terminal.d.ts.map +1 -0
- package/dist/system/terminal.js +127 -0
- package/dist/system/terminal.js.map +1 -0
- package/dist/system/types.d.ts +100 -0
- package/dist/system/types.d.ts.map +1 -0
- package/dist/system/types.js +2 -0
- package/dist/system/types.js.map +1 -0
- package/dist/vfs.d.ts +28 -4
- package/dist/vfs.d.ts.map +1 -1
- package/dist/vfs.js +95 -32
- package/dist/vfs.js.map +1 -1
- package/dist/vueCompiler.d.ts +75 -0
- package/dist/vueCompiler.d.ts.map +1 -0
- package/dist/vueCompiler.js +67 -0
- package/dist/vueCompiler.js.map +1 -0
- package/package.json +18 -2
- package/src/build.ts +105 -0
- package/src/buildHost.ts +154 -0
- package/src/buildHtml.ts +101 -0
- package/src/bundler.ts +190 -0
- package/src/check/acquire.ts +212 -0
- package/src/check/compilerHost.ts +138 -0
- package/src/check/diagnostics.ts +48 -0
- package/src/check/index.ts +28 -0
- package/src/check/projects.ts +149 -0
- package/src/check/shims.ts +88 -0
- package/src/check/typeStore.ts +103 -0
- package/src/check/typecheck.ts +134 -0
- package/src/compileComponent.ts +21 -0
- package/src/compileScript.ts +42 -13
- package/src/components.ts +59 -0
- package/src/detectProject.ts +18 -6
- package/src/devServer.ts +16 -11
- package/src/hash.ts +22 -0
- package/src/index.ts +35 -6
- package/src/installer/bins.ts +64 -0
- package/src/installer/index.ts +13 -0
- package/src/installer/install.ts +275 -0
- package/src/installer/lockfile.ts +146 -0
- package/src/installer/registry.ts +175 -0
- package/src/installer/semver.ts +190 -0
- package/src/installer/spec.ts +53 -0
- package/src/installer/tar.ts +155 -0
- package/src/installer/tree.ts +236 -0
- package/src/node/assert.ts +127 -0
- package/src/node/buffer.ts +304 -0
- package/src/node/builtins.ts +123 -0
- package/src/node/callable.ts +25 -0
- package/src/node/childProcess.ts +164 -0
- package/src/node/crypto.ts +187 -0
- package/src/node/esm.ts +196 -0
- package/src/node/events.ts +176 -0
- package/src/node/fs/index.ts +277 -0
- package/src/node/fs/stats.ts +110 -0
- package/src/node/fs/sync.ts +335 -0
- package/src/node/hashes.ts +171 -0
- package/src/node/http/client.ts +173 -0
- package/src/node/http/index.ts +122 -0
- package/src/node/http/server.ts +308 -0
- package/src/node/http/status.ts +13 -0
- package/src/node/inspect.ts +166 -0
- package/src/node/loader.ts +293 -0
- package/src/node/loop.ts +193 -0
- package/src/node/misc.ts +250 -0
- package/src/node/path.ts +135 -0
- package/src/node/process.ts +324 -0
- package/src/node/program.ts +170 -0
- package/src/node/readline.ts +157 -0
- package/src/node/resolve.ts +216 -0
- package/src/node/runtime.ts +184 -0
- package/src/node/stream/index.ts +196 -0
- package/src/node/stream/readable.ts +345 -0
- package/src/node/stream/writable.ts +244 -0
- package/src/node/urlqs.ts +162 -0
- package/src/node/util.ts +145 -0
- package/src/node/zlib.ts +145 -0
- package/src/packageCdn.ts +91 -7
- package/src/projectConfig.ts +34 -7
- package/src/shell/builtins.ts +141 -0
- package/src/shell/context.ts +89 -0
- package/src/shell/devHandoff.ts +49 -0
- package/src/shell/exec.ts +268 -0
- package/src/shell/expand.ts +145 -0
- package/src/shell/fileCommands.ts +206 -0
- package/src/shell/lineEditor.ts +233 -0
- package/src/shell/npm.ts +229 -0
- package/src/shell/parse.ts +295 -0
- package/src/shell/program.ts +223 -0
- package/src/shell/textCommands.ts +177 -0
- package/src/styleModules.ts +15 -4
- package/src/svelteCompiler.ts +31 -0
- package/src/system/commands.ts +72 -0
- package/src/system/index.ts +22 -0
- package/src/system/kernel.ts +106 -0
- package/src/system/ports.ts +73 -0
- package/src/system/process.ts +158 -0
- package/src/system/programs.ts +31 -0
- package/src/system/terminal.ts +135 -0
- package/src/system/types.ts +103 -0
- package/src/vfs.ts +92 -28
- package/src/vueCompiler.ts +121 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node's module resolution over the VFS: builtins (`fs`, `node:fs`), relative and
|
|
3
|
+
* absolute paths with extension and directory probing, `node_modules` lookup up
|
|
4
|
+
* the tree, package.json `main`, `exports` (conditions, subpath patterns, arrays,
|
|
5
|
+
* `null` exclusions), `imports` (`#internal`) and package self-reference.
|
|
6
|
+
*
|
|
7
|
+
* Distinct from ../resolve.ts, which resolves the way Vite does for the preview.
|
|
8
|
+
*/
|
|
9
|
+
import type { VirtualFileSystem } from '../vfs.js';
|
|
10
|
+
import { dirname, join, normalizePath } from '../paths.js';
|
|
11
|
+
import { splitPackageSpecifier } from '../resolve.js';
|
|
12
|
+
|
|
13
|
+
/** Conditions `require()` matches; `import` swaps `require` for `import`. */
|
|
14
|
+
export const REQUIRE_CONDITIONS = ['node', 'require', 'default'] as const;
|
|
15
|
+
export const IMPORT_CONDITIONS = ['node', 'import', 'default'] as const;
|
|
16
|
+
|
|
17
|
+
const EXTENSIONS = ['.js', '.json', '.cjs', '.mjs', '.node'];
|
|
18
|
+
|
|
19
|
+
export type Resolution = { builtin: string } | { path: string };
|
|
20
|
+
|
|
21
|
+
interface PackageJsonLike {
|
|
22
|
+
name?: string;
|
|
23
|
+
main?: string;
|
|
24
|
+
type?: string;
|
|
25
|
+
exports?: unknown;
|
|
26
|
+
imports?: unknown;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function moduleNotFound(request: string, from?: string): Error {
|
|
30
|
+
const error = new Error(`Cannot find module '${request}'${from ? `\nRequire stack:\n- ${from}` : ''}`) as Error & { code: string; requireStack?: string[] };
|
|
31
|
+
error.code = 'MODULE_NOT_FOUND';
|
|
32
|
+
if (from) error.requireStack = [from];
|
|
33
|
+
return error;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readPackageJson(fs: VirtualFileSystem, dir: string): PackageJsonLike | undefined {
|
|
37
|
+
const text = fs.readText(join(dir, 'package.json'));
|
|
38
|
+
if (text === undefined) return undefined;
|
|
39
|
+
try {
|
|
40
|
+
return JSON.parse(text) as PackageJsonLike;
|
|
41
|
+
} catch {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** The nearest package.json at or above `dir`: its directory and contents. */
|
|
47
|
+
export function findPackageScope(fs: VirtualFileSystem, dir: string): { dir: string; pkg: PackageJsonLike } | undefined {
|
|
48
|
+
for (let current = normalizePath(dir); ; current = dirname(current)) {
|
|
49
|
+
if (!current.endsWith('/node_modules')) {
|
|
50
|
+
const pkg = readPackageJson(fs, current);
|
|
51
|
+
if (pkg) return { dir: current, pkg };
|
|
52
|
+
}
|
|
53
|
+
if (current === '/') return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function loadAsFile(fs: VirtualFileSystem, path: string): string | undefined {
|
|
58
|
+
if (fs.isFile(path)) return path;
|
|
59
|
+
for (const ext of EXTENSIONS) if (fs.isFile(path + ext)) return path + ext;
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function loadIndex(fs: VirtualFileSystem, dir: string): string | undefined {
|
|
64
|
+
for (const ext of EXTENSIONS) if (fs.isFile(join(dir, 'index' + ext))) return join(dir, 'index' + ext);
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function loadAsDirectory(fs: VirtualFileSystem, dir: string): string | undefined {
|
|
69
|
+
if (!fs.isDirectory(dir)) return undefined;
|
|
70
|
+
const main = readPackageJson(fs, dir)?.main;
|
|
71
|
+
if (typeof main === 'string' && main) {
|
|
72
|
+
const target = join(dir, main);
|
|
73
|
+
const hit = loadAsFile(fs, target) ?? loadIndex(fs, target);
|
|
74
|
+
if (hit) return hit;
|
|
75
|
+
}
|
|
76
|
+
return loadIndex(fs, dir);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function loadPath(fs: VirtualFileSystem, path: string): string | undefined {
|
|
80
|
+
return loadAsFile(fs, path) ?? loadAsDirectory(fs, path);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Resolve one exports/imports target against `conditions`. `null` = explicitly excluded. */
|
|
84
|
+
function resolveTarget(target: unknown, match: string, conditions: readonly string[]): string | null | undefined {
|
|
85
|
+
if (typeof target === 'string') return target.replace(/\*/g, match);
|
|
86
|
+
if (Array.isArray(target)) {
|
|
87
|
+
for (const item of target) {
|
|
88
|
+
const hit = resolveTarget(item, match, conditions);
|
|
89
|
+
if (hit !== undefined) return hit;
|
|
90
|
+
}
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
if (target && typeof target === 'object') {
|
|
94
|
+
for (const [key, value] of Object.entries(target)) {
|
|
95
|
+
if (key !== 'default' && !conditions.includes(key)) continue;
|
|
96
|
+
const hit = resolveTarget(value, match, conditions);
|
|
97
|
+
if (hit !== undefined) return hit;
|
|
98
|
+
}
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
return target === null ? null : undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Match `subpath` (`.`, `./feature`, `#dep`) in an exports/imports map. */
|
|
105
|
+
export function resolveMap(map: unknown, subpath: string, conditions: readonly string[]): string | null | undefined {
|
|
106
|
+
const isSugar = typeof map === 'string' || Array.isArray(map) || (map && typeof map === 'object' && !Object.keys(map).some((k) => k.startsWith('.') || k.startsWith('#')));
|
|
107
|
+
const record = (isSugar ? { '.': map } : map) as Record<string, unknown>;
|
|
108
|
+
if (!record || typeof record !== 'object') return undefined;
|
|
109
|
+
if (Object.prototype.hasOwnProperty.call(record, subpath) && !subpath.includes('*')) return resolveTarget(record[subpath], '', conditions);
|
|
110
|
+
|
|
111
|
+
let best: { key: string; match: string } | undefined;
|
|
112
|
+
for (const key of Object.keys(record)) {
|
|
113
|
+
const star = key.indexOf('*');
|
|
114
|
+
if (star >= 0) {
|
|
115
|
+
const prefix = key.slice(0, star);
|
|
116
|
+
const suffix = key.slice(star + 1);
|
|
117
|
+
if (subpath.startsWith(prefix) && subpath.length >= key.length - 1 && subpath.endsWith(suffix) && (!best || prefix.length > best.key.indexOf('*'))) {
|
|
118
|
+
best = { key, match: subpath.slice(prefix.length, subpath.length - suffix.length) };
|
|
119
|
+
}
|
|
120
|
+
} else if (key.endsWith('/') && subpath.startsWith(key) && (!best || key.length > best.key.length)) {
|
|
121
|
+
best = { key, match: '' }; // legacy folder mapping
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (!best) return undefined;
|
|
125
|
+
const resolved = resolveTarget(record[best.key], best.match, conditions);
|
|
126
|
+
if (resolved && best.key.endsWith('/') && !best.key.includes('*')) return resolved + subpath.slice(best.key.length);
|
|
127
|
+
return resolved;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function exportsError(name: string, subpath: string): Error {
|
|
131
|
+
const error = new Error(`Package subpath '${subpath}' is not defined by "exports" in /node_modules/${name}/package.json`) as Error & { code: string };
|
|
132
|
+
error.code = 'ERR_PACKAGE_PATH_NOT_EXPORTED';
|
|
133
|
+
return error;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function resolvePackage(fs: VirtualFileSystem, pkgDir: string, name: string, subpath: string, conditions: readonly string[], request: string, from?: string): string {
|
|
137
|
+
const pkg = readPackageJson(fs, pkgDir);
|
|
138
|
+
if (pkg?.exports !== undefined && pkg.exports !== null) {
|
|
139
|
+
const key = subpath ? `.${subpath}` : '.';
|
|
140
|
+
const target = resolveMap(pkg.exports, key, conditions);
|
|
141
|
+
if (!target) throw exportsError(name, key);
|
|
142
|
+
const file = join(pkgDir, target);
|
|
143
|
+
if (fs.isFile(file)) return file;
|
|
144
|
+
throw moduleNotFound(request, from);
|
|
145
|
+
}
|
|
146
|
+
const hit = loadPath(fs, join(pkgDir, subpath || '.'));
|
|
147
|
+
if (!hit) throw moduleNotFound(request, from);
|
|
148
|
+
return hit;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface NodeResolveOptions {
|
|
152
|
+
conditions: readonly string[];
|
|
153
|
+
isBuiltin(name: string): boolean;
|
|
154
|
+
/** The requiring file, for "Require stack" in errors. */
|
|
155
|
+
from?: string;
|
|
156
|
+
/** Extra lookup roots (`require.resolve(x, { paths })`). */
|
|
157
|
+
paths?: string[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function resolveNodeModule(fs: VirtualFileSystem, request: string, fromDir: string, options: NodeResolveOptions): Resolution {
|
|
161
|
+
const { conditions, from } = options;
|
|
162
|
+
if (request.startsWith('node:')) {
|
|
163
|
+
const name = request.slice(5);
|
|
164
|
+
if (!options.isBuiltin(name)) throw Object.assign(new Error(`No such built-in module: ${request}`), { code: 'ERR_UNKNOWN_BUILTIN_MODULE' });
|
|
165
|
+
return { builtin: name };
|
|
166
|
+
}
|
|
167
|
+
if (options.isBuiltin(request)) return { builtin: request };
|
|
168
|
+
|
|
169
|
+
if (request.startsWith('#')) {
|
|
170
|
+
const scope = findPackageScope(fs, fromDir);
|
|
171
|
+
const target = scope?.pkg.imports ? resolveMap(scope.pkg.imports, request, conditions) : undefined;
|
|
172
|
+
if (!target || !scope) throw Object.assign(new Error(`Package import specifier "${request}" is not defined${scope ? ` in package ${scope.dir}/package.json` : ''}`), { code: 'ERR_PACKAGE_IMPORT_NOT_DEFINED' });
|
|
173
|
+
if (!target.startsWith('./')) return resolveNodeModule(fs, target, scope.dir, options);
|
|
174
|
+
const file = join(scope.dir, target);
|
|
175
|
+
if (fs.isFile(file)) return { path: file };
|
|
176
|
+
throw moduleNotFound(request, from);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (request === '.' || request === '..' || request.startsWith('./') || request.startsWith('../') || request.startsWith('/')) {
|
|
180
|
+
const base = request.startsWith('/') ? normalizePath(request) : join(fromDir, request);
|
|
181
|
+
const hit = request.endsWith('/') ? loadAsDirectory(fs, base) : loadPath(fs, base);
|
|
182
|
+
if (!hit) throw moduleNotFound(request, from);
|
|
183
|
+
return { path: hit };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const { name, subpath } = splitPackageSpecifier(request);
|
|
187
|
+
// Self-reference: a package importing itself by name through its own "exports".
|
|
188
|
+
const scope = findPackageScope(fs, fromDir);
|
|
189
|
+
if (scope?.pkg.name === name && scope.pkg.exports !== undefined) {
|
|
190
|
+
return { path: resolvePackage(fs, scope.dir, name, subpath, conditions, request, from) };
|
|
191
|
+
}
|
|
192
|
+
const roots = options.paths ?? [];
|
|
193
|
+
const lookup: string[] = [];
|
|
194
|
+
for (let dir = normalizePath(fromDir); ; dir = dirname(dir)) {
|
|
195
|
+
if (!dir.endsWith('/node_modules')) lookup.push(join(dir, 'node_modules'));
|
|
196
|
+
if (dir === '/') break;
|
|
197
|
+
}
|
|
198
|
+
for (const root of roots) lookup.push(root.endsWith('node_modules') ? root : join(root, 'node_modules'));
|
|
199
|
+
for (const nm of lookup) {
|
|
200
|
+
const pkgDir = join(nm, name);
|
|
201
|
+
if (fs.isDirectory(pkgDir) || fs.isFile(pkgDir + '.js') || fs.isFile(pkgDir + '.json')) {
|
|
202
|
+
if (!fs.isDirectory(pkgDir)) return { path: loadAsFile(fs, pkgDir)! };
|
|
203
|
+
return { path: resolvePackage(fs, pkgDir, name, subpath, conditions, request, from) };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
throw moduleNotFound(request, from);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** `module.paths` for a directory: every enclosing node_modules. */
|
|
210
|
+
export function nodeModulePaths(fromDir: string): string[] {
|
|
211
|
+
const out: string[] = [];
|
|
212
|
+
for (let dir = normalizePath(fromDir); ; dir = dirname(dir)) {
|
|
213
|
+
if (!dir.endsWith('/node_modules')) out.push(join(dir, 'node_modules'));
|
|
214
|
+
if (dir === '/') return out;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One Node process: event loop + process object + builtins + module system,
|
|
3
|
+
* wired to a program's IO and the system's ports. `startNode` evaluates the
|
|
4
|
+
* entry and resolves `exit` with the code once the process exits — by
|
|
5
|
+
* `process.exit()`, an uncaught exception, being killed, or the loop going idle.
|
|
6
|
+
*/
|
|
7
|
+
import type { ProgramIO, System } from '../system/types.js';
|
|
8
|
+
import { Buffer } from './buffer.js';
|
|
9
|
+
import { createBuiltins } from './builtins.js';
|
|
10
|
+
import { createModuleSystem, type ModuleSystem } from './loader.js';
|
|
11
|
+
import { EventLoop } from './loop.js';
|
|
12
|
+
import { createConsole, createProcess, ProcessExit, type NodeProcess } from './process.js';
|
|
13
|
+
import { esmReady } from './esm.js';
|
|
14
|
+
import { inspect } from './inspect.js';
|
|
15
|
+
|
|
16
|
+
export interface NodeOptions {
|
|
17
|
+
system: System;
|
|
18
|
+
io: ProgramIO;
|
|
19
|
+
cwd: string;
|
|
20
|
+
env: Record<string, string>;
|
|
21
|
+
/** `process.argv` from index 1: the script path, then its arguments. */
|
|
22
|
+
argv: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Also install `process`, `Buffer`, `global`, timers and `fetch` on
|
|
25
|
+
* `globalThis` — for a dedicated worker, where code reaching for globals
|
|
26
|
+
* directly (`globalThis.process`) must find them. Off when several runtimes
|
|
27
|
+
* share one realm.
|
|
28
|
+
*/
|
|
29
|
+
installGlobals?: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface NodeInstance {
|
|
33
|
+
readonly process: NodeProcess;
|
|
34
|
+
readonly modules: ModuleSystem;
|
|
35
|
+
/** Settles with the exit code. */
|
|
36
|
+
readonly exit: Promise<number>;
|
|
37
|
+
/** Run code in the process (the entry, `-e`, a REPL line). Errors become uncaught exceptions. */
|
|
38
|
+
run(fn: () => unknown): void;
|
|
39
|
+
/** Deliver a signal: `SIGINT` runs listeners if any, otherwise exits 130. */
|
|
40
|
+
kill(signal?: string): void;
|
|
41
|
+
/** An error the host caught outside the loop (a worker's unhandledrejection). */
|
|
42
|
+
reportUncaught(error: unknown): void;
|
|
43
|
+
/** Keep the process alive until the returned function is called. */
|
|
44
|
+
hold(): () => void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const SIGNAL_CODES: Record<string, number> = { SIGINT: 130, SIGTERM: 143, SIGKILL: 137, SIGHUP: 129 };
|
|
48
|
+
|
|
49
|
+
export async function startNode(options: NodeOptions): Promise<NodeInstance> {
|
|
50
|
+
await esmReady;
|
|
51
|
+
const { system, io } = options;
|
|
52
|
+
let resolveExit!: (code: number) => void;
|
|
53
|
+
const exit = new Promise<number>((resolve) => (resolveExit = resolve));
|
|
54
|
+
let finished = false;
|
|
55
|
+
const servers = new Set<{ close(): void }>();
|
|
56
|
+
|
|
57
|
+
// Servers die with the process: wrap listen so exit can close what is left open.
|
|
58
|
+
const processSystem: System = {
|
|
59
|
+
...system,
|
|
60
|
+
listen(port, handler) {
|
|
61
|
+
const registration = system.listen(port, handler);
|
|
62
|
+
const tracked = {
|
|
63
|
+
port: registration.port,
|
|
64
|
+
close() {
|
|
65
|
+
servers.delete(tracked);
|
|
66
|
+
registration.close();
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
servers.add(tracked);
|
|
70
|
+
return tracked;
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const finish = (code: number) => {
|
|
75
|
+
if (finished) return;
|
|
76
|
+
finished = true;
|
|
77
|
+
loop.stop();
|
|
78
|
+
for (const server of [...servers]) server.close();
|
|
79
|
+
resolveExit(code);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const uncaught = (error: unknown) => {
|
|
83
|
+
if (error instanceof ProcessExit || finished) return;
|
|
84
|
+
if (proc.listenerCount('uncaughtException')) {
|
|
85
|
+
try {
|
|
86
|
+
proc.emit('uncaughtException', error, 'uncaughtException');
|
|
87
|
+
return;
|
|
88
|
+
} catch (nested) {
|
|
89
|
+
error = nested;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const text = error instanceof Error ? error.stack ?? `${error.name}: ${error.message}` : `Uncaught ${inspect(error)}`;
|
|
93
|
+
io.stderr(`${text}\n\nNode.js v${proc.versions.node}\n`);
|
|
94
|
+
exitQuietly(proc.exitCode && proc.exitCode !== 0 ? proc.exitCode : 1);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const exitQuietly = (code?: number) => {
|
|
98
|
+
try {
|
|
99
|
+
proc.exit(code);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
if (!(error instanceof ProcessExit)) throw error;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const loop = new EventLoop({
|
|
106
|
+
onIdle() {
|
|
107
|
+
if (finished) return;
|
|
108
|
+
try {
|
|
109
|
+
proc.emit('beforeExit', Number(proc.exitCode ?? 0));
|
|
110
|
+
} catch (error) {
|
|
111
|
+
uncaught(error);
|
|
112
|
+
}
|
|
113
|
+
if (loop.alive) return; // a beforeExit listener scheduled more work
|
|
114
|
+
exitQuietly();
|
|
115
|
+
},
|
|
116
|
+
onError: uncaught,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const proc = createProcess({
|
|
120
|
+
argv: ['/usr/local/bin/node', ...options.argv],
|
|
121
|
+
env: options.env,
|
|
122
|
+
cwd: options.cwd,
|
|
123
|
+
fs: system.fs,
|
|
124
|
+
io,
|
|
125
|
+
loop,
|
|
126
|
+
onExit: finish,
|
|
127
|
+
});
|
|
128
|
+
const console = createConsole(proc);
|
|
129
|
+
const builtins = createBuiltins({ fs: system.fs, process: proc, loop, system: processSystem, io, console });
|
|
130
|
+
|
|
131
|
+
const globals: Record<string, unknown> = {
|
|
132
|
+
process: proc,
|
|
133
|
+
Buffer,
|
|
134
|
+
console,
|
|
135
|
+
setTimeout: loop.setTimeout,
|
|
136
|
+
setInterval: loop.setInterval,
|
|
137
|
+
setImmediate: loop.setImmediate,
|
|
138
|
+
clearTimeout: loop.clearTimeout,
|
|
139
|
+
clearInterval: loop.clearInterval,
|
|
140
|
+
clearImmediate: loop.clearImmediate,
|
|
141
|
+
fetch: builtins.fetch,
|
|
142
|
+
};
|
|
143
|
+
if (options.installGlobals) {
|
|
144
|
+
Object.assign(globalThis, globals, { global: globalThis });
|
|
145
|
+
globals.global = globalThis;
|
|
146
|
+
} else {
|
|
147
|
+
// A per-process view of the global object: reads fall through to the real
|
|
148
|
+
// one, Node's own names resolve to this process's.
|
|
149
|
+
globals.global = Object.assign(Object.create(globalThis), globals);
|
|
150
|
+
}
|
|
151
|
+
globals.globalThis = globals.global;
|
|
152
|
+
|
|
153
|
+
const modules = createModuleSystem({ fs: system.fs, isBuiltin: builtins.isBuiltin, builtin: builtins.get, globals });
|
|
154
|
+
(modules.Module as unknown as { builtinModules: string[] }).builtinModules = builtins.names;
|
|
155
|
+
Object.defineProperty(proc, 'mainModule', { get: () => modules.main, configurable: true });
|
|
156
|
+
|
|
157
|
+
const run = (fn: () => unknown) => {
|
|
158
|
+
if (finished) return;
|
|
159
|
+
try {
|
|
160
|
+
const result = fn();
|
|
161
|
+
if (result instanceof Promise) result.catch(uncaught).finally(() => loop.scheduleCheck());
|
|
162
|
+
} catch (error) {
|
|
163
|
+
uncaught(error);
|
|
164
|
+
}
|
|
165
|
+
loop.scheduleCheck();
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
process: proc,
|
|
170
|
+
modules,
|
|
171
|
+
exit,
|
|
172
|
+
run,
|
|
173
|
+
kill(signal = 'SIGTERM') {
|
|
174
|
+
if (finished) return;
|
|
175
|
+
if (signal !== 'SIGKILL' && proc.listenerCount(signal)) {
|
|
176
|
+
loop._run(() => proc.emit(signal, signal));
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
finish(SIGNAL_CODES[signal] ?? 1);
|
|
180
|
+
},
|
|
181
|
+
reportUncaught: uncaught,
|
|
182
|
+
hold: () => loop.hold(),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duplex, Transform, PassThrough, the legacy `Stream` base, and the `stream`
|
|
3
|
+
* module object with `pipeline`/`finished` (callback and promise forms).
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitterBase } from '../events.js';
|
|
6
|
+
import { callable } from '../callable.js';
|
|
7
|
+
import { initReadable, Readable, tick, type ReadableOptions } from './readable.js';
|
|
8
|
+
import { initWritable, Writable, type WritableOptions } from './writable.js';
|
|
9
|
+
|
|
10
|
+
type Callback = (error?: Error | null) => void;
|
|
11
|
+
type AnyStream = EventEmitterBase & { destroy?(error?: Error): unknown; pipe?(dest: unknown, opts?: unknown): unknown; _readableState?: { endEmitted: boolean }; _writableState?: { finished: boolean } };
|
|
12
|
+
|
|
13
|
+
/** The pre-streams2 base class: an emitter with a simple `pipe`. */
|
|
14
|
+
class LegacyStream extends EventEmitterBase {
|
|
15
|
+
pipe(dest: { write(chunk: unknown): boolean; end(): void }): unknown {
|
|
16
|
+
this.on('data', (chunk: unknown) => dest.write(chunk));
|
|
17
|
+
this.on('end', () => dest.end());
|
|
18
|
+
return dest;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
Object.setPrototypeOf(Readable.prototype, LegacyStream.prototype);
|
|
22
|
+
Object.setPrototypeOf(Writable.prototype, LegacyStream.prototype);
|
|
23
|
+
|
|
24
|
+
export interface DuplexOptions extends Omit<ReadableOptions, 'destroy'>, Omit<WritableOptions, 'destroy'> {
|
|
25
|
+
allowHalfOpen?: boolean;
|
|
26
|
+
destroy?(this: Duplex, error: Error | null, callback: (error?: Error | null) => void): void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function initDuplex(self: Duplex, options: DuplexOptions = {}): void {
|
|
30
|
+
initReadable(self, options as ReadableOptions);
|
|
31
|
+
initWritable(self as unknown as Writable, options as WritableOptions);
|
|
32
|
+
self.allowHalfOpen = options.allowHalfOpen !== false;
|
|
33
|
+
if (!self.allowHalfOpen) self.once('end', () => (self as unknown as Writable).end());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface Duplex extends Omit<Writable, keyof EventEmitterBase | 'destroy' | 'destroyed' | '_destroy' | '_write' | '_final'> {
|
|
37
|
+
_write(chunk: any, encoding: string, callback: Callback): void;
|
|
38
|
+
_final?(callback: Callback): void;
|
|
39
|
+
}
|
|
40
|
+
export class Duplex extends Readable {
|
|
41
|
+
declare allowHalfOpen: boolean;
|
|
42
|
+
|
|
43
|
+
constructor(options?: DuplexOptions) {
|
|
44
|
+
super(options);
|
|
45
|
+
initDuplex(this, options);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
override destroy(error?: Error | null): this {
|
|
49
|
+
const w = this._writableState;
|
|
50
|
+
if (w) w.destroyed = true;
|
|
51
|
+
return super.destroy(error);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
for (const key of Object.getOwnPropertyNames(Writable.prototype)) {
|
|
55
|
+
if (key === 'constructor' || key === 'destroy' || key === 'destroyed' || key === '_destroy' || key in Duplex.prototype && Object.getOwnPropertyDescriptor(Duplex.prototype, key)) continue;
|
|
56
|
+
Object.defineProperty(Duplex.prototype, key, Object.getOwnPropertyDescriptor(Writable.prototype, key)!);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface TransformOptions extends DuplexOptions {
|
|
60
|
+
transform?(this: Transform, chunk: any, encoding: string, callback: (error?: Error | null, data?: unknown) => void): void;
|
|
61
|
+
flush?(this: Transform, callback: (error?: Error | null, data?: unknown) => void): void;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function initTransform(self: Transform, options: TransformOptions = {}): void {
|
|
65
|
+
initDuplex(self, options);
|
|
66
|
+
if (typeof options.transform === 'function') self._transform = options.transform;
|
|
67
|
+
if (typeof options.flush === 'function') self._flush = options.flush;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export class Transform extends Duplex {
|
|
71
|
+
_flush?(callback: (error?: Error | null, data?: unknown) => void): void;
|
|
72
|
+
|
|
73
|
+
constructor(options?: TransformOptions) {
|
|
74
|
+
super(options);
|
|
75
|
+
initTransform(this, options);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_transform(_chunk: unknown, _encoding: string, _callback: (error?: Error | null, data?: unknown) => void): void {
|
|
79
|
+
throw new Error('The _transform() method is not implemented');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
override _read(): void {
|
|
83
|
+
// data is pushed as it is written
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
_write(chunk: unknown, encoding: string, callback: Callback): void {
|
|
87
|
+
this._transform(chunk, encoding, (error, data) => {
|
|
88
|
+
if (error) return callback(error);
|
|
89
|
+
if (data !== undefined && data !== null) this.push(data);
|
|
90
|
+
callback();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
_final(callback: Callback): void {
|
|
95
|
+
const done = (error?: Error | null, data?: unknown) => {
|
|
96
|
+
if (error) return callback(error);
|
|
97
|
+
if (data !== undefined && data !== null) this.push(data);
|
|
98
|
+
this.push(null);
|
|
99
|
+
callback();
|
|
100
|
+
};
|
|
101
|
+
if (this._flush) this._flush(done);
|
|
102
|
+
else done();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export class PassThrough extends Transform {
|
|
107
|
+
override _transform(chunk: unknown, _encoding: string, callback: (error?: Error | null, data?: unknown) => void): void {
|
|
108
|
+
callback(null, chunk);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Call back once when `stream` has ended, finished, errored or closed. */
|
|
113
|
+
export function finished(stream: AnyStream, options: unknown, callback?: Callback): () => void {
|
|
114
|
+
const cb = (typeof options === 'function' ? options : callback) as Callback;
|
|
115
|
+
let done = false;
|
|
116
|
+
const once = (error?: Error | null) => {
|
|
117
|
+
if (done) return;
|
|
118
|
+
done = true;
|
|
119
|
+
cleanup();
|
|
120
|
+
cb(error ?? null);
|
|
121
|
+
};
|
|
122
|
+
const onError = (error: Error) => once(error);
|
|
123
|
+
const onEnd = () => once();
|
|
124
|
+
const onClose = () => {
|
|
125
|
+
const r = stream._readableState;
|
|
126
|
+
const w = stream._writableState;
|
|
127
|
+
if ((r && !r.endEmitted) || (w && !w.finished)) once(Object.assign(new Error('Premature close'), { code: 'ERR_STREAM_PREMATURE_CLOSE' }));
|
|
128
|
+
else once();
|
|
129
|
+
};
|
|
130
|
+
const isWritableOnly = !!stream._writableState && !stream._readableState;
|
|
131
|
+
stream.on('error', onError);
|
|
132
|
+
stream.on(isWritableOnly ? 'finish' : 'end', onEnd);
|
|
133
|
+
if (stream._readableState && stream._writableState) stream.on('finish', () => stream._readableState!.endEmitted && once());
|
|
134
|
+
stream.on('close', onClose);
|
|
135
|
+
const cleanup = () => {
|
|
136
|
+
stream.removeListener('error', onError);
|
|
137
|
+
stream.removeListener('end', onEnd);
|
|
138
|
+
stream.removeListener('finish', onEnd);
|
|
139
|
+
stream.removeListener('close', onClose);
|
|
140
|
+
};
|
|
141
|
+
if ((stream._readableState?.endEmitted && !stream._writableState) || (isWritableOnly && stream._writableState!.finished)) tick(() => once());
|
|
142
|
+
return cleanup;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function pipeline(...args: unknown[]): unknown {
|
|
146
|
+
const callback = typeof args[args.length - 1] === 'function' ? (args.pop() as Callback) : undefined;
|
|
147
|
+
const streams = (Array.isArray(args[0]) ? args[0] : args) as AnyStream[];
|
|
148
|
+
if (streams.length < 2) throw new Error('pipeline requires at least two streams');
|
|
149
|
+
let failed = false;
|
|
150
|
+
const fail = (error: Error) => {
|
|
151
|
+
if (failed) return;
|
|
152
|
+
failed = true;
|
|
153
|
+
for (const s of streams) s.destroy?.(error);
|
|
154
|
+
callback?.(error);
|
|
155
|
+
};
|
|
156
|
+
for (let i = 0; i < streams.length - 1; i++) streams[i]!.pipe!(streams[i + 1]);
|
|
157
|
+
streams.forEach((s, i) => {
|
|
158
|
+
if (i < streams.length - 1) s.on('error', fail);
|
|
159
|
+
});
|
|
160
|
+
const last = streams[streams.length - 1]!;
|
|
161
|
+
finished(last, (error?: Error | null) => {
|
|
162
|
+
if (error) fail(error);
|
|
163
|
+
else if (!failed) callback?.(null);
|
|
164
|
+
});
|
|
165
|
+
return last;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function createStreamModule(): Record<string, unknown> {
|
|
169
|
+
const Stream = callable(LegacyStream, () => undefined) as unknown as Record<string, unknown>;
|
|
170
|
+
const wrapped = {
|
|
171
|
+
Readable: callable(Readable, (self, options) => initReadable(self, options)),
|
|
172
|
+
Writable: callable(Writable, (self, options) => initWritable(self, options)),
|
|
173
|
+
Duplex: callable(Duplex, (self, options) => initDuplex(self, options)),
|
|
174
|
+
Transform: callable(Transform, (self, options) => initTransform(self, options)),
|
|
175
|
+
PassThrough: callable(PassThrough, (self, options) => initTransform(self, options)),
|
|
176
|
+
};
|
|
177
|
+
const promises = {
|
|
178
|
+
pipeline: (...streams: unknown[]) => new Promise<void>((resolve, reject) => pipeline(...streams, (error?: Error | null) => (error ? reject(error) : resolve()))),
|
|
179
|
+
finished: (stream: AnyStream) => new Promise<void>((resolve, reject) => finished(stream, (error?: Error | null) => (error ? reject(error) : resolve()))),
|
|
180
|
+
};
|
|
181
|
+
Object.assign(Stream, wrapped, {
|
|
182
|
+
Stream,
|
|
183
|
+
pipeline,
|
|
184
|
+
finished,
|
|
185
|
+
promises,
|
|
186
|
+
addAbortSignal: (_signal: AbortSignal, stream: unknown) => stream,
|
|
187
|
+
isReadable: (s: Readable) => !!s?.readable,
|
|
188
|
+
isErrored: (s: Readable) => !!s?._readableState?.errored,
|
|
189
|
+
isDisturbed: (s: Readable) => !!s?._readableState?.endEmitted || (s?._readableState?.flowing ?? null) !== null,
|
|
190
|
+
getDefaultHighWaterMark: (objectMode: boolean) => (objectMode ? 16 : 16 * 1024),
|
|
191
|
+
setDefaultHighWaterMark: () => undefined,
|
|
192
|
+
});
|
|
193
|
+
return Stream;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export { Readable, Writable, tick };
|