@nuxt/kit 3.0.0-rc.9 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,46 +1,27 @@
1
- import { parse, basename, resolve, relative, join, normalize, isAbsolute, dirname } from 'pathe';
2
- import { existsSync, readFileSync, promises } from 'node:fs';
3
- import hash from 'hash-sum';
1
+ import { promises, existsSync, readFileSync } from 'node:fs';
2
+ import defu, { defu as defu$1 } from 'defu';
3
+ import { applyDefaults } from 'untyped';
4
+ import { dirname, join, normalize, relative, isAbsolute, resolve, basename, parse } from 'pathe';
5
+ import consola from 'consola';
4
6
  import { getContext } from 'unctx';
5
- import { kebabCase, pascalCase } from 'scule';
6
7
  import satisfies from 'semver/functions/satisfies.js';
7
- import consola from 'consola';
8
+ import lodashTemplate from 'lodash.template';
9
+ import { genSafeVariableName, genDynamicImport, genImport } from 'knitwork';
8
10
  import { pathToFileURL, fileURLToPath } from 'node:url';
9
- import { globby } from 'globby';
10
- import { normalizeAliases } from 'pathe/utils';
11
11
  import { interopDefault } from 'mlly';
12
12
  import jiti from 'jiti';
13
+ import { globby } from 'globby';
14
+ import { resolveAlias as resolveAlias$1 } from 'pathe/utils';
13
15
  import ignore from 'ignore';
14
- import defu from 'defu';
15
- import { applyDefaults } from 'untyped';
16
- import lodashTemplate from 'lodash.template';
17
- import { genSafeVariableName, genDynamicImport, genImport } from 'knitwork';
18
16
  import { loadConfig } from 'c12';
19
17
  import { NuxtConfigSchema } from '@nuxt/schema';
20
18
  import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
19
+ import { kebabCase, pascalCase } from 'scule';
20
+ import hash from 'hash-sum';
21
21
 
