169 lines
5.1 KiB
JavaScript
169 lines
5.1 KiB
JavaScript
import { getCurrentInstance, reactive } from "vue";
|
|
import { createHooks } from "hookable";
|
|
import { getContext } from "unctx";
|
|
const nuxtAppCtx = getContext("nuxt-app");
|
|
export const NuxtPluginIndicator = "__nuxt_plugin";
|
|
export function createNuxtApp(options) {
|
|
let hydratingCount = 0;
|
|
const nuxtApp = {
|
|
provide: void 0,
|
|
globalName: "nuxt",
|
|
payload: reactive({
|
|
data: {},
|
|
state: {},
|
|
_errors: {},
|
|
...process.client ? window.__NUXT__ : { serverRendered: true }
|
|
}),
|
|
static: {
|
|
data: {}
|
|
},
|
|
isHydrating: process.client,
|
|
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");
|
|
}
|
|
};
|
|
},
|
|
_asyncDataPromises: {},
|
|
_asyncData: {},
|
|
...options
|
|
};
|
|
nuxtApp.hooks = createHooks();
|
|
nuxtApp.hook = nuxtApp.hooks.hook;
|
|
nuxtApp.callHook = nuxtApp.hooks.callHook;
|
|
nuxtApp.provide = (name, value) => {
|
|
const $name = "$" + name;
|
|
defineGetter(nuxtApp, $name, value);
|
|
defineGetter(nuxtApp.vueApp.config.globalProperties, $name, value);
|
|
};
|
|
defineGetter(nuxtApp.vueApp, "$nuxt", nuxtApp);
|
|
defineGetter(nuxtApp.vueApp.config.globalProperties, "$nuxt", nuxtApp);
|
|
if (process.server) {
|
|
if (nuxtApp.ssrContext) {
|
|
nuxtApp.ssrContext.nuxt = nuxtApp;
|
|
}
|
|
nuxtApp.ssrContext = nuxtApp.ssrContext || {};
|
|
if (nuxtApp.ssrContext.payload) {
|
|
Object.assign(nuxtApp.payload, nuxtApp.ssrContext.payload);
|
|
}
|
|
nuxtApp.ssrContext.payload = nuxtApp.payload;
|
|
nuxtApp.payload.config = {
|
|
public: options.ssrContext.runtimeConfig.public,
|
|
app: options.ssrContext.runtimeConfig.app
|
|
};
|
|
}
|
|
const runtimeConfig = process.server ? options.ssrContext.runtimeConfig : reactive(nuxtApp.payload.config);
|
|
const compatibilityConfig = new Proxy(runtimeConfig, {
|
|
get(target, prop) {
|
|
if (prop === "public") {
|
|
return target.public;
|
|
}
|
|
return target[prop] ?? target.public[prop];
|
|
},
|
|
set(target, prop, value) {
|
|
if (process.server || prop === "public" || prop === "app") {
|
|
return false;
|
|
}
|
|
target[prop] = value;
|
|
target.public[prop] = value;
|
|
return true;
|
|
}
|
|
});
|
|
nuxtApp.provide("config", compatibilityConfig);
|
|
return nuxtApp;
|
|
}
|
|
export async function applyPlugin(nuxtApp, plugin) {
|
|
if (typeof plugin !== "function") {
|
|
return;
|
|
}
|
|
const { provide } = await callWithNuxt(nuxtApp, plugin, [nuxtApp]) || {};
|
|
if (provide && typeof provide === "object") {
|
|
for (const key in provide) {
|
|
nuxtApp.provide(key, provide[key]);
|
|
}
|
|
}
|
|
}
|
|
export async function applyPlugins(nuxtApp, plugins) {
|
|
for (const plugin of plugins) {
|
|
await applyPlugin(nuxtApp, plugin);
|
|
}
|
|
}
|
|
export function normalizePlugins(_plugins) {
|
|
const unwrappedPlugins = [];
|
|
const legacyInjectPlugins = [];
|
|
const invalidPlugins = [];
|
|
const plugins = _plugins.map((plugin) => {
|
|
if (typeof plugin !== "function") {
|
|
invalidPlugins.push(plugin);
|
|
return null;
|
|
}
|
|
if (plugin.length > 1) {
|
|
legacyInjectPlugins.push(plugin);
|
|
return (nuxtApp) => plugin(nuxtApp, nuxtApp.provide);
|
|
}
|
|
if (!isNuxtPlugin(plugin)) {
|
|
unwrappedPlugins.push(plugin);
|
|
}
|
|
return plugin;
|
|
}).filter(Boolean);
|
|
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(","));
|
|
}
|
|
return plugins;
|
|
}
|
|
export function defineNuxtPlugin(plugin) {
|
|
plugin[NuxtPluginIndicator] = true;
|
|
return plugin;
|
|
}
|
|
export function isNuxtPlugin(plugin) {
|
|
return typeof plugin === "function" && NuxtPluginIndicator in plugin;
|
|
}
|
|
export function callWithNuxt(nuxt, setup, args) {
|
|
const fn = () => args ? setup(...args) : setup();
|
|
if (process.server) {
|
|
return nuxtAppCtx.callAsync(nuxt, fn);
|
|
} else {
|
|
nuxtAppCtx.set(nuxt);
|
|
return fn();
|
|
}
|
|
}
|
|
export function useNuxtApp() {
|
|
const nuxtAppInstance = nuxtAppCtx.tryUse();
|
|
if (!nuxtAppInstance) {
|
|
const vm = getCurrentInstance();
|
|
if (!vm) {
|
|
throw new Error("nuxt instance unavailable");
|
|
}
|
|
return vm.appContext.app.$nuxt;
|
|
}
|
|
return nuxtAppInstance;
|
|
}
|
|
export function useRuntimeConfig() {
|
|
return useNuxtApp().$config;
|
|
}
|
|
function defineGetter(obj, key, val) {
|
|
Object.defineProperty(obj, key, { get: () => val });
|
|
}
|
|
export function defineAppConfig(config) {
|
|
return config;
|
|
}
|