feat: provide fallback instance for backward compatibility

This commit is contained in:
Julien Huang 2025-01-09 15:04:13 +01:00
parent a3487893a3
commit 680690fbdc
3 changed files with 48 additions and 18 deletions

View File

@ -1,9 +1,11 @@
import { getContext } from 'unctx'
import type { Nuxt } from '@nuxt/schema'
import { asyncNameStorage } from './utils'
import { logger } from './logger'
/** Direct access to the Nuxt context - see https://github.com/unjs/unctx. */
export const nuxtCtx = () => getContext<Nuxt>(asyncNameStorage.getStore()!)
export const fallbackNuxtCtx = getContext<Nuxt>('nuxt-fallback')
// TODO: Use use/tryUse from unctx. https://github.com/unjs/unctx/issues/6
@ -19,6 +21,11 @@ export const nuxtCtx = () => getContext<Nuxt>(asyncNameStorage.getStore()!)
export function useNuxt (): Nuxt {
const instance = nuxtCtx().tryUse()
if (!instance) {
const fallbackInstance = fallbackNuxtCtx.tryUse()
if (fallbackInstance) {
logger.warn('Using fallback global Nuxt instance. You may be using a @nuxt/kit composable outside of a Nuxt context, this behavior is deprecated and will be removed in v4.')
return fallbackInstance }
throw new Error('Nuxt instance is unavailable!')
}
return instance
@ -37,5 +44,10 @@ export function useNuxt (): Nuxt {
* ```
*/
export function tryUseNuxt (): Nuxt | null {
return nuxtCtx().tryUse()
const nuxt = nuxtCtx().tryUse()
if(!nuxt) {
logger.warn('Using fallback global Nuxt instance. You may be using a @nuxt/kit composable outside of a Nuxt context, this behavior is deprecated and will be removed in v4.')
return fallbackNuxtCtx.tryUse()
}
return nuxt
}

View File

@ -4,7 +4,7 @@ import { join, normalize, relative, resolve } from 'pathe'
import { createDebugger, createHooks } from 'hookable'
import ignore from 'ignore'
import type { LoadNuxtOptions } from '@nuxt/kit'
import { addBuildPlugin, addComponent, addPlugin, addPluginTemplate, addRouteMiddleware, addServerPlugin, addTypeTemplate, addVitePlugin, addWebpackPlugin, installModule, loadNuxtConfig, nuxtCtx, resolveAlias, resolveFiles, resolveIgnorePatterns, resolvePath, tryResolveModule, useNitro, asyncNameStorage } from '@nuxt/kit'
import { addBuildPlugin, addComponent, addPlugin, addPluginTemplate, addRouteMiddleware, addServerPlugin, addTypeTemplate, addVitePlugin, addWebpackPlugin, installModule, loadNuxtConfig, nuxtCtx, resolveAlias, resolveFiles, resolveIgnorePatterns, resolvePath, tryResolveModule, useNitro, asyncNameStorage, fallbackNuxtCtx } from '@nuxt/kit'
import type { Nuxt, NuxtHooks, NuxtModule, NuxtOptions } from 'nuxt/schema'
import type { PackageJson } from 'pkg-types'
import { readPackageJSON } from 'pkg-types'
@ -173,10 +173,18 @@ async function initNuxt (nuxt: Nuxt) {
}
}
})
if (!fallbackNuxtCtx.tryUse()) {
// backward compatibility with 3.x
fallbackNuxtCtx.set(nuxt)
nuxt.hook('close', () => {
fallbackNuxtCtx.unset()
})
}
// Set nuxt instance for useNuxt
nuxtCtx().set(nuxt)
nuxt.hook('close', () => nuxtCtx().unset())
nuxt.hook('close', () => {
nuxtCtx().unset()
})
const coreTypePackages = nuxt.options.typescript.hoist || []

View File

@ -44,6 +44,16 @@ describe('loadNuxt', () => {
await nuxt.close()
expect(hookRan).toBe(true)
})
it('load multiple nuxt', async () => {
await Promise.all([
loadNuxt({
cwd: repoRoot,
}),
loadNuxt({
cwd: repoRoot,
})
])
})
})
describe('dependency mismatch', () => {