2021-04-09 13:48:39 +00:00
|
|
|
import { App, getCurrentInstance } from 'vue'
|
2021-01-18 12:46:19 +00:00
|
|
|
import Hookable from 'hookable'
|
2021-04-09 13:48:39 +00:00
|
|
|
import { defineGetter } from './utils'
|
2021-06-18 17:16:51 +00:00
|
|
|
import { legacyPlugin, LegacyContext } from './legacy'
|
2021-01-18 12:46:19 +00:00
|
|
|
|
2021-07-15 11:28:04 +00:00
|
|
|
type NuxtMeta = {
|
|
|
|
htmlAttrs?: string
|
|
|
|
headAttrs?: string
|
|
|
|
bodyAttrs?: string
|
|
|
|
headTags?: string
|
|
|
|
bodyPrepend?: string
|
|
|
|
bodyScripts?: string
|
|
|
|
}
|
|
|
|
|
2021-01-18 12:46:19 +00:00
|
|
|
export interface Nuxt {
|
|
|
|
app: App
|
|
|
|
globalName: string
|
|
|
|
|
|
|
|
hooks: Hookable
|
|
|
|
hook: Hookable['hook']
|
|
|
|
callHook: Hookable['callHook']
|
|
|
|
|
|
|
|
[key: string]: any
|
|
|
|
|
2021-04-03 10:03:20 +00:00
|
|
|
_asyncDataPromises?: Record<string, Promise<any>>
|
2021-06-18 17:16:51 +00:00
|
|
|
_legacyContext?: LegacyContext
|
2021-04-03 10:03:20 +00:00
|
|
|
|
2021-07-15 11:28:04 +00:00
|
|
|
ssrContext?: Record<string, any> & {
|
|
|
|
renderMeta: () => Promise<NuxtMeta> | NuxtMeta
|
|
|
|
}
|
2021-01-18 12:46:19 +00:00
|
|
|
payload: {
|
2021-03-17 09:17:18 +00:00
|
|
|
serverRendered?: true
|
|
|
|
data?: Record<string, any>
|
2021-01-18 12:46:19 +00:00
|
|
|
rendered?: Function
|
|
|
|
[key: string]: any
|
|
|
|
}
|
|
|
|
|
|
|
|
provide: (name: string, value: any) => void
|
|
|
|
}
|
|
|
|
|
2021-06-18 17:16:51 +00:00
|
|
|
export const NuxtPluginIndicator = '__nuxt_plugin'
|
2021-01-18 12:46:19 +00:00
|
|
|
export interface Plugin {
|
2021-06-18 17:16:51 +00:00
|
|
|
(nuxt: Nuxt): Promise<void> | void
|
|
|
|
[NuxtPluginIndicator]?: true
|
|
|
|
}
|
|
|
|
export interface LegacyPlugin {
|
|
|
|
(context: LegacyContext, provide: Nuxt['provide']): Promise<void> | void
|
2021-01-18 12:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface CreateOptions {
|
|
|
|
app: Nuxt['app']
|
|
|
|
ssrContext?: Nuxt['ssrContext']
|
|
|
|
globalName?: Nuxt['globalName']
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createNuxt (options: CreateOptions) {
|
|
|
|
const nuxt: Nuxt = {
|
|
|
|
provide: undefined,
|
|
|
|
globalName: 'nuxt',
|
|
|
|
state: {},
|
|
|
|
payload: {},
|
|
|
|
isHydrating: process.client,
|
|
|
|
...options
|
|
|
|
} as any as Nuxt
|
|
|
|
|
|
|
|
nuxt.hooks = new Hookable()
|
|
|
|
nuxt.hook = nuxt.hooks.hook
|
|
|
|
nuxt.callHook = nuxt.hooks.callHook
|
|
|
|
|
|
|
|
nuxt.provide = (name: string, value: any) => {
|
|
|
|
const $name = '$' + name
|
2021-02-03 18:14:30 +00:00
|
|
|
defineGetter(nuxt, $name, value)
|
2021-01-18 12:46:19 +00:00
|
|
|
defineGetter(nuxt.app.config.globalProperties, $name, value)
|
|
|
|
}
|
|
|
|
|
2021-02-03 18:14:30 +00:00
|
|
|
// Inject $nuxt
|
|
|
|
defineGetter(nuxt.app, '$nuxt', nuxt)
|
|
|
|
defineGetter(nuxt.app.config.globalProperties, '$nuxt', nuxt)
|
2021-01-18 12:46:19 +00:00
|
|
|
|
|
|
|
// Expose nuxt to the renderContext
|
|
|
|
if (nuxt.ssrContext) {
|
|
|
|
nuxt.ssrContext.nuxt = nuxt
|
|
|
|
}
|
|
|
|
|
|
|
|
if (process.server) {
|
|
|
|
nuxt.payload = {
|
2021-06-18 17:16:51 +00:00
|
|
|
serverRendered: true
|
2021-01-18 12:46:19 +00:00
|
|
|
}
|
|
|
|
|
2021-03-17 09:17:18 +00:00
|
|
|
nuxt.ssrContext = nuxt.ssrContext || {}
|
|
|
|
|
2021-01-18 12:46:19 +00:00
|
|
|
// Expose to server renderer to create window.__NUXT__
|
|
|
|
nuxt.ssrContext.payload = nuxt.payload
|
|
|
|
}
|
|
|
|
|
|
|
|
if (process.client) {
|
|
|
|
nuxt.payload = window.__NUXT__ || {}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nuxt
|
|
|
|
}
|
|
|
|
|
|
|
|
export function applyPlugin (nuxt: Nuxt, plugin: Plugin) {
|
2021-02-19 01:08:45 +00:00
|
|
|
if (typeof plugin !== 'function') { return }
|
2021-06-18 17:16:51 +00:00
|
|
|
return callWithNuxt(nuxt, () => plugin(nuxt))
|
2021-01-18 12:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export async function applyPlugins (nuxt: Nuxt, plugins: Plugin[]) {
|
|
|
|
for (const plugin of plugins) {
|
|
|
|
await applyPlugin(nuxt, plugin)
|
|
|
|
}
|
|
|
|
}
|
2021-04-09 13:48:39 +00:00
|
|
|
|
2021-06-18 17:16:51 +00:00
|
|
|
export function normalizePlugins (_plugins: Array<Plugin | LegacyPlugin>) {
|
|
|
|
let needsLegacyContext = false
|
|
|
|
|
|
|
|
const plugins = _plugins.map((plugin) => {
|
|
|
|
if (isLegacyPlugin(plugin)) {
|
|
|
|
needsLegacyContext = true
|
|
|
|
return (nuxt: Nuxt) => plugin(nuxt._legacyContext!, nuxt.provide)
|
|
|
|
}
|
|
|
|
return plugin
|
|
|
|
})
|
|
|
|
|
|
|
|
if (needsLegacyContext) {
|
|
|
|
plugins.unshift(legacyPlugin)
|
|
|
|
}
|
|
|
|
|
|
|
|
return plugins as Plugin[]
|
|
|
|
}
|
|
|
|
|
|
|
|
export function defineNuxtPlugin (plugin: Plugin) {
|
|
|
|
plugin[NuxtPluginIndicator] = true
|
|
|
|
return plugin
|
|
|
|
}
|
|
|
|
|
|
|
|
export function isLegacyPlugin (plugin: unknown): plugin is LegacyPlugin {
|
|
|
|
return !plugin[NuxtPluginIndicator]
|
|
|
|
}
|
|
|
|
|
2021-04-09 13:48:39 +00:00
|
|
|
let currentNuxtInstance: Nuxt | null
|
|
|
|
|
|
|
|
export const setNuxtInstance = (nuxt: Nuxt | null) => {
|
|
|
|
currentNuxtInstance = nuxt
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
export async function callWithNuxt (nuxt: Nuxt, setup: () => any) {
|
|
|
|
setNuxtInstance(nuxt)
|
|
|
|
const p = setup()
|
|
|
|
setNuxtInstance(null)
|
|
|
|
await p
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the current Nuxt instance.
|
|
|
|
*/
|
|
|
|
export function useNuxt (): Nuxt {
|
|
|
|
const vm = getCurrentInstance()
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
if (!currentNuxtInstance) {
|
|
|
|
throw new Error('nuxt instance unavailable')
|
|
|
|
}
|
|
|
|
return currentNuxtInstance
|
|
|
|
}
|
|
|
|
|
|
|
|
return vm.appContext.app.$nuxt
|
|
|
|
}
|