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
137 lines (117 loc) · 4.12 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
import { computed, reactive, shallowRef } from 'vue'
import {
createRouter,
createWebHistory,
createMemoryHistory,
RouterLink,
NavigationGuard
} from 'vue-router'
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) {
throw result || new Error(`Route navigation aborted: ${nuxtApp.ssrContext.url}`)
}
}
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) {
const error = new Error(`Page not found: ${nuxtApp.ssrContext.url}`)
// @ts-ignore
error.statusCode = 404
nuxtApp.ssrContext.error = error
}
} catch (error) {
error.statusCode = error.statusCode || 500
nuxtApp.ssrContext.error = error
}
})
return { provide: { router } }
})