@pyreon/router 0.12.12 → 0.12.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -242,6 +242,19 @@ interface Router<TNames extends string = string> {
242
242
  * Useful for SSR and for delaying rendering until the first route is resolved.
243
243
  */
244
244
  isReady(): Promise<void>;
245
+ /**
246
+ * Resolve `path` and prepare everything needed to render it: load any lazy
247
+ * route components into the router's cache and run the matched routes'
248
+ * loaders. After this resolves, a `RouterView` rendered against this router
249
+ * for `path` will produce final HTML synchronously — no loading fallbacks,
250
+ * no `useLoaderData()` returning `undefined`.
251
+ *
252
+ * Used by SSR/SSG to hydrate the route tree before `renderToString`.
253
+ * The router's `currentRoute` is NOT changed by `preload` — pass the path
254
+ * separately when creating the router (`createRouter({ url, ... })`) or
255
+ * call this for the same `url` you initialised the router with.
256
+ */
257
+ preload(path: string): Promise<void>;
245
258
  /** Remove all event listeners, clear caches, and abort in-flight navigations. */
246
259
  destroy(): void;
247
260
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/components.tsx","../../../src/loader.ts","../../../src/match.ts","../../../src/router.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/components.tsx","../../../src/loader.ts","../../../src/match.ts","../../../src/router.ts"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/router",
3
- "version": "0.12.12",
3
+ "version": "0.12.14",
4
4
  "description": "Official router for Pyreon",
5
5
  "homepage": "https://github.com/pyreon/pyreon/tree/main/packages/router#readme",
6
6
  "bugs": {
@@ -37,17 +37,20 @@
37
37
  "build": "vl_rolldown_build",
38
38
  "dev": "vl_rolldown_build-watch",
39
39
  "test": "vitest run",
40
+ "test:browser": "vitest run --config ./vitest.browser.config.ts",
40
41
  "typecheck": "tsc --noEmit",
41
42
  "lint": "oxlint .",
42
43
  "prepublishOnly": "bun run build"
43
44
  },
44
45
  "dependencies": {
45
- "@pyreon/core": "^0.12.12",
46
- "@pyreon/reactivity": "^0.12.12",
47
- "@pyreon/runtime-dom": "^0.12.12"
46
+ "@pyreon/core": "^0.12.14",
47
+ "@pyreon/reactivity": "^0.12.14",
48
+ "@pyreon/runtime-dom": "^0.12.14"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@happy-dom/global-registrator": "^20.8.9",
52
+ "@pyreon/test-utils": "^0.12.10",
53
+ "@vitest/browser-playwright": "^4.1.4",
51
54
  "happy-dom": "^20.8.3"
52
55
  }
53
56
  }
package/src/router.ts CHANGED
@@ -56,7 +56,7 @@ export function useRouter(): Router {
56
56
  const router = useContext(RouterContext) ?? _activeRouter
57
57
  if (!router)
58
58
  throw new Error(
59
- '[pyreon-router] No router installed. Wrap your app in <RouterProvider router={router}>.',
59
+ '[Pyreon] No router installed. Wrap your app in <RouterProvider router={router}>.',
60
60
  )
61
61
  return router
62
62
  }
@@ -68,7 +68,7 @@ export function useRoute<TPath extends string = string>(): () => ResolvedRoute<
68
68
  const router = useContext(RouterContext) ?? _activeRouter
69
69
  if (!router)
70
70
  throw new Error(
71
- '[pyreon-router] No router installed. Wrap your app in <RouterProvider router={router}>.',
71
+ '[Pyreon] No router installed. Wrap your app in <RouterProvider router={router}>.',
72
72
  )
73
73
  return router.currentRoute as never
74
74
  }
