fix(nuxt): ensure getRouteRules works with nitro signature (#30277)

This commit is contained in:
Daniel Roe 2024-12-16 20:51:18 +00:00 committed by GitHub
parent cb169b52d5
commit 48e50c030a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 34 additions and 9 deletions

View File

@ -1,6 +1,8 @@
import type { MatcherExport, RouteMatcher } from 'radix3'
import { createMatcherFromExport, createRouter as createRadixRouter, toRouteMatcher } from 'radix3'
import { defu } from 'defu'
import type { H3Event } from 'h3'
import type { NitroRouteRules } from 'nitro/types'
import { useNuxtApp, useRuntimeConfig } from '../nuxt'
// @ts-expect-error virtual file
import { appManifest as isAppManifestEnabled } from '#build/nuxt.config.mjs'
@ -52,13 +54,18 @@ export function getAppManifest (): Promise<NuxtAppManifest> {
}
/** @since 3.7.4 */
export async function getRouteRules (url: string) {
export async function getRouteRules (event: H3Event): Promise<NitroRouteRules>
export async function getRouteRules (options: { path: string }): Promise<Record<string, any>>
/** @deprecated use `getRouteRules({ path })` instead */
export async function getRouteRules (url: string): Promise<Record<string, any>>
export async function getRouteRules (arg: string | H3Event | { path: string }) {
const path = typeof arg === 'string' ? arg : arg.path
if (import.meta.server) {
useNuxtApp().ssrContext!._preloadManifest = true
const _routeRulesMatcher = toRouteMatcher(
createRadixRouter({ routes: useRuntimeConfig().nitro!.routeRules }),
)
return defu({} as Record<string, any>, ..._routeRulesMatcher.matchAll(url).reverse())
return defu({} as Record<string, any>, ..._routeRulesMatcher.matchAll(path).reverse())
}
await getAppManifest()
if (!matcher) {
@ -66,7 +73,7 @@ export async function getRouteRules (url: string) {
return {}
}
try {
return defu({} as Record<string, any>, ...matcher.matchAll(url).reverse())
return defu({} as Record<string, any>, ...matcher.matchAll(path).reverse())
} catch (e) {
console.error('[nuxt] Error matching route rules.', e)
return {}

View File

@ -94,7 +94,7 @@ export async function isPrerendered (url = useRoute().path) {
return true
}
return nuxtApp.runWithContext(async () => {
const rules = await getRouteRules(url)
const rules = await getRouteRules({ path: url })
return !!rules.prerender && !rules.redirect
})
}

View File

@ -4,7 +4,7 @@ import { getRouteRules } from '../composables/manifest'
export default defineNuxtRouteMiddleware(async (to) => {
if (import.meta.server || import.meta.test) { return }
const rules = await getRouteRules(to.path)
const rules = await getRouteRules({ path: to.path })
if (rules.redirect) {
if (hasProtocol(rules.redirect, { acceptRelative: true })) {
window.location.href = rules.redirect

View File

@ -248,7 +248,7 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>({
const middlewareEntries = new Set<RouteGuard>([...globalMiddleware, ...nuxtApp._middleware.global])
if (isAppManifestEnabled) {
const routeRules = await nuxtApp.runWithContext(() => getRouteRules(to.path))
const routeRules = await nuxtApp.runWithContext(() => getRouteRules({ path: to.path }))
if (routeRules.appMiddleware) {
for (const key in routeRules.appMiddleware) {

View File

@ -199,7 +199,7 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
}
if (isAppManifestEnabled) {
const routeRules = await nuxtApp.runWithContext(() => getRouteRules(to.path))
const routeRules = await nuxtApp.runWithContext(() => getRouteRules({ path: to.path }))
if (routeRules.appMiddleware) {
for (const key in routeRules.appMiddleware) {

View File

@ -2,6 +2,9 @@ import { describe, expectTypeOf, it } from 'vitest'
import type { Ref, SlotsType } from 'vue'
import type { FetchError } from 'ofetch'
import type { NavigationFailure, RouteLocationNormalized, RouteLocationRaw, Router, useRouter as vueUseRouter } from 'vue-router'
import type { H3Event } from 'h3'
import { getRouteRules as getNitroRouteRules } from 'nitro/runtime'
import type { NitroRouteRules } from 'nitro/types'
import type { AppConfig, RuntimeValue, UpperSnakeCase } from 'nuxt/schema'
import { defineNuxtModule } from 'nuxt/kit'
@ -110,6 +113,21 @@ describe('API routes', () => {
})
})
describe('nitro compatible APIs', () => {
it('getRouteRules', async () => {
const a = await getRouteRules('/test')
const b = await getRouteRules({} as H3Event)
const c = getNitroRouteRules({} as H3Event)
expectTypeOf(b).toEqualTypeOf(c)
expectTypeOf(c).toEqualTypeOf<NitroRouteRules>()
expectTypeOf(a).toEqualTypeOf<Record<string, any>>()
})
it('useRuntimeConfig', () => {
useRuntimeConfig({} as H3Event)
})
})
describe('aliases', () => {
it('allows importing from path aliases', () => {
expectTypeOf(useRouter).toEqualTypeOf<typeof vueUseRouter>()

View File

@ -557,8 +557,8 @@ describe.skipIf(process.env.TEST_MANIFEST === 'manifest-off')('app manifests', (
`)
})
it('getRouteRules', async () => {
expect(await getRouteRules('/')).toMatchInlineSnapshot('{}')
expect(await getRouteRules('/pre')).toMatchInlineSnapshot(`
expect(await getRouteRules({ path: '/' })).toMatchInlineSnapshot('{}')
expect(await getRouteRules({ path: '/pre' })).toMatchInlineSnapshot(`
{
"prerender": true,
}