diff --git a/packages/kit/src/ignore.ts b/packages/kit/src/ignore.ts index e44d97dd74b..65a5c41f71e 100644 --- a/packages/kit/src/ignore.ts +++ b/packages/kit/src/ignore.ts @@ -11,7 +11,7 @@ export function isIgnored (pathname: string): boolean { // Happens with CLI reloads if (!nuxt) { - return null + return false } if (!nuxt._ignore) { @@ -28,5 +28,5 @@ export function isIgnored (pathname: string): boolean { if (relativePath.startsWith('..')) { return false } - return relativePath && nuxt._ignore.ignores(relativePath) + return !!(relativePath && nuxt._ignore.ignores(relativePath)) } diff --git a/packages/kit/src/internal/cjs.ts b/packages/kit/src/internal/cjs.ts index 47dc0528b90..8103c5ea37b 100644 --- a/packages/kit/src/internal/cjs.ts +++ b/packages/kit/src/internal/cjs.ts @@ -85,10 +85,10 @@ export function requireModulePkg (id: string, opts: RequireModuleOptions = {}) { /** Resolve the path of a module. */ export function resolveModule (id: string, opts: ResolveModuleOptions = {}) { return normalize(_require.resolve(id, { - paths: [].concat( + paths: ([] as string[]).concat( // @ts-ignore global.__NUXT_PREPATHS__, - opts.paths, + opts.paths || [], process.cwd(), // @ts-ignore global.__NUXT_PATHS__ @@ -100,8 +100,8 @@ export function resolveModule (id: string, opts: ResolveModuleOptions = {}) { export function tryResolveModule (path: string, opts: ResolveModuleOptions = {}): string | null { try { return resolveModule(path, opts) - } catch (error) { - if (error.code !== 'MODULE_NOT_FOUND') { + } catch (error: any) { + if (error?.code !== 'MODULE_NOT_FOUND') { throw error } } diff --git a/packages/kit/src/internal/task.ts b/packages/kit/src/internal/task.ts index 7c57653ece4..45ed2c439b1 100644 --- a/packages/kit/src/internal/task.ts +++ b/packages/kit/src/internal/task.ts @@ -15,11 +15,11 @@ export function parallel ( return Promise.all(tasks.map(fn)) } -export function chainFn (base, fn) { +export function chainFn (base: Fn, fn: Fn): Fn { if (typeof fn !== 'function') { return base } - return function (...args) { + return function (this: any, ...args: any[]) { if (typeof base !== 'function') { return fn.apply(this, args) } @@ -38,5 +38,5 @@ export function chainFn (base, fn) { return baseResult } return fnResult - } + } as unknown as Fn } diff --git a/packages/kit/src/layout.ts b/packages/kit/src/layout.ts index 5bd2f986da1..15d6fd062d1 100644 --- a/packages/kit/src/layout.ts +++ b/packages/kit/src/layout.ts @@ -6,10 +6,10 @@ import { useNuxt } from './context' import { logger } from './logger' import { addTemplate } from './template' -export function addLayout (tmpl: NuxtTemplate, name?: string) { +export function addLayout (this: any, template: NuxtTemplate, name?: string) { const nuxt = useNuxt() - const { filename, src } = addTemplate(tmpl) - const layoutName = kebabCase(name || parse(tmpl.filename).name).replace(/["']/g, '') + const { filename, src } = addTemplate(template) + const layoutName = kebabCase(name || parse(filename).name).replace(/["']/g, '') if (isNuxt2(nuxt)) { // Nuxt 2 adds layouts in options diff --git a/packages/kit/src/loader/config.ts b/packages/kit/src/loader/config.ts index 112c404a5a8..384f3066b89 100644 --- a/packages/kit/src/loader/config.ts +++ b/packages/kit/src/loader/config.ts @@ -7,7 +7,7 @@ import { NuxtConfigSchema } from '@nuxt/schema' export interface LoadNuxtConfigOptions extends LoadConfigOptions {} export async function loadNuxtConfig (opts: LoadNuxtConfigOptions): Promise { - const { config: nuxtConfig, configFile, layers, cwd } = await loadConfig({ + const result = await loadConfig({ name: 'nuxt', configFile: 'nuxt.config', rcFile: '.nuxtrc', @@ -15,6 +15,8 @@ export async function loadNuxtConfig (opts: LoadNuxtConfigOptions): Promise { const nearestNuxtPkg = await Promise.all(['nuxt3', 'nuxt', 'nuxt-edge'] .map(pkg => resolvePackageJSON(pkg, { url: opts.cwd }).catch(() => null))) - .then(r => r.filter(Boolean).sort((a, b) => b.length - a.length)[0]) + .then(r => (r.filter(Boolean) as string[]).sort((a, b) => b.length - a.length)[0]) if (!nearestNuxtPkg) { throw new Error(`Cannot find any nuxt version from ${opts.cwd}`) } diff --git a/packages/kit/src/module/container.ts b/packages/kit/src/module/container.ts index 4cdd89e0fdc..9d5eecfb6a9 100644 --- a/packages/kit/src/module/container.ts +++ b/packages/kit/src/module/container.ts @@ -1,5 +1,5 @@ import { relative } from 'pathe' -import type { Nuxt, NuxtPluginTemplate, NuxtTemplate, ModuleContainer } from '@nuxt/schema' +import type { Nuxt, ModuleContainer } from '@nuxt/schema' import { chainFn } from '../internal/task' import { addTemplate } from '../template' import { addLayout } from '../layout' @@ -12,11 +12,10 @@ import { installModule } from './install' const MODULE_CONTAINER_KEY = '__module_container__' export function useModuleContainer (nuxt: Nuxt = useNuxt()): ModuleContainer { - if (nuxt[MODULE_CONTAINER_KEY]) { - return nuxt[MODULE_CONTAINER_KEY] - } + // @ts-ignore + if (nuxt[MODULE_CONTAINER_KEY]) { return nuxt[MODULE_CONTAINER_KEY] } - async function requireModule (moduleOpts) { + async function requireModule (moduleOpts: any) { let src, inlineOptions if (typeof moduleOpts === 'string') { src = moduleOpts @@ -35,7 +34,7 @@ export function useModuleContainer (nuxt: Nuxt = useNuxt()): ModuleContainer { await installModule(src, inlineOptions) } - nuxt[MODULE_CONTAINER_KEY] = { + const container: ModuleContainer = { nuxt, options: nuxt.options, @@ -47,7 +46,7 @@ export function useModuleContainer (nuxt: Nuxt = useNuxt()): ModuleContainer { addServerMiddleware, - addTemplate (template: string | NuxtTemplate) { + addTemplate (template) { if (typeof template === 'string') { template = { src: template } } @@ -57,15 +56,15 @@ export function useModuleContainer (nuxt: Nuxt = useNuxt()): ModuleContainer { return addTemplate(template) }, - addPlugin (pluginTemplate: NuxtPluginTemplate): NuxtPluginTemplate { + addPlugin (pluginTemplate) { return addPluginTemplate(pluginTemplate) }, - addLayout (tmpl: NuxtTemplate, name?: string) { + addLayout (tmpl, name) { return addLayout(tmpl, name) }, - addErrorLayout (dst: string) { + addErrorLayout (dst) { const relativeBuildDir = relative(nuxt.options.rootDir, nuxt.options.buildDir) nuxt.options.ErrorPage = `~/${relativeBuildDir}/${dst}` }, @@ -93,5 +92,9 @@ export function useModuleContainer (nuxt: Nuxt = useNuxt()): ModuleContainer { } } + // @ts-ignore + nuxt[MODULE_CONTAINER_KEY] = container + + // @ts-ignore return nuxt[MODULE_CONTAINER_KEY] } diff --git a/packages/kit/src/module/define.ts b/packages/kit/src/module/define.ts index 4fef48e4d95..8ed66c9eed6 100644 --- a/packages/kit/src/module/define.ts +++ b/packages/kit/src/module/define.ts @@ -2,7 +2,7 @@ import { promises as fsp } from 'node:fs' import defu from 'defu' import { applyDefaults } from 'untyped' import { dirname } from 'pathe' -import type { Nuxt, NuxtTemplate, NuxtModule, ModuleOptions, ModuleDefinition } from '@nuxt/schema' +import type { Nuxt, NuxtModule, ModuleOptions, ModuleDefinition, NuxtOptions, ResolvedNuxtTemplate } from '@nuxt/schema' import { logger } from '../logger' import { useNuxt, nuxtCtx, tryUseNuxt } from '../context' import { isNuxt2, checkNuxtCompatibility } from '../compatibility' @@ -31,9 +31,9 @@ export function defineNuxtModule (definition: Mo // Resolves module options from inline options, [configKey] in nuxt.config, defaults and schema function getOptions (inlineOptions?: OptionsT, nuxt: Nuxt = useNuxt()) { - const configKey = definition.meta.configKey || definition.meta.name + const configKey = definition.meta!.configKey || definition.meta!.name! const _defaults = definition.defaults instanceof Function ? definition.defaults(nuxt) : definition.defaults - let _options = defu(inlineOptions, nuxt.options[configKey], _defaults) as OptionsT + let _options = defu(inlineOptions, nuxt.options[configKey as keyof NuxtOptions], _defaults) as OptionsT if (definition.schema) { _options = applyDefaults(definition.schema, _options) as OptionsT } @@ -41,13 +41,13 @@ export function defineNuxtModule (definition: Mo } // Module format is always a simple function - async function normalizedModule (inlineOptions: OptionsT, nuxt: Nuxt) { + async function normalizedModule (this: any, inlineOptions: OptionsT, nuxt: Nuxt) { if (!nuxt) { nuxt = tryUseNuxt() || this.nuxt /* invoked by nuxt 2 */ } // Avoid duplicate installs - const uniqueKey = definition.meta.name || definition.meta.configKey + const uniqueKey = definition.meta!.name || definition.meta!.configKey if (uniqueKey) { nuxt.options._requiredModules = nuxt.options._requiredModules || {} if (nuxt.options._requiredModules[uniqueKey]) { @@ -58,10 +58,10 @@ export function defineNuxtModule (definition: Mo } // Check compatibility constraints - if (definition.meta.compatibility) { - const issues = await checkNuxtCompatibility(definition.meta.compatibility, nuxt) + if (definition.meta!.compatibility) { + const issues = await checkNuxtCompatibility(definition.meta!.compatibility, nuxt) if (issues.length) { - logger.warn(`Module \`${definition.meta.name}\` is disabled due to incompatibility issues:\n${issues.toString()}`) + logger.warn(`Module \`${definition.meta!.name}\` is disabled due to incompatibility issues:\n${issues.toString()}`) return } } @@ -78,7 +78,7 @@ export function defineNuxtModule (definition: Mo } // Call setup - await definition.setup?.call(null, _options, nuxt) + await definition.setup?.call(null as any, _options, nuxt) } // Define getters for options and meta @@ -92,11 +92,13 @@ export function defineNuxtModule (definition: Mo const NUXT2_SHIMS_KEY = '__nuxt2_shims_key__' function nuxt2Shims (nuxt: Nuxt) { // Avoid duplicate install and only apply to Nuxt2 + // @ts-ignore if (!isNuxt2(nuxt) || nuxt[NUXT2_SHIMS_KEY]) { return } + // @ts-ignore nuxt[NUXT2_SHIMS_KEY] = true // Allow using nuxt.hooks - // @ts-ignore Nuxt 2 extends hookable + // @ts-expect-error Nuxt 2 extends hookable nuxt.hooks = nuxt // Allow using useNuxt() @@ -106,7 +108,7 @@ function nuxt2Shims (nuxt: Nuxt) { } // Support virtual templates with getContents() by writing them to .nuxt directory - let virtualTemplates: NuxtTemplate[] + let virtualTemplates: ResolvedNuxtTemplate[] nuxt.hook('builder:prepared', (_builder, buildOptions) => { virtualTemplates = buildOptions.templates.filter(t => t.getContents) for (const template of virtualTemplates) { diff --git a/packages/kit/src/module/install.ts b/packages/kit/src/module/install.ts index f92b1d9c62d..638e5718a10 100644 --- a/packages/kit/src/module/install.ts +++ b/packages/kit/src/module/install.ts @@ -10,7 +10,12 @@ export async function installModule (moduleToInstall: string | NuxtModule, _inli const { nuxtModule, inlineOptions } = await normalizeModule(moduleToInstall, _inlineOptions) // Call module - await nuxtModule.call(useModuleContainer(), inlineOptions, nuxt) + await nuxtModule.call( + // Provide this context for backwards compatibility with Nuxt 2 + useModuleContainer() as any, + inlineOptions, + nuxt + ) nuxt.options._installedModules = nuxt.options._installedModules || [] nuxt.options._installedModules.push({ diff --git a/packages/kit/src/plugin.ts b/packages/kit/src/plugin.ts index 01a1434c0ba..a15b55b0c6e 100644 --- a/packages/kit/src/plugin.ts +++ b/packages/kit/src/plugin.ts @@ -73,7 +73,7 @@ export function addPluginTemplate (plugin: NuxtPluginTemplate | string, opts: Ad const normalizedPlugin: NuxtPlugin = typeof plugin === 'string' ? { src: plugin } // Update plugin src to template destination - : { ...plugin, src: addTemplate(plugin).dst } + : { ...plugin, src: addTemplate(plugin).dst! } return addPlugin(normalizedPlugin, opts) } diff --git a/packages/kit/src/resolve.ts b/packages/kit/src/resolve.ts index 535261b673e..6f0bd00810e 100644 --- a/packages/kit/src/resolve.ts +++ b/packages/kit/src/resolve.ts @@ -115,7 +115,7 @@ export function resolveAlias (path: string, alias?: Record): str } export interface Resolver { - resolve(...path): string + resolve(...path: string[]): string resolvePath(path: string, opts?: ResolvePathOptions): Promise } diff --git a/packages/kit/src/template.ts b/packages/kit/src/template.ts index 4bccefb30da..8d9e8f87a85 100644 --- a/packages/kit/src/template.ts +++ b/packages/kit/src/template.ts @@ -1,16 +1,16 @@ import { existsSync } from 'node:fs' import { basename, parse, resolve } from 'pathe' import hash from 'hash-sum' -import type { NuxtTemplate } from '@nuxt/schema' +import type { NuxtTemplate, ResolvedNuxtTemplate } from '@nuxt/schema' import { useNuxt } from './context' /** * Renders given template using lodash template during build into the project buildDir */ -export function addTemplate (_template: NuxtTemplate | string) { +export function addTemplate (_template: NuxtTemplate | string) { const nuxt = useNuxt() - // Noprmalize template + // Normalize template const template = normalizeTemplate(_template) // Remove any existing template with the same filename @@ -26,7 +26,7 @@ export function addTemplate (_template: NuxtTemplate | string) { /** * Normalize a nuxt template object */ -export function normalizeTemplate (template: NuxtTemplate | string): NuxtTemplate { +export function normalizeTemplate (template: NuxtTemplate | string): ResolvedNuxtTemplate { if (!template) { throw new Error('Invalid template: ' + JSON.stringify(template)) } @@ -69,5 +69,5 @@ export function normalizeTemplate (template: NuxtTemplate | string): NuxtTemplat template.dst = resolve(nuxt.options.buildDir, template.filename) } - return template + return template as ResolvedNuxtTemplate } diff --git a/packages/kit/tsconfig.json b/packages/kit/tsconfig.json new file mode 100644 index 00000000000..35a35f01926 --- /dev/null +++ b/packages/kit/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "strict": true, + "noImplicitAny": true + }, + "include": [ + "./src/**/*.ts", + "./test/**/*.ts" + ] +} diff --git a/packages/nuxt/src/app/composables/error.ts b/packages/nuxt/src/app/composables/error.ts index f1a270e87d0..ead4df01e62 100644 --- a/packages/nuxt/src/app/composables/error.ts +++ b/packages/nuxt/src/app/composables/error.ts @@ -34,7 +34,7 @@ export const clearError = async (options: { redirect?: string } = {}) => { error.value = null } -export const isNuxtError = (err?: string | object): err is NuxtError => err && typeof err === 'object' && ('__nuxt_error' in err) +export const isNuxtError = (err?: string | object): err is NuxtError => !!(err && typeof err === 'object' && ('__nuxt_error' in err)) export const createError = (err: string | Partial): NuxtError => { const _err: NuxtError = _createError(err) diff --git a/packages/nuxt/src/app/nuxt.ts b/packages/nuxt/src/app/nuxt.ts index 458d92b732c..0795cfee85e 100644 --- a/packages/nuxt/src/app/nuxt.ts +++ b/packages/nuxt/src/app/nuxt.ts @@ -80,7 +80,7 @@ interface _NuxtApp { message: string description: string data?: any - } + } | null [key: string]: any } diff --git a/packages/nuxt/src/auto-imports/transform.ts b/packages/nuxt/src/auto-imports/transform.ts index 36ae55101ba..b7b1195f85d 100644 --- a/packages/nuxt/src/auto-imports/transform.ts +++ b/packages/nuxt/src/auto-imports/transform.ts @@ -5,7 +5,7 @@ import { Unimport } from 'unimport' import { AutoImportsOptions } from '@nuxt/schema' import { normalize } from 'pathe' -export const TransformPlugin = createUnplugin(({ ctx, options, sourcemap }: {ctx: Unimport, options: Partial, sourcemap?: boolean }) => { +export const TransformPlugin = createUnplugin(({ ctx, options, sourcemap }: { ctx: Unimport, options: Partial, sourcemap?: boolean }) => { return { name: 'nuxt:auto-imports-transform', enforce: 'post', @@ -48,7 +48,9 @@ export const TransformPlugin = createUnplugin(({ ctx, options, sourcemap }: {ctx if (s.hasChanged()) { return { code: s.toString(), - map: sourcemap && s.generateMap({ source: id, includeContent: true }) + map: sourcemap + ? s.generateMap({ source: id, includeContent: true }) + : undefined } } } diff --git a/packages/nuxt/src/components/loader.ts b/packages/nuxt/src/components/loader.ts index 3dea7db7f49..63b9b7c8313 100644 --- a/packages/nuxt/src/components/loader.ts +++ b/packages/nuxt/src/components/loader.ts @@ -94,7 +94,9 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => { if (s.hasChanged()) { return { code: s.toString(), - map: options.sourcemap && s.generateMap({ source: id, includeContent: true }) + map: options.sourcemap + ? s.generateMap({ source: id, includeContent: true }) + : undefined } } } diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index 51fea129d02..5656b4dae4a 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -9,7 +9,7 @@ import { TreeShakeTemplatePlugin } from './tree-shake' const isPureObjectOrString = (val: any) => (!Array.isArray(val) && typeof val === 'object') || typeof val === 'string' const isDirectory = (p: string) => { try { return statSync(p).isDirectory() } catch (_e) { return false } } -function compareDirByPathLength ({ path: pathA }, { path: pathB }) { +function compareDirByPathLength ({ path: pathA }: { path: string}, { path: pathB }: { path: string}) { return pathB.split(/[\\/]/).filter(Boolean).length - pathA.split(/[\\/]/).filter(Boolean).length } @@ -26,7 +26,7 @@ export default defineNuxtModule({ dirs: [] }, setup (componentOptions, nuxt) { - let componentDirs = [] + let componentDirs: ComponentsDir[] = [] const context = { components: [] as Component[] } @@ -37,7 +37,7 @@ export default defineNuxtModule({ : context.components } - const normalizeDirs = (dir: any, cwd: string) => { + const normalizeDirs = (dir: any, cwd: string): ComponentsDir[] => { if (Array.isArray(dir)) { return dir.map(dir => normalizeDirs(dir, cwd)).flat().sort(compareDirByPathLength) } @@ -48,14 +48,14 @@ export default defineNuxtModule({ ] } if (typeof dir === 'string') { - return { - path: resolve(cwd, resolveAlias(dir)) - } + return [ + { path: resolve(cwd, resolveAlias(dir)) } + ] } if (!dir) { return [] } - const dirs = (dir.dirs || [dir]).map(dir => typeof dir === 'string' ? { path: dir } : dir).filter(_dir => _dir.path) + const dirs: ComponentsDir[] = (dir.dirs || [dir]).map((dir: any): ComponentsDir => typeof dir === 'string' ? { path: dir } : dir).filter((_dir: ComponentsDir) => _dir.path) return dirs.map(_dir => ({ ..._dir, path: resolve(cwd, resolveAlias(_dir.path)) @@ -113,7 +113,7 @@ export default defineNuxtModule({ // components.d.ts addTemplate({ ...componentsTypeTemplate, options: { getComponents } }) // components.plugin.mjs - addPluginTemplate({ ...componentsPluginTemplate, options: { getComponents } }) + addPluginTemplate({ ...componentsPluginTemplate, options: { getComponents } } as any) // components.server.mjs addTemplate({ ...componentsTemplate, filename: 'components.server.mjs', options: { getComponents, mode: 'server' } }) // components.client.mjs @@ -121,12 +121,12 @@ export default defineNuxtModule({ nuxt.hook('vite:extendConfig', (config, { isClient }) => { const mode = isClient ? 'client' : 'server' - config.resolve.alias['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`) + ;(config.resolve!.alias as any)['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`) }) nuxt.hook('webpack:config', (configs) => { for (const config of configs) { const mode = config.name === 'server' ? 'server' : 'client' - config.resolve.alias['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`) + ;(config.resolve!.alias as any)['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`) } }) diff --git a/packages/nuxt/src/components/scan.ts b/packages/nuxt/src/components/scan.ts index 60a329be654..4cad3c587d6 100644 --- a/packages/nuxt/src/components/scan.ts +++ b/packages/nuxt/src/components/scan.ts @@ -58,12 +58,12 @@ export async function scanComponents (dirs: ComponentsDir[], srcDir: string): Pr * * @example third-components/index.vue -> third-component * if not take the filename - * @example thid-components/Awesome.vue -> Awesome + * @example third-components/Awesome.vue -> Awesome */ let fileName = basename(filePath, extname(filePath)) const global = /\.(global)$/.test(fileName) || dir.global - const mode = fileName.match(/(?<=\.)(client|server)(\.global)?$/)?.[1] as 'client' | 'server' || 'all' + const mode = (fileName.match(/(?<=\.)(client|server)(\.global)?$/)?.[1] || 'all') as 'client' | 'server' | 'all' fileName = fileName.replace(/(\.(client|server))?(\.global)?$/, '') if (fileName.toLowerCase() === 'index') { diff --git a/packages/nuxt/src/components/templates.ts b/packages/nuxt/src/components/templates.ts index bae8b67d0a0..62879252e84 100644 --- a/packages/nuxt/src/components/templates.ts +++ b/packages/nuxt/src/components/templates.ts @@ -1,5 +1,5 @@ import { isAbsolute, relative } from 'pathe' -import type { Component, Nuxt } from '@nuxt/schema' +import type { Component, Nuxt, NuxtPluginTemplate, NuxtTemplate } from '@nuxt/schema' import { genDynamicImport, genExport, genObjectFromRawEntries } from 'knitwork' export interface ComponentsTemplateContext { @@ -25,9 +25,9 @@ const createImportMagicComments = (options: ImportMagicCommentsOptions) => { ].filter(Boolean).join(', ') } -export const componentsPluginTemplate = { +export const componentsPluginTemplate: NuxtPluginTemplate = { filename: 'components.plugin.mjs', - getContents ({ options }: ComponentsTemplateContext) { + getContents ({ options }) { const globalComponents = options.getComponents().filter(c => c.global === true) return `import { defineAsyncComponent } from 'vue' @@ -50,9 +50,9 @@ export default defineNuxtPlugin(nuxtApp => { } } -export const componentsTemplate = { +export const componentsTemplate: NuxtTemplate = { // components.[server|client].mjs' - getContents ({ options }: ComponentsTemplateContext) { + getContents ({ options }) { return [ 'import { defineAsyncComponent } from \'vue\'', ...options.getComponents(options.mode).flatMap((c) => { @@ -69,9 +69,9 @@ export const componentsTemplate = { } } -export const componentsTypeTemplate = { +export const componentsTypeTemplate: NuxtTemplate = { filename: 'components.d.ts', - getContents: ({ options, nuxt }: ComponentsTemplateContext) => { + getContents: ({ options, nuxt }) => { const buildDir = nuxt.options.buildDir const componentTypes = options.getComponents().map(c => [ c.pascalName, diff --git a/packages/nuxt/src/components/tree-shake.ts b/packages/nuxt/src/components/tree-shake.ts index c6273e30ab9..1cb14dde5c4 100644 --- a/packages/nuxt/src/components/tree-shake.ts +++ b/packages/nuxt/src/components/tree-shake.ts @@ -31,7 +31,7 @@ export const TreeShakeTemplatePlugin = createUnplugin((options: TreeShakeTemplat regexpMap.set(components, new RegExp(`(${clientOnlyComponents.join('|')})`, 'g')) } - const COMPONENTS_RE = regexpMap.get(components) + const COMPONENTS_RE = regexpMap.get(components)! const s = new MagicString(code) // Do not render client-only slots on SSR, but preserve attributes @@ -40,7 +40,9 @@ export const TreeShakeTemplatePlugin = createUnplugin((options: TreeShakeTemplat if (s.hasChanged()) { return { code: s.toString(), - map: options.sourcemap && s.generateMap({ source: id, includeContent: true }) + map: options.sourcemap + ? s.generateMap({ source: id, includeContent: true }) + : undefined } } } diff --git a/packages/nuxt/src/core/plugins/import-protection.ts b/packages/nuxt/src/core/plugins/import-protection.ts index 2646b3dd78d..493d5b7a831 100644 --- a/packages/nuxt/src/core/plugins/import-protection.ts +++ b/packages/nuxt/src/core/plugins/import-protection.ts @@ -17,8 +17,8 @@ export const vueAppPatterns = (nuxt: Nuxt) => [ [/^(nuxt3|nuxt)$/, '`nuxt3`/`nuxt` cannot be imported directly. Instead, import runtime Nuxt composables from `#app` or `#imports`.'], [/^((|~|~~|@|@@)\/)?nuxt\.config(\.|$)/, 'Importing directly from a `nuxt.config` file is not allowed. Instead, use runtime config or a module.'], [/(^|node_modules\/)@vue\/composition-api/], - ...nuxt.options.modules.filter(m => typeof m === 'string').map((m: string) => - [new RegExp(`^${escapeRE(m)}$`), 'Importing directly from module entry points is not allowed.']), + ...nuxt.options.modules.filter(m => typeof m === 'string').map((m: any) => + [new RegExp(`^${escapeRE(m as string)}$`), 'Importing directly from module entry points is not allowed.']), ...[/(^|node_modules\/)@nuxt\/kit/, /^nitropack/] .map(i => [i, 'This module cannot be imported in the Vue part of your app.']), [new RegExp(escapeRE(resolve(nuxt.options.srcDir, (nuxt.options.dir as any).server || 'server')) + '\\/(api|routes|middleware|plugins)\\/'), 'Importing from server is not allowed in the Vue part of your app.'] @@ -31,10 +31,11 @@ export const ImportProtectionPlugin = createUnplugin(function (options: ImportPr name: 'nuxt:import-protection', enforce: 'pre', resolveId (id, importer) { + if (!importer) { return } if (importersToExclude.some(p => typeof p === 'string' ? importer === p : p.test(importer))) { return } const invalidImports = options.patterns.filter(([pattern]) => pattern instanceof RegExp ? pattern.test(id) : pattern === id) - let matched: boolean + let matched = false for (const match of invalidImports) { cache[id] = cache[id] || new Map() const [pattern, warning] = match diff --git a/packages/nuxt/src/core/plugins/tree-shake.ts b/packages/nuxt/src/core/plugins/tree-shake.ts index d967efa83de..3ed8f812924 100644 --- a/packages/nuxt/src/core/plugins/tree-shake.ts +++ b/packages/nuxt/src/core/plugins/tree-shake.ts @@ -35,13 +35,15 @@ export const TreeShakePlugin = createUnplugin((options: TreeShakePluginOptions) const s = new MagicString(code) const strippedCode = stripLiteral(code) for (const match of strippedCode.matchAll(COMPOSABLE_RE) || []) { - s.overwrite(match.index, match.index + match[0].length, `${match[1]} /*#__PURE__*/ false && ${match[2]}`) + s.overwrite(match.index!, match.index! + match[0].length, `${match[1]} /*#__PURE__*/ false && ${match[2]}`) } if (s.hasChanged()) { return { code: s.toString(), - map: options.sourcemap && s.generateMap({ source: id, includeContent: true }) + map: options.sourcemap + ? s.generateMap({ source: id, includeContent: true }) + : undefined } } } diff --git a/packages/nuxt/src/head/runtime/lib/vueuse-head.plugin.ts b/packages/nuxt/src/head/runtime/lib/vueuse-head.plugin.ts index 87558cc44c0..e1e6ebce866 100644 --- a/packages/nuxt/src/head/runtime/lib/vueuse-head.plugin.ts +++ b/packages/nuxt/src/head/runtime/lib/vueuse-head.plugin.ts @@ -39,7 +39,7 @@ export default defineNuxtPlugin((nuxtApp) => { if (!vm) { return } onBeforeUnmount(() => { - head.removeHeadObjs(headObj) + head.removeHeadObjs(headObj as any) head.updateDOM() }) } diff --git a/packages/nuxt/src/pages/module.ts b/packages/nuxt/src/pages/module.ts index f8bc385e842..3af9e18062a 100644 --- a/packages/nuxt/src/pages/module.ts +++ b/packages/nuxt/src/pages/module.ts @@ -135,7 +135,7 @@ export default defineNuxtModule({ // Check for router options const routerOptionsFiles = (await Promise.all(nuxt.options._layers.map( async layer => await findPath(resolve(layer.config.srcDir, 'app/router.options')) - ))).filter(Boolean) + ))).filter(Boolean) as string[] const configRouterOptions = genObjectFromRawEntries(Object.entries(nuxt.options.router.options) .map(([key, value]) => [key, genString(value as string)])) diff --git a/packages/nuxt/test/auto-imports.test.ts b/packages/nuxt/test/auto-imports.test.ts index b61ab0478b7..ec9df68047a 100644 --- a/packages/nuxt/test/auto-imports.test.ts +++ b/packages/nuxt/test/auto-imports.test.ts @@ -20,8 +20,8 @@ describe('auto-imports:transform', () => { const transformPlugin = TransformPlugin.raw({ ctx, options: { transform: { exclude: [/node_modules/] } } }, { framework: 'rollup' }) const transform = async (source: string) => { - const { code } = await transformPlugin.transform.call({ error: null, warn: null }, source, '') || { code: null } - return code + const result = await transformPlugin.transform!.call({ error: null, warn: null } as any, source, '') + return typeof result === 'string' ? result : result?.code } it('should correct inject', async () => { @@ -29,13 +29,13 @@ describe('auto-imports:transform', () => { }) it('should ignore existing imported', async () => { - expect(await transform('import { ref } from "foo"; const a = ref(0)')).to.equal(null) - expect(await transform('import { computed as ref } from "foo"; const a = ref(0)')).to.equal(null) - expect(await transform('import ref from "foo"; const a = ref(0)')).to.equal(null) - expect(await transform('import { z as ref } from "foo"; const a = ref(0)')).to.equal(null) - expect(await transform('let ref = () => {}; const a = ref(0)')).to.equal(null) - expect(await transform('let { ref } = Vue; const a = ref(0)')).to.equal(null) - expect(await transform('let [\ncomputed,\nref\n] = Vue; const a = ref(0); const b = ref(0)')).to.equal(null) + expect(await transform('import { ref } from "foo"; const a = ref(0)')).to.equal(undefined) + expect(await transform('import { computed as ref } from "foo"; const a = ref(0)')).to.equal(undefined) + expect(await transform('import ref from "foo"; const a = ref(0)')).to.equal(undefined) + expect(await transform('import { z as ref } from "foo"; const a = ref(0)')).to.equal(undefined) + expect(await transform('let ref = () => {}; const a = ref(0)')).to.equal(undefined) + expect(await transform('let { ref } = Vue; const a = ref(0)')).to.equal(undefined) + expect(await transform('let [\ncomputed,\nref\n] = Vue; const a = ref(0); const b = ref(0)')).to.equal(undefined) }) it('should ignore comments', async () => { @@ -48,7 +48,7 @@ describe('auto-imports:transform', () => { }) it('should exclude files from transform', async () => { - expect(await transform('excluded')).toEqual(null) + expect(await transform('excluded')).toEqual(undefined) }) }) @@ -65,7 +65,7 @@ describe('auto-imports:nuxt', () => { continue } it(`should register ${name} globally`, () => { - expect(defaultPresets.find(a => a.from === '#app').imports).to.include(name) + expect(defaultPresets.find(a => a.from === '#app')!.imports).to.include(name) }) } } catch (e) { @@ -176,7 +176,7 @@ describe('auto-imports:vue', () => { continue } it(`should register ${name} globally`, () => { - expect(defaultPresets.find(a => a.from === 'vue').imports).toContain(name) + expect(defaultPresets.find(a => a.from === 'vue')!.imports).toContain(name) }) } }) diff --git a/packages/nuxt/test/pages.test.ts b/packages/nuxt/test/pages.test.ts index 9882d302d29..0e92675e546 100644 --- a/packages/nuxt/test/pages.test.ts +++ b/packages/nuxt/test/pages.test.ts @@ -304,7 +304,7 @@ describe('pages:generateRouteKey', () => { const tests = [ { description: 'should handle overrides', override: 'key', route: getRouteProps(), output: 'key' }, - { description: 'should handle overrides', override: route => route.meta.key as string, route: getRouteProps(), output: 'route-meta-key' }, + { description: 'should handle overrides', override: (route: any) => route.meta.key as string, route: getRouteProps(), output: 'route-meta-key' }, { description: 'should handle overrides', override: false as any, route: getRouteProps(), output: false }, { description: 'should key dynamic routes without keys', diff --git a/packages/nuxt/test/scan-components.test.ts b/packages/nuxt/test/scan-components.test.ts index 8bbdd037776..8e4fd12b7dc 100644 --- a/packages/nuxt/test/scan-components.test.ts +++ b/packages/nuxt/test/scan-components.test.ts @@ -4,7 +4,7 @@ import { expect, it, vi } from 'vitest' import { scanComponents } from '../src/components/scan' const fixtureDir = resolve(__dirname, 'fixture') -const rFixture = (...p) => resolve(fixtureDir, ...p) +const rFixture = (...p: string[]) => resolve(fixtureDir, ...p) vi.mock('@nuxt/kit', () => ({ isIgnored: () => false @@ -108,6 +108,7 @@ const srcDir = rFixture('.') it('components:scanComponents', async () => { const scannedComponents = await scanComponents(dirs, srcDir) for (const c of scannedComponents) { + // @ts-ignore delete c.filePath } expect(scannedComponents).deep.eq(expectedComponents) diff --git a/packages/schema/src/types/hooks.ts b/packages/schema/src/types/hooks.ts index d6d3c7fcbac..c5818e453ee 100644 --- a/packages/schema/src/types/hooks.ts +++ b/packages/schema/src/types/hooks.ts @@ -9,7 +9,7 @@ import type { NuxtTemplate, Nuxt, NuxtApp } from './nuxt' import type { Preset as ImportPreset, Import } from 'unimport' import type { NuxtConfig, NuxtOptions } from './config' import type { Nitro, NitroConfig } from 'nitropack' -import type { Component, ComponentsDir, ScanDir, ComponentsOptions } from './components' +import type { Component, ComponentsOptions } from './components' import { NuxtCompatibility, NuxtCompatibilityIssues } from '..' @@ -82,7 +82,7 @@ export interface NuxtHooks { // Components 'components:dirs': (dirs: ComponentsOptions['dirs']) => HookResult - 'components:extend': (components: (Component | ComponentsDir | ScanDir)[]) => HookResult + 'components:extend': (components: Component[]) => HookResult // @nuxt/builder 'build:before': diff --git a/packages/schema/src/types/module.ts b/packages/schema/src/types/module.ts index 4b8c3ef16a4..f963478b20b 100644 --- a/packages/schema/src/types/module.ts +++ b/packages/schema/src/types/module.ts @@ -1,5 +1,5 @@ import { NuxtHooks } from './hooks' -import type { Nuxt, NuxtTemplate } from "./nuxt" +import type { Nuxt, NuxtPluginTemplate, NuxtTemplate } from "./nuxt" import type { NuxtCompatibility } from './compatibility' export interface ModuleMeta { @@ -58,6 +58,9 @@ export interface ModuleContainer { /** Renders given template using lodash template during build into the project buildDir (`.nuxt`).*/ addTemplate(template: string | NuxtTemplate): NuxtTemplate + /** Registers a custom plugin. */ + addPlugin(template: NuxtPluginTemplate): NuxtPluginTemplate + /** Registers a custom layout. If its name is 'error' it will override the default error layout. */ addLayout(tmpl: NuxtTemplate, name: string): any diff --git a/packages/schema/src/types/nuxt.ts b/packages/schema/src/types/nuxt.ts index 926625565f0..8de75ae52ec 100644 --- a/packages/schema/src/types/nuxt.ts +++ b/packages/schema/src/types/nuxt.ts @@ -34,15 +34,20 @@ export interface NuxtTemplate> { /** The target filename once the template is copied into the Nuxt buildDir */ filename?: string /** An options object that will be accessible within the template via `<% options %>` */ - options?: Record + options?: Options /** The resolved path to the source file to be template */ src?: string /** Provided compile option instead of src */ - getContents?: (data: Record) => string | Promise + getContents?: (data: Options) => string | Promise /** Write to filesystem */ write?: boolean } +export interface ResolvedNuxtTemplate> extends NuxtTemplate { + filename: string + dst: string +} + export interface NuxtPlugin { /** @deprecated use mode */ ssr?: boolean @@ -63,5 +68,5 @@ export interface NuxtApp { configs: string[] } -type _TemplatePlugin = Omit & NuxtTemplate -export interface NuxtPluginTemplate extends _TemplatePlugin { } +type _TemplatePlugin = Omit & NuxtTemplate +export interface NuxtPluginTemplate> extends _TemplatePlugin { }