@@ -87,7 +87,7 @@ export function onBeforeRouteLeave(guard: NavigationGuard): () => void {
87
87
  const router = (useContext(RouterContext) ?? _activeRouter) as RouterInstance | null
88
88
  if (!router)
89
89
  throw new Error(
90
- '[pyreon-router] No router installed. Wrap your app in <RouterProvider router={router}>.',
90
+ '[Pyreon] No router installed. Wrap your app in <RouterProvider router={router}>.',
91
91
  )
92
92
  // Register as a global guard that only fires when leaving the current route
93
93
  const currentMatched = router.currentRoute().matched
@@ -116,7 +116,7 @@ export function onBeforeRouteUpdate(guard: NavigationGuard): () => void {
116
116
  const router = (useContext(RouterContext) ?? _activeRouter) as RouterInstance | null
117
117
  if (!router)
118
118
  throw new Error(
119
- '[pyreon-router] No router installed. Wrap your app in <RouterProvider router={router}>.',
119
+ '[Pyreon] No router installed. Wrap your app in <RouterProvider router={router}>.',
120
120
  )
121
121
  const currentMatched = router.currentRoute().matched
122
122
  const wrappedGuard: NavigationGuard = (to, from) => {
@@ -148,7 +148,7 @@ export function useBlocker(fn: BlockerFn): Blocker {
148
148
  const router = (useContext(RouterContext) ?? _activeRouter) as RouterInstance | null
149
149
  if (!router)
150
150
  throw new Error(
151
- '[pyreon-router] No router installed. Wrap your app in <RouterProvider router={router}>.',
151
+ '[Pyreon] No router installed. Wrap your app in <RouterProvider router={router}>.',
152
152
  )
153
153
  router._blockers.add(fn)
154
154
 
@@ -207,7 +207,7 @@ export function useIsActive(path: string, exact = false): () => boolean {
207
207
  const router = (useContext(RouterContext) ?? _activeRouter) as RouterInstance | null
208
208
  if (!router)
209
209
  throw new Error(
210
- '[pyreon-router] No router installed. Wrap your app in <RouterProvider router={router}>.',
210
+ '[Pyreon] No router installed. Wrap your app in <RouterProvider router={router}>.',
211
211
  )
212
212
  return () => {
213
213
  const current = router.currentRoute().path
@@ -331,7 +331,7 @@ function _getRouter(): RouterInstance {
331
331
  const router = (useContext(RouterContext) ?? _activeRouter) as RouterInstance | null
332
332
  if (!router)
333
333
  throw new Error(
334
- '[pyreon-router] No router installed. Wrap your app in <RouterProvider router={router}>.',
334
+ '[Pyreon] No router installed. Wrap your app in <RouterProvider router={router}>.',
335
335
  )
336
336
  return router
337
337
  }
@@ -428,19 +428,17 @@ export function createRouter(options: RouterOptions | RouteRecord[]): Router {
428
428
  const currentPath = signal(normalizeTrailingSlash(getInitialLocation(), trailingSlash))
429
429
  const currentRoute = computed<ResolvedRoute>(() => resolveRoute(currentPath(), routes))
430
430
 
431
- // Browser event listeners — stored so destroy() can remove them
432
- let _popstateHandler: (() => void) | null = null
433
- let _hashchangeHandler: (() => void) | null = null
431
+ // Browser event listeners — stored so destroy() can remove them.
432
+ // Ternary-bound on `_isBrowser` (a typeof-derived const) so the lint rule
433
+ // can trace these to an SSR-safe shape without needing `if (_isBrowser &&
434
+ // handler)` contortions at every use site.
435
+ const _popstateHandler: (() => void) | null =
436
+ _isBrowser && mode === 'history' ? () => currentPath.set(getCurrentLocation()) : null
437
+ const _hashchangeHandler: (() => void) | null =
438
+ _isBrowser && mode !== 'history' ? () => currentPath.set(getCurrentLocation()) : null
434
439
 
435
- if (_isBrowser) {
436
- if (mode === 'history') {
437
- _popstateHandler = () => currentPath.set(getCurrentLocation())
438
- window.addEventListener('popstate', _popstateHandler)
439
- } else {
440
- _hashchangeHandler = () => currentPath.set(getCurrentLocation())
441
- window.addEventListener('hashchange', _hashchangeHandler)
442
- }
443
- }
440
+ if (_popstateHandler) window.addEventListener('popstate', _popstateHandler)
441
+ if (_hashchangeHandler) window.addEventListener('hashchange', _hashchangeHandler)
444
442
 
445
443
  const componentCache = new Map<RouteRecord, ComponentFn>()
446
444
  const loadingSignal = signal(0)
@@ -608,12 +606,12 @@ export function createRouter(options: RouterOptions | RouteRecord[]): Router {
608
606
  return true
609
607
  }
610
608
 
611
- function commitNavigation(
609
+ async function commitNavigation(
612
610
  path: string,
613
611
  replace: boolean,
614
612
  to: ResolvedRoute,
615
613
  from: ResolvedRoute,
616
- ): void {
614
+ ): Promise<void> {
617
615
  scrollManager.save(from.path)
618
616
 
619
617
  const doCommit = () => {
@@ -638,9 +636,54 @@ export function createRouter(options: RouterOptions | RouteRecord[]): Router {
638
636
  && typeof (document as any).startViewTransition === 'function'
639
637
 
640
638
  if (useVT) {
641
- (document as any).startViewTransition(() => {
642
- doCommit()
643
- })
639
+ // `startViewTransition(cb)` runs `cb` inside an async transition. Its
640
+ // `.updateCallbackDone` promise resolves as soon as the callback
641
+ // finishes — DOM has swapped, state is live, but the fade/slide
642
+ // animation is still running. That's what `await router.push()`
643
+ // should wait for: callers need the new route live before they act
644
+ // (e.g. focus an element, inspect `location`, query a new DOM node);
645
+ // they don't want to block on the full animation (`.finished`),
646
+ // which would add 200-300ms to every programmatic navigation.
647
+ //
648
+ // Before this await, `commitNavigation` was sync: the transition
649
+ // callback ran in a later microtask, so `await router.push()`
650
+ // resolved BEFORE the DOM swap. Browser smoke tests had to opt out
651
+ // of View Transitions per-route via `meta: { viewTransition: false }`
652
+ // to stay deterministic — a flag whose only purpose was to paper
653
+ // over this bug.
654
+ type ViewTransitionLike = {
655
+ updateCallbackDone?: Promise<void>
656
+ ready?: Promise<void>
657
+ finished?: Promise<void>
658
+ }
659
+ const vt = (document as { startViewTransition?: (cb: () => void) => ViewTransitionLike | undefined })
660
+ .startViewTransition!(() => {
661
+ doCommit()
662
+ })
663
+ // `startViewTransition` may return `undefined` in test doubles
664
+ // that shim it with a bare `(cb) => cb()`. Guard accordingly.
665
+ if (vt) {
666
+ // The ViewTransition object exposes THREE promises —
667
+ // `updateCallbackDone`, `ready`, `finished`. When a newer
668
+ // `startViewTransition()` starts while this one is in flight,
669
+ // `ready` and `finished` reject with `AbortError: Transition
670
+ // was skipped`. We only need to wait on `updateCallbackDone`
671
+ // (the DOM-commit signal), but the other two MUST still be
672
+ // handled or the rejection surfaces as an unhandled promise
673
+ // rejection that breaks test runners and CI dashboards.
674
+ vt.ready?.catch(() => {})
675
+ vt.finished?.catch(() => {})
676
+ if (vt.updateCallbackDone) {
677
+ try {
678
+ await vt.updateCallbackDone
679
+ } catch {
680
+ // `updateCallbackDone` rejects if the callback itself throws.
681
+ // The DOM may be in a partial-commit state; the newer
682
+ // navigation (if any) will re-commit. Swallow so the
683
+ // navigation chain never hangs on a transition error.
684
+ }
685
+ }
686
+ }
644
687
  } else {
645
688
  doCommit()
646
689
  }
@@ -756,7 +799,7 @@ export function createRouter(options: RouterOptions | RouteRecord[]): Router {
756
799
  return
757
800
  }
758
801
 
759
- commitNavigation(path, replace, to, from)
802
+ await commitNavigation(path, replace, to, from)
760
803
  loadingSignal.update((n) => n - 1)
761
804
  }
762
805
 
@@ -861,15 +904,46 @@ export function createRouter(options: RouterOptions | RouteRecord[]): Router {
861
904
  return router._readyPromise
862
905
  },
863
906
 
907
+ async preload(path: string) {
908
+ const resolved = resolveRoute(path, routes)
909
+ // Load lazy components in parallel and populate the component cache so
910
+ // the synchronous render pass finds ready components instead of kicking
911
+ // off async imports (which would fall back to loadingComponent).
912
+ await Promise.all(
913
+ resolved.matched.map(async (record) => {
914
+ if (componentCache.has(record)) return
915
+ const raw = record.component
916
+ if (!isLazy(raw)) {
917
+ componentCache.set(record, raw)
918
+ return
919
+ }
920
+ const mod = await raw.loader()
921
+ const comp = typeof mod === 'function' ? mod : mod.default
922
+ componentCache.set(record, comp)
923
+ }),
924
+ )
925
+ // Run loaders for the matched path — uses the same code path SSR
926
+ // already relied on, so loader data ends up in `_loaderData` under the
927
+ // matched route records.
928
+ const ac = new AbortController()
929
+ router._abortController = ac
930
+ await Promise.all(
931
+ resolved.matched
932
+ .filter((r) => r.loader)
933
+ .map(async (r) => {
934
+ const data = await r.loader?.({
935
+ params: resolved.params,
936
+ query: resolved.query,
937
+ signal: ac.signal,
938
+ })
939
+ router._loaderData.set(r, data)
940
+ }),
941
+ )
942
+ },
943
+
864
944
  destroy() {
865
- if (_popstateHandler) {
866
- window.removeEventListener('popstate', _popstateHandler)
867
- _popstateHandler = null
868
- }
869
- if (_hashchangeHandler) {
870
- window.removeEventListener('hashchange', _hashchangeHandler)
871
- _hashchangeHandler = null
872
- }
945
+ if (_popstateHandler) window.removeEventListener('popstate', _popstateHandler)
946
+ if (_hashchangeHandler) window.removeEventListener('hashchange', _hashchangeHandler)
873
947
  guards.length = 0
874
948
  afterHooks.length = 0
875
949
  router._blockers.clear()
package/src/scroll.ts CHANGED
@@ -16,7 +16,11 @@ export class ScrollManager {
16
16
 
17
17
  /** Call before navigating away — saves current scroll position for `fromPath` */
18
18
  save(fromPath: string): void {
19
- // save/restore are only called from browser navigation paths (guarded by caller)
19
+ // ScrollManager methods are only invoked from browser navigation paths,
20
+ // but an explicit early-return documents the SSR-safety contract at the
21
+ // callsite (the `no-window-in-ssr` lint rule can't AST-trace indirect
22
+ // calls from router setup).
23
+ if (typeof window === 'undefined') return
20
24
  this._positions.set(fromPath, window.scrollY)
21
25
  }
22
26
 
@@ -35,6 +39,7 @@ export class ScrollManager {
35
39
  }
36
40
 
37
41
  private _applyResult(result: 'top' | 'restore' | 'none' | number, toPath: string): void {
42
+ if (typeof window === 'undefined') return
38
43
  // Hash scrolling: if the path contains #, scroll to the element
39
44
  const hashIdx = toPath.indexOf('#')
40
45
  if (hashIdx >= 0) {
@@ -1,5 +1,6 @@
1
1
  import { hydrateLoaderData, prefetchLoaderData, serializeLoaderData } from '../loader'
2
2
  import { createRouter, setActiveRouter, useIsActive, useSearchParams } from '../router'
3
+ import { lazy } from '../types'
3
4
  import type { RouteRecord, RouterInstance } from '../types'
4
5
 
5
6
  const Home = () => null
@@ -119,7 +120,7 @@ describe('useIsActive — edge cases', () => {
119
120
  })
120
121
 
121
122
  test('throws when no router installed', () => {
122
- expect(() => useIsActive('/')).toThrow('[pyreon-router] No router installed')
123
+ expect(() => useIsActive('/')).toThrow('[Pyreon] No router installed')
123
124
  })
124
125
 
125
126
  test('exact match for root path', () => {
@@ -227,7 +228,7 @@ describe('useSearchParams — edge cases', () => {
227
228
  })
228
229
 
229
230
  test('throws when no router installed', () => {
230
- expect(() => useSearchParams()).toThrow('[pyreon-router] No router installed')
231
+ expect(() => useSearchParams()).toThrow('[Pyreon] No router installed')
231
232
  })
232
233
 
233
234
  test('returns query params from current route', () => {
@@ -513,3 +514,52 @@ describe('router — staleWhileRevalidate', () => {
513
514
  expect(loaderCallCount).toBe(2)
514
515
  })
515
516
  })
517
+
518
+ describe('router.preload', () => {
519
+ test('runs loaders for the preloaded path', async () => {
520
+ let calls = 0
521
+ const routes: RouteRecord[] = [
522
+ { path: '/', component: Home },
523
+ {
524
+ path: '/u/:id',
525
+ component: User,
526
+ loader: async ({ params }) => {
527
+ calls++
528
+ return { id: params.id, name: `User ${params.id}` }
529
+ },
530
+ },
531
+ ]
532
+ const router = createRouter({ routes, url: '/' }) as RouterInstance
533
+
534
+ await router.preload('/u/7')
535
+
536
+ expect(calls).toBe(1)
537
+ expect(router._loaderData.get(routes[1] as RouteRecord)).toEqual({
538
+ id: '7',
539
+ name: 'User 7',
540
+ })
541
+ // currentRoute is unchanged — preload prepares data, doesn't navigate
542
+ expect(router.currentRoute().path).toBe('/')
543
+ })
544
+
545
+ test('loads lazy components into the cache so render is synchronous', async () => {
546
+ let lazyLoadCalls = 0
547
+ const Lazy = () => null
548
+ const routes: RouteRecord[] = [
549
+ { path: '/', component: Home },
550
+ {
551
+ path: '/lazy',
552
+ component: lazy(async () => {
553
+ lazyLoadCalls++
554
+ return Lazy
555
+ }),
556
+ },
557
+ ]
558
+ const router = createRouter({ routes, url: '/' }) as RouterInstance
559
+
560
+ await router.preload('/lazy')
561
+
562
+ expect(lazyLoadCalls).toBe(1)
563
+ expect(router._componentCache.get(routes[1] as RouteRecord)).toBe(Lazy)
564
+ })
565
+ })