2021-10-06 12:37:45 +00:00
/* eslint-disable no-use-before-define */
2023-04-12 08:42:45 +00:00
import { getCurrentInstance , reactive } from 'vue'
2023-04-07 16:02:47 +00:00
import type { App , Ref , VNode , onErrorCaptured } from 'vue'
2023-03-14 13:08: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'
2022-08-07 09:52:34 +00:00
import type { SSRContext } from 'vue-bundle-renderer/runtime'
2022-10-15 18:42:57 +00:00
import type { H3Event } from 'h3'
2023-04-07 16:02:47 +00:00
import type { AppConfig , AppConfigInput , RuntimeConfig } from 'nuxt/schema'
2023-03-11 21:16:01 +00:00
2022-11-24 12:24:14 +00:00
// eslint-disable-next-line import/no-restricted-paths
import type { NuxtIslandContext } from '../core/runtime/nitro/renderer'
2023-03-14 10:09:50 +00:00
import type { RouteMiddleware } from '../../app'
2023-04-07 10:34:35 +00:00
import type { NuxtError } from '../app/composables/error'
2021-01-18 12:46:19 +00:00
2023-03-07 22:51:08 +00:00
const nuxtAppCtx = /* #__PURE__ */ getContext < NuxtApp > ( 'nuxt-app' )
2022-04-01 09:55:23 +00:00
2021-07-15 11:28:04 +00:00
type NuxtMeta = {
htmlAttrs? : string
headAttrs? : string
bodyAttrs? : string
headTags? : string
2022-02-16 17:56:30 +00:00
bodyScriptsPrepend? : string
2021-07-15 11:28:04 +00:00
bodyScripts? : string
}
2021-08-26 18:57:36 +00:00
type HookResult = Promise < void > | void
2022-08-11 16:34:39 +00:00
type AppRenderedContext = { ssrContext : NuxtApp [ 'ssrContext' ] }
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
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
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
payload : _NuxtApp [ 'payload' ]
teleports? : Record < string , string >
renderMeta ? : ( ) = > Promise < NuxtMeta > | NuxtMeta
2022-11-24 12:24:14 +00:00
islandContext? : NuxtIslandContext
2023-04-07 10:34:35 +00:00
/** @internal */
_payloadReducers : Record < string , ( data : any ) = > any >
2022-08-12 17:47:58 +00:00
}
2021-11-18 13:11:34 +00:00
interface _NuxtApp {
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-03-14 10:09:50 +00:00
[ key : string ] : unknown
2021-01-18 12:46:19 +00:00
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 , {
data : Ref < any >
pending : Ref < boolean >
error : Ref < any >
2022-10-08 14:18:57 +00:00
} | undefined >
2023-03-14 10:09:50 +00:00
/** @internal */
_middleware : {
global : RouteMiddleware [ ]
named : Record < string , RouteMiddleware >
}
/** @internal */
_observer ? : { observe : ( element : Element , callback : ( ) = > void ) = > ( ) = > void }
/** @internal */
_payloadCache? : Record < string , Promise < Record < string , any > > | Record < string , any > >
/** @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 >
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
2021-01-18 12:46:19 +00:00
payload : {
2022-06-08 19:37:50 +00:00
serverRendered? : boolean
2022-09-10 13:57:16 +00:00
prerenderedAt? : number
2022-08-12 17:47:58 +00:00
data : Record < string , any >
state : Record < string , any >
2022-08-08 14:33:31 +00:00
error? : Error | {
url : string
2023-02-13 22:55:29 +00:00
statusCode : number
2022-08-08 14:33:31 +00:00
statusMessage : string
message : string
description : string
data? : any
2022-08-22 10:12:02 +00:00
} | null
2023-04-07 10:34:35 +00:00
_errors : Record < string , NuxtError | undefined >
2021-01-18 12:46:19 +00:00
[ key : string ] : any
}
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'
/ * *
* 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
}
export interface ResolvedPluginMeta {
name? : string
order : number
}
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
}
export interface ObjectPluginInput < Injections extends Record < string , unknown > = Record < string , unknown > > extends PluginMeta {
hooks? : Partial < RuntimeNuxtHooks >
setup? : Plugin < Injections >
2021-06-18 17:16:51 +00:00
}
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
}
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 = {
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__ } ,
get vue ( ) { return nuxtApp . vueApp . version }
} ,
2023-04-12 08:42:45 +00:00
payload : reactive ( {
data : { } ,
state : { } ,
_errors : { } ,
2023-04-07 10:34:35 +00:00
. . . ( process . client ? window . __NUXT__ ? ? { } : { serverRendered : true } )
2021-10-11 17:48:03 +00:00
} ) ,
2022-11-10 13:27:59 +00:00
static : {
data : { }
} ,
2021-01-18 12:46:19 +00:00
isHydrating : process.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 : { } ,
2022-08-30 10:34:09 +00:00
_asyncData : { } ,
2023-04-07 10:34:35 +00:00
_payloadRevivers : { } ,
2021-01-18 12:46:19 +00:00
. . . options
2021-08-27 13:30:53 +00:00
} as any as NuxtApp
2021-01-18 12:46:19 +00:00
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
if ( process . server ) {
async function contextCaller ( hooks : HookCallback [ ] , args : any [ ] ) {
for ( const hook of hooks ) {
await nuxtAppCtx . call ( nuxtApp , ( ) = > hook ( . . . args ) )
}
}
// 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
if ( process . server ) {
2022-08-08 14:33:31 +00:00
// Expose nuxt to the renderContext
if ( nuxtApp . ssrContext ) {
nuxtApp . ssrContext . nuxt = nuxtApp
}
2023-04-07 10:34:35 +00:00
// Expose payload types
if ( nuxtApp . ssrContext ) {
nuxtApp . ssrContext . _payloadReducers = { }
}
// 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 ,
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
if ( process . client ) {
window . addEventListener ( 'nuxt.preloadError' , ( event ) = > {
nuxtApp . callHook ( 'app:chunkError' , { error : ( event as Event & { payload : Error } ) . payload } )
} )
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
2023-04-07 11:36:45 +00:00
const runtimeConfig = process . server ? options . ssrContext ! . runtimeConfig : reactive ( nuxtApp . payload . config )
2022-04-12 14:59:48 +00:00
2023-04-07 11:36:45 +00:00
// TODO: remove in v3.5
2022-08-12 17:47:58 +00:00
// Backward compatibility following #4254
2022-04-12 14:59:48 +00:00
const compatibilityConfig = new Proxy ( runtimeConfig , {
2023-04-07 11:36:45 +00:00
get ( target , prop : string ) {
if ( prop in target ) {
return target [ prop ]
2022-04-12 14:59:48 +00:00
}
2023-04-07 11:36:45 +00:00
if ( process . dev && prop in target . public ) {
console . warn ( ` [nuxt] [runtimeConfig] You are trying to access a public runtime config value ( \` ${ prop } \` ) directly from the top level. This currently works (for backward compatibility with Nuxt 2) but this compatibility layer will be removed in v3.5. Instead, you can update \` config[' ${ prop } '] \` to \` config.public[' ${ prop } '] \` . ` )
}
return target . public [ prop ]
2022-04-12 14:59:48 +00:00
} ,
set ( target , prop , value ) {
if ( process . server || prop === 'public' || prop === 'app' ) {
return false // Throws TypeError
}
target [ prop ] = value
target . public [ prop ] = value
return true
}
} )
nuxtApp . provide ( 'config' , compatibilityConfig )
2021-10-18 18:31:37 +00:00
return nuxtApp
2021-01-18 12:46:19 +00:00
}
2021-11-18 13:11:34 +00:00
export async function applyPlugin ( nuxtApp : NuxtApp , plugin : Plugin ) {
2021-02-19 01:08:45 +00:00
if ( typeof plugin !== 'function' ) { return }
2022-01-25 12:29:11 +00:00
const { provide } = await callWithNuxt ( nuxtApp , plugin , [ nuxtApp ] ) || { }
2021-11-18 13:11:34 +00:00
if ( provide && typeof provide === 'object' ) {
for ( const key in provide ) {
nuxtApp . provide ( key , provide [ key ] )
}
}
2021-01-18 12:46:19 +00:00
}
2021-10-18 18:31:37 +00:00
export async function applyPlugins ( nuxtApp : NuxtApp , plugins : Plugin [ ] ) {
2021-01-18 12:46:19 +00:00
for ( const plugin of plugins ) {
2021-10-18 18:31:37 +00:00
await applyPlugin ( nuxtApp , plugin )
2021-01-18 12:46:19 +00:00
}
}
2021-04-09 13:48:39 +00:00
2022-07-06 19:15:00 +00:00
export function normalizePlugins ( _plugins : Plugin [ ] ) {
2022-08-12 17:47:58 +00:00
const unwrappedPlugins : Plugin [ ] = [ ]
const legacyInjectPlugins : Plugin [ ] = [ ]
const invalidPlugins : Plugin [ ] = [ ]
2022-07-12 17:06:55 +00:00
2023-04-11 11:58:43 +00:00
const plugins : Plugin [ ] = [ ]
for ( const plugin of _plugins ) {
2021-11-02 09:49:45 +00:00
if ( typeof plugin !== 'function' ) {
2023-04-11 11:58:43 +00:00
if ( process . dev ) { invalidPlugins . push ( plugin ) }
continue
2022-07-12 17:06:55 +00:00
}
2023-04-11 11:58:43 +00:00
// TODO: Skip invalid plugins in next releases
let _plugin = plugin
2022-07-12 17:06:55 +00:00
if ( plugin . length > 1 ) {
// Allow usage without wrapper but warn
2023-04-11 11:58:43 +00:00
if ( process . dev ) { legacyInjectPlugins . push ( plugin ) }
// @ts-expect-error deliberate invalid second argument
_plugin = ( nuxtApp : NuxtApp ) = > plugin ( nuxtApp , nuxtApp . provide )
2021-11-02 09:49:45 +00:00
}
2023-04-11 11:58:43 +00:00
// Allow usage without wrapper but warn
if ( process . dev && ! isNuxtPlugin ( _plugin ) ) { unwrappedPlugins . push ( _plugin ) }
plugins . push ( _plugin )
}
plugins . sort ( ( a , b ) = > ( a . meta ? . order || orderMap . default ) - ( b . meta ? . order || orderMap . default ) )
2022-07-12 17:06:55 +00:00
if ( process . dev && legacyInjectPlugins . length ) {
console . warn ( '[warn] [nuxt] You are using a plugin with legacy Nuxt 2 format (context, inject) which is likely to be broken. In the future they will be ignored:' , legacyInjectPlugins . map ( p = > p . name || p ) . join ( ',' ) )
}
if ( process . dev && invalidPlugins . length ) {
console . warn ( '[warn] [nuxt] Some plugins are not exposing a function and skipped:' , invalidPlugins )
}
if ( process . dev && unwrappedPlugins . length ) {
console . warn ( '[warn] [nuxt] You are using a plugin that has not been wrapped in `defineNuxtPlugin`. It is advised to wrap your plugins as in the future this may enable enhancements:' , unwrappedPlugins . map ( p = > p . name || p ) . join ( ',' ) )
}
2021-06-18 17:16:51 +00:00
2023-04-11 11:58:43 +00:00
return plugins
}
// -50: pre-all (nuxt)
// -40: custom payload revivers (user)
// -30: payload reviving (nuxt)
// -20: pre (user) <-- pre mapped to this
// -10: default (nuxt)
// 0: default (user) <-- default behavior
// +10: post (nuxt)
// +20: post (user) <-- post mapped to this
// +30: post-all (nuxt)
const orderMap : Record < NonNullable < ObjectPluginInput [ ' enforce ' ] > , number > = {
pre : - 20 ,
default : 0 ,
post : 20
2021-06-18 17:16:51 +00:00
}
2023-04-11 11:58:43 +00:00
export function definePayloadPlugin < T extends Record < string , unknown > > ( plugin : Plugin < T > | ObjectPluginInput < T > ) {
return defineNuxtPlugin ( plugin , { order : - 40 } )
}
export function defineNuxtPlugin < T extends Record < string , unknown > > ( plugin : Plugin < T > | ObjectPluginInput < T > , meta? : PluginMeta ) : Plugin < T > {
if ( typeof plugin === 'function' ) { return defineNuxtPlugin ( { setup : plugin } , meta ) }
const wrapper : Plugin < T > = ( nuxtApp ) = > {
if ( plugin . hooks ) {
nuxtApp . hooks . addHooks ( plugin . hooks )
}
if ( plugin . setup ) {
return plugin . setup ( nuxtApp )
}
}
wrapper . meta = {
name : meta?.name || plugin . name || plugin . setup ? . name ,
order :
meta ? . order ||
plugin . order ||
orderMap [ plugin . enforce || 'default' ] ||
orderMap . default
}
wrapper [ NuxtPluginIndicator ] = true
return wrapper
2021-06-18 17:16:51 +00:00
}
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
/ * *
* Ensures that the setup function passed in has access to the Nuxt instance via ` useNuxt ` .
2021-04-15 18:49:29 +00:00
*
2021-04-09 13:48:39 +00:00
* @param nuxt A Nuxt instance
* @param setup The function to call
* /
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 ( )
2021-11-23 17:50:20 +00:00
if ( process . server ) {
2023-03-11 18:22:29 +00:00
return 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 )
2022-04-01 09:55:23 +00:00
return fn ( )
2021-11-23 17:50:20 +00:00
}
2021-04-09 13:48:39 +00:00
}
/ * *
* Returns the current Nuxt instance .
* /
2022-02-15 09:50:11 +00:00
export function useNuxtApp ( ) {
2022-08-04 11:00:01 +00:00
const nuxtAppInstance = nuxtAppCtx . tryUse ( )
2021-04-09 13:48:39 +00:00
2022-06-15 12:00:34 +00:00
if ( ! nuxtAppInstance ) {
const vm = getCurrentInstance ( )
if ( ! vm ) {
2021-04-09 13:48:39 +00:00
throw new Error ( 'nuxt instance unavailable' )
}
2022-06-15 12:00:34 +00:00
return vm . appContext . app . $nuxt as NuxtApp
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
2021-11-10 12:40:02 +00:00
export function useRuntimeConfig ( ) : 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
export function defineAppConfig < C extends AppConfigInput > ( config : C ) : C {
return config
}