@nuxt/kit 3.20.0 → 3.20.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/README.md +8 -8
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +58 -28
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
[](https://nuxt.com)
|
|
2
2
|
|
|
3
3
|
# Nuxt
|
|
4
4
|
|
|
5
5
|
<p>
|
|
6
6
|
<a href="https://www.npmjs.com/package/nuxt"><img src="https://img.shields.io/npm/v/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="Version"></a>
|
|
7
7
|
<a href="https://www.npmjs.com/package/nuxt"><img src="https://img.shields.io/npm/dm/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="Downloads"></a>
|
|
8
|
-
<a href="https://github.com/nuxt/nuxt/
|
|
8
|
+
<a href="https://github.com/nuxt/nuxt/blob/main/LICENSE"><img src="https://img.shields.io/github/license/nuxt/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="License"></a>
|
|
9
9
|
<a href="https://nuxt.com"><img src="https://img.shields.io/badge/Nuxt%20Docs-18181B?logo=nuxt" alt="Website"></a>
|
|
10
10
|
<a href="https://chat.nuxt.dev"><img src="https://img.shields.io/badge/Nuxt%20Discord-18181B?logo=discord" alt="Discord"></a>
|
|
11
11
|
<a href="https://securityscorecards.dev/"><img src="https://api.securityscorecards.dev/projects/github.com/nuxt/nuxt/badge" alt="Nuxt openssf scorecard score"></a>
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
Nuxt is a free and open-source framework with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with Vue.js.
|
|
15
15
|
|
|
16
16
|
It provides a number of features that make it easy to build fast, SEO-friendly, and scalable web applications, including:
|
|
17
|
-
- Server-side rendering,
|
|
17
|
+
- Server-side rendering, static site generation, hybrid rendering and edge-side rendering
|
|
18
18
|
- Automatic routing with code-splitting and pre-fetching
|
|
19
19
|
- Data fetching and state management
|
|
20
|
-
-
|
|
20
|
+
- Search engine optimization and defining meta tags
|
|
21
21
|
- Auto imports of components, composables and utils
|
|
22
22
|
- TypeScript with zero configuration
|
|
23
|
-
- Go
|
|
23
|
+
- Go full-stack with our server/ directory
|
|
24
24
|
- Extensible with [200+ modules](https://nuxt.com/modules)
|
|
25
25
|
- Deployment to a variety of [hosting platforms](https://nuxt.com/deploy)
|
|
26
26
|
- ...[and much more](https://nuxt.com) 🚀
|
|
@@ -31,7 +31,7 @@ It provides a number of features that make it easy to build fast, SEO-friendly,
|
|
|
31
31
|
- 💻 [ Vue Development](#vue-development)
|
|
32
32
|
- 📖 [Documentation](#documentation)
|
|
33
33
|
- 🧩 [Modules](#modules)
|
|
34
|
-
- ❤️
|
|
34
|
+
- ❤️ [Contribute](#contribute)
|
|
35
35
|
- 🏠 [Local Development](#local-development)
|
|
36
36
|
- 🛟 [Professional Support](#professional-support)
|
|
37
37
|
- 🔗 [Follow Us](#follow-us)
|
|
@@ -109,9 +109,9 @@ Follow the docs to [Set Up Your Local Development Environment](https://nuxt.com/
|
|
|
109
109
|
## <a name="follow-us">🔗 Follow Us</a>
|
|
110
110
|
|
|
111
111
|
<p valign="center">
|
|
112
|
-
<a href="https://go.nuxt.com/discord"><img width="20px" src="https://github.com/nuxt/nuxt/
|
|
112
|
+
<a href="https://go.nuxt.com/discord"><img width="20px" src="https://github.com/nuxt/nuxt/blob/main/.github/assets/discord.svg" alt="Discord"></a> <a href="https://go.nuxt.com/x"><img width="20px" src="https://github.com/nuxt/nuxt/blob/main/.github/assets/twitter.svg" alt="Twitter"></a> <a href="https://go.nuxt.com/github"><img width="20px" src="https://github.com/nuxt/nuxt/blob/main/.github/assets/github.svg" alt="GitHub"></a> <a href="https://go.nuxt.com/bluesky"><img width="20px" src="https://github.com/nuxt/nuxt/blob/main/.github/assets/bluesky.svg" alt="Bluesky"></a>
|
|
113
113
|
</p>
|
|
114
114
|
|
|
115
115
|
## <a name="license">⚖️ License</a>
|
|
116
116
|
|
|
117
|
-
[MIT](https://github.com/nuxt/nuxt/
|
|
117
|
+
[MIT](https://github.com/nuxt/nuxt/blob/main/LICENSE)
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import { ModuleOptions, ModuleDefinition, NuxtModule, NuxtConfig, Nuxt, ModuleMeta, NuxtOptions, SchemaDefinition, NuxtAppConfig,
|
|
2
|
+
import { ModuleOptions, ModuleDefinition, NuxtModule, NuxtConfig, Nuxt, ModuleMeta, NuxtOptions, SchemaDefinition, NuxtAppConfig, NuxtCompatibility, NuxtCompatibilityIssues, Component, ComponentsDir, NuxtTemplate, NuxtMiddleware, NuxtHooks, NuxtPlugin, NuxtPluginTemplate, ResolvedNuxtTemplate, NuxtServerTemplate, NuxtTypeTemplate } from '@nuxt/schema';
|
|
3
3
|
import { LoadConfigOptions } from 'c12';
|
|
4
|
-
import { Import } from 'unimport';
|
|
4
|
+
import { Import, InlinePreset } from 'unimport';
|
|
5
5
|
import { WebpackPluginInstance, Configuration } from 'webpack';
|
|
6
6
|
import { RspackPluginInstance } from '@rspack/core';
|
|
7
7
|
import { Plugin, UserConfig } from 'vite';
|
|
@@ -124,7 +124,7 @@ declare function addImports(imports: Import | Import[]): void;
|
|
|
124
124
|
declare function addImportsDir(dirs: string | string[], opts?: {
|
|
125
125
|
prepend?: boolean;
|
|
126
126
|
}): void;
|
|
127
|
-
declare function addImportsSources(presets:
|
|
127
|
+
declare function addImportsSources(presets: InlinePreset | InlinePreset[]): void;
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
130
|
* Access 'resolved' Nuxt runtime configuration, with values updated from environment.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import { ModuleOptions, ModuleDefinition, NuxtModule, NuxtConfig, Nuxt, ModuleMeta, NuxtOptions, SchemaDefinition, NuxtAppConfig,
|
|
2
|
+
import { ModuleOptions, ModuleDefinition, NuxtModule, NuxtConfig, Nuxt, ModuleMeta, NuxtOptions, SchemaDefinition, NuxtAppConfig, NuxtCompatibility, NuxtCompatibilityIssues, Component, ComponentsDir, NuxtTemplate, NuxtMiddleware, NuxtHooks, NuxtPlugin, NuxtPluginTemplate, ResolvedNuxtTemplate, NuxtServerTemplate, NuxtTypeTemplate } from '@nuxt/schema';
|
|
3
3
|
import { LoadConfigOptions } from 'c12';
|
|
4
|
-
import { Import } from 'unimport';
|
|
4
|
+
import { Import, InlinePreset } from 'unimport';
|
|
5
5
|
import { WebpackPluginInstance, Configuration } from 'webpack';
|
|
6
6
|
import { RspackPluginInstance } from '@rspack/core';
|
|
7
7
|
import { Plugin, UserConfig } from 'vite';
|
|
@@ -124,7 +124,7 @@ declare function addImports(imports: Import | Import[]): void;
|
|
|
124
124
|
declare function addImportsDir(dirs: string | string[], opts?: {
|
|
125
125
|
prepend?: boolean;
|
|
126
126
|
}): void;
|
|
127
|
-
declare function addImportsSources(presets:
|
|
127
|
+
declare function addImportsSources(presets: InlinePreset | InlinePreset[]): void;
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
130
|
* Access 'resolved' Nuxt runtime configuration, with values updated from environment.
|
package/dist/index.mjs
CHANGED
|
@@ -11,17 +11,17 @@ import { readPackageJSON, resolvePackageJSON } from 'pkg-types';
|
|
|
11
11
|
import { genSafeVariableName, genDynamicImport, genImport } from 'knitwork';
|
|
12
12
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
13
13
|
import { createJiti } from 'jiti';
|
|
14
|
-
import { parseNodeModulePath, interopDefault, resolveModuleExportNames } from 'mlly';
|
|
14
|
+
import { parseNodeModulePath, interopDefault, lookupNodeModuleSubpath, resolveModuleExportNames } from 'mlly';
|
|
15
15
|
import { resolveModulePath, resolveModuleURL } from 'exsolve';
|
|
16
16
|
import { isRelative, withTrailingSlash as withTrailingSlash$2 } from 'ufo';
|
|
17
17
|
import { read, update } from 'rc9';
|
|
18
18
|
import semver, { gte } from 'semver';
|
|
19
19
|
import { captureStackTrace } from 'errx';
|
|
20
|
+
import process from 'node:process';
|
|
20
21
|
import { glob } from 'tinyglobby';
|
|
21
22
|
import { resolveAlias as resolveAlias$1, reverseResolveAlias } from 'pathe/utils';
|
|
22
23
|
import ignore from 'ignore';
|
|
23
24
|
import { loadConfig } from 'c12';
|
|
24
|
-
import process$1 from 'node:process';
|
|
25
25
|
import destr from 'destr';
|
|
26
26
|
import { snakeCase, pascalCase, kebabCase } from 'scule';
|
|
27
27
|
import { klona } from 'klona';
|
|
@@ -2573,7 +2573,7 @@ async function installModules(modulesToInstall, resolvedModulePaths, nuxt = useN
|
|
|
2573
2573
|
localLayerModuleDirs.push(resolve(srcDir, l.config?.dir?.modules || "modules").replace(/\/?$/, "/"));
|
|
2574
2574
|
}
|
|
2575
2575
|
}
|
|
2576
|
-
|
|
2576
|
+
nuxt._moduleOptionsFunctions ||= /* @__PURE__ */ new Map();
|
|
2577
2577
|
const resolvedModules = [];
|
|
2578
2578
|
const inlineConfigKeys = new Set(
|
|
2579
2579
|
await Promise.all([...modulesToInstall].map(([mod]) => typeof mod !== "string" && Promise.resolve(mod.getMeta?.())?.then((r) => r?.configKey)))
|
|
@@ -2608,8 +2608,8 @@ async function installModules(modulesToInstall, resolvedModulePaths, nuxt = useN
|
|
|
2608
2608
|
}
|
|
2609
2609
|
}
|
|
2610
2610
|
if (value.overrides || value.defaults) {
|
|
2611
|
-
const currentFns =
|
|
2612
|
-
|
|
2611
|
+
const currentFns = nuxt._moduleOptionsFunctions.get(resolvedModule.module) || [];
|
|
2612
|
+
nuxt._moduleOptionsFunctions.set(resolvedModule.module, [
|
|
2613
2613
|
...currentFns,
|
|
2614
2614
|
() => ({ defaults: value.defaults, overrides: value.overrides })
|
|
2615
2615
|
]);
|
|
@@ -2644,25 +2644,28 @@ async function installModules(modulesToInstall, resolvedModulePaths, nuxt = useN
|
|
|
2644
2644
|
}
|
|
2645
2645
|
for (const { nuxtModule, meta, moduleToInstall, buildTimeModuleMeta, resolvedModulePath, inlineOptions } of resolvedModules) {
|
|
2646
2646
|
const configKey = meta?.configKey;
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
]
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2647
|
+
const optionsFns = [
|
|
2648
|
+
...nuxt._moduleOptionsFunctions.get(moduleToInstall) || [],
|
|
2649
|
+
...meta?.name ? nuxt._moduleOptionsFunctions.get(meta.name) || [] : [],
|
|
2650
|
+
// TODO: consider dropping options functions keyed by config key
|
|
2651
|
+
...configKey ? nuxt._moduleOptionsFunctions.get(configKey) || [] : []
|
|
2652
|
+
];
|
|
2653
|
+
if (optionsFns.length > 0) {
|
|
2654
|
+
const overrides = [];
|
|
2655
|
+
const defaults = [];
|
|
2656
|
+
for (const fn of optionsFns) {
|
|
2657
|
+
const options = fn();
|
|
2658
|
+
overrides.push(options.overrides);
|
|
2659
|
+
defaults.push(options.defaults);
|
|
2660
|
+
}
|
|
2661
|
+
if (configKey) {
|
|
2660
2662
|
nuxt.options[configKey] = defu(...overrides, nuxt.options[configKey], ...defaults);
|
|
2661
2663
|
}
|
|
2662
2664
|
}
|
|
2663
2665
|
await callLifecycleHooks(nuxtModule, meta, inlineOptions, nuxt);
|
|
2664
2666
|
await callModule(nuxtModule, meta, inlineOptions, resolvedModulePath, moduleToInstall, localLayerModuleDirs, buildTimeModuleMeta, nuxt);
|
|
2665
2667
|
}
|
|
2668
|
+
delete nuxt._moduleOptionsFunctions;
|
|
2666
2669
|
}
|
|
2667
2670
|
async function installModule(moduleToInstall, inlineOptions, nuxt = useNuxt()) {
|
|
2668
2671
|
const { nuxtModule, buildTimeModuleMeta, resolvedModulePath } = await loadNuxtModuleInstance(moduleToInstall, nuxt);
|
|
@@ -2673,8 +2676,27 @@ async function installModule(moduleToInstall, inlineOptions, nuxt = useNuxt()) {
|
|
|
2673
2676
|
}
|
|
2674
2677
|
}
|
|
2675
2678
|
const meta = await nuxtModule.getMeta?.();
|
|
2676
|
-
|
|
2677
|
-
|
|
2679
|
+
let mergedOptions = inlineOptions;
|
|
2680
|
+
const configKey = meta?.configKey;
|
|
2681
|
+
if (configKey && nuxt._moduleOptionsFunctions) {
|
|
2682
|
+
const optionsFns = [
|
|
2683
|
+
...nuxt._moduleOptionsFunctions.get(moduleToInstall) || [],
|
|
2684
|
+
...nuxt._moduleOptionsFunctions.get(configKey) || []
|
|
2685
|
+
];
|
|
2686
|
+
if (optionsFns.length > 0) {
|
|
2687
|
+
const overrides = [];
|
|
2688
|
+
const defaults = [];
|
|
2689
|
+
for (const fn of optionsFns) {
|
|
2690
|
+
const options = fn();
|
|
2691
|
+
overrides.push(options.overrides);
|
|
2692
|
+
defaults.push(options.defaults);
|
|
2693
|
+
}
|
|
2694
|
+
mergedOptions = defu(inlineOptions, ...overrides, nuxt.options[configKey], ...defaults);
|
|
2695
|
+
nuxt.options[configKey] = mergedOptions;
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
await callLifecycleHooks(nuxtModule, meta, mergedOptions, nuxt);
|
|
2699
|
+
await callModule(nuxtModule, meta, mergedOptions, resolvedModulePath, moduleToInstall, localLayerModuleDirs, buildTimeModuleMeta, nuxt);
|
|
2678
2700
|
}
|
|
2679
2701
|
function resolveModuleWithOptions(definition, nuxt) {
|
|
2680
2702
|
const [module, options = {}] = Array.isArray(definition) ? definition : [definition, {}];
|
|
@@ -2790,8 +2812,13 @@ async function callModule(nuxtModule, meta = {}, inlineOptions, resolvedModulePa
|
|
|
2790
2812
|
return;
|
|
2791
2813
|
}
|
|
2792
2814
|
const modulePath = resolvedModulePath || moduleToInstall;
|
|
2815
|
+
let entryPath;
|
|
2793
2816
|
if (typeof modulePath === "string") {
|
|
2794
2817
|
const parsed = parseNodeModulePath(modulePath);
|
|
2818
|
+
if (parsed.name) {
|
|
2819
|
+
const subpath = await lookupNodeModuleSubpath(modulePath) || ".";
|
|
2820
|
+
entryPath = join(parsed.name, subpath === "./" ? "." : subpath);
|
|
2821
|
+
}
|
|
2795
2822
|
const moduleRoot = parsed.dir ? parsed.dir + parsed.name : await resolvePackageJSON(modulePath, { try: true }).then((r) => r ? dirname(r) : modulePath);
|
|
2796
2823
|
nuxt.options.build.transpile.push(normalizeModuleTranspilePath(moduleRoot));
|
|
2797
2824
|
const directory = moduleRoot.replace(/\/?$/, "/");
|
|
@@ -2800,7 +2827,7 @@ async function callModule(nuxtModule, meta = {}, inlineOptions, resolvedModulePa
|
|
|
2800
2827
|
}
|
|
2801
2828
|
}
|
|
2802
2829
|
nuxt.options._installedModules ||= [];
|
|
2803
|
-
|
|
2830
|
+
entryPath ||= typeof moduleToInstall === "string" ? resolveAlias(moduleToInstall, nuxt.options.alias) : void 0;
|
|
2804
2831
|
if (typeof moduleToInstall === "string" && entryPath !== moduleToInstall) {
|
|
2805
2832
|
buildTimeModuleMeta.rawPath = moduleToInstall;
|
|
2806
2833
|
}
|
|
@@ -2896,12 +2923,15 @@ async function loadNuxtConfig(opts) {
|
|
|
2896
2923
|
const processedLayers = /* @__PURE__ */ new Set();
|
|
2897
2924
|
const localRelativePaths = new Set(localLayers);
|
|
2898
2925
|
for (const layer of layers) {
|
|
2899
|
-
layer.config
|
|
2900
|
-
layer.config
|
|
2901
|
-
|
|
2926
|
+
const resolvedRootDir = layer.config?.rootDir ?? layer.cwd;
|
|
2927
|
+
layer.config = {
|
|
2928
|
+
...layer.config || {},
|
|
2929
|
+
rootDir: resolvedRootDir
|
|
2930
|
+
};
|
|
2931
|
+
if (processedLayers.has(resolvedRootDir)) {
|
|
2902
2932
|
continue;
|
|
2903
2933
|
}
|
|
2904
|
-
processedLayers.add(
|
|
2934
|
+
processedLayers.add(resolvedRootDir);
|
|
2905
2935
|
layer.config = await applyDefaults(layerSchema, layer.config);
|
|
2906
2936
|
if (!layer.configFile || layer.configFile.endsWith(".nuxtrc")) {
|
|
2907
2937
|
continue;
|
|
@@ -3113,7 +3143,7 @@ function useRuntimeConfig() {
|
|
|
3113
3143
|
return applyEnv(klona(nuxt.options.nitro.runtimeConfig), {
|
|
3114
3144
|
prefix: "NITRO_",
|
|
3115
3145
|
altPrefix: "NUXT_",
|
|
3116
|
-
envExpansion: nuxt.options.nitro.experimental?.envExpansion ?? !!process
|
|
3146
|
+
envExpansion: nuxt.options.nitro.experimental?.envExpansion ?? !!process.env.NITRO_ENV_EXPANSION
|
|
3117
3147
|
});
|
|
3118
3148
|
}
|
|
3119
3149
|
function updateRuntimeConfig(runtimeConfig) {
|
|
@@ -3124,7 +3154,7 @@ function updateRuntimeConfig(runtimeConfig) {
|
|
|
3124
3154
|
} catch {
|
|
3125
3155
|
}
|
|
3126
3156
|
}
|
|
3127
|
-
function getEnv(key, opts, env = process
|
|
3157
|
+
function getEnv(key, opts, env = process.env) {
|
|
3128
3158
|
const envKey = snakeCase(key).toUpperCase();
|
|
3129
3159
|
return destr(
|
|
3130
3160
|
env[opts.prefix + envKey] ?? env[opts.altPrefix + envKey]
|
|
@@ -3156,7 +3186,7 @@ function applyEnv(obj, opts, parentKey = "") {
|
|
|
3156
3186
|
return obj;
|
|
3157
3187
|
}
|
|
3158
3188
|
const envExpandRx = /\{\{([^{}]*)\}\}/g;
|
|
3159
|
-
function _expandFromEnv(value, env = process
|
|
3189
|
+
function _expandFromEnv(value, env = process.env) {
|
|
3160
3190
|
return value.replace(envExpandRx, (match, key) => {
|
|
3161
3191
|
return env[key] || match;
|
|
3162
3192
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxt/kit",
|
|
3
|
-
"version": "3.20.
|
|
3
|
+
"version": "3.20.2",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/nuxt/nuxt.git",
|
|
@@ -23,16 +23,16 @@
|
|
|
23
23
|
"dist"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"c12": "^3.3.
|
|
26
|
+
"c12": "^3.3.2",
|
|
27
27
|
"consola": "^3.4.2",
|
|
28
28
|
"defu": "^6.1.4",
|
|
29
29
|
"destr": "^2.0.5",
|
|
30
30
|
"errx": "^0.1.0",
|
|
31
|
-
"exsolve": "^1.0.
|
|
31
|
+
"exsolve": "^1.0.8",
|
|
32
32
|
"ignore": "^7.0.5",
|
|
33
33
|
"jiti": "^2.6.1",
|
|
34
34
|
"klona": "^2.0.6",
|
|
35
|
-
"knitwork": "^1.
|
|
35
|
+
"knitwork": "^1.3.0",
|
|
36
36
|
"mlly": "^1.8.0",
|
|
37
37
|
"ohash": "^2.0.11",
|
|
38
38
|
"pathe": "^2.0.3",
|
|
@@ -46,18 +46,18 @@
|
|
|
46
46
|
"untyped": "^2.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@rspack/core": "1.
|
|
49
|
+
"@rspack/core": "1.6.7",
|
|
50
50
|
"@types/lodash-es": "4.17.12",
|
|
51
51
|
"@types/semver": "7.7.1",
|
|
52
52
|
"hookable": "5.5.3",
|
|
53
53
|
"lodash-es": "4.17.21",
|
|
54
|
-
"nitropack": "2.12.
|
|
54
|
+
"nitropack": "2.12.9",
|
|
55
55
|
"unbuild": "3.6.1",
|
|
56
|
-
"unimport": "5.
|
|
57
|
-
"vite": "7.
|
|
56
|
+
"unimport": "5.5.0",
|
|
57
|
+
"vite": "7.2.7",
|
|
58
58
|
"vitest": "3.2.4",
|
|
59
|
-
"webpack": "5.
|
|
60
|
-
"@nuxt/schema": "3.20.
|
|
59
|
+
"webpack": "5.103.0",
|
|
60
|
+
"@nuxt/schema": "3.20.2"
|
|
61
61
|
},
|
|
62
62
|
"engines": {
|
|
63
63
|
"node": ">=18.12.0"
|