mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-22 11:22:43 +00:00
fix: correctly set context when creating nuxt and provide an internal run fn and wrap callhooks
This commit is contained in:
parent
37fd4ab37c
commit
78649f6662
@ -1,6 +1,7 @@
|
|||||||
import { existsSync } from 'node:fs'
|
import { existsSync } from 'node:fs'
|
||||||
import { rm } from 'node:fs/promises'
|
import { rm } from 'node:fs/promises'
|
||||||
import { randomUUID } from 'node:crypto'
|
import { randomUUID } from 'node:crypto'
|
||||||
|
import { AsyncLocalStorage, AsyncResource } from 'node:async_hooks'
|
||||||
import { join, normalize, relative, resolve } from 'pathe'
|
import { join, normalize, relative, resolve } from 'pathe'
|
||||||
import { createDebugger, createHooks } from 'hookable'
|
import { createDebugger, createHooks } from 'hookable'
|
||||||
import ignore from 'ignore'
|
import ignore from 'ignore'
|
||||||
@ -52,6 +53,12 @@ import { VirtualFSPlugin } from './plugins/virtual'
|
|||||||
export function createNuxt (options: NuxtOptions): Nuxt {
|
export function createNuxt (options: NuxtOptions): Nuxt {
|
||||||
const hooks = createHooks<NuxtHooks>()
|
const hooks = createHooks<NuxtHooks>()
|
||||||
const name = randomUUID()
|
const name = randomUUID()
|
||||||
|
|
||||||
|
const { callHook, callHookParallel, callHookWith } = hooks
|
||||||
|
hooks.callHook = (...args) => asyncNameStorage.run(name, () => callHook(...args))
|
||||||
|
hooks.callHookParallel = (...args) => asyncNameStorage.run(name, () => callHookParallel(...args))
|
||||||
|
hooks.callHookWith = (...args) => asyncNameStorage.run(name, () => callHookWith(...args))
|
||||||
|
|
||||||
const nuxt: Nuxt = {
|
const nuxt: Nuxt = {
|
||||||
_version: version,
|
_version: version,
|
||||||
options,
|
options,
|
||||||
@ -64,8 +71,24 @@ export function createNuxt (options: NuxtOptions): Nuxt {
|
|||||||
vfs: {},
|
vfs: {},
|
||||||
apps: {},
|
apps: {},
|
||||||
__name: name,
|
__name: name,
|
||||||
|
run: fn => asyncNameStorage.run(name, fn),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!nuxtCtx.tryUse()) {
|
||||||
|
// backward compatibility with 3.x
|
||||||
|
nuxtCtx.set(nuxt)
|
||||||
|
nuxt.hook('close', () => {
|
||||||
|
nuxtCtx.unset()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
nuxt.run(() => {
|
||||||
|
// Set nuxt instance for useNuxt
|
||||||
|
getNuxtCtx().set(nuxt)
|
||||||
|
nuxt.hook('close', () => {
|
||||||
|
getNuxtCtx().unset()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
hooks.hookOnce('close', () => { hooks.removeAllHooks() })
|
hooks.hookOnce('close', () => { hooks.removeAllHooks() })
|
||||||
|
|
||||||
return nuxt
|
return nuxt
|
||||||
@ -175,19 +198,6 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (!nuxtCtx.tryUse()) {
|
|
||||||
// backward compatibility with 3.x
|
|
||||||
nuxtCtx.set(nuxt)
|
|
||||||
nuxt.hook('close', () => {
|
|
||||||
nuxtCtx.unset()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// Set nuxt instance for useNuxt
|
|
||||||
getNuxtCtx().set(nuxt)
|
|
||||||
nuxt.hook('close', () => {
|
|
||||||
getNuxtCtx().unset()
|
|
||||||
})
|
|
||||||
|
|
||||||
const coreTypePackages = nuxt.options.typescript.hoist || []
|
const coreTypePackages = nuxt.options.typescript.hoist || []
|
||||||
|
|
||||||
// Disable environment types entirely if `typescript.builder` is false
|
// Disable environment types entirely if `typescript.builder` is false
|
||||||
@ -812,18 +822,20 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
|||||||
|
|
||||||
const nuxt = createNuxt(options)
|
const nuxt = createNuxt(options)
|
||||||
|
|
||||||
for (const dep of keyDependencies) {
|
nuxt.run(() => {
|
||||||
checkDependencyVersion(dep, nuxt._version)
|
for (const dep of keyDependencies) {
|
||||||
}
|
checkDependencyVersion(dep, nuxt._version)
|
||||||
|
}
|
||||||
|
|
||||||
// We register hooks layer-by-layer so any overrides need to be registered separately
|
// We register hooks layer-by-layer so any overrides need to be registered separately
|
||||||
if (opts.overrides?.hooks) {
|
if (opts.overrides?.hooks) {
|
||||||
nuxt.hooks.addHooks(opts.overrides.hooks)
|
nuxt.hooks.addHooks(opts.overrides.hooks)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nuxt.options.debug) {
|
if (nuxt.options.debug) {
|
||||||
createDebugger(nuxt.hooks, { tag: 'nuxt' })
|
createDebugger(nuxt.hooks, { tag: 'nuxt' })
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if (opts.ready !== false) {
|
if (opts.ready !== false) {
|
||||||
await nuxt.ready()
|
await nuxt.ready()
|
||||||
|
@ -4,9 +4,11 @@ import { normalize } from 'pathe'
|
|||||||
import { withoutTrailingSlash } from 'ufo'
|
import { withoutTrailingSlash } from 'ufo'
|
||||||
import { readPackageJSON } from 'pkg-types'
|
import { readPackageJSON } from 'pkg-types'
|
||||||
import { inc } from 'semver'
|
import { inc } from 'semver'
|
||||||
|
import { asyncNameStorage, useNuxt } from '@nuxt/kit'
|
||||||
import { loadNuxt } from '../src'
|
import { loadNuxt } from '../src'
|
||||||
import { version } from '../package.json'
|
import { version } from '../package.json'
|
||||||
|
import { logger } from '@nuxt/kit'
|
||||||
|
import { beforeEach } from 'node:test'
|
||||||
const repoRoot = withoutTrailingSlash(normalize(fileURLToPath(new URL('../../../', import.meta.url))))
|
const repoRoot = withoutTrailingSlash(normalize(fileURLToPath(new URL('../../../', import.meta.url))))
|
||||||
|
|
||||||
vi.stubGlobal('console', {
|
vi.stubGlobal('console', {
|
||||||
@ -15,6 +17,7 @@ vi.stubGlobal('console', {
|
|||||||
warn: vi.fn(console.warn),
|
warn: vi.fn(console.warn),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const loggerWarn = vi.spyOn(logger, 'warn')
|
||||||
vi.mock('pkg-types', async (og) => {
|
vi.mock('pkg-types', async (og) => {
|
||||||
const originalPkgTypes = (await og<typeof import('pkg-types')>())
|
const originalPkgTypes = (await og<typeof import('pkg-types')>())
|
||||||
return {
|
return {
|
||||||
@ -23,6 +26,9 @@ vi.mock('pkg-types', async (og) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
loggerWarn.mockClear()
|
||||||
|
})
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
vi.clearAllMocks()
|
vi.clearAllMocks()
|
||||||
})
|
})
|
||||||
@ -53,7 +59,24 @@ describe('loadNuxt', () => {
|
|||||||
cwd: repoRoot,
|
cwd: repoRoot,
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
expect(console.warn).not.toHaveBeenCalled()
|
expect(loggerWarn).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('expect hooks to get the correct context outside of initNuxt', async () => {
|
||||||
|
const nuxt = await loadNuxt({
|
||||||
|
cwd: repoRoot,
|
||||||
|
})
|
||||||
|
|
||||||
|
// @ts-expect-error - random hook
|
||||||
|
await nuxt.hook('test', () => {
|
||||||
|
const nuxt = useNuxt()
|
||||||
|
expect(asyncNameStorage.getStore()).toBe(nuxt.__name)
|
||||||
|
})
|
||||||
|
|
||||||
|
// @ts-expect-error - random hook
|
||||||
|
await nuxt.callHook('test')
|
||||||
|
|
||||||
|
expect(loggerWarn).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -87,6 +87,10 @@ export interface Nuxt {
|
|||||||
_version: string
|
_version: string
|
||||||
_ignore?: Ignore
|
_ignore?: Ignore
|
||||||
_dependencies?: Set<string>
|
_dependencies?: Set<string>
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
run: <T extends (...args: any[]) => any>(fn: T) => ReturnType<T>
|
||||||
|
|
||||||
/** The resolved Nuxt configuration. */
|
/** The resolved Nuxt configuration. */
|
||||||
options: NuxtOptions
|
options: NuxtOptions
|
||||||
|
Loading…
Reference in New Issue
Block a user