kiru 0.54.0-preview.0 → 0.54.0

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.
Files changed (178) hide show
  1. package/dist/components/memo.d.ts +1 -3
  2. package/dist/components/memo.d.ts.map +1 -1
  3. package/dist/components/memo.js +2 -2
  4. package/dist/components/memo.js.map +1 -1
  5. package/dist/context.d.ts.map +1 -1
  6. package/dist/context.js +1 -23
  7. package/dist/context.js.map +1 -1
  8. package/dist/dom.d.ts.map +1 -1
  9. package/dist/dom.js +109 -72
  10. package/dist/dom.js.map +1 -1
  11. package/dist/error.d.ts.map +1 -1
  12. package/dist/error.js +2 -4
  13. package/dist/error.js.map +1 -1
  14. package/dist/form/index.d.ts.map +1 -1
  15. package/dist/form/index.js +6 -10
  16. package/dist/form/index.js.map +1 -1
  17. package/dist/globals.d.ts +1 -1
  18. package/dist/globals.d.ts.map +1 -1
  19. package/dist/globals.js.map +1 -1
  20. package/dist/hmr.d.ts +1 -0
  21. package/dist/hmr.d.ts.map +1 -1
  22. package/dist/hmr.js +11 -3
  23. package/dist/hmr.js.map +1 -1
  24. package/dist/hooks/useEffectEvent.d.ts.map +1 -1
  25. package/dist/hooks/useEffectEvent.js.map +1 -1
  26. package/dist/hooks/usePromise.d.ts.map +1 -1
  27. package/dist/hooks/usePromise.js.map +1 -1
  28. package/dist/hooks/utils.d.ts.map +1 -1
  29. package/dist/hooks/utils.js +10 -10
  30. package/dist/hooks/utils.js.map +1 -1
  31. package/dist/hydration.d.ts +6 -13
  32. package/dist/hydration.d.ts.map +1 -1
  33. package/dist/hydration.js +20 -50
  34. package/dist/hydration.js.map +1 -1
  35. package/dist/reconciler.d.ts.map +1 -1
  36. package/dist/reconciler.js +3 -6
  37. package/dist/reconciler.js.map +1 -1
  38. package/dist/recursiveRender.d.ts.map +1 -1
  39. package/dist/recursiveRender.js +9 -8
  40. package/dist/recursiveRender.js.map +1 -1
  41. package/dist/renderToString.d.ts.map +1 -1
  42. package/dist/renderToString.js.map +1 -1
  43. package/dist/router/client/index.d.ts +2 -4
  44. package/dist/router/client/index.d.ts.map +1 -1
  45. package/dist/router/client/index.js +11 -49
  46. package/dist/router/client/index.js.map +1 -1
  47. package/dist/router/context.d.ts +5 -2
  48. package/dist/router/context.d.ts.map +1 -1
  49. package/dist/router/context.js +1 -5
  50. package/dist/router/context.js.map +1 -1
  51. package/dist/router/fileRouter.d.ts.map +1 -1
  52. package/dist/router/fileRouter.js +2 -4
  53. package/dist/router/fileRouter.js.map +1 -1
  54. package/dist/router/fileRouterController.d.ts +2 -2
  55. package/dist/router/fileRouterController.d.ts.map +1 -1
  56. package/dist/router/fileRouterController.js +39 -101
  57. package/dist/router/fileRouterController.js.map +1 -1
  58. package/dist/router/globals.d.ts +0 -3
  59. package/dist/router/globals.d.ts.map +1 -1
  60. package/dist/router/globals.js +0 -3
  61. package/dist/router/globals.js.map +1 -1
  62. package/dist/router/head.d.ts.map +1 -1
  63. package/dist/router/head.js +7 -5
  64. package/dist/router/head.js.map +1 -1
  65. package/dist/router/index.d.ts +1 -2
  66. package/dist/router/index.d.ts.map +1 -1
  67. package/dist/router/index.js +1 -2
  68. package/dist/router/index.js.map +1 -1
  69. package/dist/router/link.js +3 -3
  70. package/dist/router/link.js.map +1 -1
  71. package/dist/router/{ssg → server}/index.d.ts +3 -4
  72. package/dist/router/server/index.d.ts.map +1 -0
  73. package/dist/router/{ssg → server}/index.js +5 -8
  74. package/dist/router/server/index.js.map +1 -0
  75. package/dist/router/types.d.ts +4 -37
  76. package/dist/router/types.d.ts.map +1 -1
  77. package/dist/router/types.internal.d.ts +0 -4
  78. package/dist/router/types.internal.d.ts.map +1 -1
  79. package/dist/router/utils/index.d.ts +3 -8
  80. package/dist/router/utils/index.d.ts.map +1 -1
  81. package/dist/router/utils/index.js +8 -40
  82. package/dist/router/utils/index.js.map +1 -1
  83. package/dist/scheduler.d.ts.map +1 -1
  84. package/dist/scheduler.js +60 -53
  85. package/dist/scheduler.js.map +1 -1
  86. package/dist/signals/base.d.ts +0 -2
  87. package/dist/signals/base.d.ts.map +1 -1
  88. package/dist/signals/base.js +0 -6
  89. package/dist/signals/base.js.map +1 -1
  90. package/dist/signals/computed.d.ts +3 -0
  91. package/dist/signals/computed.d.ts.map +1 -1
  92. package/dist/signals/computed.js +29 -20
  93. package/dist/signals/computed.js.map +1 -1
  94. package/dist/signals/for.d.ts +3 -3
  95. package/dist/signals/for.d.ts.map +1 -1
  96. package/dist/signals/for.js +2 -1
  97. package/dist/signals/for.js.map +1 -1
  98. package/dist/signals/utils.d.ts.map +1 -1
  99. package/dist/signals/utils.js +2 -1
  100. package/dist/signals/utils.js.map +1 -1
  101. package/dist/signals/watch.d.ts.map +1 -1
  102. package/dist/signals/watch.js +18 -22
  103. package/dist/signals/watch.js.map +1 -1
  104. package/dist/ssr/client.d.ts +1 -1
  105. package/dist/ssr/client.d.ts.map +1 -1
  106. package/dist/ssr/client.js +0 -2
  107. package/dist/ssr/client.js.map +1 -1
  108. package/dist/ssr/server.d.ts +2 -1
  109. package/dist/ssr/server.d.ts.map +1 -1
  110. package/dist/ssr/server.js +19 -16
  111. package/dist/ssr/server.js.map +1 -1
  112. package/dist/types.d.ts +0 -7
  113. package/dist/types.d.ts.map +1 -1
  114. package/dist/types.dom.d.ts +3 -3
  115. package/dist/types.dom.d.ts.map +1 -1
  116. package/dist/utils/format.d.ts +1 -2
  117. package/dist/utils/format.d.ts.map +1 -1
  118. package/dist/utils/format.js +1 -4
  119. package/dist/utils/format.js.map +1 -1
  120. package/dist/utils/runtime.d.ts +3 -2
  121. package/dist/utils/runtime.d.ts.map +1 -1
  122. package/dist/utils/runtime.js +5 -2
  123. package/dist/utils/runtime.js.map +1 -1
  124. package/dist/utils/vdom.d.ts.map +1 -1
  125. package/dist/utils/vdom.js +2 -2
  126. package/dist/utils/vdom.js.map +1 -1
  127. package/package.json +4 -8
  128. package/src/components/memo.ts +3 -11
  129. package/src/context.ts +1 -24
  130. package/src/dom.ts +145 -96
  131. package/src/error.ts +2 -4
  132. package/src/form/index.ts +6 -9
  133. package/src/globals.ts +1 -1
  134. package/src/hmr.ts +14 -5
  135. package/src/hooks/useEffectEvent.ts +0 -1
  136. package/src/hooks/usePromise.ts +0 -1
  137. package/src/hooks/utils.ts +12 -12
  138. package/src/hydration.ts +21 -57
  139. package/src/reconciler.ts +2 -6
  140. package/src/recursiveRender.ts +10 -9
  141. package/src/renderToString.ts +0 -1
  142. package/src/router/client/index.ts +14 -100
  143. package/src/router/context.ts +6 -7
  144. package/src/router/fileRouter.ts +2 -6
  145. package/src/router/fileRouterController.ts +39 -159
  146. package/src/router/globals.ts +0 -4
  147. package/src/router/head.ts +7 -5
  148. package/src/router/index.ts +1 -12
  149. package/src/router/link.ts +3 -3
  150. package/src/router/{ssg → server}/index.ts +10 -17
  151. package/src/router/types.internal.ts +0 -5
  152. package/src/router/types.ts +4 -48
  153. package/src/router/utils/index.ts +16 -79
  154. package/src/scheduler.ts +83 -70
  155. package/src/signals/base.ts +0 -8
  156. package/src/signals/computed.ts +30 -18
  157. package/src/signals/for.ts +15 -10
  158. package/src/signals/utils.ts +2 -1
  159. package/src/signals/watch.ts +27 -22
  160. package/src/ssr/client.ts +1 -4
  161. package/src/ssr/server.ts +21 -20
  162. package/src/types.dom.ts +4 -5
  163. package/src/types.ts +0 -10
  164. package/src/utils/format.ts +0 -5
  165. package/src/utils/runtime.ts +6 -2
  166. package/src/utils/vdom.ts +2 -7
  167. package/dist/router/guard.d.ts +0 -17
  168. package/dist/router/guard.d.ts.map +0 -1
  169. package/dist/router/guard.js +0 -45
  170. package/dist/router/guard.js.map +0 -1
  171. package/dist/router/ssg/index.d.ts.map +0 -1
  172. package/dist/router/ssg/index.js.map +0 -1
  173. package/dist/router/ssr/index.d.ts +0 -20
  174. package/dist/router/ssr/index.d.ts.map +0 -1
  175. package/dist/router/ssr/index.js +0 -160
  176. package/dist/router/ssr/index.js.map +0 -1
  177. package/src/router/guard.ts +0 -72
  178. package/src/router/ssr/index.ts +0 -247
