2024-05-16 14:14:25 +00:00
import { effectScope , getCurrentInstance , getCurrentScope , hasInjectionContext , reactive , shallowReactive } from 'vue'
2023-10-15 14:52:46 +00:00
import type { App , EffectScope , Ref , VNode , onErrorCaptured } from 'vue'
2024-06-24 18:00:43 +00:00
import type { RouteLocationNormalizedLoaded } from 'vue-router'
2023-04-07 16:02:47 +00:00
import type { HookCallback , Hookable } from 'hookable'
2022-12-11 21:44:52 +00:00
import { createHooks } from 'hookable'
2022-04-01 09:55:23 +00:00
import { getContext } from 'unctx'
2023-06-07 09:25:05 +00:00
import type { SSRContext , createRenderer } from 'vue-bundle-renderer/runtime'
2024-01-29 11:49:29 +00:00
import type { EventHandlerRequest , H3Event } from 'h3'
2023-04-07 16:02:47 +00:00
import type { AppConfig , AppConfigInput , RuntimeConfig } from 'nuxt/schema'
2024-06-26 13:18:05 +00:00
import type { RenderResponse } from 'nitro/types'
2024-03-15 23:36:47 +00:00
import type { LogObject } from 'consola'
2023-07-30 18:46:16 +00:00
import type { MergeHead , VueHeadClient } from '@unhead/vue'
2023-10-30 21:05:02 +00:00
2024-03-08 22:58:37 +00:00
import type { NuxtIslandContext } from '../app/types'
2023-10-30 21:05:02 +00:00
import type { RouteMiddleware } from '../app/composables/router'
2023-04-07 10:34:35 +00:00
import type { NuxtError } from '../app/composables/error'
2023-06-09 21:38:14 +00:00
import type { AsyncDataRequestStatus } from '../app/composables/asyncData'
2023-10-30 21:05:02 +00:00
import type { NuxtAppManifestMeta } from '../app/composables/manifest'
2024-01-18 10:04:59 +00:00
import type { LoadingIndicator } from '../app/composables/loading-indicator'
2024-04-17 15:58:13 +00:00
import type { RouteAnnouncer } from '../app/composables/route-announcer'
2024-03-06 15:58:40 +00:00
import type { ViewTransition } from './plugins/view-transitions.client'
2021-01-18 12:46:19 +00:00
2024-05-17 03:41:31 +00:00
// @ts-expect-error virtual file
import { appId } from '#build/nuxt.config.mjs'
2023-12-14 17:11:08 +00:00
2024-05-17 03:41:31 +00:00
import type { NuxtAppLiterals } from '#app'
2024-05-08 12:32:45 +00:00
2024-05-17 03:41:31 +00:00
function getNuxtAppCtx ( appName = appId || 'nuxt-app' ) {
return getContext < NuxtApp > ( appName , {
2024-05-08 12:32:45 +00:00
asyncContext : ! ! __NUXT_ASYNC_CONTEXT__ && import . meta . server ,
} )
}
2022-04-01 09:55:23 +00:00
2021-08-26 18:57:36 +00:00
type HookResult = Promise < void > | void
2022-08-11 16:34:39 +00:00
2023-06-07 09:25:05 +00:00
type AppRenderedContext = { ssrContext : NuxtApp [ 'ssrContext' ] , renderResult : null | Awaited < ReturnType < ReturnType < typeof createRenderer > [ 'renderToString' ] >> }
2021-08-26 18:57:36 +00:00
export interface RuntimeNuxtHooks {
'app:created' : ( app : App < Element > ) = > HookResult
'app:beforeMount' : ( app : App < Element > ) = > HookResult
'app:mounted' : ( app : App < Element > ) = > HookResult
2022-08-11 16:34:39 +00:00
'app:rendered' : ( ctx : AppRenderedContext ) = > HookResult
2022-04-19 19:13:11 +00:00
'app:redirected' : ( ) = > HookResult
2022-01-26 17:24:54 +00:00
'app:suspense:resolve' : ( Component? : VNode ) = > HookResult
2022-03-11 08:22:16 +00:00
'app:error' : ( err : any ) = > HookResult
'app:error:cleared' : ( options : { redirect? : string } ) = > HookResult
2023-02-16 12:43:58 +00:00
'app:chunkError' : ( options : { error : any } ) = > HookResult
2022-03-28 17:12:41 +00:00
'app:data:refresh' : ( keys? : string [ ] ) = > HookResult
2023-09-19 21:31:18 +00:00
'app:manifest:update' : ( meta? : NuxtAppManifestMeta ) = > HookResult
2024-03-15 23:36:47 +00:00
'dev:ssr-logs' : ( logs : LogObject [ ] ) = > void | Promise < void >
2022-09-13 20:20:23 +00:00
'link:prefetch' : ( link : string ) = > HookResult
2021-08-26 18:57:36 +00:00
'page:start' : ( Component? : VNode ) = > HookResult
'page:finish' : ( Component? : VNode ) = > HookResult
2023-04-10 11:33:14 +00:00
'page:transition:start' : ( ) = > HookResult
2022-10-19 12:43:03 +00:00
'page:transition:finish' : ( Component? : VNode ) = > HookResult
2024-03-06 15:58:40 +00:00
'page:view-transition:start' : ( transition : ViewTransition ) = > HookResult
2023-12-19 10:18:10 +00:00
'page:loading:start' : ( ) = > HookResult
'page:loading:end' : ( ) = > HookResult
2021-12-21 14:44:35 +00:00
'vue:setup' : ( ) = > void
2022-03-11 08:22:16 +00:00
'vue:error' : ( . . . args : Parameters < Parameters < typeof onErrorCaptured > [ 0 ] > ) = > HookResult
2021-08-26 18:57:36 +00:00
}
2022-08-12 17:47:58 +00:00
export interface NuxtSSRContext extends SSRContext {
url : string
2022-10-15 18:42:57 +00:00
event : H3Event
2022-08-12 17:47:58 +00:00
runtimeConfig : RuntimeConfig
noSSR : boolean
/** whether we are rendering an SSR error */
error? : boolean
nuxt : _NuxtApp
2024-06-11 18:59:48 +00:00
payload : Partial < NuxtPayload >
2023-07-30 18:46:16 +00:00
head : VueHeadClient < MergeHead >
2023-06-22 13:14:21 +00:00
/** This is used solely to render runtime config with SPA renderer. */
config? : Pick < RuntimeConfig , ' public ' | ' app ' >
2022-08-12 17:47:58 +00:00
teleports? : Record < string , string >
2022-11-24 12:24:14 +00:00
islandContext? : NuxtIslandContext
2023-04-07 10:34:35 +00:00
/** @internal */
2023-04-28 10:18:03 +00:00
_renderResponse? : Partial < RenderResponse >
/** @internal */
2023-04-07 10:34:35 +00:00
_payloadReducers : Record < string , ( data : any ) = > any >
2024-01-18 10:01:39 +00:00
/** @internal */
_sharedPrerenderCache ? : {
2024-03-08 17:03:38 +00:00
get < T = unknown > ( key : string ) : Promise < T > | undefined
2024-01-18 10:01:39 +00:00
set < T > ( key : string , value : Promise < T > ) : Promise < void >
}
2022-08-12 17:47:58 +00:00
}
2023-06-22 13:14:21 +00:00
export interface NuxtPayload {
path? : string
serverRendered? : boolean
prerenderedAt? : number
data : Record < string , any >
state : Record < string , any >
2023-12-19 11:00:11 +00:00
once : Set < string >
2023-06-22 13:14:21 +00:00
config? : Pick < RuntimeConfig , ' public ' | ' app ' >
2024-06-19 17:04:40 +00:00
error? : NuxtError | undefined
_errors : Record < string , NuxtError | undefined >
2023-06-22 13:14:21 +00:00
[ key : string ] : unknown
}
2021-11-18 13:11:34 +00:00
interface _NuxtApp {
2024-05-08 12:32:45 +00:00
/** @internal */
_name : string
2021-10-18 18:31:37 +00:00
vueApp : App < Element >
2021-01-18 12:46:19 +00:00
globalName : string
2023-03-01 15:08:23 +00:00
versions : Record < string , string >
2021-01-18 12:46:19 +00:00
2021-08-27 12:51:40 +00:00
hooks : Hookable < RuntimeNuxtHooks >
2021-11-18 13:11:34 +00:00
hook : _NuxtApp [ 'hooks' ] [ 'hook' ]
callHook : _NuxtApp [ 'hooks' ] [ 'callHook' ]
2021-01-18 12:46:19 +00:00
2023-05-03 10:02:07 +00:00
runWithContext : < T extends ( ) = > any > ( fn : T ) = > ReturnType < T > | Promise < Awaited < ReturnType < T > >>
2023-03-14 10:09:50 +00:00
[ key : string ] : unknown
2021-01-18 12:46:19 +00:00
2024-01-30 09:10:13 +00:00
/** @internal */
_id? : number
2023-10-15 14:52:46 +00:00
/** @internal */
_scope : EffectScope
2023-03-14 10:09:50 +00:00
/** @internal */
2022-08-12 17:47:58 +00:00
_asyncDataPromises : Record < string , Promise < any > | undefined >
2023-03-14 10:09:50 +00:00
/** @internal */
2022-08-30 10:34:09 +00:00
_asyncData : Record < string , {
2024-05-22 14:42:19 +00:00
data : Ref < unknown >
2024-07-11 06:04:37 +00:00
/ * *
* @deprecated This may be removed in a future major version .
* /
2022-08-30 10:34:09 +00:00
pending : Ref < boolean >
2024-06-19 17:04:40 +00:00
error : Ref < Error | undefined >
2023-06-09 21:38:14 +00:00
status : Ref < AsyncDataRequestStatus >
2024-05-22 14:42:19 +00:00
/** @internal */
_default : ( ) = > unknown
2022-10-08 14:18:57 +00:00
} | undefined >
2023-12-19 10:18:10 +00:00
/** @internal */
_loadingIndicator? : LoadingIndicator
/** @internal */
_loadingIndicatorDeps? : number
2023-03-14 10:09:50 +00:00
/** @internal */
_middleware : {
global : RouteMiddleware [ ]
named : Record < string , RouteMiddleware >
}
2023-12-19 11:00:11 +00:00
/** @internal */
_once : {
[ key : string ] : Promise < any >
}
2023-03-14 10:09:50 +00:00
/** @internal */
_observer ? : { observe : ( element : Element , callback : ( ) = > void ) = > ( ) = > void }
/** @internal */
2023-09-19 21:31:18 +00:00
_payloadCache? : Record < string , Promise < Record < string , any > > | Record < string , any > | null >
2023-03-14 10:09:50 +00:00
/** @internal */
_appConfig : AppConfig
/** @internal */
_route : RouteLocationNormalizedLoaded
/** @internal */
_islandPromises? : Record < string , Promise < any > >
2023-04-07 10:34:35 +00:00
/** @internal */
_payloadRevivers : Record < string , ( data : any ) = > any >
2024-04-17 15:58:13 +00:00
/** @internal */
_routeAnnouncer? : RouteAnnouncer
/** @internal */
_routeAnnouncerDeps? : number
2023-03-14 10:09:50 +00:00
// Nuxt injections
$config : RuntimeConfig
2022-10-08 14:18:57 +00:00
isHydrating? : boolean
deferHydration : ( ) = > ( ) = > void | Promise < void >
2022-08-12 17:47:58 +00:00
ssrContext? : NuxtSSRContext
2023-06-22 13:14:21 +00:00
payload : NuxtPayload
2022-11-10 13:27:59 +00:00
static : {
data : Record < string , any >
}
2021-01-18 12:46:19 +00:00
provide : ( name : string , value : any ) = > void
}
2022-09-01 09:08:56 +00:00
export interface NuxtApp extends _NuxtApp { }
2021-11-18 13:11:34 +00:00
2021-06-18 17:16:51 +00:00
export const NuxtPluginIndicator = '__nuxt_plugin'
2023-04-11 11:58:43 +00:00
export interface PluginMeta {
name? : string
enforce ? : 'pre' | 'default' | 'post'
2023-12-14 17:11:08 +00:00
/ * *
* Await for other named plugins to finish before running this plugin .
* /
dependsOn? : NuxtAppLiterals [ 'pluginName' ] [ ]
2023-04-11 11:58:43 +00:00
/ * *
* This allows more granular control over plugin order and should only be used by advanced users .
* It overrides the value of ` enforce ` and is used to sort plugins .
* /
order? : number
}
2023-07-30 21:36:11 +00:00
export interface PluginEnvContext {
/ * *
* This enable the plugin for islands components .
* Require ` experimental.componentsIslands ` .
* @default true
* /
islands? : boolean
}
2023-04-11 11:58:43 +00:00
export interface ResolvedPluginMeta {
name? : string
2023-05-16 08:50:43 +00:00
parallel? : boolean
2023-04-11 11:58:43 +00:00
}
2023-03-14 13:08:43 +00:00
export interface Plugin < Injections extends Record < string , unknown > = Record < string , unknown > > {
2021-11-18 13:11:34 +00:00
( nuxt : _NuxtApp ) : Promise < void > | Promise < { provide? : Injections } > | void | { provide? : Injections }
2021-06-18 17:16:51 +00:00
[ NuxtPluginIndicator ] ? : true
2023-04-11 11:58:43 +00:00
meta? : ResolvedPluginMeta
}
2023-06-19 23:00:03 +00:00
export interface ObjectPlugin < Injections extends Record < string , unknown > = Record < string , unknown > > extends PluginMeta {
2023-04-11 11:58:43 +00:00
hooks? : Partial < RuntimeNuxtHooks >
setup? : Plugin < Injections >
2023-07-30 21:36:11 +00:00
env? : PluginEnvContext
2023-05-16 08:50:43 +00:00
/ * *
* Execute plugin in parallel with other parallel plugins .
* @default false
* /
parallel? : boolean
2023-12-14 17:11:08 +00:00
/ * *
* @internal
* /
_name? : string
2021-06-18 17:16:51 +00:00
}
2021-01-18 12:46:19 +00:00
2023-06-19 23:00:03 +00:00
/** @deprecated Use `ObjectPlugin` */
export type ObjectPluginInput < Injections extends Record < string , unknown > = Record < string , unknown > > = ObjectPlugin < Injections >
2021-01-18 12:46:19 +00:00
export interface CreateOptions {
2021-10-18 18:31:37 +00:00
vueApp : NuxtApp [ 'vueApp' ]
2021-08-27 13:30:53 +00:00
ssrContext? : NuxtApp [ 'ssrContext' ]
globalName? : NuxtApp [ 'globalName' ]
2021-01-18 12:46:19 +00:00
}
2024-04-19 14:58:19 +00:00
/** @since 3.0.0 */
2021-10-02 18:40:10 +00:00
export function createNuxtApp ( options : CreateOptions ) {
2022-10-08 14:18:57 +00:00
let hydratingCount = 0
2021-10-18 18:31:37 +00:00
const nuxtApp : NuxtApp = {
2024-05-17 03:41:31 +00:00
_name : appId || 'nuxt-app' ,
2023-10-15 14:52:46 +00:00
_scope : effectScope ( ) ,
2021-01-18 12:46:19 +00:00
provide : undefined ,
globalName : 'nuxt' ,
2023-03-01 15:08:23 +00:00
versions : {
get nuxt ( ) { return __NUXT_VERSION__ } ,
2024-04-05 18:08:32 +00:00
get vue ( ) { return nuxtApp . vueApp . version } ,
2023-03-01 15:08:23 +00:00
} ,
2024-05-16 14:14:25 +00:00
payload : shallowReactive ( {
data : shallowReactive ( { } ) ,
state : reactive ( { } ) ,
2023-12-19 11:00:11 +00:00
once : new Set < string > ( ) ,
2024-05-16 14:14:25 +00:00
_errors : shallowReactive ( { } ) ,
2021-10-11 17:48:03 +00:00
} ) ,
2022-11-10 13:27:59 +00:00
static : {
2024-04-05 18:08:32 +00:00
data : { } ,
2022-11-10 13:27:59 +00:00
} ,
2024-04-23 09:34:41 +00:00
runWithContext ( fn : any ) {
2024-05-03 10:27:38 +00:00
if ( nuxtApp . _scope . active && ! getCurrentScope ( ) ) {
2024-04-23 09:34:41 +00:00
return nuxtApp . _scope . run ( ( ) = > callWithNuxt ( nuxtApp , fn ) )
}
return callWithNuxt ( nuxtApp , fn )
} ,
2023-08-07 22:03:40 +00:00
isHydrating : import.meta.client ,
2022-10-08 14:18:57 +00:00
deferHydration ( ) {
if ( ! nuxtApp . isHydrating ) { return ( ) = > { } }
hydratingCount ++
let called = false
return ( ) = > {
if ( called ) { return }
called = true
hydratingCount --
if ( hydratingCount === 0 ) {
nuxtApp . isHydrating = false
return nuxtApp . callHook ( 'app:suspense:resolve' )
}
}
} ,
2021-10-08 14:21:55 +00:00
_asyncDataPromises : { } ,
2024-05-16 14:14:25 +00:00
_asyncData : shallowReactive ( { } ) ,
2023-04-07 10:34:35 +00:00
_payloadRevivers : { } ,
2024-04-05 18:08:32 +00:00
. . . options ,
2021-08-27 13:30:53 +00:00
} as any as NuxtApp
2021-01-18 12:46:19 +00:00
2024-05-16 14:14:25 +00:00
if ( import . meta . server ) {
nuxtApp . payload . serverRendered = true
}
// TODO: remove/refactor in https://github.com/nuxt/nuxt/issues/25336
if ( import . meta . client && window . __NUXT__ ) {
for ( const key in window . __NUXT__ ) {
switch ( key ) {
case 'data' :
case 'state' :
case '_errors' :
// Preserve reactivity for non-rich payload support
Object . assign ( nuxtApp . payload [ key ] , window . __NUXT__ [ key ] )
break
default :
nuxtApp . payload [ key ] = window . __NUXT__ [ key ]
}
}
}
2021-10-18 18:31:37 +00:00
nuxtApp . hooks = createHooks < RuntimeNuxtHooks > ( )
nuxtApp . hook = nuxtApp . hooks . hook
2023-03-17 19:01:16 +00:00
2023-08-07 22:03:40 +00:00
if ( import . meta . server ) {
2023-11-09 17:01:13 +00:00
const contextCaller = async function ( hooks : HookCallback [ ] , args : any [ ] ) {
2023-03-17 19:01:16 +00:00
for ( const hook of hooks ) {
2023-05-03 10:02:07 +00:00
await nuxtApp . runWithContext ( ( ) = > hook ( . . . args ) )
2023-03-17 19:01:16 +00:00
}
}
// Patch callHook to preserve NuxtApp context on server
// TODO: Refactor after https://github.com/unjs/hookable/issues/74
nuxtApp . hooks . callHook = ( name : any , . . . args : any [ ] ) = > nuxtApp . hooks . callHookWith ( contextCaller , name , . . . args )
}
2021-10-18 18:31:37 +00:00
nuxtApp . callHook = nuxtApp . hooks . callHook
2021-01-18 12:46:19 +00:00
2021-10-18 18:31:37 +00:00
nuxtApp . provide = ( name : string , value : any ) = > {
2021-01-18 12:46:19 +00:00
const $name = '$' + name
2021-10-18 18:31:37 +00:00
defineGetter ( nuxtApp , $name , value )
defineGetter ( nuxtApp . vueApp . config . globalProperties , $name , value )
2021-01-18 12:46:19 +00:00
}
2021-02-03 18:14:30 +00:00
// Inject $nuxt
2021-10-18 18:31:37 +00:00
defineGetter ( nuxtApp . vueApp , '$nuxt' , nuxtApp )
defineGetter ( nuxtApp . vueApp . config . globalProperties , '$nuxt' , nuxtApp )
2021-01-18 12:46:19 +00:00
2023-08-07 22:03:40 +00:00
if ( import . meta . server ) {
2022-08-08 14:33:31 +00:00
if ( nuxtApp . ssrContext ) {
2023-06-06 21:47:32 +00:00
// Expose nuxt to the renderContext
2022-08-08 14:33:31 +00:00
nuxtApp . ssrContext . nuxt = nuxtApp
2023-06-06 21:47:32 +00:00
// Expose payload types
2023-04-07 10:34:35 +00:00
nuxtApp . ssrContext . _payloadReducers = { }
2023-06-06 21:47:32 +00:00
// Expose current path
2023-06-21 10:04:44 +00:00
nuxtApp . payload . path = nuxtApp . ssrContext . url
2023-04-07 10:34:35 +00:00
}
// Expose to server renderer to create payload
2022-06-08 19:37:50 +00:00
nuxtApp . ssrContext = nuxtApp . ssrContext || { } as any
2022-08-12 17:47:58 +00:00
if ( nuxtApp . ssrContext ! . payload ) {
Object . assign ( nuxtApp . payload , nuxtApp . ssrContext ! . payload )
2022-08-08 14:33:31 +00:00
}
2022-08-12 17:47:58 +00:00
nuxtApp . ssrContext ! . payload = nuxtApp . payload
2021-01-18 12:46:19 +00:00
2022-08-08 14:33:31 +00:00
// Expose client runtime-config to the payload
2023-04-07 10:34:35 +00:00
nuxtApp . ssrContext ! . config = {
2022-08-12 17:47:58 +00:00
public : options . ssrContext ! . runtimeConfig . public ,
2024-04-05 18:08:32 +00:00
app : options.ssrContext ! . runtimeConfig . app ,
2022-04-11 19:55:43 +00:00
}
2021-10-02 20:30:20 +00:00
}
2023-02-16 12:43:58 +00:00
// Listen to chunk load errors
2023-08-07 22:03:40 +00:00
if ( import . meta . client ) {
2023-02-16 12:43:58 +00:00
window . addEventListener ( 'nuxt.preloadError' , ( event ) = > {
nuxtApp . callHook ( 'app:chunkError' , { error : ( event as Event & { payload : Error } ) . payload } )
} )
2023-06-19 16:17:15 +00:00
window . useNuxtApp = window . useNuxtApp || useNuxtApp
2023-03-09 14:37:39 +00:00
// Log errors captured when running plugins, in the `app:created` and `app:beforeMount` hooks
2023-03-31 09:17:10 +00:00
// as well as when mounting the app.
const unreg = nuxtApp . hook ( 'app:error' , ( . . . args ) = > { console . error ( '[nuxt] error caught during app initialization' , . . . args ) } )
nuxtApp . hook ( 'app:mounted' , unreg )
2023-03-09 14:37:39 +00:00
}
2023-02-21 15:06:10 +00:00
2022-04-12 14:59:48 +00:00
// Expose runtime config
2024-03-30 07:48:43 +00:00
const runtimeConfig = import . meta . server ? options . ssrContext ! . runtimeConfig : nuxtApp.payload.config !
2024-06-07 15:55:49 +00:00
nuxtApp . provide ( 'config' , import . meta . client && import . meta . dev ? wrappedConfig ( runtimeConfig ) : runtimeConfig )
2022-04-12 14:59:48 +00:00
2021-10-18 18:31:37 +00:00
return nuxtApp
2021-01-18 12:46:19 +00:00
}
2024-06-10 18:41:36 +00:00
/** @since 3.12.0 */
export function registerPluginHooks ( nuxtApp : NuxtApp , plugin : Plugin & ObjectPlugin < any > ) {
2023-06-19 23:00:03 +00:00
if ( plugin . hooks ) {
nuxtApp . hooks . addHooks ( plugin . hooks )
}
2024-06-10 18:41:36 +00:00
}
/** @since 3.0.0 */
export async function applyPlugin ( nuxtApp : NuxtApp , plugin : Plugin & ObjectPlugin < any > ) {
2023-06-19 23:00:03 +00:00
if ( typeof plugin === 'function' ) {
const { provide } = await nuxtApp . runWithContext ( ( ) = > plugin ( nuxtApp ) ) || { }
if ( provide && typeof provide === 'object' ) {
for ( const key in provide ) {
nuxtApp . provide ( key , provide [ key ] )
}
2021-11-18 13:11:34 +00:00
}
}
2021-01-18 12:46:19 +00:00
}
2024-04-19 14:58:19 +00:00
/** @since 3.0.0 */
2023-06-19 23:00:03 +00:00
export async function applyPlugins ( nuxtApp : NuxtApp , plugins : Array < Plugin & ObjectPlugin < any > > ) {
2023-12-14 17:11:08 +00:00
const resolvedPlugins : string [ ] = [ ]
const unresolvedPlugins : [ Set < string > , Plugin & ObjectPlugin < any > ] [ ] = [ ]
2023-05-16 08:50:43 +00:00
const parallels : Promise < any > [ ] = [ ]
const errors : Error [ ] = [ ]
2023-12-14 17:11:08 +00:00
let promiseDepth = 0
async function executePlugin ( plugin : Plugin & ObjectPlugin < any > ) {
2024-01-27 22:14:18 +00:00
const unresolvedPluginsForThisPlugin = plugin . dependsOn ? . filter ( name = > plugins . some ( p = > p . _name === name ) && ! resolvedPlugins . includes ( name ) ) ? ? [ ]
2024-01-22 09:57:17 +00:00
if ( unresolvedPluginsForThisPlugin . length > 0 ) {
unresolvedPlugins . push ( [ new Set ( unresolvedPluginsForThisPlugin ) , plugin ] )
2023-05-16 08:50:43 +00:00
} else {
2023-12-14 17:11:08 +00:00
const promise = applyPlugin ( nuxtApp , plugin ) . then ( async ( ) = > {
if ( plugin . _name ) {
resolvedPlugins . push ( plugin . _name )
await Promise . all ( unresolvedPlugins . map ( async ( [ dependsOn , unexecutedPlugin ] ) = > {
if ( dependsOn . has ( plugin . _name ! ) ) {
dependsOn . delete ( plugin . _name ! )
if ( dependsOn . size === 0 ) {
promiseDepth ++
await executePlugin ( unexecutedPlugin )
}
}
} ) )
}
} )
if ( plugin . parallel ) {
parallels . push ( promise . catch ( e = > errors . push ( e ) ) )
} else {
await promise
}
2023-05-16 08:50:43 +00:00
}
2021-01-18 12:46:19 +00:00
}
2023-12-14 17:11:08 +00:00
2024-06-10 18:41:36 +00:00
for ( const plugin of plugins ) {
if ( import . meta . server && nuxtApp . ssrContext ? . islandContext && plugin . env ? . islands === false ) { continue }
registerPluginHooks ( nuxtApp , plugin )
}
2023-12-14 17:11:08 +00:00
for ( const plugin of plugins ) {
if ( import . meta . server && nuxtApp . ssrContext ? . islandContext && plugin . env ? . islands === false ) { continue }
await executePlugin ( plugin )
}
2023-05-16 08:50:43 +00:00
await Promise . all ( parallels )
2023-12-14 17:11:08 +00:00
if ( promiseDepth ) {
for ( let i = 0 ; i < promiseDepth ; i ++ ) {
await Promise . all ( parallels )
}
}
2023-05-16 08:50:43 +00:00
if ( errors . length ) { throw errors [ 0 ] }
2021-01-18 12:46:19 +00:00
}
2021-04-09 13:48:39 +00:00
2024-04-19 14:58:19 +00:00
/** @since 3.0.0 */
2024-03-09 06:48:15 +00:00
/* @__NO_SIDE_EFFECTS__ */
2023-06-19 23:00:03 +00:00
export function defineNuxtPlugin < T extends Record < string , unknown > > ( plugin : Plugin < T > | ObjectPlugin < T > ) : Plugin < T > & ObjectPlugin < T > {
if ( typeof plugin === 'function' ) { return plugin }
2023-12-14 17:11:08 +00:00
const _name = plugin . _name || plugin . name
2023-06-19 23:00:03 +00:00
delete plugin . name
2023-12-14 17:11:08 +00:00
return Object . assign ( plugin . setup || ( ( ) = > { } ) , plugin , { [ NuxtPluginIndicator ] : true , _name } as const )
2023-04-11 11:58:43 +00:00
}
2024-03-09 06:48:15 +00:00
/* @__NO_SIDE_EFFECTS__ */
2023-06-19 23:00:03 +00:00
export const definePayloadPlugin = defineNuxtPlugin
2021-06-18 17:16:51 +00:00
2024-04-19 14:58:19 +00:00
/** @since 3.0.0 */
2022-07-12 17:06:55 +00:00
export function isNuxtPlugin ( plugin : unknown ) {
return typeof plugin === 'function' && NuxtPluginIndicator in plugin
}
2021-04-09 13:48:39 +00:00
/ * *
2024-04-15 14:19:57 +00:00
* Ensures that the setup function passed in has access to the Nuxt instance via ` useNuxtApp ` .
2021-04-09 13:48:39 +00:00
* @param nuxt A Nuxt instance
* @param setup The function to call
2024-04-19 14:58:19 +00:00
* @since 3.0 . 0
2021-04-09 13:48:39 +00:00
* /
2022-03-16 22:44:22 +00:00
export function callWithNuxt < T extends ( ...args : any [ ] ) = > any > ( nuxt : NuxtApp | _NuxtApp , setup : T , args? : Parameters < T > ) {
2023-01-23 11:13:21 +00:00
const fn : ( ) = > ReturnType < T > = ( ) = > args ? setup ( . . . args as Parameters < T > ) : setup ( )
2024-05-08 12:32:45 +00:00
const nuxtAppCtx = getNuxtAppCtx ( nuxt . _name )
2023-08-07 22:03:40 +00:00
if ( import . meta . server ) {
2023-05-11 11:39:08 +00:00
return nuxt . vueApp . runWithContext ( ( ) = > nuxtAppCtx . callAsync ( nuxt as NuxtApp , fn ) )
2022-04-01 09:55:23 +00:00
} else {
// In client side we could assume nuxt app is singleton
2023-03-11 18:22:29 +00:00
nuxtAppCtx . set ( nuxt as NuxtApp )
2023-05-11 11:39:08 +00:00
return nuxt . vueApp . runWithContext ( fn )
2021-11-23 17:50:20 +00:00
}
2021-04-09 13:48:39 +00:00
}
2024-03-09 06:48:15 +00:00
/* @__NO_SIDE_EFFECTS__ */
2021-04-09 13:48:39 +00:00
/ * *
* Returns the current Nuxt instance .
2024-01-30 09:10:13 +00:00
*
2024-01-18 09:59:59 +00:00
* Returns ` null ` if Nuxt instance is unavailable .
2024-04-19 14:58:19 +00:00
* @since 3.10 . 0
2021-04-09 13:48:39 +00:00
* /
2024-05-08 12:32:45 +00:00
export function tryUseNuxtApp ( ) : NuxtApp | null
export function tryUseNuxtApp ( appName? : string ) : NuxtApp | null {
2023-05-17 12:26:16 +00:00
let nuxtAppInstance
if ( hasInjectionContext ( ) ) {
nuxtAppInstance = getCurrentInstance ( ) ? . appContext . app . $nuxt
}
2024-05-08 12:32:45 +00:00
nuxtAppInstance = nuxtAppInstance || getNuxtAppCtx ( appName ) . tryUse ( )
2021-04-09 13:48:39 +00:00
2024-01-18 09:59:59 +00:00
return nuxtAppInstance || null
}
2024-03-09 06:48:15 +00:00
/* @__NO_SIDE_EFFECTS__ */
2024-01-18 09:59:59 +00:00
/ * *
* Returns the current Nuxt instance .
2024-01-30 09:10:13 +00:00
*
2024-01-18 09:59:59 +00:00
* Throws an error if Nuxt instance is unavailable .
2024-04-19 14:58:19 +00:00
* @since 3.0 . 0
2024-01-18 09:59:59 +00:00
* /
2024-05-08 12:32:45 +00:00
export function useNuxtApp ( ) : NuxtApp
export function useNuxtApp ( appName? : string ) : NuxtApp {
// @ts-expect-error internal usage of appName
const nuxtAppInstance = tryUseNuxtApp ( appName )
2024-01-18 09:59:59 +00:00
2022-06-15 12:00:34 +00:00
if ( ! nuxtAppInstance ) {
2023-08-07 22:03:40 +00:00
if ( import . meta . dev ) {
2023-10-27 21:53:09 +00:00
throw new Error ( '[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at `https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables`.' )
2023-05-17 12:26:16 +00:00
} else {
throw new Error ( '[nuxt] instance unavailable' )
2021-04-09 13:48:39 +00:00
}
}
2022-06-15 12:00:34 +00:00
return nuxtAppInstance
2021-04-09 13:48:39 +00:00
}
2021-10-02 20:30:20 +00:00
2024-04-19 14:58:19 +00:00
/** @since 3.0.0 */
2024-03-09 06:48:15 +00:00
/* @__NO_SIDE_EFFECTS__ */
2024-01-29 11:49:29 +00:00
export function useRuntimeConfig ( _event? : H3Event < EventHandlerRequest > ) : RuntimeConfig {
2021-10-02 20:30:20 +00:00
return useNuxtApp ( ) . $config
}
2021-10-18 18:31:37 +00:00
function defineGetter < K extends string | number | symbol , V > ( obj : Record < K , V > , key : K , val : V ) {
Object . defineProperty ( obj , key , { get : ( ) = > val } )
}
2022-08-17 15:23:13 +00:00
2024-04-19 14:58:19 +00:00
/** @since 3.0.0 */
2022-08-17 15:23:13 +00:00
export function defineAppConfig < C extends AppConfigInput > ( config : C ) : C {
return config
}
2024-06-07 15:55:49 +00:00
/ * *
* Configure error getter on runtime secret property access that doesn ' t exist on the client side
* /
2024-06-12 11:39:40 +00:00
const loggedKeys = new Set < string > ( )
2024-06-07 15:55:49 +00:00
function wrappedConfig ( runtimeConfig : Record < string , unknown > ) {
if ( ! import . meta . dev || import . meta . server ) { return runtimeConfig }
const keys = Object . keys ( runtimeConfig ) . map ( key = > ` \` ${ key } \` ` )
const lastKey = keys . pop ( )
return new Proxy ( runtimeConfig , {
2024-06-10 22:42:55 +00:00
get ( target , p , receiver ) {
if ( typeof p === 'string' && p !== 'public' && ! ( p in target ) && ! p . startsWith ( '__v' ) /* vue check for reactivity, e.g. `__v_isRef` */ ) {
2024-06-12 11:39:40 +00:00
if ( ! loggedKeys . has ( p ) ) {
loggedKeys . add ( p )
2024-06-12 18:51:09 +00:00
console . warn ( ` [nuxt] Could not access \` ${ p } \` . The only available runtime config keys on the client side are ${ keys . join ( ', ' ) } and ${ lastKey } . See https://nuxt.com/docs/guide/going-further/runtime-config for more information. ` )
2024-06-12 11:39:40 +00:00
}
2024-06-07 15:55:49 +00:00
}
return Reflect . get ( target , p , receiver )
} ,
} )
}