@nuxt/kit 4.0.2 → 4.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.d.mts CHANGED
@@ -7,6 +7,7 @@ import { RspackPluginInstance } from '@rspack/core';
7
7
  import { Plugin, UserConfig } from 'vite';
8
8
  import * as unctx from 'unctx';
9
9
  import { NitroRouteConfig, NitroEventHandler, NitroDevEventHandler, Nitro } from 'nitropack/types';
10
+ import { GlobOptions } from 'tinyglobby';
10
11
  import * as consola from 'consola';
11
12
  import { ConsolaOptions } from 'consola';
12
13
 
@@ -19,15 +20,29 @@ declare function defineNuxtModule<TOptions extends ModuleOptions>(): {
19
20
  with: <TOptionsDefaults extends Partial<TOptions>>(definition: ModuleDefinition<TOptions, TOptionsDefaults, true> | NuxtModule<TOptions, TOptionsDefaults, true>) => NuxtModule<TOptions, TOptionsDefaults, true>;
20
21
  };
21
22
 
22
- /** Installs a module on a Nuxt instance. */
23
+ type ModuleToInstall = string | NuxtModule<ModuleOptions, Partial<ModuleOptions>, false>;
24
+ /**
25
+ * Installs a set of modules on a Nuxt instance.
26
+ * @internal
27
+ */
28
+ declare function installModules(modulesToInstall: Map<ModuleToInstall, Record<string, any>>, resolvedModulePaths: Set<string>, nuxt?: Nuxt): Promise<void>;
29
+ /**
30
+ * Installs a module on a Nuxt instance.
31
+ * @deprecated Use module dependencies.
32
+ */
23
33
  declare function installModule<T extends string | NuxtModule, Config extends Extract<NonNullable<NuxtConfig['modules']>[number], [T, any]>>(moduleToInstall: T, inlineOptions?: [Config] extends [never] ? any : Config[1], nuxt?: Nuxt): Promise<void>;
24
- declare function getDirectory(p: string): string;
25
- declare const normalizeModuleTranspilePath: (p: string) => string;
34
+ declare function resolveModuleWithOptions(definition: NuxtModule<any> | string | false | undefined | null | [(NuxtModule | string)?, Record<string, any>?], nuxt: Nuxt): {
35
+ resolvedPath?: string;
36
+ module: string | NuxtModule<any>;
37
+ options: Record<string, any>;
38
+ } | undefined;
26
39
  declare function loadNuxtModuleInstance(nuxtModule: string | NuxtModule, nuxt?: Nuxt): Promise<{
27
40
  nuxtModule: NuxtModule<any>;
28
41
  buildTimeModuleMeta: ModuleMeta;
29
42
  resolvedModulePath?: string;
30
43
  }>;
44
+ declare function getDirectory(p: string): string;
45
+ declare const normalizeModuleTranspilePath: (p: string) => string;
31
46
 
32
47
  /**
33
48
  * Check if a Nuxt module is installed by name.
@@ -63,6 +78,41 @@ interface LoadNuxtOptions extends LoadNuxtConfigOptions {
63
78
  declare function loadNuxt(opts: LoadNuxtOptions): Promise<Nuxt>;
64
79
  declare function buildNuxt(nuxt: Nuxt): Promise<any>;
65
80
 
81
+ interface LayerDirectories {
82
+ /** Nuxt rootDir (`/` by default) */
83
+ readonly root: string;
84
+ /** Nitro source directory (`/server` by default) */
85
+ readonly server: string;
86
+ /** Local modules directory (`/modules` by default) */
87
+ readonly modules: string;
88
+ /** Shared directory (`/shared` by default) */
89
+ readonly shared: string;
90
+ /** Public directory (`/public` by default) */
91
+ readonly public: string;
92
+ /** Nuxt srcDir (`/app/` by default) */
93
+ readonly app: string;
94
+ /** Layouts directory (`/app/layouts` by default) */
95
+ readonly appLayouts: string;
96
+ /** Middleware directory (`/app/middleware` by default) */
97
+ readonly appMiddleware: string;
98
+ /** Pages directory (`/app/pages` by default) */
99
+ readonly appPages: string;
100
+ /** Plugins directory (`/app/plugins` by default) */
101
+ readonly appPlugins: string;
102
+ }
103
+ /**
104
+ * Get the resolved directory paths for all layers in a Nuxt application.
105
+ *
106
+ * Returns an array of LayerDirectories objects, ordered by layer priority:
107
+ * - The first layer is the user/project layer (highest priority)
108
+ * - Earlier layers override later layers in the array
109
+ * - Base layers appear last in the array (lowest priority)
110
+ *
111
+ * @param nuxt - The Nuxt instance to get layers from. Defaults to the current Nuxt context.
112
+ * @returns Array of LayerDirectories objects, ordered by priority (user layer first)
113
+ */
114
+ declare function getLayerDirectories(nuxt?: _nuxt_schema.Nuxt): LayerDirectories[];
115
+
66
116
  declare function addImports(imports: Import | Import[]): void;
