Skip to content

Commit

Permalink
Implement router.route
Browse files Browse the repository at this point in the history
  • Loading branch information
pleek91 committed Jan 7, 2024
1 parent a0a6888 commit db646d5
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 10 deletions.
45 changes: 45 additions & 0 deletions src/utilities/createRouter.browser.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { expect, test } from 'vitest'
import { createRouter } from '@/utilities/createRouter'
import { component } from '@/utilities/testHelpers'

test('initial route is set', () => {
const root = {
name: 'root',
component,
path: '/',
}

const { route } = createRouter([root], {
initialUrl: root.path,
})

expect(route.matched).toMatchObject(root)
})

test('throws error if route is not matched', () => {
expect(() => createRouter([])).toThrowError('not implemented')
})

test('updates the route when navigating', async () => {
const first = {
name: 'first',
component,
path: '/first',
}

const second = {
name: 'second',
component,
path: '/second',
}

const { push, route } = createRouter([first, second], {
initialUrl: first.path,
})

expect(route.matched).toMatchObject(first)

await push(second.path)

expect(route.matched).toMatchObject(second)
})
6 changes: 6 additions & 0 deletions src/utilities/createRouter.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { expect, test } from 'vitest'
import { createRouter } from '@/utilities/createRouter'

test('throws error if initial route is not set', () => {
expect(() => createRouter([])).toThrowError('initialUrl must be set if window.location is unavailable')
})
49 changes: 39 additions & 10 deletions src/utilities/createRouter.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,70 @@
import { readonly } from 'vue'
import { DeepReadonly, reactive, readonly } from 'vue'
import { Resolved, Route, RouteMethods, Routes } from '@/types'
import { createRouteMethods, createRouterNavigation, resolveRoutes, routeMatch } from '@/utilities'
import { isBrowser } from '@/utilities/isBrowser'
import { resolveRoutesRegex } from '@/utilities/resolveRoutesRegex'

type RouterOptions = {
initialUrl?: string,
}

type RouterPush = (url: string, options?: { replace: boolean }) => Promise<void>
type RouterReplace = (url: string) => Promise<void>

export type Router<
TRoutes extends Routes
> = {
routes: RouteMethods<TRoutes>,
route: Readonly<Resolved<Route>>,
route: DeepReadonly<Resolved<Route>>,
push: RouterPush,
replace: RouterReplace,
back: () => void,
forward: () => void,
go: (delta: number) => void,
}

export function createRouter<T extends Routes>(routes: T): Router<T> {
export function createRouter<T extends Routes>(routes: T, options?: RouterOptions): Router<T> {
const resolved = resolveRoutes(routes)
const resolvedWithRegex = resolveRoutesRegex(resolved)
const navigation = createRouterNavigation({
onLocationUpdate,
})

// todo: implement this
const route: Router<T>['route'] = readonly({} as any)
const route: Resolved<Route> = reactive(getInitialRoute())

async function onLocationUpdate(url: string): Promise<void> {
const match = routeMatch(resolvedWithRegex, url)
function getInitialUrl(): string {
if (options?.initialUrl) {
return options.initialUrl
}

if (isBrowser()) {
return window.location.toString()
}

throw new Error('initialUrl must be set if window.location is unavailable')
}

if (!match) {
function getInitialRoute(): Resolved<Route> {
const url = getInitialUrl()

return getRoute(url)
}

function getRoute(url: string): Resolved<Route> {
const route = routeMatch(resolvedWithRegex, url)

if (!route) {
// not found
throw 'not implemented'
}

throw 'not implemented'
return route
}

async function onLocationUpdate(url: string): Promise<void> {
const newRoute = getRoute(url)

Object.assign(route, newRoute)
}

const push: RouterPush = async (url, options) => {
Expand All @@ -48,7 +77,7 @@ export function createRouter<T extends Routes>(routes: T): Router<T> {

const router = {
routes: createRouteMethods<T>(resolved),
route,
route: readonly(route),
push,
replace,
forward: navigation.forward,
Expand Down

0 comments on commit db646d5

Please sign in to comment.