@nubjs/nub-win32-x64 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/nub.exe +0 -0
- package/package.json +2 -2
- package/runtime/addons/nub-native.node +0 -0
- package/runtime/navigator-locks.mjs +135 -0
- package/runtime/node_modules/get-tsconfig/LICENSE +21 -0
- package/runtime/node_modules/get-tsconfig/README.md +268 -0
- package/runtime/node_modules/get-tsconfig/dist/index.cjs +7 -0
- package/runtime/node_modules/get-tsconfig/dist/index.d.cts +2116 -0
- package/runtime/node_modules/get-tsconfig/dist/index.d.mts +2116 -0
- package/runtime/node_modules/get-tsconfig/dist/index.mjs +7 -0
- package/runtime/node_modules/get-tsconfig/package.json +46 -0
- package/runtime/node_modules/oxc-transform/LICENSE +22 -0
- package/runtime/node_modules/oxc-transform/README.md +84 -0
- package/runtime/node_modules/oxc-transform/browser.js +1 -0
- package/runtime/node_modules/oxc-transform/index.d.ts +658 -0
- package/runtime/node_modules/oxc-transform/index.js +598 -0
- package/runtime/node_modules/oxc-transform/package.json +114 -0
- package/runtime/node_modules/oxc-transform/webcontainer-fallback.cjs +21 -0
- package/runtime/polyfills.mjs +160 -0
- package/runtime/preload.mjs +363 -0
- package/runtime/worker-polyfill.mjs +91 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "oxc-transform",
|
|
3
|
+
"version": "0.132.0",
|
|
4
|
+
"description": "Oxc Transformer Node API",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"babel",
|
|
7
|
+
"javascript",
|
|
8
|
+
"jsx",
|
|
9
|
+
"oxc",
|
|
10
|
+
"transform",
|
|
11
|
+
"transformer",
|
|
12
|
+
"tsx",
|
|
13
|
+
"typescript"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://oxc.rs/docs/guide/usage/transformer",
|
|
16
|
+
"bugs": "https://github.com/oxc-project/oxc/issues",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "Boshen and oxc contributors",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/oxc-project/oxc.git",
|
|
22
|
+
"directory": "napi/transform"
|
|
23
|
+
},
|
|
24
|
+
"funding": {
|
|
25
|
+
"url": "https://github.com/sponsors/Boshen"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"browser.js",
|
|
29
|
+
"index.d.ts",
|
|
30
|
+
"index.js",
|
|
31
|
+
"webcontainer-fallback.cjs"
|
|
32
|
+
],
|
|
33
|
+
"type": "module",
|
|
34
|
+
"main": "index.js",
|
|
35
|
+
"browser": "browser.js",
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public",
|
|
38
|
+
"registry": "https://registry.npmjs.org/"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@emnapi/core": "1.10.0",
|
|
42
|
+
"@emnapi/runtime": "1.10.0",
|
|
43
|
+
"@napi-rs/cli": "3.6.2",
|
|
44
|
+
"@types/node": "24.1.0",
|
|
45
|
+
"publint": "0.3.21",
|
|
46
|
+
"vitest": "4.1.6"
|
|
47
|
+
},
|
|
48
|
+
"napi": {
|
|
49
|
+
"binaryName": "transform",
|
|
50
|
+
"packageName": "@oxc-transform/binding",
|
|
51
|
+
"targets": [
|
|
52
|
+
"aarch64-apple-darwin",
|
|
53
|
+
"aarch64-linux-android",
|
|
54
|
+
"aarch64-pc-windows-msvc",
|
|
55
|
+
"aarch64-unknown-linux-gnu",
|
|
56
|
+
"aarch64-unknown-linux-musl",
|
|
57
|
+
"aarch64-unknown-linux-ohos",
|
|
58
|
+
"armv7-linux-androideabi",
|
|
59
|
+
"armv7-unknown-linux-gnueabihf",
|
|
60
|
+
"armv7-unknown-linux-musleabihf",
|
|
61
|
+
"i686-pc-windows-msvc",
|
|
62
|
+
"powerpc64le-unknown-linux-gnu",
|
|
63
|
+
"riscv64gc-unknown-linux-gnu",
|
|
64
|
+
"riscv64gc-unknown-linux-musl",
|
|
65
|
+
"s390x-unknown-linux-gnu",
|
|
66
|
+
"wasm32-wasip1-threads",
|
|
67
|
+
"x86_64-apple-darwin",
|
|
68
|
+
"x86_64-pc-windows-msvc",
|
|
69
|
+
"x86_64-unknown-freebsd",
|
|
70
|
+
"x86_64-unknown-linux-gnu",
|
|
71
|
+
"x86_64-unknown-linux-musl"
|
|
72
|
+
],
|
|
73
|
+
"wasm": {
|
|
74
|
+
"browser": {
|
|
75
|
+
"fs": false
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"engines": {
|
|
80
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
81
|
+
},
|
|
82
|
+
"optionalDependencies": {
|
|
83
|
+
"@oxc-transform/binding-darwin-arm64": "0.132.0",
|
|
84
|
+
"@oxc-transform/binding-android-arm64": "0.132.0",
|
|
85
|
+
"@oxc-transform/binding-win32-arm64-msvc": "0.132.0",
|
|
86
|
+
"@oxc-transform/binding-linux-arm64-gnu": "0.132.0",
|
|
87
|
+
"@oxc-transform/binding-linux-arm64-musl": "0.132.0",
|
|
88
|
+
"@oxc-transform/binding-openharmony-arm64": "0.132.0",
|
|
89
|
+
"@oxc-transform/binding-android-arm-eabi": "0.132.0",
|
|
90
|
+
"@oxc-transform/binding-linux-arm-gnueabihf": "0.132.0",
|
|
91
|
+
"@oxc-transform/binding-linux-arm-musleabihf": "0.132.0",
|
|
92
|
+
"@oxc-transform/binding-win32-ia32-msvc": "0.132.0",
|
|
93
|
+
"@oxc-transform/binding-linux-ppc64-gnu": "0.132.0",
|
|
94
|
+
"@oxc-transform/binding-linux-riscv64-gnu": "0.132.0",
|
|
95
|
+
"@oxc-transform/binding-linux-riscv64-musl": "0.132.0",
|
|
96
|
+
"@oxc-transform/binding-linux-s390x-gnu": "0.132.0",
|
|
97
|
+
"@oxc-transform/binding-wasm32-wasi": "0.132.0",
|
|
98
|
+
"@oxc-transform/binding-darwin-x64": "0.132.0",
|
|
99
|
+
"@oxc-transform/binding-win32-x64-msvc": "0.132.0",
|
|
100
|
+
"@oxc-transform/binding-freebsd-x64": "0.132.0",
|
|
101
|
+
"@oxc-transform/binding-linux-x64-gnu": "0.132.0",
|
|
102
|
+
"@oxc-transform/binding-linux-x64-musl": "0.132.0"
|
|
103
|
+
},
|
|
104
|
+
"scripts": {
|
|
105
|
+
"build-dev": "napi build --esm --platform",
|
|
106
|
+
"build-test": "pnpm run build-dev --profile coverage",
|
|
107
|
+
"build": "pnpm run build-dev --features allocator --release",
|
|
108
|
+
"postbuild": "publint",
|
|
109
|
+
"postbuild-dev": "node scripts/patch.js",
|
|
110
|
+
"build-wasm": "pnpm run build-wasm-dev --release",
|
|
111
|
+
"build-wasm-dev": "pnpm run build-dev --target wasm32-wasip1-threads",
|
|
112
|
+
"test": "vitest run --dir ./test"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const fs = require("node:fs");
|
|
2
|
+
const childProcess = require("node:child_process");
|
|
3
|
+
|
|
4
|
+
const pkg = JSON.parse(fs.readFileSync(require.resolve("oxc-transform/package.json"), "utf-8"));
|
|
5
|
+
const { version } = pkg;
|
|
6
|
+
const baseDir = `/tmp/oxc-transform-${version}`;
|
|
7
|
+
const bindingEntry = `${baseDir}/node_modules/@oxc-transform/binding-wasm32-wasi/transform.wasi.cjs`;
|
|
8
|
+
|
|
9
|
+
if (!fs.existsSync(bindingEntry)) {
|
|
10
|
+
fs.rmSync(baseDir, { recursive: true, force: true });
|
|
11
|
+
fs.mkdirSync(baseDir, { recursive: true });
|
|
12
|
+
const bindingPkg = `@oxc-transform/binding-wasm32-wasi@${version}`;
|
|
13
|
+
// oxlint-disable-next-line no-console
|
|
14
|
+
console.log(`[oxc-transform] Downloading ${bindingPkg} on WebContainer...`);
|
|
15
|
+
childProcess.execFileSync("pnpm", ["i", bindingPkg], {
|
|
16
|
+
cwd: baseDir,
|
|
17
|
+
stdio: "inherit",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = require(bindingEntry);
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// Polyfill preloads for Nub v0.1. All feature-detect and bow out
|
|
2
|
+
// if the global is already present. Loaded via the main preload.
|
|
3
|
+
//
|
|
4
|
+
// Node 22.15+ (our floor) already has: navigator, navigator.locks,
|
|
5
|
+
// navigator.hardwareConcurrency, WebSocket. No polyfills needed.
|
|
6
|
+
//
|
|
7
|
+
// Node 24+ adds: URLPattern, RegExp.escape, Error.isError, Promise.try.
|
|
8
|
+
// We polyfill those on Node 22.x only.
|
|
9
|
+
//
|
|
10
|
+
// No Node version ships: Temporal, reportError, browser-shape Worker.
|
|
11
|
+
// These need polyfills on all supported versions.
|
|
12
|
+
|
|
13
|
+
// ── reportError (WinterTC min-common-API, not in any Node) ──────────
|
|
14
|
+
if (typeof globalThis.reportError !== "function") {
|
|
15
|
+
globalThis.reportError = (err) => {
|
|
16
|
+
queueMicrotask(() => {
|
|
17
|
+
throw err;
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ── URLPattern (native on Node 24+, missing on 22.x) ───────────────
|
|
23
|
+
if (typeof globalThis.URLPattern === "undefined") {
|
|
24
|
+
const mod = globalThis.__nubPreloaded?.urlpattern;
|
|
25
|
+
const URLPattern = mod?.URLPattern;
|
|
26
|
+
if (URLPattern) globalThis.URLPattern = URLPattern;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ── Temporal (not in any Node version) ──────────────────────────────
|
|
30
|
+
if (typeof globalThis.Temporal === "undefined") {
|
|
31
|
+
const mod = globalThis.__nubPreloaded?.temporal;
|
|
32
|
+
const Temporal = mod?.Temporal;
|
|
33
|
+
if (Temporal) globalThis.Temporal = Temporal;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ── Stage 4 polyfills (native on Node 24+, missing on 22.x) ────────
|
|
37
|
+
|
|
38
|
+
// RegExp.escape
|
|
39
|
+
if (typeof RegExp.escape !== "function") {
|
|
40
|
+
const escapeRe = /[\\^$.*+?()[\]{}|]/g;
|
|
41
|
+
RegExp.escape = (s) => String(s).replace(escapeRe, "\\$&");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Error.isError (~95% fidelity — cross-realm internal-slot unreachable)
|
|
45
|
+
if (typeof Error.isError !== "function") {
|
|
46
|
+
Error.isError = (value) => {
|
|
47
|
+
if (value == null || typeof value !== "object") return false;
|
|
48
|
+
return value instanceof Error;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Promise.try
|
|
53
|
+
if (typeof Promise.try !== "function") {
|
|
54
|
+
Promise.try = (fn, ...args) => {
|
|
55
|
+
return new Promise((resolve) => resolve(fn(...args)));
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Float16Array (TC39 Stage 4, native on Node 24+)
|
|
60
|
+
// Partial TypedArray integration: instanceof TypedArray works via
|
|
61
|
+
// prototype chain setup, but ArrayBuffer.isView() returns false
|
|
62
|
+
// (requires V8 internal slots we can't set from userland).
|
|
63
|
+
if (typeof globalThis.Float16Array === "undefined") {
|
|
64
|
+
const TypedArray = Object.getPrototypeOf(Uint8Array);
|
|
65
|
+
const buf = new ArrayBuffer(2);
|
|
66
|
+
const f32 = new Float32Array(1);
|
|
67
|
+
const u32 = new Uint32Array(f32.buffer);
|
|
68
|
+
const u16view = new Uint16Array(buf);
|
|
69
|
+
|
|
70
|
+
function f32ToF16(val) {
|
|
71
|
+
f32[0] = val;
|
|
72
|
+
const bits = u32[0];
|
|
73
|
+
const sign = (bits >> 16) & 0x8000;
|
|
74
|
+
const exp = ((bits >> 23) & 0xff) - 127 + 15;
|
|
75
|
+
const frac = (bits >> 13) & 0x3ff;
|
|
76
|
+
if (exp <= 0) return sign;
|
|
77
|
+
if (exp >= 31) return sign | 0x7c00 | (frac ? 1 : 0);
|
|
78
|
+
return sign | (exp << 10) | frac;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function f16ToF32(h) {
|
|
82
|
+
const sign = (h & 0x8000) >> 15;
|
|
83
|
+
const exp = (h & 0x7c00) >> 10;
|
|
84
|
+
const frac = h & 0x03ff;
|
|
85
|
+
if (exp === 0) {
|
|
86
|
+
if (frac === 0) return sign ? -0 : 0;
|
|
87
|
+
let e = -1;
|
|
88
|
+
let f = frac;
|
|
89
|
+
while ((f & 0x400) === 0) { f <<= 1; e--; }
|
|
90
|
+
f &= 0x3ff;
|
|
91
|
+
u32[0] = (sign << 31) | ((e + 127) << 23) | (f << 13);
|
|
92
|
+
return f32[0];
|
|
93
|
+
}
|
|
94
|
+
if (exp === 31) {
|
|
95
|
+
return frac ? NaN : (sign ? -Infinity : Infinity);
|
|
96
|
+
}
|
|
97
|
+
u32[0] = (sign << 31) | ((exp - 15 + 127) << 23) | (frac << 13);
|
|
98
|
+
return f32[0];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
class Float16Array {
|
|
102
|
+
#data;
|
|
103
|
+
constructor(arg) {
|
|
104
|
+
if (typeof arg === "number") {
|
|
105
|
+
this.#data = new Uint16Array(arg);
|
|
106
|
+
} else if (arg instanceof ArrayBuffer || arg instanceof SharedArrayBuffer) {
|
|
107
|
+
this.#data = new Uint16Array(arg);
|
|
108
|
+
} else if (ArrayBuffer.isView(arg) || Array.isArray(arg)) {
|
|
109
|
+
this.#data = new Uint16Array(arg.length);
|
|
110
|
+
for (let i = 0; i < arg.length; i++) this.#data[i] = f32ToF16(Number(arg[i]));
|
|
111
|
+
} else {
|
|
112
|
+
this.#data = new Uint16Array(0);
|
|
113
|
+
}
|
|
114
|
+
this.length = this.#data.length;
|
|
115
|
+
this.byteLength = this.#data.byteLength;
|
|
116
|
+
this.byteOffset = this.#data.byteOffset;
|
|
117
|
+
this.buffer = this.#data.buffer;
|
|
118
|
+
this.BYTES_PER_ELEMENT = 2;
|
|
119
|
+
return new Proxy(this, {
|
|
120
|
+
get(target, prop) {
|
|
121
|
+
if (typeof prop === "string" && /^\d+$/.test(prop)) return f16ToF32(target.#data[prop]);
|
|
122
|
+
return Reflect.get(target, prop);
|
|
123
|
+
},
|
|
124
|
+
set(target, prop, value) {
|
|
125
|
+
if (typeof prop === "string" && /^\d+$/.test(prop)) { target.#data[prop] = f32ToF16(Number(value)); return true; }
|
|
126
|
+
return Reflect.set(target, prop, value);
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
[Symbol.iterator]() { let i = 0; const d = this.#data; return { next: () => i < d.length ? { value: f16ToF32(d[i++]), done: false } : { done: true } }; }
|
|
131
|
+
static get BYTES_PER_ELEMENT() { return 2; }
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Set up prototype chain so `instanceof TypedArray` works.
|
|
135
|
+
Object.setPrototypeOf(Float16Array.prototype, TypedArray.prototype);
|
|
136
|
+
Object.setPrototypeOf(Float16Array, TypedArray);
|
|
137
|
+
|
|
138
|
+
globalThis.Float16Array = Float16Array;
|
|
139
|
+
|
|
140
|
+
if (typeof DataView.prototype.getFloat16 !== "function") {
|
|
141
|
+
DataView.prototype.getFloat16 = function (offset, le) {
|
|
142
|
+
return f16ToF32(this.getUint16(offset, le));
|
|
143
|
+
};
|
|
144
|
+
DataView.prototype.setFloat16 = function (offset, value, le) {
|
|
145
|
+
this.setUint16(offset, f32ToF16(value), le);
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (typeof Math.f16round !== "function") {
|
|
150
|
+
Math.f16round = (x) => f16ToF32(f32ToF16(x));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ── navigator.locks (native on Node 24+, missing on 22.x) ──────────
|
|
155
|
+
if (typeof globalThis.navigator?.locks === "undefined") {
|
|
156
|
+
await import("./navigator-locks.mjs");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ── Worker (browser-shape global, not in any Node) ──────────────────
|
|
160
|
+
await import("./worker-polyfill.mjs");
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import module from "node:module";
|
|
2
|
+
import { readFileSync, writeFileSync, mkdirSync, statSync } from "node:fs";
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import { join, dirname, resolve as pathResolve, extname as pathExtname } from "node:path";
|
|
7
|
+
import { transformSync } from "oxc-transform";
|
|
8
|
+
import { getTsconfig, createPathsMatcher } from "get-tsconfig";
|
|
9
|
+
|
|
10
|
+
const __require = createRequire(import.meta.url);
|
|
11
|
+
|
|
12
|
+
// ── Constants ───────────────────────────────────────────────────────
|
|
13
|
+
const TRANSPILE_EXTS = new Set([".ts", ".tsx", ".mts", ".cts", ".jsx"]);
|
|
14
|
+
const DATA_EXTS = { ".jsonc": "jsonc", ".json5": "json5", ".toml": "toml", ".yaml": "yaml", ".yml": "yaml", ".txt": "txt" };
|
|
15
|
+
const TS_PARENT_EXTS = new Set([".ts", ".tsx", ".mts", ".cts"]);
|
|
16
|
+
|
|
17
|
+
// Nub's N-API addon for data-format parsing (Rust-native YAML/TOML/JSON5/JSONC).
|
|
18
|
+
let nubNative = null;
|
|
19
|
+
for (const rel of ["./addons/nub-native.node", "../runtime/addons/nub-native.node"]) {
|
|
20
|
+
try { nubNative = __require(fileURLToPath(new URL(rel, import.meta.url))); break; } catch {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Packages resolved from Nub's distribution, not the user's.
|
|
24
|
+
const VENDORED_PACKAGES = new Set(["@oxc-project/runtime"]);
|
|
25
|
+
|
|
26
|
+
// Built-in modules provided by Nub (resolved to files in this distribution).
|
|
27
|
+
// connect() sockets deferred per design decision — "sockets" specifier not clobbered.
|
|
28
|
+
const BUILTIN_MODULES = new Map();
|
|
29
|
+
|
|
30
|
+
// Package clobbering: specifiers that resolve to a synthetic module
|
|
31
|
+
// re-exporting the native global instead of the userland package.
|
|
32
|
+
const CLOBBER_MAP = new Map([
|
|
33
|
+
["@js-temporal/polyfill", () => `const T = globalThis.Temporal; export default T; export const Temporal = T;`],
|
|
34
|
+
["urlpattern-polyfill", () => `export const URLPattern = globalThis.URLPattern;`],
|
|
35
|
+
["abort-controller", () => `export const AbortController = globalThis.AbortController; export const AbortSignal = globalThis.AbortSignal; export default globalThis.AbortController;`],
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
// ── tsconfig cache ──────────────────────────────────────────────────
|
|
39
|
+
const tsconfigCache = new Map();
|
|
40
|
+
|
|
41
|
+
function getTsconfigForDir(dir) {
|
|
42
|
+
if (tsconfigCache.has(dir)) return tsconfigCache.get(dir);
|
|
43
|
+
const result = getTsconfig(dir);
|
|
44
|
+
const matcher = result ? createPathsMatcher(result) : null;
|
|
45
|
+
const entry = { tsconfig: result, matcher };
|
|
46
|
+
tsconfigCache.set(dir, entry);
|
|
47
|
+
return entry;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ── Transpile cache ─────────────────────────────────────────────────
|
|
51
|
+
const NUB_VERSION = "0.1.0";
|
|
52
|
+
const CACHE_DISABLED = process.permission?.has !== undefined;
|
|
53
|
+
let cacheDir = null;
|
|
54
|
+
|
|
55
|
+
if (!CACHE_DISABLED) {
|
|
56
|
+
const base = process.env.XDG_CACHE_HOME || (process.env.HOME ? join(process.env.HOME, ".cache") : null);
|
|
57
|
+
if (base) {
|
|
58
|
+
cacheDir = join(base, "nub", "transpile");
|
|
59
|
+
try { mkdirSync(cacheDir, { recursive: true }); } catch { cacheDir = null; }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function cacheKey(source) {
|
|
64
|
+
return createHash("sha256").update(NUB_VERSION).update("\0").update(source).digest("hex");
|
|
65
|
+
}
|
|
66
|
+
function cacheGet(key) {
|
|
67
|
+
if (!cacheDir) return null;
|
|
68
|
+
const path = join(cacheDir, key);
|
|
69
|
+
const s = statSync(path, { throwIfNoEntry: false });
|
|
70
|
+
if (!s || !s.isFile()) return null;
|
|
71
|
+
return readFileSync(path, "utf8");
|
|
72
|
+
}
|
|
73
|
+
function cacheSet(key, value) {
|
|
74
|
+
if (!cacheDir) return;
|
|
75
|
+
try { writeFileSync(join(cacheDir, key), value); } catch {}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
79
|
+
function extname(url) {
|
|
80
|
+
const path = url.includes("?") ? url.slice(0, url.indexOf("?")) : url;
|
|
81
|
+
const dot = path.lastIndexOf(".");
|
|
82
|
+
return dot === -1 ? "" : path.slice(dot);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isNodeModules(url) {
|
|
86
|
+
return url.includes("/node_modules/") || url.includes("\\node_modules\\");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function fileExists(filePath) {
|
|
90
|
+
const s = statSync(filePath, { throwIfNoEntry: false });
|
|
91
|
+
return s !== undefined && s.isFile();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function dirExists(filePath) {
|
|
95
|
+
const s = statSync(filePath, { throwIfNoEntry: false });
|
|
96
|
+
return s !== undefined && s.isDirectory();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function safeRequireResolve(specifier) {
|
|
100
|
+
try { return __require.resolve(specifier); } catch { return null; }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function barePkg(specifier) {
|
|
104
|
+
return specifier.startsWith("@")
|
|
105
|
+
? specifier.split("/").slice(0, 2).join("/")
|
|
106
|
+
: specifier.split("/")[0];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ── Resolve hook ────────────────────────────────────────────────────
|
|
110
|
+
function resolve(specifier, context, nextResolve) {
|
|
111
|
+
// Skip node: and data: protocols.
|
|
112
|
+
if (specifier.startsWith("node:") || specifier.startsWith("data:")) {
|
|
113
|
+
return nextResolve(specifier, context);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Skip Node built-in module names (without node: prefix).
|
|
117
|
+
if (module.builtinModules.includes(specifier)) {
|
|
118
|
+
return nextResolve(specifier, context);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 1. Built-in modules provided by Nub.
|
|
122
|
+
if (BUILTIN_MODULES.has(specifier)) {
|
|
123
|
+
return { url: BUILTIN_MODULES.get(specifier), shortCircuit: true };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 2. Vendored packages (e.g. @oxc-project/runtime).
|
|
127
|
+
const bare = barePkg(specifier);
|
|
128
|
+
if (VENDORED_PACKAGES.has(bare)) {
|
|
129
|
+
const resolved = safeRequireResolve(specifier);
|
|
130
|
+
if (resolved) return { url: pathToFileURL(resolved).href, shortCircuit: true };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 2. Package clobbering.
|
|
134
|
+
if (CLOBBER_MAP.has(bare) && !isNodeModules(context.parentURL || "")) {
|
|
135
|
+
return { url: `data:text/javascript,${encodeURIComponent(CLOBBER_MAP.get(bare)())}`, shortCircuit: true };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 3. tsconfig-paths (only for bare/aliased specifiers, not relative).
|
|
139
|
+
const parentURL = String(context.parentURL || "");
|
|
140
|
+
const parentExt = extname(parentURL);
|
|
141
|
+
if (!specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.startsWith("file:") && !isNodeModules(parentURL)) {
|
|
142
|
+
const parentDir = parentURL.startsWith("file:") ? dirname(fileURLToPath(parentURL)) : process.cwd();
|
|
143
|
+
const { matcher } = getTsconfigForDir(parentDir);
|
|
144
|
+
if (matcher) {
|
|
145
|
+
const mapped = matcher(specifier);
|
|
146
|
+
if (mapped && mapped.length > 0) {
|
|
147
|
+
for (const candidate of mapped) {
|
|
148
|
+
const resolved = tryResolveFile(candidate, parentExt);
|
|
149
|
+
if (resolved) {
|
|
150
|
+
return { url: pathToFileURL(resolved).href, shortCircuit: true };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// 4. Extensionless probing (only when parent is a TS file).
|
|
158
|
+
if (TS_PARENT_EXTS.has(parentExt) && (specifier.startsWith("./") || specifier.startsWith("../"))) {
|
|
159
|
+
const parentDir = dirname(fileURLToPath(parentURL));
|
|
160
|
+
const target = pathResolve(parentDir, specifier);
|
|
161
|
+
const resolved = tryResolveFile(target, parentExt);
|
|
162
|
+
if (resolved) {
|
|
163
|
+
return { url: pathToFileURL(resolved).href, shortCircuit: true };
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return nextResolve(specifier, context);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Try to resolve a file path with extensionless probing + .js→.ts swap.
|
|
171
|
+
function tryResolveFile(target, parentExt) {
|
|
172
|
+
// If the target already has an extension and exists, use it.
|
|
173
|
+
const existingExt = pathExtname(target);
|
|
174
|
+
if (existingExt && fileExists(target)) return target;
|
|
175
|
+
|
|
176
|
+
// .js → .ts swap (tsc emit convention reversal).
|
|
177
|
+
if (existingExt === ".js") {
|
|
178
|
+
const tsSwap = target.slice(0, -3) + ".ts";
|
|
179
|
+
if (fileExists(tsSwap)) return tsSwap;
|
|
180
|
+
const tsxSwap = target.slice(0, -3) + ".tsx";
|
|
181
|
+
if (fileExists(tsxSwap)) return tsxSwap;
|
|
182
|
+
}
|
|
183
|
+
if (existingExt === ".jsx") {
|
|
184
|
+
const tsxSwap = target.slice(0, -4) + ".tsx";
|
|
185
|
+
if (fileExists(tsxSwap)) return tsxSwap;
|
|
186
|
+
}
|
|
187
|
+
// .mjs → .mts swap (Bun does this).
|
|
188
|
+
if (existingExt === ".mjs") {
|
|
189
|
+
const mtsSwap = target.slice(0, -4) + ".mts";
|
|
190
|
+
if (fileExists(mtsSwap)) return mtsSwap;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Extensionless: probe in parent-ext-aware order.
|
|
194
|
+
if (!existingExt) {
|
|
195
|
+
const probeOrder = getProbeOrder(parentExt);
|
|
196
|
+
for (const ext of probeOrder) {
|
|
197
|
+
if (fileExists(target + ext)) return target + ext;
|
|
198
|
+
}
|
|
199
|
+
// Directory index probing.
|
|
200
|
+
if (dirExists(target)) {
|
|
201
|
+
for (const ext of probeOrder) {
|
|
202
|
+
const idx = join(target, "index" + ext);
|
|
203
|
+
if (fileExists(idx)) return idx;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function getProbeOrder(parentExt) {
|
|
212
|
+
switch (parentExt) {
|
|
213
|
+
case ".tsx": return [".tsx", ".ts", ".jsx", ".js", ".json"];
|
|
214
|
+
case ".mts": return [".mts", ".mjs"];
|
|
215
|
+
case ".cts": return [".cts", ".cjs"];
|
|
216
|
+
default: return [".ts", ".tsx", ".js", ".jsx", ".json"];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ── Load hook ───────────────────────────────────────────────────────
|
|
221
|
+
function load(url, context, nextLoad) {
|
|
222
|
+
const ext = extname(url);
|
|
223
|
+
|
|
224
|
+
if (TRANSPILE_EXTS.has(ext)) return loadTranspile(url, ext);
|
|
225
|
+
if (ext in DATA_EXTS) return loadData(url, ext);
|
|
226
|
+
|
|
227
|
+
return nextLoad(url, context);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function loadTranspile(url, ext) {
|
|
231
|
+
const filePath = fileURLToPath(url);
|
|
232
|
+
const source = readFileSync(filePath, "utf8");
|
|
233
|
+
const dir = dirname(filePath);
|
|
234
|
+
const { tsconfig } = getTsconfigForDir(dir);
|
|
235
|
+
const co = tsconfig?.config?.compilerOptions;
|
|
236
|
+
|
|
237
|
+
// Cache key includes tsconfig compilerOptions so tsconfig changes invalidate.
|
|
238
|
+
const tsconfigHash = co ? JSON.stringify(co) : "";
|
|
239
|
+
const key = cacheKey(source + "\0" + ext + "\0" + tsconfigHash);
|
|
240
|
+
const cached = cacheGet(key);
|
|
241
|
+
if (cached) {
|
|
242
|
+
return { format: ext === ".cts" ? "commonjs" : "module", source: cached, shortCircuit: true };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const lang = ext === ".tsx" ? "tsx" : ext === ".jsx" ? "jsx" : "ts";
|
|
246
|
+
const opts = {
|
|
247
|
+
lang,
|
|
248
|
+
sourceType: ext === ".cts" ? "commonjs" : "module",
|
|
249
|
+
sourcemap: true,
|
|
250
|
+
typescript: {},
|
|
251
|
+
decorator: co?.experimentalDecorators !== false
|
|
252
|
+
? { legacy: true, emitDecoratorMetadata: co?.emitDecoratorMetadata !== false }
|
|
253
|
+
: undefined,
|
|
254
|
+
};
|
|
255
|
+
if (ext === ".tsx" || ext === ".jsx") {
|
|
256
|
+
opts.jsx = {
|
|
257
|
+
runtime: co?.jsx === "react" ? "classic" : "automatic",
|
|
258
|
+
importSource: co?.jsxImportSource || "react",
|
|
259
|
+
};
|
|
260
|
+
if (co?.jsxFactory) opts.jsx.pragma = co.jsxFactory;
|
|
261
|
+
if (co?.jsxFragmentFactory) opts.jsx.pragmaFrag = co.jsxFragmentFactory;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const result = transformSync(filePath, source, opts);
|
|
265
|
+
if (result.errors.length > 0) {
|
|
266
|
+
const details = result.errors.map((e) => e.codeframe || e.message).join("\n\n");
|
|
267
|
+
throw new Error(`Transpile error in ${filePath}:\n${details}`);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
let code = result.code;
|
|
271
|
+
if (result.map) {
|
|
272
|
+
const map = typeof result.map === "string" ? JSON.parse(result.map) : result.map;
|
|
273
|
+
map.sourcesContent = [source];
|
|
274
|
+
code += `\n//# sourceMappingURL=data:application/json;base64,${Buffer.from(JSON.stringify(map)).toString("base64")}\n`;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
cacheSet(key, code);
|
|
278
|
+
return { format: ext === ".cts" ? "commonjs" : "module", source: code, shortCircuit: true };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function loadData(url, ext) {
|
|
282
|
+
const filePath = fileURLToPath(url);
|
|
283
|
+
const raw = readFileSync(filePath, "utf8");
|
|
284
|
+
const kind = DATA_EXTS[ext];
|
|
285
|
+
|
|
286
|
+
if (kind === "txt") {
|
|
287
|
+
return { format: "module", source: `export default ${JSON.stringify(raw)};\n`, shortCircuit: true };
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
let parsed;
|
|
291
|
+
if (nubNative) {
|
|
292
|
+
if (kind === "yaml") parsed = nubNative.parseYaml(raw);
|
|
293
|
+
else if (kind === "toml") parsed = nubNative.parseToml(raw);
|
|
294
|
+
else if (kind === "json5") parsed = nubNative.parseJson5(raw);
|
|
295
|
+
else if (kind === "jsonc") parsed = nubNative.parseJsonc(raw);
|
|
296
|
+
} else {
|
|
297
|
+
if (kind === "yaml") parsed = lazyRequire("yaml").parse(raw);
|
|
298
|
+
else if (kind === "toml") parsed = lazyRequire("@iarna/toml").parse(raw);
|
|
299
|
+
else if (kind === "json5") parsed = lazyRequire("json5").parse(raw);
|
|
300
|
+
else if (kind === "jsonc") parsed = JSON.parse(stripJsonComments(raw));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (parsed == null) {
|
|
304
|
+
return { format: "module", source: "export default undefined;\n", shortCircuit: true };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
let code = `const _data = ${JSON.stringify(parsed)};\nexport default _data;\n`;
|
|
308
|
+
if (typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
309
|
+
for (const key of Object.keys(parsed)) {
|
|
310
|
+
if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)) {
|
|
311
|
+
code += `export const ${key} = _data[${JSON.stringify(key)}];\n`;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return { format: "module", source: code, shortCircuit: true };
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function lazyRequire(pkg) {
|
|
319
|
+
try { return __require(pkg); } catch {
|
|
320
|
+
throw new Error(`Nub: importing this file requires the "${pkg}" package.\nInstall it: npm install ${pkg}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function stripJsonComments(text) {
|
|
325
|
+
let result = "", i = 0, inString = false, escape = false;
|
|
326
|
+
while (i < text.length) {
|
|
327
|
+
const ch = text[i];
|
|
328
|
+
if (escape) { result += ch; escape = false; i++; continue; }
|
|
329
|
+
if (inString) { if (ch === "\\") escape = true; if (ch === '"') inString = false; result += ch; i++; continue; }
|
|
330
|
+
if (ch === '"') { inString = true; result += ch; i++; continue; }
|
|
331
|
+
if (ch === "/" && text[i + 1] === "/") { while (i < text.length && text[i] !== "\n") i++; continue; }
|
|
332
|
+
if (ch === "/" && text[i + 1] === "*") { i += 2; while (i < text.length && !(text[i] === "*" && text[i + 1] === "/")) i++; i += 2; continue; }
|
|
333
|
+
result += ch; i++;
|
|
334
|
+
}
|
|
335
|
+
return result;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// ── Pre-load clobbered polyfill packages BEFORE hooks register ──────
|
|
339
|
+
// Packages in CLOBBER_MAP can't be imported after hooks register because
|
|
340
|
+
// the resolve hook returns a synthetic module instead of the real package.
|
|
341
|
+
// Load them here via CJS require (which isn't yet hooked) and stash them.
|
|
342
|
+
const __preloadedPolyfills = {};
|
|
343
|
+
try { __preloadedPolyfills.temporal = __require("@js-temporal/polyfill"); } catch {}
|
|
344
|
+
try { __preloadedPolyfills.urlpattern = __require("urlpattern-polyfill"); } catch {}
|
|
345
|
+
|
|
346
|
+
// ── Register hooks ──────────────────────────────────────────────────
|
|
347
|
+
module.registerHooks({ resolve, load });
|
|
348
|
+
|
|
349
|
+
// ── Polyfill preloads ───────────────────────────────────────────────
|
|
350
|
+
globalThis.__nubPreloaded = __preloadedPolyfills;
|
|
351
|
+
await import("./polyfills.mjs");
|
|
352
|
+
delete globalThis.__nubPreloaded;
|
|
353
|
+
delete globalThis.__nubRequire;
|
|
354
|
+
delete globalThis.__nubRequire;
|
|
355
|
+
|
|
356
|
+
// ── Watch-mode dependency reporting ─────────────────────────────────
|
|
357
|
+
if (process.env.WATCH_REPORT_DEPENDENCIES === "1" && process.send) {
|
|
358
|
+
const deps = [];
|
|
359
|
+
for (const [, entry] of tsconfigCache) {
|
|
360
|
+
if (entry.tsconfig?.path) deps.push(entry.tsconfig.path);
|
|
361
|
+
}
|
|
362
|
+
if (deps.length > 0) process.send({ "watch:require": deps });
|
|
363
|
+
}
|