Skip to content

Commit 4b8ac59

Browse files
committed
refactor: simplify new resolver to be static
1 parent ef995f4 commit 4b8ac59

File tree

12 files changed

+488
-281
lines changed

12 files changed

+488
-281
lines changed

packages/router/src/experimental/router.ts

Lines changed: 93 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,13 @@ import {
1616
type App,
1717
} from 'vue'
1818
import { RouterLink } from '../RouterLink'
19-
import { RouterView } from '../RouterView'
2019
import {
2120
NavigationType,
2221
type HistoryState,
2322
type RouterHistory,
2423
} from '../history/common'
2524
import type { PathParserOptions } from '../matcher'
26-
import {
27-
type NEW_MatcherRecordBase,
28-
type NEW_LocationResolved,
29-
type NEW_MatcherRecord,
30-
type NEW_MatcherRecordRaw,
31-
type NEW_RouterResolver,
32-
} from '../new-route-resolver/resolver'
25+
import { type NEW_LocationResolved } from '../new-route-resolver/resolver'
3326
import {
3427
parseQuery as originalParseQuery,
3528
stringifyQuery as originalStringifyQuery,
@@ -45,6 +38,7 @@ import {
4538
type RouterScrollBehavior,
4639
} from '../scrollBehavior'
4740
import type {
41+
_RouteRecordProps,
4842
NavigationGuardWithThis,
4943
NavigationHookAfter,
5044
RouteLocation,
@@ -61,8 +55,8 @@ import type {
6155
} from '../typed-routes'
6256
import {
6357
isRouteLocation,
64-
isRouteName,
6558
Lazy,
59+
RawRouteComponent,
6660
RouteLocationOptions,
6761
RouteMeta,
6862
} from '../types'
@@ -84,6 +78,10 @@ import {
8478
routerKey,
8579
routerViewLocationKey,
8680
} from '../injectionSymbols'
81+
import {
82+
EXPERIMENTAL_ResolverStatic,
83+
EXPERIMENTAL_ResolverStaticRecord,
84+
} from '../new-route-resolver/resolver-static'
8785

8886
/**
8987
* resolve, reject arguments of Promise constructor
@@ -179,30 +177,58 @@ export interface EXPERIMENTAL_RouterOptions_Base extends PathParserOptions {
179177
// linkInactiveClass?: string
180178
}
181179

180+
// TODO: is it worth to have 2 types for the undefined values?
181+
export interface EXPERIMENTAL_RouteRecordNormalized
182+
extends EXPERIMENTAL_ResolverStaticRecord {
183+
/**
184+
* Arbitrary data attached to the record.
185+
*/
186+
meta: RouteMeta
187+
188+
// TODO:
189+
redirect?: unknown
190+
191+
/**
192+
* Allow passing down params as props to the component rendered by `router-view`.
193+
*/
194+
props: Record<string, _RouteRecordProps>
195+
196+
/**
197+
* {@inheritDoc RouteRecordMultipleViews.components}
198+
*/
199+
components: Record<string, RawRouteComponent>
200+
201+
/**
202+
* Contains the original modules for lazy loaded components.
203+
* @internal
204+
*/
205+
mods: Record<string, unknown>
206+
}
207+
182208
/**
183209
* Options to initialize an experimental {@link EXPERIMENTAL_Router} instance.
184210
* @experimental
185211
*/
186212
export interface EXPERIMENTAL_RouterOptions<
187-
TMatcherRecord extends NEW_MatcherRecord
188-
> extends EXPERIMENTAL_RouterOptions_Base {
189-
/**
190-
* Initial list of routes that should be added to the router.
191-
*/
192-
routes?: Readonly<EXPERIMENTAL_RouteRecordRaw[]>
193-
213+
// TODO: probably need some generic types
214+
// TResolver extends NEW_RouterResolver_Base,
215+
>extends EXPERIMENTAL_RouterOptions_Base {
194216
/**
195217
* Matcher to use to resolve routes.
218+
*
196219
* @experimental
197220
*/
198-
resolver: NEW_RouterResolver<NEW_MatcherRecordRaw, TMatcherRecord>
221+
resolver: EXPERIMENTAL_ResolverStatic<EXPERIMENTAL_RouteRecordNormalized>
199222
}
200223

201224
/**
202225
* Router base instance.
226+
*
203227
* @experimental This version is not stable, it's meant to replace {@link Router} in the future.
204228
*/
205-
export interface EXPERIMENTAL_Router_Base<TRouteRecordRaw, TRouteRecord> {
229+
export interface EXPERIMENTAL_Router_Base<TRecord> {
230+
// NOTE: for dynamic routing we need this
231+
// <TRouteRecordRaw, TRouteRecord>
206232
/**
207233
* Current {@link RouteLocationNormalized}
208234
*/
@@ -213,31 +239,6 @@ export interface EXPERIMENTAL_Router_Base<TRouteRecordRaw, TRouteRecord> {
213239
*/
214240
listening: boolean
215241

216-
/**
217-
* Add a new {@link EXPERIMENTAL_RouteRecordRaw | route record} as the child of an existing route.
218-
*
219-
* @param parentName - Parent Route Record where `route` should be appended at
220-
* @param route - Route Record to add
221-
*/
222-
addRoute(
223-
// NOTE: it could be `keyof RouteMap` but the point of dynamic routes is not knowing the routes at build
224-
parentName: NonNullable<RouteRecordNameGeneric>,
225-
route: TRouteRecordRaw
226-
): () => void
227-
/**
228-
* Add a new {@link EXPERIMENTAL_RouteRecordRaw | route record} to the router.
229-
*
230-
* @param route - Route Record to add
231-
*/
232-
addRoute(route: TRouteRecordRaw): () => void
233-
234-
/**
235-
* Remove an existing route by its name.
236-
*
237-
* @param name - Name of the route to remove
238-
*/
239-
removeRoute(name: NonNullable<RouteRecordNameGeneric>): void
240-
241242
/**
242243
* Checks if a route with a given name exists
243244
*
@@ -248,12 +249,7 @@ export interface EXPERIMENTAL_Router_Base<TRouteRecordRaw, TRouteRecord> {
248249
/**
249250
* Get a full list of all the {@link RouteRecord | route records}.
250251
*/
251-
getRoutes(): TRouteRecord[]
252-
253-
/**
254-
* Delete all routes from the router matcher.
255-
*/
256-
clearRoutes(): void
252+
getRoutes(): TRecord[]
257253

258254
/**
259255
* Returns the {@link RouteLocation | normalized version} of a
@@ -392,65 +388,57 @@ export interface EXPERIMENTAL_Router_Base<TRouteRecordRaw, TRouteRecord> {
392388
install(app: App): void
393389
}
394390

395-
export interface EXPERIMENTAL_Router<
396-
TRouteRecordRaw, // extends NEW_MatcherRecordRaw,
397-
TRouteRecord extends NEW_MatcherRecord
398-
> extends EXPERIMENTAL_Router_Base<TRouteRecordRaw, TRouteRecord> {
391+
export interface EXPERIMENTAL_Router
392+
// TODO: dynamic routing
393+
// <
394+
// TRouteRecordRaw, // extends NEW_MatcherRecordRaw,
395+
// TRouteRecord extends NEW_MatcherRecord,
396+
// >
397+
extends EXPERIMENTAL_Router_Base<EXPERIMENTAL_RouteRecordNormalized> {
399398
/**
400399
* Original options object passed to create the Router
401400
*/
402-
readonly options: EXPERIMENTAL_RouterOptions<TRouteRecord>
403-
}
404-
405-
export interface EXPERIMENTAL_RouteRecordRaw extends NEW_MatcherRecordRaw {
406-
/**
407-
* Arbitrary data attached to the record.
408-
*/
409-
meta?: RouteMeta
410-
411-
components?: Record<string, unknown>
412-
component?: unknown
413-
414-
redirect?: unknown
415-
score: Array<number[]>
401+
readonly options: EXPERIMENTAL_RouterOptions
416402
}
417403

418-
// TODO: is it worth to have 2 types for the undefined values?
419-
export interface EXPERIMENTAL_RouteRecordNormalized
420-
extends NEW_MatcherRecordBase<EXPERIMENTAL_RouteRecordNormalized> {
421-
/**
422-
* Arbitrary data attached to the record.
423-
*/
424-
meta: RouteMeta
425-
group?: boolean
426-
score: Array<number[]>
427-
}
428-
429-
function normalizeRouteRecord(
430-
record: EXPERIMENTAL_RouteRecordRaw
431-
): EXPERIMENTAL_RouteRecordNormalized {
432-
// FIXME: implementation
433-
return {
434-
name: __DEV__ ? Symbol('anonymous route record') : Symbol(),
435-
meta: {},
436-
...record,
437-
children: (record.children || []).map(normalizeRouteRecord),
438-
}
439-
}
404+
// export interface EXPERIMENTAL_RouteRecordRaw extends NEW_MatcherRecordRaw {
405+
// /**
406+
// * Arbitrary data attached to the record.
407+
// */
408+
// meta?: RouteMeta
409+
//
410+
// components?: Record<string, unknown>
411+
// component?: unknown
412+
//
413+
// redirect?: unknown
414+
// // TODO: Not needed
415+
// score: Array<number[]>
416+
// }
417+
//
418+
//
419+
// function normalizeRouteRecord(
420+
// record: EXPERIMENTAL_RouteRecordRaw
421+
// ): EXPERIMENTAL_RouteRecordNormalized {
422+
// // FIXME: implementation
423+
// return {
424+
// name: __DEV__ ? Symbol('anonymous route record') : Symbol(),
425+
// meta: {},
426+
// ...record,
427+
// children: (record.children || []).map(normalizeRouteRecord),
428+
// }
429+
// }
440430

441431
export function experimental_createRouter(
442-
options: EXPERIMENTAL_RouterOptions<EXPERIMENTAL_RouteRecordNormalized>
443-
): EXPERIMENTAL_Router<
444-
EXPERIMENTAL_RouteRecordRaw,
445-
EXPERIMENTAL_RouteRecordNormalized
446-
> {
432+
options: EXPERIMENTAL_RouterOptions
433+
): EXPERIMENTAL_Router {
447434
const {
448435
resolver,
449436
parseQuery = originalParseQuery,
450437
stringifyQuery = originalStringifyQuery,
451438
history: routerHistory,
452439
} = options
453440

441+
// FIXME: can be removed, it was for migration purposes
454442
if (__DEV__ && !routerHistory)
455443
throw new Error(
456444
'Provide the "history" option when calling "createRouter()":' +
@@ -466,59 +454,16 @@ export function experimental_createRouter(
466454
let pendingLocation: RouteLocation = START_LOCATION_NORMALIZED
467455

468456
// leave the scrollRestoration if no scrollBehavior is provided
469-
if (isBrowser && options.scrollBehavior && 'scrollRestoration' in history) {
457+
if (isBrowser && options.scrollBehavior) {
470458
history.scrollRestoration = 'manual'
471459
}
472460

473-
function addRoute(
474-
parentOrRoute:
475-
| NonNullable<RouteRecordNameGeneric>
476-
| EXPERIMENTAL_RouteRecordRaw,
477-
route?: EXPERIMENTAL_RouteRecordRaw
478-
) {
479-
let parent: Parameters<(typeof resolver)['addMatcher']>[1] | undefined
480-
let rawRecord: EXPERIMENTAL_RouteRecordRaw
481-
482-
if (isRouteName(parentOrRoute)) {
483-
parent = resolver.getMatcher(parentOrRoute)
484-
if (__DEV__ && !parent) {
485-
warn(
486-
`Parent route "${String(
487-
parentOrRoute
488-
)}" not found when adding child route`,
489-
route
490-
)
491-
}
492-
rawRecord = route!
493-
} else {
494-
rawRecord = parentOrRoute
495-
}
496-
497-
const addedRecord = resolver.addMatcher(
498-
normalizeRouteRecord(rawRecord),
499-
parent
500-
)
501-
502-
return () => {
503-
resolver.removeMatcher(addedRecord)
504-
}
505-
}
506-
507-
function removeRoute(name: NonNullable<RouteRecordNameGeneric>) {
508-
const recordMatcher = resolver.getMatcher(name)
509-
if (recordMatcher) {
510-
resolver.removeMatcher(recordMatcher)
511-
} else if (__DEV__) {
512-
warn(`Cannot remove non-existent route "${String(name)}"`)
513-
}
514-
}
515-
516461
function getRoutes() {
517-
return resolver.getMatchers()
462+
return resolver.getRecords()
518463
}
519464

520465
function hasRoute(name: NonNullable<RouteRecordNameGeneric>): boolean {
521-
return !!resolver.getMatcher(name)
466+
return !!resolver.getRecord(name)
522467
}
523468

524469
function locationAsObject(
@@ -812,9 +757,10 @@ export function experimental_createRouter(
812757

813758
function runWithContext<T>(fn: () => T): T {
814759
const app: App | undefined = installedApps.values().next().value
760+
// FIXME: remove safeguard and ensure
815761
// TODO: remove safeguard and bump required minimum version of Vue
816762
// support Vue < 3.3
817-
return app && typeof app.runWithContext === 'function'
763+
return typeof app?.runWithContext === 'function'
818764
? app.runWithContext(fn)
819765
: fn()
820766
}
@@ -1223,16 +1169,10 @@ export function experimental_createRouter(
12231169
let started: boolean | undefined
12241170
const installedApps = new Set<App>()
12251171

1226-
const router: EXPERIMENTAL_Router<
1227-
EXPERIMENTAL_RouteRecordRaw,
1228-
EXPERIMENTAL_RouteRecordNormalized
1229-
> = {
1172+
const router: EXPERIMENTAL_Router = {
12301173
currentRoute,
12311174
listening: true,
12321175

1233-
addRoute,
1234-
removeRoute,
1235-
clearRoutes: resolver.clearMatchers,
12361176
hasRoute,
12371177
getRoutes,
12381178
resolve,
@@ -1252,9 +1192,9 @@ export function experimental_createRouter(
12521192
isReady,
12531193

12541194
install(app: App) {
1255-
const router = this
1256-
app.component('RouterLink', RouterLink)
1257-
app.component('RouterView', RouterView)
1195+
// Must be done by user for vapor variants
1196+
// app.component('RouterLink', RouterLink)
1197+
// app.component('RouterView', RouterView)
12581198

12591199
// @ts-expect-error: FIXME: refactor with new types once it's possible
12601200
app.config.globalProperties.$router = router
@@ -1293,9 +1233,8 @@ export function experimental_createRouter(
12931233
app.provide(routeLocationKey, shallowReactive(reactiveRoute))
12941234
app.provide(routerViewLocationKey, currentRoute)
12951235

1296-
const unmountApp = app.unmount
12971236
installedApps.add(app)
1298-
app.unmount = function () {
1237+
app.onUnmount(() => {
12991238
installedApps.delete(app)
13001239
// the router is not attached to an app anymore
13011240
if (installedApps.size < 1) {
@@ -1307,8 +1246,7 @@ export function experimental_createRouter(
13071246
started = false
13081247
ready = false
13091248
}
1310-
unmountApp()
1311-
}
1249+
})
13121250

13131251
// TODO: this probably needs to be updated so it can be used by vue-termui
13141252
if ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && isBrowser) {

0 commit comments

Comments
 (0)