Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

refactor(nuxt, kit): improve type strictness #6685

Merged
merged 8 commits into from
Aug 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/kit/src/ignore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function isIgnored (pathname: string): boolean {

// Happens with CLI reloads
if (!nuxt) {
return null
return false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Context: This was to distinguish situations where isIgnored cannot identify ignoring from when it detects file is actually ignored.

}

if (!nuxt._ignore) {
Expand All @@ -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))
}
8 changes: 4 additions & 4 deletions packages/kit/src/internal/cjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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__
Expand All @@ -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
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/kit/src/internal/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ export function parallel<T, R> (
return Promise.all(tasks.map(fn))
}

export function chainFn (base, fn) {
export function chainFn<Fn> (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)
}
Expand All @@ -38,5 +38,5 @@ export function chainFn (base, fn) {
return baseResult
}
return fnResult
}
} as unknown as Fn
}
6 changes: 3 additions & 3 deletions packages/kit/src/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions packages/kit/src/loader/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import { NuxtConfigSchema } from '@nuxt/schema'
export interface LoadNuxtConfigOptions extends LoadConfigOptions<NuxtConfig> {}

export async function loadNuxtConfig (opts: LoadNuxtConfigOptions): Promise<NuxtOptions> {
const { config: nuxtConfig, configFile, layers, cwd } = await loadConfig<NuxtConfig>({
const result = await loadConfig<NuxtConfig>({
name: 'nuxt',
configFile: 'nuxt.config',
rcFile: '.nuxtrc',
dotenv: true,
globalRc: true,
...opts
})
const { configFile, layers = [], cwd } = result
const nuxtConfig = result.config!

// Fill config
nuxtConfig.rootDir = nuxtConfig.rootDir || cwd
Expand All @@ -25,7 +27,7 @@ export async function loadNuxtConfig (opts: LoadNuxtConfigOptions): Promise<Nuxt
for (const layer of layers) {
layer.config = layer.config || {}
layer.config.rootDir = layer.config.rootDir ?? layer.cwd
layer.config.srcDir = resolve(layer.config.rootDir, layer.config.srcDir)
layer.config.srcDir = resolve(layer.config.rootDir!, layer.config.srcDir!)
}

// Filter layers
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/loader/nuxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {

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}`)
}
Expand Down
23 changes: 13 additions & 10 deletions packages/kit/src/module/container.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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
Expand All @@ -35,7 +34,7 @@ export function useModuleContainer (nuxt: Nuxt = useNuxt()): ModuleContainer {
await installModule(src, inlineOptions)
}

nuxt[MODULE_CONTAINER_KEY] = <ModuleContainer>{
const container: ModuleContainer = {
nuxt,
options: nuxt.options,

Expand All @@ -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 }
}
Expand All @@ -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}`
},
Expand Down Expand Up @@ -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]
}
24 changes: 13 additions & 11 deletions packages/kit/src/module/define.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -31,23 +31,23 @@ export function defineNuxtModule<OptionsT extends ModuleOptions> (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
}
return Promise.resolve(_options)
}

// 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]) {
Expand All @@ -58,10 +58,10 @@ export function defineNuxtModule<OptionsT extends ModuleOptions> (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
}
}
Expand All @@ -78,7 +78,7 @@ export function defineNuxtModule<OptionsT extends ModuleOptions> (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
Expand All @@ -92,11 +92,13 @@ export function defineNuxtModule<OptionsT extends ModuleOptions> (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()
Expand All @@ -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) {
Expand Down
7 changes: 6 additions & 1 deletion packages/kit/src/module/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
2 changes: 1 addition & 1 deletion packages/kit/src/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export function resolveAlias (path: string, alias?: Record<string, string>): str
}

export interface Resolver {
resolve(...path): string
resolve(...path: string[]): string
resolvePath(path: string, opts?: ResolvePathOptions): Promise<string>
}

Expand Down
10 changes: 5 additions & 5 deletions packages/kit/src/template.ts
Original file line number Diff line number Diff line change
@@ -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<any> | string) {
const nuxt = useNuxt()

// Noprmalize template
// Normalize template
const template = normalizeTemplate(_template)

// Remove any existing template with the same filename
Expand All @@ -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<any> | string): ResolvedNuxtTemplate<any> {
if (!template) {
throw new Error('Invalid template: ' + JSON.stringify(template))
}
Expand Down Expand Up @@ -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<any>
}
11 changes: 11 additions & 0 deletions packages/kit/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"strict": true,
"noImplicitAny": true
},
"include": [
"./src/**/*.ts",
"./test/**/*.ts"
]
}
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/composables/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>): NuxtError => {
const _err: NuxtError = _createError(err)
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/nuxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ interface _NuxtApp {
message: string
description: string
data?: any
}
} | null
[key: string]: any
}

Expand Down
6 changes: 4 additions & 2 deletions packages/nuxt/src/auto-imports/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<AutoImportsOptions>, sourcemap?: boolean }) => {
export const TransformPlugin = createUnplugin(({ ctx, options, sourcemap }: { ctx: Unimport, options: Partial<AutoImportsOptions>, sourcemap?: boolean }) => {
return {
name: 'nuxt:auto-imports-transform',
enforce: 'post',
Expand Down Expand Up @@ -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
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion packages/nuxt/src/components/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
Expand Down
Loading