From 45d92d67ee9efa450e9c6669496c9563b75640c8 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 6 Aug 2024 17:41:51 +0200 Subject: [PATCH] feat(nuxt): allow specifying app id when creating a nuxt app (#28392) --- packages/nuxt/src/app/composables/id.ts | 8 +++--- packages/nuxt/src/app/nuxt.ts | 35 ++++++++++++++++--------- packages/schema/src/config/common.ts | 4 ++- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/nuxt/src/app/composables/id.ts b/packages/nuxt/src/app/composables/id.ts index c5019b0c2b..ba920a8f84 100644 --- a/packages/nuxt/src/app/composables/id.ts +++ b/packages/nuxt/src/app/composables/id.ts @@ -7,6 +7,8 @@ const SEPARATOR = '-' /** * Generate an SSR-friendly unique identifier that can be passed to accessibility attributes. + * + * The generated ID is unique in the context of the current Nuxt instance and key. */ export function useId (): string export function useId (key?: string): string { @@ -24,7 +26,7 @@ export function useId (key?: string): string { throw new TypeError('[nuxt] `useId` must be called within a component setup function.') } - nuxtApp._id ||= 0 + nuxtApp._genId ||= 0 instance._nuxtIdIndex ||= {} instance._nuxtIdIndex[key] ||= 0 @@ -32,7 +34,7 @@ export function useId (key?: string): string { if (import.meta.server) { const ids = JSON.parse(instance.attrs[ATTR_KEY] as string | undefined || '{}') - ids[instanceIndex] = key + SEPARATOR + nuxtApp._id++ + ids[instanceIndex] = key + SEPARATOR + nuxtApp._genId++ instance.attrs[ATTR_KEY] = JSON.stringify(ids) return ids[instanceIndex] } @@ -54,5 +56,5 @@ export function useId (key?: string): string { } // pure client-side ids, avoiding potential collision with server-side ids - return key + '_' + nuxtApp._id++ + return key + '_' + nuxtApp._genId++ } diff --git a/packages/nuxt/src/app/nuxt.ts b/packages/nuxt/src/app/nuxt.ts index fea0b1c0d2..dbaf9db389 100644 --- a/packages/nuxt/src/app/nuxt.ts +++ b/packages/nuxt/src/app/nuxt.ts @@ -27,8 +27,8 @@ import { appId } from '#build/nuxt.config.mjs' import type { DefaultAsyncDataErrorValue, DefaultErrorValue } from '#app/defaults' import type { NuxtAppLiterals } from '#app' -function getNuxtAppCtx (appName = appId || 'nuxt-app') { - return getContext(appName, { +function getNuxtAppCtx (id = appId || 'nuxt-app') { + return getContext(id, { asyncContext: !!__NUXT_ASYNC_CONTEXT__ && import.meta.server, }) } @@ -100,8 +100,6 @@ export interface NuxtPayload { } interface _NuxtApp { - /** @internal */ - _name: string vueApp: App globalName: string versions: Record @@ -116,8 +114,15 @@ interface _NuxtApp { /** @internal */ _cookies?: Record - /** @internal */ - _id?: number + /** + * The id of the Nuxt application. + * @internal */ + _id: string + /** + * The next id that can be used for generating unique ids via `useId`. + * @internal + */ + _genId?: number /** @internal */ _scope: EffectScope /** @internal */ @@ -248,13 +253,17 @@ export interface CreateOptions { vueApp: NuxtApp['vueApp'] ssrContext?: NuxtApp['ssrContext'] globalName?: NuxtApp['globalName'] + /** + * The id of the Nuxt application, overrides the default id specified in the Nuxt config (default: `nuxt-app`). + */ + id?: NuxtApp['_id'] } /** @since 3.0.0 */ export function createNuxtApp (options: CreateOptions) { let hydratingCount = 0 const nuxtApp: NuxtApp = { - _name: appId || 'nuxt-app', + _id: options.id || appId || 'nuxt-app', _scope: effectScope(), provide: undefined, globalName: 'nuxt', @@ -494,7 +503,7 @@ export function isNuxtPlugin (plugin: unknown) { */ export function callWithNuxt any> (nuxt: NuxtApp | _NuxtApp, setup: T, args?: Parameters) { const fn: () => ReturnType = () => args ? setup(...args as Parameters) : setup() - const nuxtAppCtx = getNuxtAppCtx(nuxt._name) + const nuxtAppCtx = getNuxtAppCtx(nuxt._id) if (import.meta.server) { return nuxt.vueApp.runWithContext(() => nuxtAppCtx.callAsync(nuxt as NuxtApp, fn)) } else { @@ -512,13 +521,13 @@ export function callWithNuxt any> (nuxt: NuxtApp | * @since 3.10.0 */ export function tryUseNuxtApp (): NuxtApp | null -export function tryUseNuxtApp (appName?: string): NuxtApp | null { +export function tryUseNuxtApp (id?: string): NuxtApp | null { let nuxtAppInstance if (hasInjectionContext()) { nuxtAppInstance = getCurrentInstance()?.appContext.app.$nuxt } - nuxtAppInstance = nuxtAppInstance || getNuxtAppCtx(appName).tryUse() + nuxtAppInstance = nuxtAppInstance || getNuxtAppCtx(id).tryUse() return nuxtAppInstance || null } @@ -531,9 +540,9 @@ export function tryUseNuxtApp (appName?: string): NuxtApp | null { * @since 3.0.0 */ export function useNuxtApp (): NuxtApp -export function useNuxtApp (appName?: string): NuxtApp { - // @ts-expect-error internal usage of appName - const nuxtAppInstance = tryUseNuxtApp(appName) +export function useNuxtApp (id?: string): NuxtApp { + // @ts-expect-error internal usage of id + const nuxtAppInstance = tryUseNuxtApp(id) if (!nuxtAppInstance) { if (import.meta.dev) { diff --git a/packages/schema/src/config/common.ts b/packages/schema/src/config/common.ts index 267f315f1a..ad8e5f20b0 100644 --- a/packages/schema/src/config/common.ts +++ b/packages/schema/src/config/common.ts @@ -179,7 +179,9 @@ export default defineUntypedSchema({ }, /** - * For multi-app projects, the unique name of the Nuxt application. + * For multi-app projects, the unique id of the Nuxt application. + * + * Defaults to `nuxt-app`. */ appId: { $resolve: (val: string) => val ?? 'nuxt-app',