@eggjs/utils 5.0.2-beta.2 → 5.0.2-beta.22
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/README.md +59 -0
- package/dist/import.d.ts +36 -1
- package/dist/import.js +100 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/package.json +13 -7
package/README.md
CHANGED
|
@@ -42,6 +42,65 @@ npm i @eggjs/utils
|
|
|
42
42
|
- {String} baseDir - the current directory of application
|
|
43
43
|
- {String} framework - the directory of framework
|
|
44
44
|
|
|
45
|
+
### `setBundleModuleLoader(loader)`
|
|
46
|
+
|
|
47
|
+
Register a module loader hook for bundled Egg apps. The hook runs before the
|
|
48
|
+
normal `importModule()` resolution path.
|
|
49
|
+
|
|
50
|
+
- {Function | undefined} loader - a synchronous function that receives the
|
|
51
|
+
original `filepath` argument passed to `importModule()` after POSIX separator
|
|
52
|
+
normalization, or a virtual specifier. It does not receive the resolved
|
|
53
|
+
absolute file path from `importResolve()`. Return `undefined` to fall back to
|
|
54
|
+
the normal import path.
|
|
55
|
+
|
|
56
|
+
The bundle loader is stored on `globalThis`, so bundled and external copies of
|
|
57
|
+
`@eggjs/utils` share the same loader. Non-`undefined` results follow the same
|
|
58
|
+
default export unwrapping rules as `importModule()`, including
|
|
59
|
+
`importDefaultOnly`.
|
|
60
|
+
|
|
61
|
+
### Bundle / snapshot module-loading hooks
|
|
62
|
+
|
|
63
|
+
`importModule()` resolves a module through the following hooks, in order. The
|
|
64
|
+
first one that produces a value wins; otherwise it falls back to the native
|
|
65
|
+
`import()` / `require()` path:
|
|
66
|
+
|
|
67
|
+
1. **`globalThis.__EGG_BUNDLE_MODULE_LOADER__`** — set via
|
|
68
|
+
`setBundleModuleLoader()`. Looks up a module already inlined into the bundle
|
|
69
|
+
(typically a static bundle map emitted by `egg-bundler`). Runs before on-disk
|
|
70
|
+
resolution and receives the POSIX-normalized `importModule()` filepath or a
|
|
71
|
+
virtual specifier. Return `undefined` to fall through.
|
|
72
|
+
2. **Snapshot module loader** — set via `setSnapshotModuleLoader()`. This is a
|
|
73
|
+
module-local hook (not a `globalThis` global) used by the V8 snapshot entry
|
|
74
|
+
generator to serve pre-bundled modules synchronously, keyed by the resolved
|
|
75
|
+
path. Once registered it handles every load that reaches it, so the importer
|
|
76
|
+
below is not consulted while it is active.
|
|
77
|
+
3. **`globalThis.__EGG_MODULE_IMPORTER__`** — an async (or sync, since the value
|
|
78
|
+
is awaited) importer that receives the resolved file path (the
|
|
79
|
+
`importResolve()` result, with OS-native separators — not normalized). When
|
|
80
|
+
set, and the two hooks above did not resolve the module, it replaces the
|
|
81
|
+
native `await import(filePath)`.
|
|
82
|
+
|
|
83
|
+
The bundle loader and importer globals are typed in `@eggjs/typings`
|
|
84
|
+
(`BundleModuleLoader` / `ModuleImporter`); import `@eggjs/typings/global` to pick
|
|
85
|
+
up the `declare global` augmentation. These hooks are the contract that
|
|
86
|
+
`egg-bundler`'s generated entry relies on. `@eggjs/core`'s `ManifestLoaderFS`
|
|
87
|
+
consults `__EGG_BUNDLE_MODULE_LOADER__` directly; its importer/native fallback is
|
|
88
|
+
reached through `@eggjs/loader-fs`, which calls back into `importModule()`. The
|
|
89
|
+
tegg loader (`LoaderUtil.loadFile`) consults both globals directly, passing the
|
|
90
|
+
loader filepath with separators normalized to POSIX.
|
|
91
|
+
|
|
92
|
+
`__EGG_MODULE_IMPORTER__` has two main uses:
|
|
93
|
+
|
|
94
|
+
- **Bundler-based test runners (e.g. Vitest):** route module loading through the
|
|
95
|
+
runner's own module graph so the loader and the test file share a single
|
|
96
|
+
module instance (otherwise `ctx.getEggObject(ClassRef)` fails with
|
|
97
|
+
"can not get proto").
|
|
98
|
+
- **V8 startup-snapshot restore:** the deserialized main function runs without a
|
|
99
|
+
host dynamic-import callback, so native `import()` throws. The snapshot entry
|
|
100
|
+
installs a synchronous `require()`-based importer (`createRequire()` over the
|
|
101
|
+
bundle output dir); `require()` can load ESM on Node >= 22, so modules resolve
|
|
102
|
+
without dynamic import.
|
|
103
|
+
|
|
45
104
|
## License
|
|
46
105
|
|
|
47
106
|
[MIT](LICENSE)
|
package/dist/import.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { BundleModuleLoader, BundleModuleLoader as BundleModuleLoader$1 } from "@eggjs/typings";
|
|
2
|
+
|
|
1
3
|
//#region src/import.d.ts
|
|
2
4
|
interface ImportResolveOptions {
|
|
3
5
|
paths?: string[];
|
|
@@ -10,6 +12,39 @@ declare function getRequire(): NodeRequire;
|
|
|
10
12
|
declare function getExtensions(): NodeJS.RequireExtensions;
|
|
11
13
|
declare function isSupportTypeScript(): boolean;
|
|
12
14
|
declare function importResolve(filepath: string, options?: ImportResolveOptions): string;
|
|
15
|
+
/**
|
|
16
|
+
* Module loader function type for V8 snapshot support.
|
|
17
|
+
* Called with the resolved absolute file path, returns the module exports.
|
|
18
|
+
*/
|
|
19
|
+
type SnapshotModuleLoader = (resolvedPath: string) => any;
|
|
20
|
+
/**
|
|
21
|
+
* Register a snapshot module loader that intercepts `importModule()` calls.
|
|
22
|
+
*
|
|
23
|
+
* When set, `importModule()` delegates to this loader instead of calling
|
|
24
|
+
* `import()` or `require()`. This is used by the V8 snapshot entry generator
|
|
25
|
+
* to provide pre-bundled modules — the bundler generates a static module map
|
|
26
|
+
* from the egg manifest and registers it via this API.
|
|
27
|
+
*
|
|
28
|
+
* Also sets `isESM = false` because the snapshot bundle is CJS and
|
|
29
|
+
* esbuild's `import.meta` polyfill causes incorrect ESM detection.
|
|
30
|
+
*
|
|
31
|
+
* Pass `undefined` to clear the loader and restore the auto-detected `isESM`
|
|
32
|
+
* value. Always clear it once snapshot mode is no longer needed (e.g. in test
|
|
33
|
+
* teardown) so the module-level state does not leak into other files when
|
|
34
|
+
* vitest runs with `isolate: false`.
|
|
35
|
+
*/
|
|
36
|
+
declare function setSnapshotModuleLoader(loader: SnapshotModuleLoader | undefined): void;
|
|
37
|
+
/**
|
|
38
|
+
* Register a bundle module loader. Uses globalThis so that bundled and
|
|
39
|
+
* external copies of @eggjs/utils share the same loader.
|
|
40
|
+
*
|
|
41
|
+
* The loader receives a POSIX-normalized filepath or virtual specifier before
|
|
42
|
+
* normal resolution runs. Return `undefined` to fall through to the default
|
|
43
|
+
* import path. Non-undefined hits use the same default unwrapping semantics as
|
|
44
|
+
* normal imports, including `importDefaultOnly` and double-default `__esModule`
|
|
45
|
+
* compatibility.
|
|
46
|
+
*/
|
|
47
|
+
declare function setBundleModuleLoader(loader: BundleModuleLoader | undefined): void;
|
|
13
48
|
declare function importModule(filepath: string, options?: ImportModuleOptions): Promise<any>;
|
|
14
49
|
//#endregion
|
|
15
|
-
export { ImportModuleOptions, ImportResolveOptions, getExtensions, getRequire, importModule, importResolve, isESM, isSupportTypeScript };
|
|
50
|
+
export { type BundleModuleLoader$1 as BundleModuleLoader, ImportModuleOptions, ImportResolveOptions, SnapshotModuleLoader, getExtensions, getRequire, importModule, importResolve, isESM, isSupportTypeScript, setBundleModuleLoader, setSnapshotModuleLoader };
|
package/dist/import.js
CHANGED
|
@@ -8,17 +8,30 @@ import { debuglog } from "node:util";
|
|
|
8
8
|
|
|
9
9
|
//#region src/import.ts
|
|
10
10
|
const debug = debuglog("egg/utils/import");
|
|
11
|
+
let nativeDynamicImport;
|
|
12
|
+
/* v8 ignore next -- covered by the spawned Node fixture; Vitest cannot instrument this opaque import. */
|
|
13
|
+
function getNativeDynamicImport() {
|
|
14
|
+
if (!nativeDynamicImport) try {
|
|
15
|
+
nativeDynamicImport = new Function("specifier", "return import(specifier);");
|
|
16
|
+
} catch (err) {
|
|
17
|
+
const error = /* @__PURE__ */ new Error("Native dynamic import fallback for bundled module loader misses requires code generation from strings.");
|
|
18
|
+
error.cause = err;
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
return nativeDynamicImport;
|
|
22
|
+
}
|
|
11
23
|
let isESM = true;
|
|
12
24
|
try {
|
|
13
25
|
if (typeof import.meta !== "undefined") isESM = true;
|
|
14
26
|
} catch {
|
|
15
27
|
isESM = false;
|
|
16
28
|
}
|
|
29
|
+
const detectedIsESM = isESM;
|
|
17
30
|
const nodeMajorVersion = parseInt(process.versions.node.split(".", 1)[0], 10);
|
|
18
|
-
const supportImportMetaResolve = nodeMajorVersion >= 18;
|
|
31
|
+
const supportImportMetaResolve = nodeMajorVersion >= 18 && typeof import.meta !== "undefined" && typeof import.meta.resolve === "function";
|
|
19
32
|
let _customRequire;
|
|
20
33
|
function getRequire() {
|
|
21
|
-
if (!_customRequire) if (typeof __require !== "undefined") _customRequire = __require;
|
|
34
|
+
if (!_customRequire) if (typeof __require !== "undefined" && __require.extensions) _customRequire = __require;
|
|
22
35
|
else _customRequire = createRequire(process.cwd());
|
|
23
36
|
return _customRequire;
|
|
24
37
|
}
|
|
@@ -193,6 +206,11 @@ function importResolve(filepath, options) {
|
|
|
193
206
|
}
|
|
194
207
|
}
|
|
195
208
|
}
|
|
209
|
+
const bundleModuleLoader = globalThis.__EGG_BUNDLE_MODULE_LOADER__;
|
|
210
|
+
if (bundleModuleLoader && bundleModuleLoader(normalizeBundleModulePath(filepath)) !== void 0) {
|
|
211
|
+
debug("[importResolve:bundle] %o => %o", filepath, filepath);
|
|
212
|
+
return filepath;
|
|
213
|
+
}
|
|
196
214
|
const extname = path.extname(filepath);
|
|
197
215
|
if (!isAbsolute && extname === ".json" || !isESM) moduleFilePath = getRequire().resolve(filepath, { paths });
|
|
198
216
|
else if (supportImportMetaResolve) {
|
|
@@ -205,19 +223,95 @@ function importResolve(filepath, options) {
|
|
|
205
223
|
if (moduleFilePath.startsWith("file://")) moduleFilePath = fileURLToPath(moduleFilePath);
|
|
206
224
|
debug("[importResolve] import.meta.resolve %o => %o", filepath, moduleFilePath);
|
|
207
225
|
if (!fs.statSync(moduleFilePath, { throwIfNoEntry: false })?.isFile()) throw new TypeError(`Cannot find module ${filepath}, because ${moduleFilePath} does not exists`);
|
|
208
|
-
} else moduleFilePath = getRequire().resolve(filepath);
|
|
226
|
+
} else moduleFilePath = getRequire().resolve(filepath, paths ? { paths } : void 0);
|
|
209
227
|
debug("[importResolve:success] %o, options: %o => %o, isESM: %s", filepath, options, moduleFilePath, isESM);
|
|
210
228
|
return moduleFilePath;
|
|
211
229
|
}
|
|
230
|
+
let _snapshotModuleLoader;
|
|
231
|
+
/**
|
|
232
|
+
* Register a snapshot module loader that intercepts `importModule()` calls.
|
|
233
|
+
*
|
|
234
|
+
* When set, `importModule()` delegates to this loader instead of calling
|
|
235
|
+
* `import()` or `require()`. This is used by the V8 snapshot entry generator
|
|
236
|
+
* to provide pre-bundled modules — the bundler generates a static module map
|
|
237
|
+
* from the egg manifest and registers it via this API.
|
|
238
|
+
*
|
|
239
|
+
* Also sets `isESM = false` because the snapshot bundle is CJS and
|
|
240
|
+
* esbuild's `import.meta` polyfill causes incorrect ESM detection.
|
|
241
|
+
*
|
|
242
|
+
* Pass `undefined` to clear the loader and restore the auto-detected `isESM`
|
|
243
|
+
* value. Always clear it once snapshot mode is no longer needed (e.g. in test
|
|
244
|
+
* teardown) so the module-level state does not leak into other files when
|
|
245
|
+
* vitest runs with `isolate: false`.
|
|
246
|
+
*/
|
|
247
|
+
function setSnapshotModuleLoader(loader) {
|
|
248
|
+
_snapshotModuleLoader = loader;
|
|
249
|
+
isESM = loader ? false : detectedIsESM;
|
|
250
|
+
}
|
|
251
|
+
function normalizeBundleModulePath(filepath) {
|
|
252
|
+
return filepath.split(path.win32.sep).join(path.posix.sep);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Register a bundle module loader. Uses globalThis so that bundled and
|
|
256
|
+
* external copies of @eggjs/utils share the same loader.
|
|
257
|
+
*
|
|
258
|
+
* The loader receives a POSIX-normalized filepath or virtual specifier before
|
|
259
|
+
* normal resolution runs. Return `undefined` to fall through to the default
|
|
260
|
+
* import path. Non-undefined hits use the same default unwrapping semantics as
|
|
261
|
+
* normal imports, including `importDefaultOnly` and double-default `__esModule`
|
|
262
|
+
* compatibility.
|
|
263
|
+
*/
|
|
264
|
+
function setBundleModuleLoader(loader) {
|
|
265
|
+
globalThis.__EGG_BUNDLE_MODULE_LOADER__ = loader;
|
|
266
|
+
}
|
|
267
|
+
const _inflightImports = /* @__PURE__ */ new Map();
|
|
212
268
|
async function importModule(filepath, options) {
|
|
269
|
+
const _bundleModuleLoader = globalThis.__EGG_BUNDLE_MODULE_LOADER__;
|
|
270
|
+
if (_bundleModuleLoader) {
|
|
271
|
+
const hit = _bundleModuleLoader(normalizeBundleModulePath(filepath));
|
|
272
|
+
if (hit !== void 0) {
|
|
273
|
+
let obj$1 = hit;
|
|
274
|
+
if (obj$1?.default?.__esModule === true && "default" in obj$1.default) obj$1 = obj$1.default;
|
|
275
|
+
if (options?.importDefaultOnly && obj$1 && typeof obj$1 === "object" && "default" in obj$1) obj$1 = obj$1.default;
|
|
276
|
+
return obj$1;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
213
279
|
const moduleFilePath = importResolve(filepath, options);
|
|
280
|
+
if (_snapshotModuleLoader) {
|
|
281
|
+
let obj$1 = _snapshotModuleLoader(moduleFilePath);
|
|
282
|
+
if (obj$1 && typeof obj$1 === "object" && obj$1.default?.__esModule === true && obj$1.default && "default" in obj$1.default) obj$1 = obj$1.default;
|
|
283
|
+
if (options?.importDefaultOnly) {
|
|
284
|
+
if (obj$1 && typeof obj$1 === "object" && "default" in obj$1) obj$1 = obj$1.default;
|
|
285
|
+
}
|
|
286
|
+
return obj$1;
|
|
287
|
+
}
|
|
288
|
+
const _moduleImporter = globalThis.__EGG_MODULE_IMPORTER__;
|
|
289
|
+
if (_moduleImporter) {
|
|
290
|
+
let obj$1 = await _moduleImporter(moduleFilePath);
|
|
291
|
+
if (obj$1 && typeof obj$1 === "object" && obj$1.default?.__esModule === true && obj$1.default && "default" in obj$1.default) obj$1 = obj$1.default;
|
|
292
|
+
if (options?.importDefaultOnly && obj$1 && typeof obj$1 === "object" && "default" in obj$1) obj$1 = obj$1.default;
|
|
293
|
+
return obj$1;
|
|
294
|
+
}
|
|
214
295
|
let obj;
|
|
215
296
|
if (isESM) {
|
|
216
297
|
const fileUrl = pathToFileURL(moduleFilePath).toString();
|
|
217
298
|
debug("[importModule:start] await import fileUrl: %s, isESM: %s", fileUrl, isESM);
|
|
218
|
-
|
|
299
|
+
/* v8 ignore if -- covered by the spawned Node fixture; Vitest cannot instrument this opaque import. */
|
|
300
|
+
if (_bundleModuleLoader) obj = await getNativeDynamicImport()(fileUrl);
|
|
301
|
+
else {
|
|
302
|
+
let pending = _inflightImports.get(fileUrl);
|
|
303
|
+
if (pending === void 0) {
|
|
304
|
+
pending = import(fileUrl);
|
|
305
|
+
_inflightImports.set(fileUrl, pending);
|
|
306
|
+
const clearInflight = () => {
|
|
307
|
+
if (_inflightImports.get(fileUrl) === pending) _inflightImports.delete(fileUrl);
|
|
308
|
+
};
|
|
309
|
+
pending.then(clearInflight, clearInflight);
|
|
310
|
+
}
|
|
311
|
+
obj = await pending;
|
|
312
|
+
}
|
|
219
313
|
debug("[importModule:success] await import %o", fileUrl);
|
|
220
|
-
if (obj?.default?.__esModule === true && "default" in obj
|
|
314
|
+
if (obj?.default?.__esModule === true && obj.default && "default" in obj.default) obj = obj.default;
|
|
221
315
|
if (options?.importDefaultOnly) {
|
|
222
316
|
if ("default" in obj) obj = obj.default;
|
|
223
317
|
}
|
|
@@ -231,4 +325,4 @@ async function importModule(filepath, options) {
|
|
|
231
325
|
}
|
|
232
326
|
|
|
233
327
|
//#endregion
|
|
234
|
-
export { getExtensions, getRequire, importModule, importResolve, isESM, isSupportTypeScript };
|
|
328
|
+
export { getExtensions, getRequire, importModule, importResolve, isESM, isSupportTypeScript, setBundleModuleLoader, setSnapshotModuleLoader };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getFrameworkOrEggPath } from "./deprecated.js";
|
|
2
2
|
import { getFrameworkPath } from "./framework.js";
|
|
3
3
|
import { findEggCore, getConfig, getLoadUnits, getLoader, getPlugins } from "./plugin.js";
|
|
4
|
-
import { ImportModuleOptions, ImportResolveOptions, getExtensions, getRequire, importModule, importResolve, isESM, isSupportTypeScript } from "./import.js";
|
|
4
|
+
import { BundleModuleLoader, ImportModuleOptions, ImportResolveOptions, SnapshotModuleLoader, getExtensions, getRequire, importModule, importResolve, isESM, isSupportTypeScript, setBundleModuleLoader, setSnapshotModuleLoader } from "./import.js";
|
|
5
5
|
import { ImportResolveError } from "./error/ImportResolveError.js";
|
|
6
6
|
|
|
7
7
|
//#region src/index.d.ts
|
|
@@ -25,4 +25,4 @@ type EggType = (typeof EggType)[keyof typeof EggType];
|
|
|
25
25
|
*/
|
|
26
26
|
declare function detectType(baseDir: string): Promise<keyof typeof EggType>;
|
|
27
27
|
//#endregion
|
|
28
|
-
export { EggType, ImportModuleOptions, ImportResolveError, ImportResolveOptions, _default as default, detectType, findEggCore, getConfig, getExtensions, getFrameworkOrEggPath, getFrameworkPath, getLoadUnits, getLoader, getPlugins, getRequire, importModule, importResolve, isESM, isSupportTypeScript };
|
|
28
|
+
export { BundleModuleLoader, EggType, ImportModuleOptions, ImportResolveError, ImportResolveOptions, SnapshotModuleLoader, _default as default, detectType, findEggCore, getConfig, getExtensions, getFrameworkOrEggPath, getFrameworkPath, getLoadUnits, getLoader, getPlugins, getRequire, importModule, importResolve, isESM, isSupportTypeScript, setBundleModuleLoader, setSnapshotModuleLoader };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getFrameworkOrEggPath } from "./deprecated.js";
|
|
2
2
|
import { ImportResolveError } from "./error/ImportResolveError.js";
|
|
3
|
-
import { getExtensions, getRequire, importModule, importResolve, isESM, isSupportTypeScript } from "./import.js";
|
|
3
|
+
import { getExtensions, getRequire, importModule, importResolve, isESM, isSupportTypeScript, setBundleModuleLoader, setSnapshotModuleLoader } from "./import.js";
|
|
4
4
|
import { getFrameworkPath } from "./framework.js";
|
|
5
5
|
import { findEggCore, getConfig, getLoadUnits, getLoader, getPlugins } from "./plugin.js";
|
|
6
6
|
import fs from "node:fs/promises";
|
|
@@ -42,4 +42,4 @@ async function detectType(baseDir) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
//#endregion
|
|
45
|
-
export { EggType, ImportResolveError, src_default as default, detectType, findEggCore, getConfig, getExtensions, getFrameworkOrEggPath, getFrameworkPath, getLoadUnits, getLoader, getPlugins, getRequire, importModule, importResolve, isESM, isSupportTypeScript };
|
|
45
|
+
export { EggType, ImportResolveError, src_default as default, detectType, findEggCore, getConfig, getExtensions, getFrameworkOrEggPath, getFrameworkPath, getLoadUnits, getLoader, getPlugins, getRequire, importModule, importResolve, isESM, isSupportTypeScript, setBundleModuleLoader, setSnapshotModuleLoader };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eggjs/utils",
|
|
3
|
-
"version": "5.0.2-beta.
|
|
3
|
+
"version": "5.0.2-beta.22",
|
|
4
4
|
"description": "Utils for all egg projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"egg",
|
|
@@ -26,9 +26,18 @@
|
|
|
26
26
|
"./package.json": "./package.json"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
|
-
"access": "public"
|
|
29
|
+
"access": "public",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": "./dist/index.js",
|
|
32
|
+
"./package.json": "./package.json"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"typecheck": "tsgo --noEmit"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@eggjs/typings": "4.1.2-beta.22"
|
|
30
40
|
},
|
|
31
|
-
"dependencies": {},
|
|
32
41
|
"devDependencies": {
|
|
33
42
|
"coffee": "5",
|
|
34
43
|
"mm": "^4.0.2",
|
|
@@ -37,8 +46,5 @@
|
|
|
37
46
|
},
|
|
38
47
|
"engines": {
|
|
39
48
|
"node": ">=22.18.0"
|
|
40
|
-
},
|
|
41
|
-
"scripts": {
|
|
42
|
-
"typecheck": "tsgo --noEmit"
|
|
43
49
|
}
|
|
44
|
-
}
|
|
50
|
+
}
|