@@ -2,15 +2,9 @@ import { Signal } from "../signals/base.js"
2
2
  import { watch } from "../signals/watch.js"
3
3
  import { __DEV__ } from "../env.js"
4
4
  import { flushSync, nextIdle } from "../scheduler.js"
5
- import { toArray } from "../utils/format.js"
6
5
  import { ReloadOptions, type FileRouterContextType } from "./context.js"
7
6
  import { FileRouterDataLoadError } from "./errors.js"
8
- import {
9
- fileRouterInstance,
10
- fileRouterRoute,
11
- requestContext,
12
- routerCache,
13
- } from "./globals.js"
7
+ import { fileRouterInstance, fileRouterRoute, routerCache } from "./globals.js"
14
8
  import type {
15
9
  FileRouterConfig,
16
10
  PageConfig,
@@ -23,22 +17,17 @@ import type {
23
17
  CurrentPage,
24
18
  DevtoolsInterface,
25
19
  FormattedViteImportMap,
26
- GuardModule,
27
20
  PageModule,
28
21
  ViteImportMap,
29
22
  } from "./types.internal.js"
30
23
  import {
31
24
  formatViteImportMap,
32
- matchModules,
25
+ matchLayouts,
33
26
  matchRoute,
34
27
  match404Route,
35
28
  normalizePrefixPath,
36
29
  parseQuery,
37
30
  wrapWithLayouts,
38
- runAfterEachGuards,
39
- runBeforeEachGuards,
40
- runBeforeEnterHooks,
41
- runBeforeLeaveHooks,
42
31
  } from "./utils/index.js"
43
32
  import { RouterCache, type CacheKey } from "./cache.js"
44
33
  import { scrollStack } from "./scrollStack.js"
@@ -66,9 +55,9 @@ export class FileRouterController {
66
55
  private historyIndex: number
67
56
  private layouts: FormattedViteImportMap
68
57
  private pages: FormattedViteImportMap<PageModule>
69
- private guards: FormattedViteImportMap<GuardModule>
70
58
  private pageRouteToConfig?: Map<string, PageConfig>
71
59
  private state: RouterState
60
+ private baseUrl = "/"
72
61
 
73
62
  constructor() {
74
63
  routerCache.current ??= new RouterCache()
@@ -80,7 +69,6 @@ export class FileRouterController {
80
69
  this.historyIndex = 0
81
70
  this.layouts = {}
82
71
  this.pages = {}
83
- this.guards = {}
84
72
  this.state = {
85
73
  pathname: window.location.pathname,
86
74
  hash: window.location.hash,
@@ -88,27 +76,7 @@ export class FileRouterController {
88
76
  query: {},
89
77
  signal: this.abortController.signal,
90
78
  }
91
- const __this = this
92
- this.contextValue = {
93
- invalidate: async (...paths: string[]) => {
94
- if (this.invalidate(...paths)) {
95
- return this.loadRoute(void 0, void 0, true)
96
- }
97
- },
98
- get state() {
99
- return { ...__this.state }
100
- },
101
- navigate: this.navigate.bind(this),
102
- prefetchRouteModules: this.prefetchRouteModules.bind(this),
103
- reload: async (options?: ReloadOptions) => {
104
- if (options?.invalidate ?? true) {
105
- this.invalidate(this.state.pathname)
106
- }
107
- return this.loadRoute(void 0, void 0, options?.transition)
108
- },
109
- setQuery: this.setQuery.bind(this),
110
- setHash: this.setHash.bind(this),
111
- }
79
+ this.contextValue = this.createContextValue()
112
80
  if (__DEV__) {
113
81
  this.filePathToPageRoute = new Map()
114
82
  this.pageRouteToConfig = new Map()
@@ -200,7 +168,6 @@ export class FileRouterController {
200
168
  const {
201
169
  pages,
202
170
  layouts,
203
- guards,
204
171
  dir = "/pages",
205
172
  baseUrl = "/",
206
173
  transition,
@@ -211,12 +178,12 @@ export class FileRouterController {
211
178
  normalizePrefixPath(dir),
212
179
  normalizePrefixPath(baseUrl),
213
180
  ]
181
+ this.baseUrl = normalizedBaseUrl.slice(0, -1)
214
182
 
215
183
  if (preloaded) {
216
184
  const {
217
185
  pages,
218
186
  layouts,
219
- guards,
220
187
  page,
221
188
  pageProps,
222
189
  pageLayouts,
@@ -241,8 +208,6 @@ export class FileRouterController {
241
208
  this.currentLayouts.value = pageLayouts.map((l) => l.default)
242
209
  this.pages = pages
243
210
  this.layouts = layouts
244
- this.guards = (guards ??
245
- {}) as unknown as FormattedViteImportMap<GuardModule>
246
211
  if (__DEV__) {
247
212
  if (page.config) {
248
213
  this.dev_onPageConfigDefined!(route, page.config)
@@ -290,14 +255,6 @@ export class FileRouterController {
290
255
  normalizedDir,
291
256
  normalizedBaseUrl
292
257
  )
293
- this.guards = !guards
294
- ? {}
295
- : (formatViteImportMap(
296
- guards as ViteImportMap,
297
- normalizedDir,
298
- normalizedBaseUrl
299
- ) as unknown as FormattedViteImportMap<GuardModule>)
300
-
301
258
  if (__DEV__) {
302
259
  validateRoutes(this.pages)
303
260
  }
@@ -340,31 +297,10 @@ export class FileRouterController {
340
297
  window.history.scrollRestoration = "auto"
341
298
  })
342
299
 
343
- let ignorePopState = false
344
-
345
300
  window.addEventListener("popstate", (e) => {
346
301
  e.preventDefault()
347
-
348
- if (
349
- !ignorePopState &&
350
- this.onBeforeLeave(window.location.pathname) === false
351
- ) {
352
- ignorePopState = true
353
- if (e.state !== null) {
354
- if (e.state.index > this.historyIndex) {
355
- window.history.go(-1)
356
- } else if (e.state.index < this.historyIndex) {
357
- window.history.go(1)
358
- }
359
- }
360
- return
361
- }
362
- if (ignorePopState) {
363
- ignorePopState = false
364
- return
365
- }
366
-
367
302
  scrollStack.replace(this.historyIndex, window.scrollX, window.scrollY)
303
+
368
304
  this.loadRoute().then(() => {
369
305
  if (e.state != null) {
370
306
  this.historyIndex = e.state.index
@@ -377,31 +313,6 @@ export class FileRouterController {
377
313
  })
378
314
  }
379
315
 
380
- private onBeforeLeave(to: string) {
381
- const currentPage = this.currentPage.peek()
382
- if (!currentPage) {
383
- return true
384
- }
385
-
386
- let config = currentPage.config ?? ({} as PageConfig)
387
- if (__DEV__) {
388
- if (this.pageRouteToConfig?.has(currentPage.route)) {
389
- config = this.pageRouteToConfig.get(currentPage.route)!
390
- }
391
- }
392
-
393
- const onBeforeLeave = config.hooks?.onBeforeLeave
394
- if (onBeforeLeave) {
395
- return runBeforeLeaveHooks(
396
- toArray(onBeforeLeave),
397
- { ...requestContext.current },
398
- to,
399
- this.state.pathname
400
- )
401
- }
402
- return true
403
- }
404
-
405
316
  public getChildren() {
406
317
  const page = this.currentPage.value
407
318
  if (!page) return null
@@ -452,38 +363,10 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
452
363
 
453
364
  const { route, pageEntry, params, routeSegments } = routeMatch
454
365
 
455
- // Apply beforeEach guards before loading route
456
- const guardEntries = matchModules(
457
- this.guards as unknown as FormattedViteImportMap,
458
- routeSegments
459
- )
460
- const guardModules = await Promise.all(
461
- guardEntries.map(
462
- (entry) => entry.load() as unknown as Promise<GuardModule>
463
- )
464
- )
465
-
466
- const fromPath = this.state.pathname
467
- const redirectPath = await runBeforeEachGuards(
468
- guardModules,
469
- { ...requestContext.current },
470
- path,
471
- fromPath
472
- )
473
-
474
- // If redirect was requested, navigate to that path instead
475
- if (redirectPath !== null) {
476
- this.state.pathname = path
477
- return this.navigate(redirectPath, {
478
- replace: true,
479
- transition: enableTransition,
480
- })
481
- }
482
-
483
366
  fileRouterRoute.current = route
484
367
  const pagePromise = pageEntry.load()
485
368
 
486
- const layoutPromises = matchModules(this.layouts, routeSegments).map(
369
+ const layoutPromises = matchLayouts(this.layouts, routeSegments).map(
487
370
  (layoutEntry) => layoutEntry.load()
488
371
  )
489
372
 
@@ -517,23 +400,7 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
517
400
  }
518
401
  }
519
402
 
520
- const { loader, hooks } = config
521
-
522
- if (hooks?.onBeforeEnter) {
523
- const redirectPath = await runBeforeEnterHooks(
524
- toArray(hooks.onBeforeEnter),
525
- requestContext,
526
- path,
527
- fromPath
528
- )
529
- if (redirectPath) {
530
- this.state.pathname = path
531
- return this.navigate(redirectPath, {
532
- replace: true,
533
- transition: enableTransition,
534
- })
535
- }
536
- }
403
+ const { loader } = config
537
404
 
538
405
  if (loader) {
539
406
  if (loader.mode !== "static" || __DEV__) {
@@ -590,6 +457,7 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
590
457
 
591
458
  return handleStateTransition(signal, enableTransition, () => {
592
459
  this.state = routerState
460
+ this.contextValue = this.createContextValue()
593
461
  this.currentPage.value = {
594
462
  component: page.default,
595
463
  config,
@@ -599,15 +467,6 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
599
467
  this.currentLayouts.value = layouts
600
468
  .filter((m) => typeof m.default === "function")
601
469
  .map((m) => m.default)
602
-
603
- nextIdle(() => {
604
- runAfterEachGuards(
605
- guardModules,
606
- { ...requestContext.current },
607
- path,
608
- fromPath
609
- )
610
- })
611
470
  })
612
471
  } catch (error) {
613
472
  console.error("[kiru/router]: Failed to load route component:", error)
@@ -625,7 +484,7 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
625
484
 
626
485
  // Load data from loader (cache check is now done earlier in loadRoute)
627
486
  loader
628
- .load({ ...routerState, context: { ...requestContext.current } })
487
+ .load(routerState)
629
488
  .then(
630
489
  (data) => {
631
490
  // Cache the data if caching is enabled
@@ -649,7 +508,7 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
649
508
  data: null,
650
509
  error: new FileRouterDataLoadError(error),
651
510
  loading: false,
652
- } satisfies PageProps<PageConfig<unknown>>)
511
+ }) satisfies PageProps<PageConfig<unknown>>
653
512
  )
654
513
  .then((state) => {
655
514
  if (routerState.signal.aborted) return
@@ -694,9 +553,6 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
694
553
  return
695
554
  }
696
555
 
697
- if (this.onBeforeLeave(prevPath) === false) {
698
- return
699
- }
700
556
  this.updateHistoryState(path, options)
701
557
 
702
558
  this.loadRoute(
@@ -730,7 +586,7 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
730
586
  const { pageEntry, route } = routeMatch
731
587
  fileRouterRoute.current = route
732
588
  const pagePromise = pageEntry.load()
733
- const layoutPromises = matchModules(this.layouts, route.split("/")).map(
589
+ const layoutPromises = matchLayouts(this.layouts, route.split("/")).map(
734
590
  (layoutEntry) => layoutEntry.load()
735
591
  )
736
592
  await Promise.all([pagePromise, ...layoutPromises])
@@ -776,15 +632,13 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
776
632
  path
777
633
  )
778
634
  } else {
779
- const current = scrollStack.get()
780
-
781
635
  // if we've gone back and are now going forward, we need to
782
636
  // truncate the scroll stack so it doesn't just permanently grow.
783
637
  // this should keep it at the same length as the history stack.
638
+ const current = scrollStack.get()
784
639
  if (this.historyIndex < window.history.length - 1) {
785
640
  current.length = this.historyIndex
786
641
  }
787
-
788
642
  scrollStack.save([...current, [window.scrollX, window.scrollY]])
789
643
  window.history.pushState(
790
644
  { ...window.history.state, index: ++this.historyIndex },
@@ -793,6 +647,32 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
793
647
  )
794
648
  }
795
649
  }
650
+ private createContextValue() {
651
+ const __this = this
652
+ return {
653
+ get baseUrl() {
654
+ return __this.baseUrl
655
+ },
656
+ invalidate: async (...paths: string[]) => {
657
+ if (this.invalidate(...paths)) {
658
+ return this.loadRoute(void 0, void 0, true)
659
+ }
660
+ },
661
+ get state() {
662
+ return { ...__this.state }
663
+ },
664
+ navigate: this.navigate.bind(this),
665
+ prefetchRouteModules: this.prefetchRouteModules.bind(this),
666
+ reload: async (options?: ReloadOptions) => {
667
+ if (options?.invalidate ?? true) {
668
+ this.invalidate(this.state.pathname)
669
+ }
670
+ return this.loadRoute(void 0, void 0, options?.transition)
671
+ },
672
+ setQuery: this.setQuery.bind(this),
673
+ setHash: this.setHash.bind(this),
674
+ }
675
+ }
796
676
  }
797
677
 
798
678
  function buildQueryString(
@@ -12,7 +12,3 @@ export const fileRouterRoute = {
12
12
  export const routerCache = {
13
13
  current: null as RouterCache | null,
14
14
  }
15
-
16
- export const requestContext = {
17
- current: {} as Kiru.RequestContext,
18
- }
@@ -1,5 +1,5 @@
1
1
  import { Signal } from "../signals/base.js"
2
- import { isValidTextChild, isVNode, toArray } from "../utils/index.js"
2
+ import { isValidTextChild, isVNode } from "../utils/index.js"
3
3
  import { createElement } from "../element.js"
4
4
  import { __DEV__ } from "../env.js"
5
5
  import { KiruError } from "../error.js"
@@ -12,7 +12,7 @@ const validHeadChildren = ["title", "base", "link", "meta", "style", "script"]
12
12
  function HeadContent({ children }: { children: JSX.Children }): JSX.Element {
13
13
  if (__DEV__) {
14
14
  const n = node.current!
15
- const asArray = toArray(children)
15
+ const asArray = Array.isArray(children) ? children : [children]
16
16
  const invalidNodes = asArray.filter(
17
17
  (c) =>
18
18
  !isVNode(c) ||
@@ -29,14 +29,16 @@ function HeadContent({ children }: { children: JSX.Children }): JSX.Element {
29
29
  }
30
30
  }
31
31
  if ("window" in globalThis) {
32
- const c = toArray(children)
33
- const titleNode = c.find(
32
+ const asArray = Array.isArray(children) ? children : [children]
33
+ const titleNode = asArray.find(
34
34
  (c) => isVNode(c) && c.type === "title"
35
35
  ) as Kiru.VNode
36
36
 
37
37
  if (titleNode) {
38
38
  const props = titleNode.props
39
- const titleChildren = toArray(props.children)
39
+ const titleChildren = Array.isArray(props.children)
40
+ ? props.children
41
+ : [props.children]
40
42
 
41
43
  document.title = titleChildren
42
44
  .map((c) => (Signal.isSignal(c) ? c.value : c))
@@ -1,20 +1,9 @@
1
1
  import { createElement } from "../element.js"
2
2
  import { __DEV__ } from "../env.js"
3
3
 
4
- export {
5
- useRequestContext,
6
- useFileRouter,
7
- type FileRouterContextType,
8
- } from "./context.js"
4
+ export { useFileRouter, type FileRouterContextType } from "./context.js"
9
5
  export * from "./errors.js"
10
6
  export { FileRouter, type FileRouterProps } from "./fileRouter.js"
11
- export {
12
- createNavGuard,
13
- type GuardBeforeEach,
14
- type GuardAfterEach,
15
- type NavGuard,
16
- type NavGuardBuilder,
17
- } from "./guard.js"
18
7
  export * from "./link.js"
19
8
  export * from "./pageConfig.js"
20
9
  export type * from "./types.js"
@@ -37,7 +37,7 @@ export const Link: Kiru.FC<LinkProps> = ({
37
37
  prefetchJs,
38
38
  ...props
39
39
  }) => {
40
- const { navigate, prefetchRouteModules } = useFileRouter()
40
+ const { navigate, prefetchRouteModules, baseUrl } = useFileRouter()
41
41
 
42
42
  const handleMouseOver = useCallback(
43
43
  (e: Kiru.MouseEvent<HTMLAnchorElement>) => {
@@ -63,13 +63,13 @@ export const Link: Kiru.FC<LinkProps> = ({
63
63
  onclick?.(e)
64
64
  if (e.defaultPrevented) return
65
65
  e.preventDefault()
66
- navigate(to, { replace, transition })
66
+ navigate(baseUrl + to, { replace, transition })
67
67
  },
68
68
  [onclick, navigate, to, replace, transition]
69
69
  )
70
70
 
71
71
  return createElement("a", {
72
- href: to,
72
+ href: baseUrl + to,
73
73
  onclick: handleClick,
74
74
  onmouseover: handleMouseOver,
75
75
  onfocus: handleFocus,
@@ -1,29 +1,25 @@
1
1
  import { createElement, Fragment } from "../../element.js"
2
+
2
3
  import {
3
- matchModules,
4
+ matchLayouts,
4
5
  matchRoute,
5
6
  match404Route,
6
7
  parseQuery,
7
8
  wrapWithLayouts,
8
9
  } from "../utils/index.js"
9
10
  import { RouterContext } from "../context.js"
11
+ import type { PageConfig, PageProps, RouterState } from "../types.js"
12
+ import { FormattedViteImportMap, PageModule } from "../types.internal.js"
10
13
  import { __DEV__ } from "../../env.js"
11
14
  import { FileRouterDataLoadError } from "../errors.js"
12
15
  import { renderToString } from "../../renderToString.js"
13
- import type { PageConfig, PageProps, RouterState } from "../types.js"
14
- import type {
15
- FormattedViteImportMap,
16
- GuardModule,
17
- PageModule,
18
- } from "../types.internal.js"
19
16
 
20
17
  export interface RenderContext {
21
- pages: FormattedViteImportMap<PageModule>
18
+ pages: FormattedViteImportMap
22
19
  layouts: FormattedViteImportMap
23
- guards: FormattedViteImportMap<GuardModule>
24
20
  Document: Kiru.FC
25
21
  registerModule: (moduleId: string) => void
26
- registerStaticProps: (props: Record<string, unknown>) => void
22
+ registerPreloadedPageProps: (props: Record<string, unknown>) => void
27
23
  }
28
24
 
29
25
  export interface RenderResult {
@@ -68,7 +64,7 @@ export async function render(
68
64
 
69
65
  const { pageEntry, routeSegments, params } = routeMatch
70
66
  const is404Route = routeMatch.routeSegments.includes("404")
71
- const layoutEntries = matchModules(ctx.layouts, routeSegments)
67
+ const layoutEntries = matchLayouts(ctx.layouts, routeSegments)
72
68
 
73
69
  ;[pageEntry, ...layoutEntries].forEach((e) => {
74
70
  ctx.registerModule(e.filePath)
@@ -103,10 +99,7 @@ export async function render(
103
99
  }, 10000)
104
100
 
105
101
  try {
106
- const data = await config.loader.load({
107
- ...routerState,
108
- context: {},
109
- })
102
+ const data = await config.loader.load(routerState)
110
103
  props = {
111
104
  data,
112
105
  error: null,
@@ -120,7 +113,7 @@ export async function render(
120
113
  }
121
114
  } finally {
122
115
  clearTimeout(timeout)
123
- ctx.registerStaticProps({ data: props.data, error: props.error })
116
+ ctx.registerPreloadedPageProps({ data: props.data, error: props.error })
124
117
  }
125
118
  }
126
119
  }
@@ -186,7 +179,7 @@ export async function render(
186
179
  // console.log("immediate", immediate)
187
180
 
188
181
  return {
189
- status: is404Route ? 404 : result?.status ?? 200,
182
+ status: is404Route ? 404 : (result?.status ?? 200),
190
183
  body: `<!doctype html>${prePageOutlet}<body>${pageOutletContent}</body>${postPageOutlet}`,
191
184
  }
192
185
  }
@@ -1,6 +1,5 @@
1
1
  import type { FileRouterContextType } from "./context"
2
2
  import type { PageConfig } from "./types"
3
- import type { NavGuardBuilder } from "./guard"
4
3
 
5
4
  export interface CurrentPage {
6
5
  component: Kiru.FC<any>
@@ -21,10 +20,6 @@ export interface PageModule {
21
20
  >
22
21
  }
23
22
 
24
- export interface GuardModule {
25
- guard: NavGuardBuilder
26
- }
27
-
28
23
  export interface ViteImportMap {
29
24
  [fp: string]: () => Promise<DefaultComponentModule>
30
25
  }
@@ -3,14 +3,12 @@ import type { FileRouterDataLoadError } from "./errors"
3
3
  import type {
4
4
  DefaultComponentModule,
5
5
  FormattedViteImportMap,
6
- GuardModule,
7
6
  PageModule,
8
7
  } from "./types.internal"
9
8
 
10
9
  export interface FileRouterPreloadConfig {
11
- pages: FormattedViteImportMap<PageModule>
10
+ pages: FormattedViteImportMap
12
11
  layouts: FormattedViteImportMap
13
- guards?: FormattedViteImportMap<GuardModule>
14
12
  page: PageModule
15
13
  pageProps: Record<string, unknown>
16
14
  pageLayouts: DefaultComponentModule[]
@@ -42,14 +40,6 @@ export interface FileRouterConfig {
42
40
  * ```
43
41
  */
44
42
  layouts: Record<string, unknown>
45
- /**
46
- * The import map to use for loading nav guards
47
- * @example
48
- * ```tsx
49
- * <FileRouter config={{ guards: import.meta.glob("/∗∗/guard.{ts,js}"), ... }} />
50
- * ```
51
- */
52
- guards?: Record<string, unknown>
53
43
 
54
44
  /**
55
45
  * The base url to use as a prefix for route matching
@@ -108,34 +98,18 @@ export interface RouterState {
108
98
  signal: AbortSignal
109
99
  }
110
100
 
101
+ type PageDataLoaderContext = RouterState & {}
102
+
111
103
  export interface PageDataLoaderCacheConfig {
112
104
  type: "memory" | "localStorage" | "sessionStorage"
113
105
  ttl: number
114
106
  }
115
107
 
116
- interface LoaderContext extends RouterState {
117
- /**
118
- * The request context - in SSR, this is the data from the server
119
- * that's passed to the `renderPage` function
120
- * @example
121
- * ```ts
122
- * // server.ts
123
- * renderPage({ url, context: { test: 123 } })
124
- *
125
- * // page.tsx
126
- * loader: {
127
- * load: ({ context }) => context.test
128
- * }
129
- * ```
130
- */
131
- context: Kiru.RequestContext
132
- }
133
-
134
108
  export type PageDataLoaderConfig<T = unknown> = {
135
109
  /**
136
110
  * The function to load the page data
137
111
  */
138
- load: (context: LoaderContext) => Promise<T>
112
+ load: (context: PageDataLoaderContext) => Promise<T>
139
113
  } & (
140
114
  | {
141
115
  /**
@@ -175,22 +149,6 @@ export type PageDataLoaderConfig<T = unknown> = {
175
149
  }
176
150
  )
177
151
 
178
- export type NavigationHook<T> = (
179
- context: Kiru.RequestContext,
180
- to: string,
181
- from: string
182
- ) => T
183
-
184
- export type OnBeforeEnterHook = NavigationHook<
185
- string | void | Promise<string | void>
186
- >
187
- export type OnBeforeLeaveHook = NavigationHook<false | void>
188
-
189
- interface PageContextHooks {
190
- onBeforeEnter?: OnBeforeEnterHook | OnBeforeEnterHook[]
191
- onBeforeLeave?: OnBeforeLeaveHook | OnBeforeLeaveHook[]
192
- }
193
-
194
152
  export interface PageConfig<T = unknown> {
195
153
  /**
196
154
  * The loader configuration for this page
@@ -201,8 +159,6 @@ export interface PageConfig<T = unknown> {
201
159
  * returned, a page will be generated
202
160
  */
203
161
  generateStaticParams?: () => RouteParams[] | Promise<RouteParams[]>
204
-
205
- hooks?: PageContextHooks
206
162
  }
207
163
 
208
164
  export type PageProps<T extends PageConfig<any>> = T extends PageConfig<infer U>