This repository has been archived by the owner on Apr 6, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
router.ts
141 lines (121 loc) · 4.18 KB
/
router.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import { computed, reactive, shallowRef } from 'vue'
import {
createRouter,
createWebHistory,
createMemoryHistory,
RouterLink,
NavigationGuard
} from 'vue-router'
import { createError } from 'h3'
import NuxtPage from './page'
import NuxtLayout from './layout'
import { callWithNuxt, defineNuxtPlugin, useRuntimeConfig } from '#app'
// @ts-ignore
import routes from '#build/routes'
// @ts-ignore
import { globalMiddleware, namedMiddleware } from '#build/middleware'
declare module 'vue' {
export interface GlobalComponents {
NuxtPage: typeof NuxtPage
NuxtLayout: typeof NuxtLayout
NuxtLink: typeof RouterLink
/** @deprecated */
NuxtNestedPage: typeof NuxtPage
/** @deprecated */
NuxtChild: typeof NuxtPage
}
}
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component('NuxtPage', NuxtPage)
nuxtApp.vueApp.component('NuxtLayout', NuxtLayout)
nuxtApp.vueApp.component('NuxtLink', RouterLink)
// TODO: remove before release - present for backwards compatibility & intentionally undocumented
nuxtApp.vueApp.component('NuxtNestedPage', NuxtPage)
nuxtApp.vueApp.component('NuxtChild', NuxtPage)
const { baseURL } = useRuntimeConfig().app
const routerHistory = process.client
? createWebHistory(baseURL)
: createMemoryHistory(baseURL)
const router = createRouter({
history: routerHistory,
routes
})
nuxtApp.vueApp.use(router)
const previousRoute = shallowRef(router.currentRoute.value)
router.afterEach((_to, from) => {
previousRoute.value = from
})
Object.defineProperty(nuxtApp.vueApp.config.globalProperties, 'previousRoute', {
get: () => previousRoute.value
})
// https://github.com/vuejs/vue-router-next/blob/master/src/router.ts#L1192-L1200
const route = {}
for (const key in router.currentRoute.value) {
route[key] = computed(() => router.currentRoute.value[key])
}
nuxtApp._route = reactive(route)
nuxtApp._middleware = nuxtApp._middleware || {
global: [],
named: {}
}
router.beforeEach(async (to, from) => {
to.meta = reactive(to.meta)
nuxtApp._processingMiddleware = true
type MiddlewareDef = string | NavigationGuard
const middlewareEntries = new Set<MiddlewareDef>([...globalMiddleware, ...nuxtApp._middleware.global])
for (const component of to.matched) {
const componentMiddleware = component.meta.middleware as MiddlewareDef | MiddlewareDef[]
if (!componentMiddleware) { continue }
if (Array.isArray(componentMiddleware)) {
for (const entry of componentMiddleware) {
middlewareEntries.add(entry)
}
} else {
middlewareEntries.add(componentMiddleware)
}
}
for (const entry of middlewareEntries) {
const middleware = typeof entry === 'string' ? nuxtApp._middleware.named[entry] || await namedMiddleware[entry]?.().then(r => r.default || r) : entry
if (process.dev && !middleware) {
console.warn(`Unknown middleware: ${entry}. Valid options are ${Object.keys(namedMiddleware).join(', ')}.`)
}
const result = await callWithNuxt(nuxtApp, middleware, [to, from])
if (process.server) {
if (result === false || result instanceof Error) {
const error = result || createError({
statusMessage: `Route navigation aborted: ${nuxtApp.ssrContext.url}`
})
nuxtApp.ssrContext.error = error
throw error
}
}
if (result || result === false) { return result }
}
})
router.afterEach(() => {
delete nuxtApp._processingMiddleware
})
nuxtApp.hook('app:created', async () => {
if (process.server) {
router.push(nuxtApp.ssrContext.url)
router.afterEach((to) => {
if (to.fullPath !== nuxtApp.ssrContext.url) {
nuxtApp.ssrContext.res.setHeader('Location', to.fullPath)
}
})
}
try {
await router.isReady()
const is404 = router.currentRoute.value.matched.length === 0
if (process.server && is404) {
throw createError({
statusCode: 404,
statusMessage: `Page not found: ${nuxtApp.ssrContext.url}`
})
}
} catch (error) {
nuxtApp.ssrContext.error = error
}
})
return { provide: { router } }
})