22
- function chainFn(base, fn) {
23
- if (typeof fn !== "function") {
24
- return base;
25
- }
26
- return function(...args) {
27
- if (typeof base !== "function") {
28
- return fn.apply(this, args);
29
- }
30
- let baseResult = base.apply(this, args);
31
- if (baseResult === void 0) {
32
- [baseResult] = args;
33
- }
34
- const fnResult = fn.call(
35
- this,
36
- baseResult,
37
- ...Array.prototype.slice.call(args, 1)
38
- );
39
- if (fnResult === void 0) {
40
- return baseResult;
41
- }
42
- return fnResult;
43
- };
22
+ const logger = consola;
23
+ function useLogger(scope) {
24
+ return scope ? logger.withScope(scope) : logger;
44
25
  }
45
26
 
46
27
  const nuxtCtx = getContext("nuxt");
@@ -55,52 +36,11 @@ function tryUseNuxt() {
55
36
  return nuxtCtx.tryUse();
56
37
  }
57
38
 
58
- function addTemplate(_template) {
59
- const nuxt = useNuxt();
60
- const template = normalizeTemplate(_template);
61
- nuxt.options.build.templates = nuxt.options.build.templates.filter((p) => normalizeTemplate(p).filename !== template.filename);
62
- nuxt.options.build.templates.push(template);
63
- return template;
64
- }
65
- function normalizeTemplate(template) {
66
- if (!template) {
67
- throw new Error("Invalid template: " + JSON.stringify(template));
68
- }
69
- if (typeof template === "string") {
70
- template = { src: template };
71
- } else {
72
- template = { ...template };
73
- }
74
- if (template.src) {
75
- if (!existsSync(template.src)) {
76
- throw new Error("Template not found: " + template.src);
77
- }
78
- if (!template.filename) {
79
- const srcPath = parse(template.src);
80
- template.filename = template.fileName || `${basename(srcPath.dir)}.${srcPath.name}.${hash(template.src)}${srcPath.ext}`;
81
- }
82
- }
83
- if (!template.src && !template.getContents) {
84
- throw new Error("Invalid template. Either getContents or src options should be provided: " + JSON.stringify(template));
85
- }
86
- if (!template.filename) {
87
- throw new Error("Invalid template. Either filename should be provided: " + JSON.stringify(template));
88
- }
89
- if (template.filename.endsWith(".d.ts")) {
90
- template.write = true;
91
- }
92
- if (!template.dst) {
93
- const nuxt = useNuxt();
94
- template.dst = resolve(nuxt.options.buildDir, template.filename);
95
- }
96
- return template;
97
- }
98
-
99
39
  async function checkNuxtCompatibility(constraints, nuxt = useNuxt()) {
100
40
  const issues = [];
101
41
  if (constraints.nuxt) {
102
42
  const nuxtVersion = getNuxtVersion(nuxt);
103
- const nuxtSemanticVersion = nuxtVersion.replace(/-[0-9]+\.[0-9a-f]{7}/, "");
43
+ const nuxtSemanticVersion = nuxtVersion.replace(/-[0-9]+\.[0-9a-f]{7,8}/, "");
104
44
  if (!satisfies(nuxtSemanticVersion, constraints.nuxt, { includePrerelease: true })) {
105
45
  issues.push({
106
46
  name: "nuxt",
@@ -152,59 +92,125 @@ function getNuxtVersion(nuxt = useNuxt()) {
152
92
  return version;
153
93
  }
154
94
 
155
- const logger = consola;
156
- function useLogger(scope) {
157
- return scope ? logger.withScope(scope) : logger;
95
+ async function compileTemplate(template, ctx) {
96
+ const data = { ...ctx, options: template.options };
97
+ if (template.src) {
98
+ try {
99
+ const srcContents = await promises.readFile(template.src, "utf-8");
100
+ return lodashTemplate(srcContents, {})(data);
101
+ } catch (err) {
102
+ console.error("Error compiling template: ", template);
103
+ throw err;
104
+ }
105
+ }
106
+ if (template.getContents) {
107
+ return template.getContents(data);
108
+ }
109
+ throw new Error("Invalid template: " + JSON.stringify(template));
158
110
  }
111
+ const serialize = (data) => JSON.stringify(data, null, 2).replace(/"{(.+)}"(?=,?$)/gm, (r) => JSON.parse(r).replace(/^{(.*)}$/, "$1"));
112
+ const importSources = (sources, { lazy = false } = {}) => {
113
+ if (!Array.isArray(sources)) {
114
+ sources = [sources];
115
+ }
116
+ return sources.map((src) => {
117
+ if (lazy) {
118
+ return `const ${genSafeVariableName(src)} = ${genDynamicImport(src, { comment: `webpackChunkName: ${JSON.stringify(src)}` })}`;
119
+ }
120
+ return genImport(src, genSafeVariableName(src));
121
+ }).join("\n");
122
+ };
123
+ const importName = genSafeVariableName;
124
+ const templateUtils = { serialize, importName, importSources };
159
125
 
160
- function addLayout(template, name) {
161
- const nuxt = useNuxt();
162
- const { filename, src } = addTemplate(template);
163
- const layoutName = kebabCase(name || parse(filename).name).replace(/["']/g, "");
164
- if (isNuxt2(nuxt)) {
165
- const layout = nuxt.options.layouts[layoutName];
166
- if (layout) {
167
- return logger.warn(
168
- `Not overriding \`${layoutName}\` (provided by \`${layout}\`) with \`${src || filename}\`.`
169
- );
126
+ function defineNuxtModule(definition) {
127
+ if (!definition.meta) {
128
+ definition.meta = {};
129
+ }
130
+ if (definition.meta.configKey === void 0) {
131
+ definition.meta.configKey = definition.meta.name;
132
+ }
133
+ async function getOptions(inlineOptions, nuxt = useNuxt()) {
134
+ const configKey = definition.meta.configKey || definition.meta.name;
135
+ const _defaults = definition.defaults instanceof Function ? definition.defaults(nuxt) : definition.defaults;
136
+ let _options = defu(inlineOptions, nuxt.options[configKey], _defaults);
137
+ if (definition.schema) {
138
+ _options = await applyDefaults(definition.schema, _options);
170
139
  }
171
- nuxt.options.layouts[layoutName] = `./${filename}`;
172
- if (name === "error") {
173
- this.addErrorLayout(filename);
140
+ return Promise.resolve(_options);
141
+ }
142
+ async function normalizedModule(inlineOptions, nuxt) {
143
+ if (!nuxt) {
144
+ nuxt = tryUseNuxt() || this.nuxt;
145
+ }
146
+ const uniqueKey = definition.meta.name || definition.meta.configKey;
147
+ if (uniqueKey) {
148
+ nuxt.options._requiredModules = nuxt.options._requiredModules || {};
149
+ if (nuxt.options._requiredModules[uniqueKey]) {
150
+ return;
151
+ }
152
+ nuxt.options._requiredModules[uniqueKey] = true;
153
+ }
154
+ if (definition.meta.compatibility) {
155
+ const issues = await checkNuxtCompatibility(definition.meta.compatibility, nuxt);
156
+ if (issues.length) {
157
+ logger.warn(`Module \`${definition.meta.name}\` is disabled due to incompatibility issues:
158
+ ${issues.toString()}`);
159
+ return;
160
+ }
161
+ }
162
+ nuxt2Shims(nuxt);
163
+ const _options = await getOptions(inlineOptions, nuxt);
164
+ if (definition.hooks) {
165
+ nuxt.hooks.addHooks(definition.hooks);
174
166
  }
167
+ await definition.setup?.call(null, _options, nuxt);
168
+ }
169
+ normalizedModule.getMeta = () => Promise.resolve(definition.meta);
170
+ normalizedModule.getOptions = getOptions;
171
+ return normalizedModule;
172
+ }
173
+ const NUXT2_SHIMS_KEY = "__nuxt2_shims_key__";
174
+ function nuxt2Shims(nuxt) {
175
+ if (!isNuxt2(nuxt) || nuxt[NUXT2_SHIMS_KEY]) {
175
176
  return;
176
177
  }
177
- nuxt.hook("app:templates", (app) => {
178
- if (layoutName in app.layouts) {
179
- const relativePath = relative(nuxt.options.srcDir, app.layouts[layoutName].file);
180
- return logger.warn(
181
- `Not overriding \`${layoutName}\` (provided by \`~/${relativePath}\`) with \`${src || filename}\`.`
182
- );
178
+ nuxt[NUXT2_SHIMS_KEY] = true;
179
+ nuxt.hooks = nuxt;
180
+ if (!nuxtCtx.tryUse()) {
181
+ nuxtCtx.set(nuxt);
182
+ nuxt.hook("close", () => nuxtCtx.unset());
183
+ }
184
+ let virtualTemplates;
185
+ nuxt.hook("builder:prepared", (_builder, buildOptions) => {
186
+ virtualTemplates = buildOptions.templates.filter((t) => t.getContents);
187
+ for (const template of virtualTemplates) {
188
+ buildOptions.templates.splice(buildOptions.templates.indexOf(template), 1);
183
189
  }
184
- app.layouts[layoutName] = {
185
- file: join("#build", filename),
186
- name: layoutName
190
+ });
191
+ nuxt.hook("build:templates", async (templates) => {
192
+ const context = {
193
+ nuxt,
194
+ utils: templateUtils,
195
+ app: {
196
+ dir: nuxt.options.srcDir,
197
+ extensions: nuxt.options.extensions,
198
+ plugins: nuxt.options.plugins,
199
+ templates: [
200
+ ...templates.templatesFiles,
201
+ ...virtualTemplates
202
+ ],
203
+ templateVars: templates.templateVars
204
+ }
187
205
  };
206
+ for await (const template of virtualTemplates) {
207
+ const contents = await compileTemplate({ ...template, src: "" }, context);
208
+ await promises.mkdir(dirname(template.dst), { recursive: true });
209
+ await promises.writeFile(template.dst, contents);
210
+ }
188
211
  });
189
212
  }
190
213
 
191
- function normalizeHandlerMethod(handler) {
192
- const [, method = void 0] = handler.handler.match(/\.(get|head|patch|post|put|delete|connect|options|trace)(\.\w+)*$/) || [];
193
- return {
194
- method,
195
- ...handler
196
- };
197
- }
198
- function addServerMiddleware(middleware) {
199
- useNuxt().options.serverMiddleware.push(middleware);
200
- }
201
- function addServerHandler(handler) {
202
- useNuxt().options.serverHandlers.push(normalizeHandlerMethod(handler));
203
- }
204
- function addDevServerHandler(handler) {
205
- useNuxt().options.devServerHandlers.push(handler);
206
- }
207
-
208
214
  const _require = jiti(process.cwd(), { interopDefault: true, esmResolve: true });
209
215
  function isNodeModules(id) {
210
216
  return /[/\\]node_modules[/\\]/.test(id);
@@ -253,9 +259,11 @@ function requireModulePkg(id, opts = {}) {
253
259
  function resolveModule(id, opts = {}) {
254
260
  return normalize(_require.resolve(id, {
255
261
  paths: [].concat(
262
+ // @ts-ignore
256
263
  global.__NUXT_PREPATHS__,
257
264
  opts.paths || [],
258
265
  process.cwd(),
266
+ // @ts-ignore
259
267
  global.__NUXT_PATHS__
260
268
  ).filter(Boolean)
261
269
  }));
@@ -305,18 +313,35 @@ function isIgnored(pathname) {
305
313
  }
306
314
  if (!nuxt._ignore) {
307
315
  nuxt._ignore = ignore(nuxt.options.ignoreOptions);
308
- nuxt._ignore.add(nuxt.options.ignore);
316
+ const resolvedIgnore = nuxt.options.ignore.flatMap((s) => resolveGroupSyntax(s));
317
+ nuxt._ignore.add(resolvedIgnore);
309
318
  const nuxtignoreFile = join(nuxt.options.rootDir, ".nuxtignore");
310
319
  if (existsSync(nuxtignoreFile)) {
311
320
  nuxt._ignore.add(readFileSync(nuxtignoreFile, "utf-8"));
312
321
  }
313
322
  }
314
- const relativePath = relative(nuxt.options.rootDir, pathname);
323
+ const cwds = nuxt.options._layers?.map((layer2) => layer2.cwd).sort((a, b) => b.length - a.length);
324
+ const layer = cwds?.find((cwd) => pathname.startsWith(cwd));
325
+ const relativePath = relative(layer ?? nuxt.options.rootDir, pathname);
315
326
  if (relativePath.startsWith("..")) {
316
327
  return false;
317
328
  }
318
329
  return !!(relativePath && nuxt._ignore.ignores(relativePath));
319
330
  }
331
+ function resolveGroupSyntax(group) {
332
+ let groups = [group];
333
+ while (groups.some((group2) => group2.includes("{"))) {
334
+ groups = groups.flatMap((group2) => {
335
+ const [head, ...tail] = group2.split("{");
336
+ if (tail.length) {
337
+ const [body, ...rest] = tail.join("{").split("}");
338
+ return body.split(",").map((part) => `${head}${part}${rest.join("")}`);
339
+ }
340
+ return group2;
341
+ });
342
+ }
343
+ return groups;
344
+ }
320
345
 
321
346
  async function resolvePath(path, opts = {}) {
322
347
  const _path = path;
@@ -324,7 +349,7 @@ async function resolvePath(path, opts = {}) {
324
349
  if (isAbsolute(path) && existsSync(path) && !await isDirectory(path)) {
325
350
  return path;
326
351
  }
327
- const nuxt = useNuxt();
352
+ const nuxt = tryUseNuxt();
328
353
  const cwd = opts.cwd || (nuxt ? nuxt.options.rootDir : process.cwd());
329
354
  const extensions = opts.extensions || (nuxt ? nuxt.options.extensions : [".ts", ".mjs", ".cjs", ".json"]);
330
355
  const modulesDir = nuxt ? nuxt.options.modulesDir : [];
@@ -374,15 +399,7 @@ function resolveAlias(path, alias) {
374
399
  if (!alias) {
375
400
  alias = tryUseNuxt()?.options.alias || {};
376
401
  }
377
- for (const key in normalizeAliases(alias)) {
378
- if (key === "@" && !path.startsWith("@/")) {
379
- continue;
380
- }
381
- if (path.startsWith(key)) {
382
- path = alias[key] + path.slice(key.length);
383
- }
384
- }
385
- return path;
402
+ return resolveAlias$1(path, alias);
386
403
  }
387
404
  function createResolver(base) {
388
405
  if (!base) {
@@ -412,45 +429,13 @@ async function resolveFiles(path, pattern, opts = {}) {
412
429
  return files.map((p) => resolve(path, p)).filter((p) => !isIgnored(p)).sort();
413
430
  }
414
431
 
415
- function normalizePlugin(plugin) {
416
- if (typeof plugin === "string") {
417
- plugin = { src: plugin };
418
- } else {
419
- plugin = { ...plugin };
420
- }
421
- if (!plugin.src) {
422
- throw new Error("Invalid plugin. src option is required: " + JSON.stringify(plugin));
423
- }
424
- plugin.src = normalize(resolveAlias(plugin.src));
425
- if (plugin.ssr) {
426
- plugin.mode = "server";
427
- }
428
- if (!plugin.mode) {
429
- const [, mode = "all"] = plugin.src.match(/\.(server|client)(\.\w+)*$/) || [];
430
- plugin.mode = mode;
431
- }
432
- return plugin;
433
- }
434
- function addPlugin(_plugin, opts = {}) {
435
- const nuxt = useNuxt();
436
- const plugin = normalizePlugin(_plugin);
437
- nuxt.options.plugins = nuxt.options.plugins.filter((p) => normalizePlugin(p).src !== plugin.src);
438
- nuxt.options.plugins[opts.append ? "push" : "unshift"](plugin);
439
- return plugin;
440
- }
441
- function addPluginTemplate(plugin, opts = {}) {
442
- const normalizedPlugin = typeof plugin === "string" ? { src: plugin } : { ...plugin, src: addTemplate(plugin).dst };
443
- return addPlugin(normalizedPlugin, opts);
444
- }
445
-
446
432
  async function installModule(moduleToInstall, _inlineOptions, _nuxt) {
447
433
  const nuxt = useNuxt();
448
434
  const { nuxtModule, inlineOptions } = await normalizeModule(moduleToInstall, _inlineOptions);
449
- await nuxtModule.call(
450
- useModuleContainer(),
451
- inlineOptions,
452
- nuxt
453
- );
435
+ await nuxtModule(inlineOptions, nuxt);
436
+ if (typeof moduleToInstall === "string") {
437
+ nuxt.options.build.transpile.push(moduleToInstall);
438
+ }
454
439
  nuxt.options._installedModules = nuxt.options._installedModules || [];
455
440
  nuxt.options._installedModules.push({
456
441
  meta: await nuxtModule.getMeta?.(),
@@ -459,14 +444,15 @@ async function installModule(moduleToInstall, _inlineOptions, _nuxt) {
459
444
  }
460
445
  async function normalizeModule(nuxtModule, inlineOptions) {
461
446
  const nuxt = useNuxt();
462
- if (nuxtModule?._version || nuxtModule?.version || nuxtModule?.constructor?.version || "") {
463
- [nuxtModule, inlineOptions] = [inlineOptions, {}];
464
- console.warn(new Error("`installModule` is being called with old signature!"));
465
- }
466
447
  if (typeof nuxtModule === "string") {
467
448
  const _src = resolveModule(resolveAlias(nuxtModule), { paths: nuxt.options.modulesDir });
468
449
  const isESM = _src.endsWith(".mjs");
469
- nuxtModule = isESM ? await importModule(_src) : requireModule(_src);
450
+ try {
451
+ nuxtModule = isESM ? await importModule(_src) : requireModule(_src);
452
+ } catch (error) {
453
+ console.error(`Error while requiring module \`${nuxtModule}\`: ${error}`);
454
+ throw error;
455
+ }
470
456
  }
471
457
  if (typeof nuxtModule !== "function") {
472
458
  throw new TypeError("Nuxt module should be a function: " + nuxtModule);
@@ -474,207 +460,8 @@ async function normalizeModule(nuxtModule, inlineOptions) {
474
460
  return { nuxtModule, inlineOptions };
475
461
  }
476
462
 
477
- const MODULE_CONTAINER_KEY = "__module_container__";
478
- function useModuleContainer(nuxt = useNuxt()) {
479
- if (nuxt[MODULE_CONTAINER_KEY]) {
480
- return nuxt[MODULE_CONTAINER_KEY];
481
- }
482
- async function requireModule(moduleOpts) {
483
- let src, inlineOptions;
484
- if (typeof moduleOpts === "string") {
485
- src = moduleOpts;
486
- } else if (Array.isArray(moduleOpts)) {
487
- [src, inlineOptions] = moduleOpts;
488
- } else if (typeof moduleOpts === "object") {
489
- if (moduleOpts.src || moduleOpts.handler) {
490
- src = moduleOpts.src || moduleOpts.handler;
491
- inlineOptions = moduleOpts.options;
492
- } else {
493
- src = moduleOpts;
494
- }
495
- } else {
496
- src = moduleOpts;
497
- }
498
- await installModule(src, inlineOptions);
499
- }
500
- const container = {
501
- nuxt,
502
- options: nuxt.options,
503
- ready() {
504
- return Promise.resolve();
505
- },
506
- addVendor() {
507
- },
508
- requireModule,
509
- addModule: requireModule,
510
- addServerMiddleware,
511
- addTemplate(template) {
512
- if (typeof template === "string") {
513
- template = { src: template };
514
- }
515
- if (template.write === void 0) {
516
- template.write = true;
517
- }
518
- return addTemplate(template);
519
- },
520
- addPlugin(pluginTemplate) {
521
- return addPluginTemplate(pluginTemplate);
522
- },
523
- addLayout(tmpl, name) {
524
- return addLayout(tmpl, name);
525
- },
526
- addErrorLayout(dst) {
527
- const relativeBuildDir = relative(nuxt.options.rootDir, nuxt.options.buildDir);
528
- nuxt.options.ErrorPage = `~/${relativeBuildDir}/${dst}`;
529
- },
530
- extendBuild(fn) {
531
- nuxt.options.build.extend = chainFn(nuxt.options.build.extend, fn);
532
- if (!isNuxt2(nuxt)) {
533
- console.warn("[kit] [compat] Using `extendBuild` in Nuxt 3 has no effect. Instead call extendWebpackConfig and extendViteConfig.");
534
- }
535
- },
536
- extendRoutes(fn) {
537
- if (isNuxt2(nuxt)) {
538
- nuxt.options.router.extendRoutes = chainFn(nuxt.options.router.extendRoutes, fn);
539
- } else {
540
- nuxt.hook("pages:extend", async (pages, ...args) => {
541
- const maybeRoutes = await fn(pages, ...args);
542
- if (maybeRoutes) {
543
- console.warn("[kit] [compat] Using `extendRoutes` in Nuxt 3 needs to directly modify first argument instead of returning updated routes. Skipping extended routes.");
544
- }
545
- });
546
- }
547
- }
548
- };
549
- nuxt[MODULE_CONTAINER_KEY] = container;
550
- return nuxt[MODULE_CONTAINER_KEY];
551
- }
552
-
553
- async function compileTemplate(template, ctx) {
554
- const data = { ...ctx, options: template.options };
555
- if (template.src) {
556
- try {
557
- const srcContents = await promises.readFile(template.src, "utf-8");
558
- return lodashTemplate(srcContents, {})(data);
559
- } catch (err) {
560
- console.error("Error compiling template: ", template);
561
- throw err;
562
- }
563
- }
564
- if (template.getContents) {
565
- return template.getContents(data);
566
- }
567
- throw new Error("Invalid template: " + JSON.stringify(template));
568
- }
569
- const serialize = (data) => JSON.stringify(data, null, 2).replace(/"{(.+)}"(?=,?$)/gm, (r) => JSON.parse(r).replace(/^{(.*)}$/, "$1"));
570
- const importSources = (sources, { lazy = false } = {}) => {
571
- if (!Array.isArray(sources)) {
572
- sources = [sources];
573
- }
574
- return sources.map((src) => {
575
- if (lazy) {
576
- return `const ${genSafeVariableName(src)} = ${genDynamicImport(src, { comment: `webpackChunkName: ${JSON.stringify(src)}` })}`;
577
- }
578
- return genImport(src, genSafeVariableName(src));
579
- }).join("\n");
580
- };
581
- const importName = genSafeVariableName;
582
- const templateUtils = { serialize, importName, importSources };
583
-
584
- function defineNuxtModule(definition) {
585
- if (typeof definition === "function") {
586
- definition = definition(useNuxt());
587
- logger.warn("Module definition as function is deprecated and will be removed in the future versions", definition);
588
- }
589
- if (!definition.meta) {
590
- definition.meta = {};
591
- }
592
- if (!definition.meta.configKey) {
593
- definition.meta.name = definition.meta.name || definition.name;
594
- definition.meta.configKey = definition.configKey || definition.meta.name;
595
- }
596
- function getOptions(inlineOptions, nuxt = useNuxt()) {
597
- const configKey = definition.meta.configKey || definition.meta.name;
598
- const _defaults = definition.defaults instanceof Function ? definition.defaults(nuxt) : definition.defaults;
599
- let _options = defu(inlineOptions, nuxt.options[configKey], _defaults);
600
- if (definition.schema) {
601
- _options = applyDefaults(definition.schema, _options);
602
- }
603
- return Promise.resolve(_options);
604
- }
605
- async function normalizedModule(inlineOptions, nuxt) {
606
- if (!nuxt) {
607
- nuxt = tryUseNuxt() || this.nuxt;
608
- }
609
- const uniqueKey = definition.meta.name || definition.meta.configKey;
610
- if (uniqueKey) {
611
- nuxt.options._requiredModules = nuxt.options._requiredModules || {};
612
- if (nuxt.options._requiredModules[uniqueKey]) {
613
- return;
614
- }
615
- nuxt.options._requiredModules[uniqueKey] = true;
616
- }
617
- if (definition.meta.compatibility) {
618
- const issues = await checkNuxtCompatibility(definition.meta.compatibility, nuxt);
619
- if (issues.length) {
620
- logger.warn(`Module \`${definition.meta.name}\` is disabled due to incompatibility issues:
621
- ${issues.toString()}`);
622
- return;
623
- }
624
- }
625
- nuxt2Shims(nuxt);
626
- const _options = await getOptions(inlineOptions, nuxt);
627
- if (definition.hooks) {
628
- nuxt.hooks.addHooks(definition.hooks);
629
- }
630
- await definition.setup?.call(null, _options, nuxt);
631
- }
632
- normalizedModule.getMeta = () => Promise.resolve(definition.meta);
633
- normalizedModule.getOptions = getOptions;
634
- return normalizedModule;
635
- }
636
- const NUXT2_SHIMS_KEY = "__nuxt2_shims_key__";
637
- function nuxt2Shims(nuxt) {
638
- if (!isNuxt2(nuxt) || nuxt[NUXT2_SHIMS_KEY]) {
639
- return;
640
- }
641
- nuxt[NUXT2_SHIMS_KEY] = true;
642
- nuxt.hooks = nuxt;
643
- if (!nuxtCtx.tryUse()) {
644
- nuxtCtx.set(nuxt);
645
- nuxt.hook("close", () => nuxtCtx.unset());
646
- }
647
- let virtualTemplates;
648
- nuxt.hook("builder:prepared", (_builder, buildOptions) => {
649
- virtualTemplates = buildOptions.templates.filter((t) => t.getContents);
650
- for (const template of virtualTemplates) {
651
- buildOptions.templates.splice(buildOptions.templates.indexOf(template), 1);
652
- }
653
- });
654
- nuxt.hook("build:templates", async (templates) => {
655
- const context = {
656
- nuxt,
657
- utils: templateUtils,
658
- app: {
659
- dir: nuxt.options.srcDir,
660
- extensions: nuxt.options.extensions,
661
- plugins: nuxt.options.plugins,
662
- templates: [
663
- ...templates.templatesFiles,
664
- ...virtualTemplates
665
- ],
666
- templateVars: templates.templateVars
667
- }
668
- };
669
- for await (const template of virtualTemplates) {
670
- const contents = await compileTemplate({ ...template, src: "" }, context);
671
- await promises.mkdir(dirname(template.dst), { recursive: true });
672
- await promises.writeFile(template.dst, contents);
673
- }
674
- });
675
- }
676
-
677
463
  async function loadNuxtConfig(opts) {
464
+ globalThis.defineNuxtConfig = (c) => c;
678
465
  const result = await loadConfig({
679
466
  name: "nuxt",
680
467
  configFile: "nuxt.config",
@@ -684,6 +471,7 @@ async function loadNuxtConfig(opts) {
684
471
  globalRc: true,
685
472
  ...opts
686
473
  });
474
+ delete globalThis.defineNuxtConfig;
687
475
  const { configFile, layers = [], cwd } = result;
688
476
  const nuxtConfig = result.config;
689
477
  nuxtConfig.rootDir = nuxtConfig.rootDir || cwd;
@@ -694,8 +482,25 @@ async function loadNuxtConfig(opts) {
694
482
  layer.config.rootDir = layer.config.rootDir ?? layer.cwd;
695
483
  layer.config.srcDir = resolve(layer.config.rootDir, layer.config.srcDir);
696
484
  }
697
- nuxtConfig._layers = layers.filter((layer) => layer.configFile && !layer.configFile.endsWith(".nuxtrc"));
698
- return applyDefaults(NuxtConfigSchema, nuxtConfig);
485
+ const _layers = layers.filter((layer) => layer.configFile && !layer.configFile.endsWith(".nuxtrc"));
486
+ nuxtConfig._layers = _layers;
487
+ if (!_layers.length) {
488
+ _layers.push({
489
+ cwd,
490
+ config: {
491
+ rootDir: cwd,
492
+ srcDir: cwd
493
+ }
494
+ });
495
+ }
496
+ return await applyDefaults(NuxtConfigSchema, nuxtConfig);
497
+ }
498
+
499
+ function extendNuxtSchema(def) {
500
+ const nuxt = useNuxt();
501
+ nuxt.hook("schema:extend", (schemas) => {
502
+ schemas.push(typeof def === "function" ? def() : def);
503
+ });
699
504
  }
700
505
 
701
506
  async function loadNuxt(opts) {
@@ -721,6 +526,7 @@ async function loadNuxt(opts) {
721
526
  configOverrides: opts.overrides,
722
527
  ready: opts.ready,
723
528
  envConfig: opts.dotenv
529
+ // TODO: Backward format convertion
724
530
  });
725
531
  return nuxt;
726
532
  }
@@ -736,20 +542,26 @@ async function buildNuxt(nuxt) {
736
542
 
737
543
  function addImports(imports) {
738
544
  assertNuxtCompatibility({ bridge: true });
739
- useNuxt().hook("autoImports:extend", (_imports) => {
545
+ useNuxt().hook("imports:extend", (_imports) => {
740
546
  _imports.push(...Array.isArray(imports) ? imports : [imports]);
741
- }, { allowDeprecated: true });
547
+ });
742
548
  }
743
- const addAutoImport = addImports;
744
549
  function addImportsDir(dirs) {
745
550
  assertNuxtCompatibility({ bridge: true });
746
- useNuxt().hook("autoImports:dirs", (_dirs) => {
551
+ useNuxt().hook("imports:dirs", (_dirs) => {
747
552
  for (const dir of Array.isArray(dirs) ? dirs : [dirs]) {
748
553
  _dirs.push(dir);
749
554
  }
750
- }, { allowDeprecated: true });
555
+ });
556
+ }
557
+ function addImportsSources(presets) {
558
+ assertNuxtCompatibility({ bridge: true });
559
+ useNuxt().hook("imports:sources", (_presets) => {
560
+ for (const preset of Array.isArray(presets) ? presets : [presets]) {
561
+ _presets.push(preset);
562
+ }
563
+ });
751
564
  }
752
- const addAutoImportDir = addImportsDir;
753
565
 
754
566
  function extendWebpackConfig(fn, options = {}) {
755
567
  const nuxt = useNuxt();
@@ -772,12 +584,6 @@ function extendWebpackConfig(fn, options = {}) {
772
584
  fn(config);
773
585
  }
774
586
  }
775
- if (options.modern !== false) {
776
- const config = configs.find((i) => i.name === "modern");
777
- if (config) {
778
- fn(config);
779
- }
780
- }
781
587
  });
782
588
  }
783
589
  function extendViteConfig(fn, options = {}) {
@@ -803,13 +609,21 @@ function extendViteConfig(fn, options = {}) {
803
609
  function addWebpackPlugin(plugin, options) {
804
610
  extendWebpackConfig((config) => {
805
611
  config.plugins = config.plugins || [];
806
- config.plugins.push(plugin);
612
+ if (Array.isArray(plugin)) {
613
+ config.plugins.push(...plugin);
614
+ } else {
615
+ config.plugins.push(plugin);
616
+ }
807
617
  }, options);
808
618
  }
809
619
  function addVitePlugin(plugin, options) {
810
620
  extendViteConfig((config) => {
811
621
  config.plugins = config.plugins || [];
812
- config.plugins.push(plugin);
622
+ if (Array.isArray(plugin)) {
623
+ config.plugins.push(...plugin);
624
+ } else {
625
+ config.plugins.push(plugin);
626
+ }
813
627
  }, options);
814
628
  }
815
629
 
@@ -835,10 +649,6 @@ async function addComponent(opts) {
835
649
  preload: false,
836
650
  mode: "all",
837
651
  shortPath: opts.filePath,
838
- async: false,
839
- level: 0,
840
- asyncImport: `${genDynamicImport(opts.filePath)}.then(r => r['${opts.export || "default"}'])`,
841
- import: `require(${JSON.stringify(opts.filePath)})['${opts.export || "default"}']`,
842
652
  ...opts
843
653
  };
844
654
  nuxt.hook("components:extend", (components) => {
@@ -853,6 +663,81 @@ async function addComponent(opts) {
853
663
  });
854
664
  }
855
665
 
666
+ function addTemplate(_template) {
667
+ const nuxt = useNuxt();
668
+ const template = normalizeTemplate(_template);
669
+ nuxt.options.build.templates = nuxt.options.build.templates.filter((p) => normalizeTemplate(p).filename !== template.filename);
670
+ nuxt.options.build.templates.push(template);
671
+ return template;
672
+ }
673
+ function normalizeTemplate(template) {
674
+ if (!template) {
675
+ throw new Error("Invalid template: " + JSON.stringify(template));
676
+ }
677
+ if (typeof template === "string") {
678
+ template = { src: template };
679
+ } else {
680
+ template = { ...template };
681
+ }
682
+ if (template.src) {
683
+ if (!existsSync(template.src)) {
684
+ throw new Error("Template not found: " + template.src);
685
+ }
686
+ if (!template.filename) {
687
+ const srcPath = parse(template.src);
688
+ template.filename = template.fileName || `${basename(srcPath.dir)}.${srcPath.name}.${hash(template.src)}${srcPath.ext}`;
689
+ }
690
+ }
691
+ if (!template.src && !template.getContents) {
692
+ throw new Error("Invalid template. Either getContents or src options should be provided: " + JSON.stringify(template));
693
+ }
694
+ if (!template.filename) {
695
+ throw new Error("Invalid template. Either filename should be provided: " + JSON.stringify(template));
696
+ }
697
+ if (template.filename.endsWith(".d.ts")) {
698
+ template.write = true;
699
+ }
700
+ if (!template.dst) {
701
+ const nuxt = useNuxt();
702
+ template.dst = resolve(nuxt.options.buildDir, template.filename);
703
+ }
704
+ return template;
705
+ }
706
+ function updateTemplates(options) {
707
+ return useNuxt().hooks.callHook("builder:generateApp", options);
708
+ }
709
+
710
+ function addLayout(template, name) {
711
+ const nuxt = useNuxt();
712
+ const { filename, src } = addTemplate(template);
713
+ const layoutName = kebabCase(name || parse(filename).name).replace(/["']/g, "");
714
+ if (isNuxt2(nuxt)) {
715
+ const layout = nuxt.options.layouts[layoutName];
716
+ if (layout) {
717
+ return logger.warn(
718
+ `Not overriding \`${layoutName}\` (provided by \`${layout}\`) with \`${src || filename}\`.`
719
+ );
720
+ }
721
+ nuxt.options.layouts[layoutName] = `./${filename}`;
722
+ if (name === "error") {
723
+ this.addErrorLayout(filename);
724
+ }
725
+ return;
726
+ }
727
+ nuxt.hook("app:templates", (app) => {
728
+ if (layoutName in app.layouts) {
729
+ const relativePath = relative(nuxt.options.srcDir, app.layouts[layoutName].file);
730
+ return logger.warn(
731
+ `Not overriding \`${layoutName}\` (provided by \`~/${relativePath}\`) with \`${src || filename}\`.`
732
+ );
733
+ }
734
+ app.layouts[layoutName] = {
735
+ file: join("#build", filename),
736
+ name: layoutName
737
+ };
738
+ });
739
+ }
740
+
856
741
  function extendPages(cb) {
857
742
  const nuxt = useNuxt();
858
743
  if (isNuxt2(nuxt)) {
@@ -861,5 +746,87 @@ function extendPages(cb) {
861
746
  nuxt.hook("pages:extend", cb);
862
747
  }
863
748
  }
749
+ function extendRouteRules(route, rule, options = {}) {
750
+ const nuxt = useNuxt();
751
+ for (const opts of [nuxt.options, nuxt.options.nitro]) {
752
+ if (!opts.routeRules) {
753
+ opts.routeRules = {};
754
+ }
755
+ opts.routeRules[route] = options.override ? defu$1(rule, opts.routeRules[route]) : defu$1(opts.routeRules[route], rule);
756
+ }
757
+ }
758
+
759
+ function normalizePlugin(plugin) {
760
+ if (typeof plugin === "string") {
761
+ plugin = { src: plugin };
762
+ } else {
763
+ plugin = { ...plugin };
764
+ }
765
+ if (!plugin.src) {
766
+ throw new Error("Invalid plugin. src option is required: " + JSON.stringify(plugin));
767
+ }
768
+ plugin.src = normalize(resolveAlias(plugin.src));
769
+ if (plugin.ssr) {
770
+ plugin.mode = "server";
771
+ }
772
+ if (!plugin.mode) {
773
+ const [, mode = "all"] = plugin.src.match(/\.(server|client)(\.\w+)*$/) || [];
774
+ plugin.mode = mode;
775
+ }
776
+ return plugin;
777
+ }
778
+ function addPlugin(_plugin, opts = {}) {
779
+ const nuxt = useNuxt();
780
+ const plugin = normalizePlugin(_plugin);
781
+ nuxt.options.plugins = nuxt.options.plugins.filter((p) => normalizePlugin(p).src !== plugin.src);
782
+ nuxt.options.plugins[opts.append ? "push" : "unshift"](plugin);
783
+ return plugin;
784
+ }
785
+ function addPluginTemplate(plugin, opts = {}) {
786
+ const normalizedPlugin = typeof plugin === "string" ? { src: plugin } : { ...plugin, src: addTemplate(plugin).dst };
787
+ return addPlugin(normalizedPlugin, opts);
788
+ }
789
+
790
+ function normalizeHandlerMethod(handler) {
791
+ const [, method = void 0] = handler.handler.match(/\.(get|head|patch|post|put|delete|connect|options|trace)(\.\w+)*$/) || [];
792
+ return {
793
+ method,
794
+ ...handler,
795
+ handler: normalize(handler.handler)
796
+ };
797
+ }
798
+ function addServerHandler(handler) {
799
+ useNuxt().options.serverHandlers.push(normalizeHandlerMethod(handler));
800
+ }
801
+ function addDevServerHandler(handler) {
802
+ useNuxt().options.devServerHandlers.push(handler);
803
+ }
804
+ function addServerPlugin(plugin) {
805
+ const nuxt = useNuxt();
806
+ nuxt.options.nitro.plugins = nuxt.options.nitro.plugins || [];
807
+ nuxt.options.nitro.plugins.push(normalize(plugin));
808
+ }
809
+ function addPrerenderRoutes(routes) {
810
+ const nuxt = useNuxt();
811
+ if (!Array.isArray(routes)) {
812
+ routes = [routes];
813
+ }
814
+ routes = routes.filter(Boolean);
815
+ if (!routes.length) {
816
+ return;
817
+ }
818
+ nuxt.hook("prerender:routes", (ctx) => {
819
+ for (const route of routes) {
820
+ ctx.routes.add(route);
821
+ }
822
+ });
823
+ }
824
+ function useNitro() {
825
+ const nuxt = useNuxt();
826
+ if (!nuxt._nitro) {
827
+ throw new Error("Nitro is not initialized yet. You can call `useNitro()` only after `ready` hook.");
828
+ }
829
+ return nuxt._nitro;
830
+ }
864
831
 
865
- export { addAutoImport, addAutoImportDir, addComponent, addComponentsDir, addDevServerHandler, addImports, addImportsDir, addLayout, addPlugin, addPluginTemplate, addServerHandler, addServerMiddleware, addTemplate, addVitePlugin, addWebpackPlugin, assertNuxtCompatibility, buildNuxt, checkNuxtCompatibility, clearRequireCache, compileTemplate, createResolver, defineNuxtModule, extendPages, extendViteConfig, extendWebpackConfig, findPath, getNuxtVersion, getRequireCacheItem, hasNuxtCompatibility, importModule, installModule, isIgnored, isNodeModules, isNuxt2, isNuxt3, loadNuxt, loadNuxtConfig, logger, normalizePlugin, normalizeTemplate, nuxtCtx, requireModule, requireModulePkg, resolveAlias, resolveFiles, resolveModule, resolvePath, scanRequireTree, templateUtils, tryImportModule, tryRequireModule, tryResolveModule, tryUseNuxt, useLogger, useModuleContainer, useNuxt };
832
+ export { addComponent, addComponentsDir, addDevServerHandler, addImports, addImportsDir, addImportsSources, addLayout, addPlugin, addPluginTemplate, addPrerenderRoutes, addServerHandler, addServerPlugin, addTemplate, addVitePlugin, addWebpackPlugin, assertNuxtCompatibility, buildNuxt, checkNuxtCompatibility, clearRequireCache, compileTemplate, createResolver, defineNuxtModule, extendNuxtSchema, extendPages, extendRouteRules, extendViteConfig, extendWebpackConfig, findPath, getNuxtVersion, getRequireCacheItem, hasNuxtCompatibility, importModule, installModule, isIgnored, isNodeModules, isNuxt2, isNuxt3, loadNuxt, loadNuxtConfig, logger, normalizePlugin, normalizeTemplate, nuxtCtx, requireModule, requireModulePkg, resolveAlias, resolveFiles, resolveModule, resolvePath, scanRequireTree, templateUtils, tryImportModule, tryRequireModule, tryResolveModule, tryUseNuxt, updateTemplates, useLogger, useNitro, useNuxt };