67
117
  declare function addImportsDir(dirs: string | string[], opts?: {
68
118
  prepend?: boolean;
@@ -295,7 +345,12 @@ interface ResolvePathOptions {
295
345
  cwd?: string;
296
346
  /** An object of aliases. Default is Nuxt configured aliases. */
297
347
  alias?: Record<string, string>;
298
- /** The file extensions to try. Default is Nuxt configured extensions. */
348
+ /**
349
+ * The file extensions to try.
350
+ * Default is Nuxt configured extensions.
351
+ *
352
+ * Isn't considered when `type` is set to `'dir'`.
353
+ */
299
354
  extensions?: string[];
300
355
  /**
301
356
  * Whether to resolve files that exist in the Nuxt VFS (for example, as a Nuxt template).
@@ -304,21 +359,26 @@ interface ResolvePathOptions {
304
359
  virtual?: boolean;
305
360
  /**
306
361
  * Whether to fallback to the original path if the resolved path does not exist instead of returning the normalized input path.
307
- *
308
362
  * @default false
309
363
  */
310
364
  fallbackToOriginal?: boolean;
365
+ /**
366
+ * The type of the path to be resolved.
367
+ * @default 'file'
368
+ */
369
+ type?: PathType;
311
370
  }
312
371
  /**
313
- * Resolve full path to a file or directory respecting Nuxt alias and extensions options
372
+ * Resolve the full path to a file or a directory (based on the provided type), respecting Nuxt alias and extensions options.
314
373
  *
315
- * If path could not be resolved, normalized input path will be returned
374
+ * If a path cannot be resolved, normalized input will be returned unless the `fallbackToOriginal` option is set to `true`,
375
+ * in which case the original input path will be returned.
316
376
  */
317
377
  declare function resolvePath(path: string, opts?: ResolvePathOptions): Promise<string>;
318
378
  /**
319
379
  * Try to resolve first existing file in paths
320
380
  */
321
- declare function findPath(paths: string | string[], opts?: ResolvePathOptions, pathType?: 'file' | 'dir'): Promise<string | null>;
381
+ declare function findPath(paths: string | string[], opts?: ResolvePathOptions, pathType?: PathType): Promise<string | null>;
322
382
  /**
323
383
  * Resolve path aliases respecting Nuxt alias options
324
384
  */
@@ -332,8 +392,16 @@ interface Resolver {
332
392
  */
333
393
  declare function createResolver(base: string | URL): Resolver;
334
394
  declare function resolveNuxtModule(base: string, paths: string[]): Promise<string[]>;
395
+ type PathType = 'file' | 'dir';
396
+ /**
397
+ * Resolve absolute file paths in the provided directory with respect to `.nuxtignore` and return them sorted.
398
+ * @param path path to the directory to resolve files in
399
+ * @param pattern glob pattern or an array of glob patterns to match files
400
+ * @param opts options for globbing
401
+ */
335
402
  declare function resolveFiles(path: string, pattern: string | string[], opts?: {
336
403
  followSymbolicLinks?: boolean;
404
+ ignore?: GlobOptions['ignore'];
337
405
  }): Promise<string[]>;
338
406
 
339
407
  /**
@@ -457,5 +525,5 @@ declare function requireModule<T = unknown>(id: string, opts?: ImportModuleOptio
457
525
  */
458
526
  declare function tryRequireModule<T = unknown>(id: string, opts?: ImportModuleOptions): T | undefined;
459
527
 
460
- export { addBuildPlugin, addComponent, addComponentExports, addComponentsDir, addDevServerHandler, addImports, addImportsDir, addImportsSources, addLayout, addPlugin, addPluginTemplate, addPrerenderRoutes, addRouteMiddleware, addRspackPlugin, addServerHandler, addServerImports, addServerImportsDir, addServerPlugin, addServerScanDir, addServerTemplate, addTemplate, addTypeTemplate, addVitePlugin, addWebpackPlugin, assertNuxtCompatibility, buildNuxt, checkNuxtCompatibility, createIsIgnored, createResolver, defineNuxtModule, directoryToURL, extendNuxtSchema, extendPages, extendRouteRules, extendRspackConfig, extendViteConfig, extendWebpackConfig, findPath, getDirectory, getNuxtCtx, getNuxtModuleVersion, getNuxtVersion, hasNuxtCompatibility, hasNuxtModule, hasNuxtModuleCompatibility, importModule, installModule, isIgnored, isNuxt2, isNuxt3, isNuxtMajorVersion, loadNuxt, loadNuxtConfig, loadNuxtModuleInstance, logger, normalizeModuleTranspilePath, normalizePlugin, normalizeSemanticVersion, normalizeTemplate, nuxtCtx, requireModule, resolveAlias, resolveFiles, resolveIgnorePatterns, resolveModule, resolveNuxtModule, resolvePath, runWithNuxtContext, tryImportModule, tryRequireModule, tryResolveModule, tryUseNuxt, updateRuntimeConfig, updateTemplates, useLogger, useNitro, useNuxt, useRuntimeConfig, writeTypes };
461
- export type { AddComponentOptions, AddPluginOptions, AddRouteMiddlewareOptions, ExtendConfigOptions, ExtendRouteRulesOptions, ExtendViteConfigOptions, ExtendWebpackConfigOptions, ImportModuleOptions, LoadNuxtConfigOptions, LoadNuxtOptions, ResolveModuleOptions, ResolvePathOptions, Resolver };
528
+ export { addBuildPlugin, addComponent, addComponentExports, addComponentsDir, addDevServerHandler, addImports, addImportsDir, addImportsSources, addLayout, addPlugin, addPluginTemplate, addPrerenderRoutes, addRouteMiddleware, addRspackPlugin, addServerHandler, addServerImports, addServerImportsDir, addServerPlugin, addServerScanDir, addServerTemplate, addTemplate, addTypeTemplate, addVitePlugin, addWebpackPlugin, assertNuxtCompatibility, buildNuxt, checkNuxtCompatibility, createIsIgnored, createResolver, defineNuxtModule, directoryToURL, extendNuxtSchema, extendPages, extendRouteRules, extendRspackConfig, extendViteConfig, extendWebpackConfig, findPath, getDirectory, getLayerDirectories, getNuxtCtx, getNuxtModuleVersion, getNuxtVersion, hasNuxtCompatibility, hasNuxtModule, hasNuxtModuleCompatibility, importModule, installModule, installModules, isIgnored, isNuxt2, isNuxt3, isNuxtMajorVersion, loadNuxt, loadNuxtConfig, loadNuxtModuleInstance, logger, normalizeModuleTranspilePath, normalizePlugin, normalizeSemanticVersion, normalizeTemplate, nuxtCtx, requireModule, resolveAlias, resolveFiles, resolveIgnorePatterns, resolveModule, resolveModuleWithOptions, resolveNuxtModule, resolvePath, runWithNuxtContext, tryImportModule, tryRequireModule, tryResolveModule, tryUseNuxt, updateRuntimeConfig, updateTemplates, useLogger, useNitro, useNuxt, useRuntimeConfig, writeTypes };
529
+ export type { AddComponentOptions, AddPluginOptions, AddRouteMiddlewareOptions, ExtendConfigOptions, ExtendRouteRulesOptions, ExtendViteConfigOptions, ExtendWebpackConfigOptions, ImportModuleOptions, LayerDirectories, LoadNuxtConfigOptions, LoadNuxtOptions, ResolveModuleOptions, ResolvePathOptions, Resolver };
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ import { RspackPluginInstance } from '@rspack/core';
7
7
  import { Plugin, UserConfig } from 'vite';
8
8
  import * as unctx from 'unctx';
9
9
  import { NitroRouteConfig, NitroEventHandler, NitroDevEventHandler, Nitro } from 'nitropack/types';
10
+ import { GlobOptions } from 'tinyglobby';
10
11
  import * as consola from 'consola';
11
12
  import { ConsolaOptions } from 'consola';
12
13
 
@@ -19,15 +20,29 @@ declare function defineNuxtModule<TOptions extends ModuleOptions>(): {
19
20
  with: <TOptionsDefaults extends Partial<TOptions>>(definition: ModuleDefinition<TOptions, TOptionsDefaults, true> | NuxtModule<TOptions, TOptionsDefaults, true>) => NuxtModule<TOptions, TOptionsDefaults, true>;
20
21
  };
21
22
 
22
- /** Installs a module on a Nuxt instance. */
23
+ type ModuleToInstall = string | NuxtModule<ModuleOptions, Partial<ModuleOptions>, false>;
24
+ /**
25
+ * Installs a set of modules on a Nuxt instance.
26
+ * @internal
27
+ */
28
+ declare function installModules(modulesToInstall: Map<ModuleToInstall, Record<string, any>>, resolvedModulePaths: Set<string>, nuxt?: Nuxt): Promise<void>;
29
+ /**
30
+ * Installs a module on a Nuxt instance.
31
+ * @deprecated Use module dependencies.
32
+ */
23
33
  declare function installModule<T extends string | NuxtModule, Config extends Extract<NonNullable<NuxtConfig['modules']>[number], [T, any]>>(moduleToInstall: T, inlineOptions?: [Config] extends [never] ? any : Config[1], nuxt?: Nuxt): Promise<void>;
24
- declare function getDirectory(p: string): string;
25
- declare const normalizeModuleTranspilePath: (p: string) => string;
34
+ declare function resolveModuleWithOptions(definition: NuxtModule<any> | string | false | undefined | null | [(NuxtModule | string)?, Record<string, any>?], nuxt: Nuxt): {
35
+ resolvedPath?: string;
36
+ module: string | NuxtModule<any>;
37
+ options: Record<string, any>;
38
+ } | undefined;
26
39
  declare function loadNuxtModuleInstance(nuxtModule: string | NuxtModule, nuxt?: Nuxt): Promise<{
27
40
  nuxtModule: NuxtModule<any>;
28
41
  buildTimeModuleMeta: ModuleMeta;
29
42
  resolvedModulePath?: string;
30
43
  }>;
44
+ declare function getDirectory(p: string): string;
45
+ declare const normalizeModuleTranspilePath: (p: string) => string;
31
46
 
32
47
  /**
33
48
  * Check if a Nuxt module is installed by name.
@@ -63,6 +78,41 @@ interface LoadNuxtOptions extends LoadNuxtConfigOptions {
63
78
  declare function loadNuxt(opts: LoadNuxtOptions): Promise<Nuxt>;
64
79
  declare function buildNuxt(nuxt: Nuxt): Promise<any>;
65
80
 
81
+ interface LayerDirectories {
82
+ /** Nuxt rootDir (`/` by default) */
83
+ readonly root: string;
84
+ /** Nitro source directory (`/server` by default) */
85
+ readonly server: string;
86
+ /** Local modules directory (`/modules` by default) */
87
+ readonly modules: string;
88
+ /** Shared directory (`/shared` by default) */
89
+ readonly shared: string;
90
+ /** Public directory (`/public` by default) */
91
+ readonly public: string;
92
+ /** Nuxt srcDir (`/app/` by default) */
93
+ readonly app: string;
94
+ /** Layouts directory (`/app/layouts` by default) */
95
+ readonly appLayouts: string;
96
+ /** Middleware directory (`/app/middleware` by default) */
97
+ readonly appMiddleware: string;
98
+ /** Pages directory (`/app/pages` by default) */
99
+ readonly appPages: string;
100
+ /** Plugins directory (`/app/plugins` by default) */
101
+ readonly appPlugins: string;
102
+ }
103
+ /**
104
+ * Get the resolved directory paths for all layers in a Nuxt application.
105
+ *
106
+ * Returns an array of LayerDirectories objects, ordered by layer priority:
107
+ * - The first layer is the user/project layer (highest priority)
108
+ * - Earlier layers override later layers in the array
109
+ * - Base layers appear last in the array (lowest priority)
110
+ *
111
+ * @param nuxt - The Nuxt instance to get layers from. Defaults to the current Nuxt context.
112
+ * @returns Array of LayerDirectories objects, ordered by priority (user layer first)
113
+ */
114
+ declare function getLayerDirectories(nuxt?: _nuxt_schema.Nuxt): LayerDirectories[];
115
+
66
116
  declare function addImports(imports: Import | Import[]): void;
67
117
  declare function addImportsDir(dirs: string | string[], opts?: {
68
118
  prepend?: boolean;
@@ -295,7 +345,12 @@ interface ResolvePathOptions {
295
345
  cwd?: string;
296
346
  /** An object of aliases. Default is Nuxt configured aliases. */
297
347
  alias?: Record<string, string>;
298
- /** The file extensions to try. Default is Nuxt configured extensions. */
348
+ /**
349
+ * The file extensions to try.
350
+ * Default is Nuxt configured extensions.
351
+ *
352
+ * Isn't considered when `type` is set to `'dir'`.
353
+ */
299
354
  extensions?: string[];
300
355
  /**
301
356
  * Whether to resolve files that exist in the Nuxt VFS (for example, as a Nuxt template).
@@ -304,21 +359,26 @@ interface ResolvePathOptions {
304
359
  virtual?: boolean;
305
360
  /**
306
361
  * Whether to fallback to the original path if the resolved path does not exist instead of returning the normalized input path.
307
- *
308
362
  * @default false
309
363
  */
310
364
  fallbackToOriginal?: boolean;
365
+ /**
366
+ * The type of the path to be resolved.
367
+ * @default 'file'
368
+ */
369
+ type?: PathType;
311
370
  }
312
371
  /**
313
- * Resolve full path to a file or directory respecting Nuxt alias and extensions options
372
+ * Resolve the full path to a file or a directory (based on the provided type), respecting Nuxt alias and extensions options.
314
373
  *
315
- * If path could not be resolved, normalized input path will be returned
374
+ * If a path cannot be resolved, normalized input will be returned unless the `fallbackToOriginal` option is set to `true`,
375
+ * in which case the original input path will be returned.
316
376
  */
317
377
  declare function resolvePath(path: string, opts?: ResolvePathOptions): Promise<string>;
318
378
  /**
319
379
  * Try to resolve first existing file in paths
320
380
  */
321
- declare function findPath(paths: string | string[], opts?: ResolvePathOptions, pathType?: 'file' | 'dir'): Promise<string | null>;
381
+ declare function findPath(paths: string | string[], opts?: ResolvePathOptions, pathType?: PathType): Promise<string | null>;
322
382
  /**
323
383
  * Resolve path aliases respecting Nuxt alias options
324
384
  */
@@ -332,8 +392,16 @@ interface Resolver {
332
392
  */
333
393
  declare function createResolver(base: string | URL): Resolver;
334
394
  declare function resolveNuxtModule(base: string, paths: string[]): Promise<string[]>;
395
+ type PathType = 'file' | 'dir';
396
+ /**
397
+ * Resolve absolute file paths in the provided directory with respect to `.nuxtignore` and return them sorted.
398
+ * @param path path to the directory to resolve files in
399
+ * @param pattern glob pattern or an array of glob patterns to match files
400
+ * @param opts options for globbing
401
+ */
335
402
  declare function resolveFiles(path: string, pattern: string | string[], opts?: {
336
403
  followSymbolicLinks?: boolean;
404
+ ignore?: GlobOptions['ignore'];
337
405
  }): Promise<string[]>;
338
406
 
339
407
  /**
@@ -457,5 +525,5 @@ declare function requireModule<T = unknown>(id: string, opts?: ImportModuleOptio
457
525
  */
458
526
  declare function tryRequireModule<T = unknown>(id: string, opts?: ImportModuleOptions): T | undefined;
459
527
 
460
- export { addBuildPlugin, addComponent, addComponentExports, addComponentsDir, addDevServerHandler, addImports, addImportsDir, addImportsSources, addLayout, addPlugin, addPluginTemplate, addPrerenderRoutes, addRouteMiddleware, addRspackPlugin, addServerHandler, addServerImports, addServerImportsDir, addServerPlugin, addServerScanDir, addServerTemplate, addTemplate, addTypeTemplate, addVitePlugin, addWebpackPlugin, assertNuxtCompatibility, buildNuxt, checkNuxtCompatibility, createIsIgnored, createResolver, defineNuxtModule, directoryToURL, extendNuxtSchema, extendPages, extendRouteRules, extendRspackConfig, extendViteConfig, extendWebpackConfig, findPath, getDirectory, getNuxtCtx, getNuxtModuleVersion, getNuxtVersion, hasNuxtCompatibility, hasNuxtModule, hasNuxtModuleCompatibility, importModule, installModule, isIgnored, isNuxt2, isNuxt3, isNuxtMajorVersion, loadNuxt, loadNuxtConfig, loadNuxtModuleInstance, logger, normalizeModuleTranspilePath, normalizePlugin, normalizeSemanticVersion, normalizeTemplate, nuxtCtx, requireModule, resolveAlias, resolveFiles, resolveIgnorePatterns, resolveModule, resolveNuxtModule, resolvePath, runWithNuxtContext, tryImportModule, tryRequireModule, tryResolveModule, tryUseNuxt, updateRuntimeConfig, updateTemplates, useLogger, useNitro, useNuxt, useRuntimeConfig, writeTypes };
461
- export type { AddComponentOptions, AddPluginOptions, AddRouteMiddlewareOptions, ExtendConfigOptions, ExtendRouteRulesOptions, ExtendViteConfigOptions, ExtendWebpackConfigOptions, ImportModuleOptions, LoadNuxtConfigOptions, LoadNuxtOptions, ResolveModuleOptions, ResolvePathOptions, Resolver };
528
+ export { addBuildPlugin, addComponent, addComponentExports, addComponentsDir, addDevServerHandler, addImports, addImportsDir, addImportsSources, addLayout, addPlugin, addPluginTemplate, addPrerenderRoutes, addRouteMiddleware, addRspackPlugin, addServerHandler, addServerImports, addServerImportsDir, addServerPlugin, addServerScanDir, addServerTemplate, addTemplate, addTypeTemplate, addVitePlugin, addWebpackPlugin, assertNuxtCompatibility, buildNuxt, checkNuxtCompatibility, createIsIgnored, createResolver, defineNuxtModule, directoryToURL, extendNuxtSchema, extendPages, extendRouteRules, extendRspackConfig, extendViteConfig, extendWebpackConfig, findPath, getDirectory, getLayerDirectories, getNuxtCtx, getNuxtModuleVersion, getNuxtVersion, hasNuxtCompatibility, hasNuxtModule, hasNuxtModuleCompatibility, importModule, installModule, installModules, isIgnored, isNuxt2, isNuxt3, isNuxtMajorVersion, loadNuxt, loadNuxtConfig, loadNuxtModuleInstance, logger, normalizeModuleTranspilePath, normalizePlugin, normalizeSemanticVersion, normalizeTemplate, nuxtCtx, requireModule, resolveAlias, resolveFiles, resolveIgnorePatterns, resolveModule, resolveModuleWithOptions, resolveNuxtModule, resolvePath, runWithNuxtContext, tryImportModule, tryRequireModule, tryResolveModule, tryUseNuxt, updateRuntimeConfig, updateTemplates, useLogger, useNitro, useNuxt, useRuntimeConfig, writeTypes };
529
+ export type { AddComponentOptions, AddPluginOptions, AddRouteMiddlewareOptions, ExtendConfigOptions, ExtendRouteRulesOptions, ExtendViteConfigOptions, ExtendWebpackConfigOptions, ImportModuleOptions, LayerDirectories, LoadNuxtConfigOptions, LoadNuxtOptions, ResolveModuleOptions, ResolvePathOptions, Resolver };
package/dist/index.mjs CHANGED
@@ -8,14 +8,16 @@ import satisfies from 'semver/functions/satisfies.js';
8
8
  import { readPackageJSON, resolvePackageJSON } from 'pkg-types';
9
9
  import { existsSync, readFileSync, promises, lstatSync } from 'node:fs';
10
10
  import { pathToFileURL, fileURLToPath } from 'node:url';
11
- import { relative, join, resolve, dirname, normalize, isAbsolute, basename, parse } from 'pathe';
11
+ import { resolve, relative, join, dirname, normalize, isAbsolute, basename, parse } from 'pathe';
12
12
  import { createJiti } from 'jiti';
13
13
  import { interopDefault, parseNodeModulePath, resolveModuleExportNames } from 'mlly';
14
14
  import { resolveModulePath, resolveModuleURL } from 'exsolve';
15
- import { isRelative, withTrailingSlash } from 'ufo';
15
+ import { isRelative, withTrailingSlash as withTrailingSlash$2 } from 'ufo';
16
+ import { read, update } from 'rc9';
17
+ import semver, { gte } from 'semver';
16
18
  import { captureStackTrace } from 'errx';
17
19
  import { glob } from 'tinyglobby';
18
- import { resolveAlias as resolveAlias$1 } from 'pathe/utils';
20
+ import { resolveAlias as resolveAlias$1, reverseResolveAlias } from 'pathe/utils';
19
21
  import ignore from 'ignore';
20
22
  import { loadConfig } from 'c12';
21
23
  import process$1 from 'node:process';
@@ -23,7 +25,6 @@ import destr from 'destr';
23
25
  import { snakeCase, pascalCase, kebabCase } from 'scule';
24
26
  import { klona } from 'klona';
25
27
  import { hash } from 'ohash';
26
- import { gte } from 'semver';
27
28
  import { isAbsolute as isAbsolute$1 } from 'node:path';
28
29
 
29
30
  const logger = consola;
@@ -158,6 +159,12 @@ function _defineNuxtModule(definition) {
158
159
  }
159
160
  return Promise.resolve(options);
160
161
  }
162
+ function getModuleDependencies(nuxt = useNuxt()) {
163
+ if (typeof module.moduleDependencies === "function") {
164
+ return module.moduleDependencies(nuxt);
165
+ }
166
+ return module.moduleDependencies;
167
+ }
161
168
  async function normalizedModule(inlineOptions, nuxt = tryUseNuxt()) {
162
169
  if (!nuxt) {
163
170
  throw new TypeError("Cannot use module outside of Nuxt context");
@@ -208,6 +215,9 @@ ${issues.toString()}`;
208
215
  }
209
216
  normalizedModule.getMeta = () => Promise.resolve(module.meta);
210
217
  normalizedModule.getOptions = getOptions;
218
+ normalizedModule.getModuleDependencies = getModuleDependencies;
219
+ normalizedModule.onInstall = module.onInstall;
220
+ normalizedModule.onUpgrade = module.onUpgrade;
211
221
  return normalizedModule;
212
222
  }
213
223
 
@@ -223,6 +233,7 @@ function tryResolveModule(id, url = import.meta.url) {
223
233
  }
224
234
  function resolveModule(id, options) {
225
235
  return resolveModulePath(id, {
236
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
226
237
  from: options?.url ?? options?.paths ?? [import.meta.url],
227
238
  extensions: [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"]
228
239
  });
@@ -259,6 +270,39 @@ function tryRequireModule(id, opts) {
259
270
  }
260
271
  }
261
272
 
273
+ const layerMap = /* @__PURE__ */ new WeakMap();
274
+ function getLayerDirectories(nuxt = useNuxt()) {
275
+ return nuxt.options._layers.map((layer) => {
276
+ if (layerMap.has(layer)) {
277
+ return layerMap.get(layer);
278
+ }
279
+ const isRoot = withTrailingSlash$1(layer.config.rootDir) === withTrailingSlash$1(nuxt.options.rootDir);
280
+ const config = isRoot ? nuxt.options : layer.config;
281
+ const src = withTrailingSlash$1(config.srcDir || layer.cwd);
282
+ const root = withTrailingSlash$1(config.rootDir || layer.cwd);
283
+ const directories = {
284
+ root,
285
+ shared: withTrailingSlash$1(resolve(root, resolveAlias(config.dir?.shared || "shared", nuxt.options.alias))),
286
+ // these are resolved relative to root in `@nuxt/schema` for v4+
287
+ // so resolving relative to `src` covers backward compatibility for v3
288
+ server: withTrailingSlash$1(resolve(src, resolveAlias(config.serverDir || "server", nuxt.options.alias))),
289
+ modules: withTrailingSlash$1(resolve(src, resolveAlias(config.dir?.modules || "modules", nuxt.options.alias))),
290
+ public: withTrailingSlash$1(resolve(src, resolveAlias(config.dir?.public || "public", nuxt.options.alias))),
291
+ // nuxt app
292
+ app: src,
293
+ appLayouts: withTrailingSlash$1(resolve(src, resolveAlias(config.dir?.layouts || "layouts", nuxt.options.alias))),
294
+ appMiddleware: withTrailingSlash$1(resolve(src, resolveAlias(config.dir?.middleware || "middleware", nuxt.options.alias))),
295
+ appPages: withTrailingSlash$1(resolve(src, resolveAlias(config.dir?.pages || "pages", nuxt.options.alias))),
296
+ appPlugins: withTrailingSlash$1(resolve(src, resolveAlias(config.dir?.plugins || "plugins", nuxt.options.alias)))
297
+ };
298
+ layerMap.set(layer, directories);
299
+ return directories;
300
+ });
301
+ }
302
+ function withTrailingSlash$1(dir) {
303
+ return dir.replace(/[^/]$/, "$&/");
304
+ }
305
+
262
306
  function createIsIgnored(nuxt = tryUseNuxt()) {
263
307
  return (pathname, stats) => isIgnored(pathname, stats, nuxt);
264
308
  }
@@ -270,8 +314,8 @@ function isIgnored(pathname, _stats, nuxt = tryUseNuxt()) {
270
314
  nuxt._ignore = ignore(nuxt.options.ignoreOptions);
271
315
  nuxt._ignore.add(resolveIgnorePatterns());
272
316
  }
273
- const cwds = nuxt.options._layers?.map((layer2) => layer2.cwd).sort((a, b) => b.length - a.length);
274
- const layer = cwds?.find((cwd) => pathname.startsWith(cwd));
317
+ const cwds = getLayerDirectories(nuxt).map((dirs) => dirs.root).sort((a, b) => b.length - a.length);
318
+ const layer = cwds.find((cwd) => pathname.startsWith(cwd));
275
319
  const relativePath = relative(layer ?? nuxt.options.rootDir, pathname);
276
320
  if (relativePath[0] === "." && relativePath[1] === ".") {
277
321
  return false;
@@ -331,15 +375,20 @@ const MODE_RE = /\.(server|client)(\.\w+)*$/;
331
375
  const distDirURL = new URL(".", import.meta.url);
332
376
 
333
377
  async function resolvePath(path, opts = {}) {
334
- const res = await _resolvePathGranularly(path, opts);
335
- if (res.type === "file") {
378
+ const { type = "file" } = opts;
379
+ const res = await _resolvePathGranularly(path, { ...opts, type });
380
+ if (res.type === type) {
336
381
  return res.path;
337
382
  }
338
383
  return opts.fallbackToOriginal ? path : res.path;
339
384
  }
340
385
  async function findPath(paths, opts, pathType = "file") {
341
386
  for (const path of toArray(paths)) {
342
- const res = await _resolvePathGranularly(path, opts);
387
+ const res = await _resolvePathGranularly(path, {
388
+ ...opts,
389
+ // TODO: this is for backwards compatibility, remove the `pathType` argument in Nuxt 5
390
+ type: opts?.type || pathType
391
+ });
343
392
  if (!res.type || pathType && res.type !== pathType) {
344
393
  continue;
345
394
  }
@@ -410,12 +459,15 @@ async function _resolvePathType(path, opts = {}, skipFs = false) {
410
459
  fd?.close();
411
460
  }
412
461
  }
413
- async function _resolvePathGranularly(path, opts = {}) {
462
+ function normalizeExtension(ext) {
463
+ return ext.startsWith(".") ? ext : `.${ext}`;
464
+ }
465
+ async function _resolvePathGranularly(path, opts = { type: "file" }) {
414
466
  const _path = path;
415
467
  path = normalize(path);
416
468
  if (isAbsolute(path)) {
417
469
  const res2 = await _resolvePathType(path, opts);
418
- if (res2 && res2.type === "file") {
470
+ if (res2 && res2.type === opts.type) {
419
471
  return res2;
420
472
  }
421
473
  }
@@ -428,36 +480,39 @@ async function _resolvePathGranularly(path, opts = {}) {
428
480
  path = resolve(cwd, path);
429
481
  }
430
482
  const res = await _resolvePathType(path, opts);
431
- if (res && res.type === "file") {
483
+ if (res && res.type === opts.type) {
432
484
  return res;
433
485
  }
434
- for (const ext of extensions) {
435
- const extPath = await _resolvePathType(path + ext, opts);
436
- if (extPath && extPath.type === "file") {
437
- return extPath;
486
+ if (opts.type === "file") {
487
+ for (const ext of extensions) {
488
+ const normalizedExt = normalizeExtension(ext);
489
+ const extPath = await _resolvePathType(path + normalizedExt, opts);
490
+ if (extPath && extPath.type === "file") {
491
+ return extPath;
492
+ }
493
+ const indexPath = await _resolvePathType(
494
+ join(path, "index" + normalizedExt),
495
+ opts,
496
+ res?.type !== "dir"
497
+ /* skip checking if parent is not a directory */
498
+ );
499
+ if (indexPath && indexPath.type === "file") {
500
+ return indexPath;
501
+ }
438
502
  }
439
- const indexPath = await _resolvePathType(
440
- join(path, "index" + ext),
441
- opts,
442
- res?.type !== "dir"
443
- /* skip checking if parent is not a directory */
444
- );
445
- if (indexPath && indexPath.type === "file") {
446
- return indexPath;
503
+ const resolvedModulePath = resolveModulePath(_path, {
504
+ try: true,
505
+ suffixes: ["", "index"],
506
+ from: [cwd, ...modulesDir].map((d) => directoryToURL(d))
507
+ });
508
+ if (resolvedModulePath) {
509
+ return {
510
+ path: resolvedModulePath,
511
+ type: "file",
512
+ virtual: false
513
+ };
447
514
  }
448
515
  }
449
- const resolvedModulePath = resolveModulePath(_path, {
450
- try: true,
451
- suffixes: ["", "index"],
452
- from: [cwd, ...modulesDir].map((d) => directoryToURL(d))
453
- });
454
- if (resolvedModulePath) {
455
- return {
456
- path: resolvedModulePath,
457
- type: "file",
458
- virtual: false
459
- };
460
- }
461
516
  return {
462
517
  path
463
518
  };
@@ -478,8 +533,7 @@ function existsInVFS(path, nuxt = tryUseNuxt()) {
478
533
  }
479
534
  async function resolveFiles(path, pattern, opts = {}) {
480
535
  const files = [];
481
- for (const file of await glob(pattern, { cwd: path, followSymbolicLinks: opts.followSymbolicLinks ?? true })) {
482
- const p = resolve(path, file);
536
+ for (const p of await glob(pattern, { cwd: path, followSymbolicLinks: opts.followSymbolicLinks ?? true, absolute: true, ignore: opts.ignore })) {
483
537
  if (!isIgnored(p)) {
484
538
  files.push(p);
485
539
  }
@@ -488,8 +542,7 @@ async function resolveFiles(path, pattern, opts = {}) {
488
542
  }
489
543
 
490
544
  const NODE_MODULES_RE = /[/\\]node_modules[/\\]/;
491
- async function installModule(moduleToInstall, inlineOptions, nuxt = useNuxt()) {
492
- const { nuxtModule, buildTimeModuleMeta, resolvedModulePath } = await loadNuxtModuleInstance(moduleToInstall, nuxt);
545
+ async function installModules(modulesToInstall, resolvedModulePaths, nuxt = useNuxt()) {
493
546
  const localLayerModuleDirs = [];
494
547
  for (const l of nuxt.options._layers) {
495
548
  const srcDir = l.config.srcDir || l.cwd;
@@ -497,43 +550,132 @@ async function installModule(moduleToInstall, inlineOptions, nuxt = useNuxt()) {
497
550
  localLayerModuleDirs.push(resolve(srcDir, l.config?.dir?.modules || "modules").replace(/\/?$/, "/"));
498
551
  }
499
552
  }
500
- const res = nuxt.options.experimental?.debugModuleMutation && nuxt._asyncLocalStorageModule ? await nuxt._asyncLocalStorageModule.run(nuxtModule, () => nuxtModule(inlineOptions || {}, nuxt)) ?? {} : await nuxtModule(inlineOptions || {}, nuxt) ?? {};
501
- if (res === false) {
502
- return;
553
+ const optionsFunctions = /* @__PURE__ */ new Map();
554
+ const resolvedModules = [];
555
+ const inlineConfigKeys = new Set(
556
+ await Promise.all([...modulesToInstall].map(([mod]) => typeof mod !== "string" && Promise.resolve(mod.getMeta?.())?.then((r) => r?.configKey)))
557
+ );
558
+ let error;
559
+ const dependencyMap = /* @__PURE__ */ new Map();
560
+ for (const [key, options] of modulesToInstall) {
561
+ const res = await loadNuxtModuleInstance(key, nuxt).catch((err) => {
562
+ if (dependencyMap.has(key) && typeof key === "string") {
563
+ err.cause = `Could not resolve \`${key}\` (specified as a dependency of ${dependencyMap.get(key)}).`;
564
+ }
565
+ throw err;
566
+ });
567
+ const dependencyMeta = res.nuxtModule.getModuleDependencies?.(nuxt) || {};
568
+ for (const [name, value] of Object.entries(dependencyMeta)) {
569
+ if (!value.overrides && !value.defaults && !value.version && value.optional) {
570
+ continue;
571
+ }
572
+ const resolvedModule = resolveModuleWithOptions(name, nuxt);
573
+ const moduleToAttribute = typeof key === "string" ? `\`${key}\`` : "a module in `nuxt.options`";
574
+ if (!resolvedModule?.module) {
575
+ const message = `Could not resolve \`${name}\` (specified as a dependency of ${moduleToAttribute}).`;
576
+ error = new TypeError(message);
577
+ continue;
578
+ }
579
+ if (value.version) {
580
+ const resolvePaths = [res.resolvedModulePath, ...nuxt.options.modulesDir].filter(Boolean);
581
+ const pkg = await readPackageJSON(name, { from: resolvePaths }).catch(() => null);
582
+ if (pkg?.version && !semver.satisfies(pkg.version, value.version)) {
583
+ const message = `Module \`${name}\` version (\`${pkg.version}\`) does not satisfy \`${value.version}\` (requested by ${moduleToAttribute}).`;
584
+ error = new TypeError(message);
585
+ }
586
+ }
587
+ if (value.overrides || value.defaults) {
588
+ const currentFns = optionsFunctions.get(resolvedModule.module) || [];
589
+ optionsFunctions.set(resolvedModule.module, [
590
+ ...currentFns,
591
+ () => ({ defaults: value.defaults, overrides: value.overrides })
592
+ ]);
593
+ }
594
+ if (value.optional === true) {
595
+ continue;
596
+ }
597
+ if (resolvedModule && !modulesToInstall.has(resolvedModule.module) && (!resolvedModule.resolvedPath || !resolvedModulePaths.has(resolvedModule.resolvedPath))) {
598
+ if (typeof resolvedModule.module === "string" && inlineConfigKeys.has(resolvedModule.module)) {
599
+ continue;
600
+ }
601
+ modulesToInstall.set(resolvedModule.module, resolvedModule.options);
602
+ dependencyMap.set(resolvedModule.module, moduleToAttribute);
603
+ const path = resolvedModule.resolvedPath || resolvedModule.module;
604
+ if (typeof path === "string") {
605
+ resolvedModulePaths.add(path);
606
+ }
607
+ }
608
+ }
609
+ resolvedModules.push({
610
+ moduleToInstall: key,
611
+ meta: await res.nuxtModule.getMeta?.(),
612
+ nuxtModule: res.nuxtModule,
613
+ buildTimeModuleMeta: res.buildTimeModuleMeta,
614
+ resolvedModulePath: res.resolvedModulePath,
615
+ inlineOptions: options
616
+ });
503
617
  }
504
- const modulePath = resolvedModulePath || moduleToInstall;
505
- if (typeof modulePath === "string") {
506
- const parsed = parseNodeModulePath(modulePath);
507
- const moduleRoot = parsed.dir ? parsed.dir + parsed.name : await resolvePackageJSON(modulePath, { try: true }).then((r) => r ? dirname(r) : modulePath);
508
- nuxt.options.build.transpile.push(normalizeModuleTranspilePath(moduleRoot));
509
- const directory = moduleRoot.replace(/\/?$/, "/");
510
- if (moduleRoot !== moduleToInstall && !localLayerModuleDirs.some((dir) => directory.startsWith(dir))) {
511
- nuxt.options.modulesDir.push(join(moduleRoot, "node_modules"));
618
+ if (error) {
619
+ throw error;
620
+ }
621
+ for (const { nuxtModule, meta, moduleToInstall, buildTimeModuleMeta, resolvedModulePath, inlineOptions } of resolvedModules) {
622
+ const configKey = meta?.configKey;
623
+ if (configKey) {
624
+ const optionsFns = [
625
+ ...optionsFunctions.get(moduleToInstall) || [],
626
+ ...optionsFunctions.get(configKey) || []
627
+ ];
628
+ if (optionsFns.length > 0) {
629
+ const overrides = [];
630
+ const defaults = [];
631
+ for (const fn of optionsFns) {
632
+ const options = fn();
633
+ overrides.push(options.overrides);
634
+ defaults.push(options.defaults);
635
+ }
636
+ nuxt.options[configKey] = defu(...overrides, nuxt.options[configKey], ...defaults);
637
+ }
512
638
  }
639
+ await callLifecycleHooks(nuxtModule, meta, inlineOptions, nuxt);
640
+ await callModule(nuxtModule, meta, inlineOptions, resolvedModulePath, moduleToInstall, localLayerModuleDirs, buildTimeModuleMeta, nuxt);
513
641
  }
514
- nuxt.options._installedModules ||= [];
515
- const entryPath = typeof moduleToInstall === "string" ? resolveAlias(moduleToInstall) : void 0;
516
- if (typeof moduleToInstall === "string" && entryPath !== moduleToInstall) {
517
- buildTimeModuleMeta.rawPath = moduleToInstall;
642
+ }
643
+ async function installModule(moduleToInstall, inlineOptions, nuxt = useNuxt()) {
644
+ const { nuxtModule, buildTimeModuleMeta, resolvedModulePath } = await loadNuxtModuleInstance(moduleToInstall, nuxt);
645
+ const localLayerModuleDirs = [];
646
+ for (const dirs of getLayerDirectories(nuxt)) {
647
+ if (!NODE_MODULES_RE.test(dirs.app)) {
648
+ localLayerModuleDirs.push(dirs.modules);
649
+ }
518
650
  }
519
- nuxt.options._installedModules.push({
520
- meta: defu(await nuxtModule.getMeta?.(), buildTimeModuleMeta),
521
- module: nuxtModule,
522
- timings: res.timings,
523
- entryPath
524
- });
651
+ const meta = await nuxtModule.getMeta?.();
652
+ await callLifecycleHooks(nuxtModule, meta, inlineOptions, nuxt);
653
+ await callModule(nuxtModule, meta, inlineOptions, resolvedModulePath, moduleToInstall, localLayerModuleDirs, buildTimeModuleMeta, nuxt);
525
654
  }
526
- function getDirectory(p) {
527
- try {
528
- return isAbsolute(p) && lstatSync(p).isFile() ? dirname(p) : p;
529
- } catch {
655
+ function resolveModuleWithOptions(definition, nuxt) {
656
+ const [module, options = {}] = Array.isArray(definition) ? definition : [definition, {}];
657
+ if (!module) {
658
+ return;
530
659
  }
531
- return p;
660
+ if (typeof module !== "string") {
661
+ return {
662
+ module,
663
+ options
664
+ };
665
+ }
666
+ const modAlias = resolveAlias(module, nuxt.options.alias);
667
+ const modPath = resolveModulePath(modAlias, {
668
+ try: true,
669
+ from: nuxt.options.modulesDir.map((m) => directoryToURL(m.replace(/\/node_modules\/?$/, "/"))),
670
+ suffixes: ["nuxt", "nuxt/index", "module", "module/index", "", "index"],
671
+ extensions: [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"]
672
+ });
673
+ return {
674
+ module,
675
+ resolvedPath: modPath || modAlias,
676
+ options
677
+ };
532
678
  }
533
- const normalizeModuleTranspilePath = (p) => {
534
- return getDirectory(p).split("node_modules/").pop();
535
- };
536
- const MissingModuleMatcher = /Cannot find module\s+['"]?([^'")\s]+)['"]?/i;
537
679
  async function loadNuxtModuleInstance(nuxtModule, nuxt = useNuxt()) {
538
680
  let buildTimeModuleMeta = {};
539
681
  if (typeof nuxtModule === "function") {
@@ -580,6 +722,71 @@ async function loadNuxtModuleInstance(nuxtModule, nuxt = useNuxt()) {
580
722
  }
581
723
  throw new TypeError(`Could not load \`${nuxtModule}\`. Is it installed?`);
582
724
  }
725
+ function getDirectory(p) {
726
+ try {
727
+ return isAbsolute(p) && lstatSync(p).isFile() ? dirname(p) : p;
728
+ } catch {
729
+ }
730
+ return p;
731
+ }
732
+ const normalizeModuleTranspilePath = (p) => {
733
+ return getDirectory(p).split("node_modules/").pop();
734
+ };
735
+ const MissingModuleMatcher = /Cannot find module\s+['"]?([^'")\s]+)['"]?/i;
736
+ async function callLifecycleHooks(nuxtModule, meta = {}, inlineOptions, nuxt = useNuxt()) {
737
+ if (!meta.name || !meta.version) {
738
+ return;
739
+ }
740
+ if (!nuxtModule.onInstall && !nuxtModule.onUpgrade) {
741
+ return;
742
+ }
743
+ const rc = read({ dir: nuxt.options.rootDir, name: ".nuxtrc" });
744
+ const previousVersion = rc?.setups?.[meta.name];
745
+ try {
746
+ if (!previousVersion) {
747
+ await nuxtModule.onInstall?.(nuxt);
748
+ } else if (semver.gt(meta.version, previousVersion)) {
749
+ await nuxtModule.onUpgrade?.(inlineOptions, nuxt, previousVersion);
750
+ }
751
+ if (previousVersion !== meta.version) {
752
+ update(
753
+ { setups: { [meta.name]: meta?.version } },
754
+ { dir: nuxt.options.rootDir, name: ".nuxtrc" }
755
+ );
756
+ }
757
+ } catch (e) {
758
+ logger.error(
759
+ `Error while executing ${!previousVersion ? "install" : "upgrade"} hook for module \`${meta.name}\`: ${e}`
760
+ );
761
+ }
762
+ }
763
+ async function callModule(nuxtModule, meta = {}, inlineOptions, resolvedModulePath, moduleToInstall, localLayerModuleDirs, buildTimeModuleMeta, nuxt = useNuxt()) {
764
+ const res = nuxt.options.experimental?.debugModuleMutation && nuxt._asyncLocalStorageModule ? await nuxt._asyncLocalStorageModule.run(nuxtModule, () => nuxtModule(inlineOptions || {}, nuxt)) ?? {} : await nuxtModule(inlineOptions || {}, nuxt) ?? {};
765
+ if (res === false) {
766
+ return;
767
+ }
768
+ const modulePath = resolvedModulePath || moduleToInstall;
769
+ if (typeof modulePath === "string") {
770
+ const parsed = parseNodeModulePath(modulePath);
771
+ const moduleRoot = parsed.dir ? parsed.dir + parsed.name : await resolvePackageJSON(modulePath, { try: true }).then((r) => r ? dirname(r) : modulePath);
772
+ nuxt.options.build.transpile.push(normalizeModuleTranspilePath(moduleRoot));
773
+ const directory = moduleRoot.replace(/\/?$/, "/");
774
+ if (moduleRoot !== moduleToInstall && !localLayerModuleDirs.some((dir) => directory.startsWith(dir))) {
775
+ nuxt.options.modulesDir.push(join(moduleRoot, "node_modules"));
776
+ }
777
+ }
778
+ nuxt.options._installedModules ||= [];
779
+ const entryPath = typeof moduleToInstall === "string" ? resolveAlias(moduleToInstall, nuxt.options.alias) : void 0;
780
+ if (typeof moduleToInstall === "string" && entryPath !== moduleToInstall) {
781
+ buildTimeModuleMeta.rawPath = moduleToInstall;
782
+ }
783
+ nuxt.options._installedModules.push({
784
+ meta: defu(meta, buildTimeModuleMeta),
785
+ module: nuxtModule,
786
+ timings: res.timings,
787
+ entryPath
788
+ });
789
+ }
583
790
 
584
791
  function resolveNuxtModuleEntryName(m) {
585
792
  if (typeof m === "object" && !Array.isArray(m)) {
@@ -630,7 +837,10 @@ const merger = createDefu((obj, key, value) => {
630
837
  }
631
838
  });
632
839
  async function loadNuxtConfig(opts) {
633
- const localLayers = (await glob("layers/*", { onlyDirectories: true, cwd: opts.cwd || process.cwd() })).map((d) => d.endsWith("/") ? d.substring(0, d.length - 1) : d);
840
+ const localLayers = (await glob("layers/*", {
841
+ onlyDirectories: true,
842
+ cwd: opts.cwd || process.cwd()
843
+ })).map((d) => d.endsWith("/") ? d.substring(0, d.length - 1) : d).sort((a, b) => b.localeCompare(a));
634
844
  opts.overrides = defu$1(opts.overrides, { _extends: localLayers });
635
845
  const globalSelf = globalThis;
636
846
  globalSelf.defineNuxtConfig = (c) => c;
@@ -653,7 +863,7 @@ async function loadNuxtConfig(opts) {
653
863
  nuxtConfig.alias ||= {};
654
864
  if (meta?.name) {
655
865
  const alias = `#layers/${meta.name}`;
656
- nuxtConfig.alias[alias] ||= withTrailingSlash(nuxtConfig.rootDir);
866
+ nuxtConfig.alias[alias] ||= withTrailingSlash$2(nuxtConfig.rootDir);
657
867
  }
658
868
  const defaultBuildDir = join(nuxtConfig.rootDir, ".nuxt");
659
869
  if (!opts.overrides?._prepare && !nuxtConfig.dev && !nuxtConfig.buildDir && existsSync(defaultBuildDir)) {
@@ -687,7 +897,7 @@ async function loadNuxtConfig(opts) {
687
897
  }
688
898
  if (layer.meta?.name) {
689
899
  const alias = `#layers/${layer.meta.name}`;
690
- nuxtConfig.alias[alias] ||= withTrailingSlash(layer.config.rootDir || layer.cwd);
900
+ nuxtConfig.alias[alias] ||= withTrailingSlash$2(layer.config.rootDir || layer.cwd);
691
901
  }
692
902
  _layers.push(layer);
693
903
  }
@@ -1077,6 +1287,13 @@ function addTypeTemplate(_template, context) {
1077
1287
  sharedReferences.push({ path: template.dst });
1078
1288
  });
1079
1289
  }
1290
+ if (!context || context.nuxt || context.shared) {
1291
+ nuxt.options.vite.vue = defu(nuxt.options.vite.vue, {
1292
+ script: {
1293
+ globalTypeFiles: [template.dst]
1294
+ }
1295
+ });
1296
+ }
1080
1297
  if (context?.nitro) {
1081
1298
  nuxt.hook("nitro:prepare:types", ({ references }) => {
1082
1299
  references.push({ path: template.dst });
@@ -1117,11 +1334,11 @@ function normalizeTemplate(template, buildDir) {
1117
1334
  async function updateTemplates(options) {
1118
1335
  return await tryUseNuxt()?.hooks.callHook("builder:generateApp", options);
1119
1336
  }
1120
- function resolveLayerPaths(dir, buildDir, rootDir, srcDir) {
1121
- const relativeRootDir = relativeWithDot(buildDir, rootDir);
1122
- const relativeSrcDir = relativeWithDot(buildDir, srcDir);
1123
- const relativeModulesDir = relativeWithDot(buildDir, resolve(rootDir, dir.modules || "modules"));
1124
- const relativeSharedDir = relativeWithDot(buildDir, resolve(rootDir, dir.shared || "shared"));
1337
+ function resolveLayerPaths(dirs, projectBuildDir) {
1338
+ const relativeRootDir = relativeWithDot(projectBuildDir, dirs.root);
1339
+ const relativeSrcDir = relativeWithDot(projectBuildDir, dirs.app);
1340
+ const relativeModulesDir = relativeWithDot(projectBuildDir, dirs.modules);
1341
+ const relativeSharedDir = relativeWithDot(projectBuildDir, dirs.shared);
1125
1342
  return {
1126
1343
  nuxt: [
1127
1344
  join(relativeSrcDir, "**/*"),
@@ -1173,8 +1390,12 @@ async function _generateTypes(nuxt) {
1173
1390
  include.add(join(relative(nuxt.options.buildDir, nuxt.options.workspaceDir), "**/*"));
1174
1391
  legacyInclude.add(join(relative(nuxt.options.buildDir, nuxt.options.workspaceDir), "**/*"));
1175
1392
  }
1393
+ const layerDirs = getLayerDirectories(nuxt);
1394
+ const sourceDirs = layerDirs.map((layer) => layer.app);
1176
1395
  for (const dir of nuxt.options.modulesDir) {
1177
- exclude.add(relativeWithDot(nuxt.options.buildDir, dir));
1396
+ if (!sourceDirs.some((srcDir) => dir.startsWith(srcDir))) {
1397
+ exclude.add(relativeWithDot(nuxt.options.buildDir, dir));
1398
+ }
1178
1399
  nodeExclude.add(relativeWithDot(nuxt.options.buildDir, dir));
1179
1400
  legacyExclude.add(relativeWithDot(nuxt.options.buildDir, dir));
1180
1401
  }
@@ -1184,11 +1405,10 @@ async function _generateTypes(nuxt) {
1184
1405
  legacyExclude.add(relativeWithDot(nuxt.options.buildDir, resolve(nuxt.options.rootDir, dir)));
1185
1406
  }
1186
1407
  const rootDirWithSlash = withTrailingSlash(nuxt.options.rootDir);
1187
- for (const layer of nuxt.options._layers) {
1188
- const srcOrCwd = withTrailingSlash(layer.config.srcDir ?? layer.cwd);
1189
- if (!srcOrCwd.startsWith(rootDirWithSlash) || layer.cwd === nuxt.options.rootDir || srcOrCwd.includes("node_modules")) {
1190
- const rootGlob = join(relativeWithDot(nuxt.options.buildDir, layer.cwd), "**/*");
1191
- const paths = resolveLayerPaths(defu(layer.config.dir, nuxt.options.dir), nuxt.options.buildDir, layer.cwd, layer.config.srcDir);
1408
+ for (const dirs of layerDirs) {
1409
+ if (!dirs.app.startsWith(rootDirWithSlash) || dirs.root === rootDirWithSlash || dirs.app.includes("node_modules")) {
1410
+ const rootGlob = join(relativeWithDot(nuxt.options.buildDir, dirs.root), "**/*");
1411
+ const paths = resolveLayerPaths(dirs, nuxt.options.buildDir);
1192
1412
  for (const path of paths.nuxt) {
1193
1413
  include.add(path);
1194
1414
  legacyInclude.add(path);
@@ -1544,6 +1764,9 @@ const RELATIVE_WITH_DOT_RE = /^([^.])/;
1544
1764
  function relativeWithDot(from, to) {
1545
1765
  return relative(from, to).replace(RELATIVE_WITH_DOT_RE, "./$1") || ".";
1546
1766
  }
1767
+ function withTrailingSlash(dir) {
1768
+ return dir.replace(/[^/]$/, "$&/");
1769
+ }
1547
1770
 
1548
1771
  const LAYOUT_RE = /["']/g;
1549
1772
  function addLayout(template, name) {
@@ -1552,9 +1775,9 @@ function addLayout(template, name) {
1552
1775
  const layoutName = kebabCase(name || parse(filename).name).replace(LAYOUT_RE, "");
1553
1776
  nuxt.hook("app:templates", (app) => {
1554
1777
  if (layoutName in app.layouts) {
1555
- const relativePath = relative(nuxt.options.srcDir, app.layouts[layoutName].file);
1778
+ const relativePath = reverseResolveAlias(app.layouts[layoutName].file, { ...nuxt?.options.alias || {}, ...strippedAtAliases }).pop() || app.layouts[layoutName].file;
1556
1779
  return logger.warn(
1557
- `Not overriding \`${layoutName}\` (provided by \`~/${relativePath}\`) with \`${src || filename}\`.`
1780
+ `Not overriding \`${layoutName}\` (provided by \`${relativePath}\`) with \`${src || filename}\`.`
1558
1781
  );
1559
1782
  }
1560
1783
  app.layouts[layoutName] = {
@@ -1563,6 +1786,10 @@ function addLayout(template, name) {
1563
1786
  };
1564
1787
  });
1565
1788
  }
1789
+ const strippedAtAliases = {
1790
+ "@": "",
1791
+ "@@": ""
1792
+ };
1566
1793
 
1567
1794
  function extendPages(cb) {
1568
1795
  useNuxt().hook("pages:extend", cb);
@@ -1643,4 +1870,4 @@ function addPluginTemplate(plugin, opts = {}) {
1643
1870
  return addPlugin(normalizedPlugin, opts);
1644
1871
  }
1645
1872
 
1646
- export { addBuildPlugin, addComponent, addComponentExports, addComponentsDir, addDevServerHandler, addImports, addImportsDir, addImportsSources, addLayout, addPlugin, addPluginTemplate, addPrerenderRoutes, addRouteMiddleware, addRspackPlugin, addServerHandler, addServerImports, addServerImportsDir, addServerPlugin, addServerScanDir, addServerTemplate, addTemplate, addTypeTemplate, addVitePlugin, addWebpackPlugin, assertNuxtCompatibility, buildNuxt, checkNuxtCompatibility, createIsIgnored, createResolver, defineNuxtModule, directoryToURL, extendNuxtSchema, extendPages, extendRouteRules, extendRspackConfig, extendViteConfig, extendWebpackConfig, findPath, getDirectory, getNuxtCtx, getNuxtModuleVersion, getNuxtVersion, hasNuxtCompatibility, hasNuxtModule, hasNuxtModuleCompatibility, importModule, installModule, isIgnored, isNuxt2, isNuxt3, isNuxtMajorVersion, loadNuxt, loadNuxtConfig, loadNuxtModuleInstance, logger, normalizeModuleTranspilePath, normalizePlugin, normalizeSemanticVersion, normalizeTemplate, nuxtCtx, requireModule, resolveAlias, resolveFiles, resolveIgnorePatterns, resolveModule, resolveNuxtModule, resolvePath, runWithNuxtContext, tryImportModule, tryRequireModule, tryResolveModule, tryUseNuxt, updateRuntimeConfig, updateTemplates, useLogger, useNitro, useNuxt, useRuntimeConfig, writeTypes };
1873
+ export { addBuildPlugin, addComponent, addComponentExports, addComponentsDir, addDevServerHandler, addImports, addImportsDir, addImportsSources, addLayout, addPlugin, addPluginTemplate, addPrerenderRoutes, addRouteMiddleware, addRspackPlugin, addServerHandler, addServerImports, addServerImportsDir, addServerPlugin, addServerScanDir, addServerTemplate, addTemplate, addTypeTemplate, addVitePlugin, addWebpackPlugin, assertNuxtCompatibility, buildNuxt, checkNuxtCompatibility, createIsIgnored, createResolver, defineNuxtModule, directoryToURL, extendNuxtSchema, extendPages, extendRouteRules, extendRspackConfig, extendViteConfig, extendWebpackConfig, findPath, getDirectory, getLayerDirectories, getNuxtCtx, getNuxtModuleVersion, getNuxtVersion, hasNuxtCompatibility, hasNuxtModule, hasNuxtModuleCompatibility, importModule, installModule, installModules, isIgnored, isNuxt2, isNuxt3, isNuxtMajorVersion, loadNuxt, loadNuxtConfig, loadNuxtModuleInstance, logger, normalizeModuleTranspilePath, normalizePlugin, normalizeSemanticVersion, normalizeTemplate, nuxtCtx, requireModule, resolveAlias, resolveFiles, resolveIgnorePatterns, resolveModule, resolveModuleWithOptions, resolveNuxtModule, resolvePath, runWithNuxtContext, tryImportModule, tryRequireModule, tryResolveModule, tryUseNuxt, updateRuntimeConfig, updateTemplates, useLogger, useNitro, useNuxt, useRuntimeConfig, writeTypes };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/kit",
3
- "version": "4.0.2",
3
+ "version": "4.1.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/nuxt.git",
@@ -23,7 +23,7 @@
23
23
  "dist"
24
24
  ],
25
25
  "dependencies": {
26
- "c12": "^3.1.0",
26
+ "c12": "^3.2.0",
27
27
  "consola": "^3.4.2",
28
28
  "defu": "^6.1.4",
29
29
  "destr": "^2.0.5",
@@ -32,10 +32,11 @@
32
32
  "ignore": "^7.0.5",
33
33
  "jiti": "^2.5.1",
34
34
  "klona": "^2.0.6",
35
- "mlly": "^1.7.4",
35
+ "mlly": "^1.8.0",
36
36
  "ohash": "^2.0.11",
37
37
  "pathe": "^2.0.3",
38
- "pkg-types": "^2.2.0",
38
+ "pkg-types": "^2.3.0",
39
+ "rc9": "^2.1.2",
39
40
  "scule": "^1.3.0",
40
41
  "semver": "^7.7.2",
41
42
  "std-env": "^3.9.0",
@@ -46,15 +47,15 @@
46
47
  "untyped": "^2.0.0"
47
48
  },
48
49
  "devDependencies": {
49
- "@rspack/core": "1.4.10",
50
+ "@rspack/core": "1.5.2",
50
51
  "@types/semver": "7.7.0",
51
52
  "hookable": "5.5.3",
52
53
  "nitropack": "2.12.4",
53
- "unbuild": "3.6.0",
54
- "vite": "7.0.6",
54
+ "unbuild": "3.6.1",
55
+ "vite": "7.1.4",
55
56
  "vitest": "3.2.4",
56
- "webpack": "5.99.9",
57
- "@nuxt/schema": "4.0.2"
57
+ "webpack": "5.101.3",
58
+ "@nuxt/schema": "4.1.0"
58
59
  },
59
60
  "engines": {
60
61
  "node": ">=18.12.0"