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.
- package/dist/components/memo.d.ts +1 -3
- package/dist/components/memo.d.ts.map +1 -1
- package/dist/components/memo.js +2 -2
- package/dist/components/memo.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +1 -23
- package/dist/context.js.map +1 -1
- package/dist/dom.d.ts.map +1 -1
- package/dist/dom.js +109 -72
- package/dist/dom.js.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +2 -4
- package/dist/error.js.map +1 -1
- package/dist/form/index.d.ts.map +1 -1
- package/dist/form/index.js +6 -10
- package/dist/form/index.js.map +1 -1
- package/dist/globals.d.ts +1 -1
- package/dist/globals.d.ts.map +1 -1
- package/dist/globals.js.map +1 -1
- package/dist/hmr.d.ts +1 -0
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +11 -3
- package/dist/hmr.js.map +1 -1
- package/dist/hooks/useEffectEvent.d.ts.map +1 -1
- package/dist/hooks/useEffectEvent.js.map +1 -1
- package/dist/hooks/usePromise.d.ts.map +1 -1
- package/dist/hooks/usePromise.js.map +1 -1
- package/dist/hooks/utils.d.ts.map +1 -1
- package/dist/hooks/utils.js +10 -10
- package/dist/hooks/utils.js.map +1 -1
- package/dist/hydration.d.ts +6 -13
- package/dist/hydration.d.ts.map +1 -1
- package/dist/hydration.js +20 -50
- package/dist/hydration.js.map +1 -1
- package/dist/reconciler.d.ts.map +1 -1
- package/dist/reconciler.js +3 -6
- package/dist/reconciler.js.map +1 -1
- package/dist/recursiveRender.d.ts.map +1 -1
- package/dist/recursiveRender.js +9 -8
- package/dist/recursiveRender.js.map +1 -1
- package/dist/renderToString.d.ts.map +1 -1
- package/dist/renderToString.js.map +1 -1
- package/dist/router/client/index.d.ts +2 -4
- package/dist/router/client/index.d.ts.map +1 -1
- package/dist/router/client/index.js +11 -49
- package/dist/router/client/index.js.map +1 -1
- package/dist/router/context.d.ts +5 -2
- package/dist/router/context.d.ts.map +1 -1
- package/dist/router/context.js +1 -5
- package/dist/router/context.js.map +1 -1
- package/dist/router/fileRouter.d.ts.map +1 -1
- package/dist/router/fileRouter.js +2 -4
- package/dist/router/fileRouter.js.map +1 -1
- package/dist/router/fileRouterController.d.ts +2 -2
- package/dist/router/fileRouterController.d.ts.map +1 -1
- package/dist/router/fileRouterController.js +39 -101
- package/dist/router/fileRouterController.js.map +1 -1
- package/dist/router/globals.d.ts +0 -3
- package/dist/router/globals.d.ts.map +1 -1
- package/dist/router/globals.js +0 -3
- package/dist/router/globals.js.map +1 -1
- package/dist/router/head.d.ts.map +1 -1
- package/dist/router/head.js +7 -5
- package/dist/router/head.js.map +1 -1
- package/dist/router/index.d.ts +1 -2
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +1 -2
- package/dist/router/index.js.map +1 -1
- package/dist/router/link.js +3 -3
- package/dist/router/link.js.map +1 -1
- package/dist/router/{ssg → server}/index.d.ts +3 -4
- package/dist/router/server/index.d.ts.map +1 -0
- package/dist/router/{ssg → server}/index.js +5 -8
- package/dist/router/server/index.js.map +1 -0
- package/dist/router/types.d.ts +4 -37
- package/dist/router/types.d.ts.map +1 -1
- package/dist/router/types.internal.d.ts +0 -4
- package/dist/router/types.internal.d.ts.map +1 -1
- package/dist/router/utils/index.d.ts +3 -8
- package/dist/router/utils/index.d.ts.map +1 -1
- package/dist/router/utils/index.js +8 -40
- package/dist/router/utils/index.js.map +1 -1
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +60 -53
- package/dist/scheduler.js.map +1 -1
- package/dist/signals/base.d.ts +0 -2
- package/dist/signals/base.d.ts.map +1 -1
- package/dist/signals/base.js +0 -6
- package/dist/signals/base.js.map +1 -1
- package/dist/signals/computed.d.ts +3 -0
- package/dist/signals/computed.d.ts.map +1 -1
- package/dist/signals/computed.js +29 -20
- package/dist/signals/computed.js.map +1 -1
- package/dist/signals/for.d.ts +3 -3
- package/dist/signals/for.d.ts.map +1 -1
- package/dist/signals/for.js +2 -1
- package/dist/signals/for.js.map +1 -1
- package/dist/signals/utils.d.ts.map +1 -1
- package/dist/signals/utils.js +2 -1
- package/dist/signals/utils.js.map +1 -1
- package/dist/signals/watch.d.ts.map +1 -1
- package/dist/signals/watch.js +18 -22
- package/dist/signals/watch.js.map +1 -1
- package/dist/ssr/client.d.ts +1 -1
- package/dist/ssr/client.d.ts.map +1 -1
- package/dist/ssr/client.js +0 -2
- package/dist/ssr/client.js.map +1 -1
- package/dist/ssr/server.d.ts +2 -1
- package/dist/ssr/server.d.ts.map +1 -1
- package/dist/ssr/server.js +19 -16
- package/dist/ssr/server.js.map +1 -1
- package/dist/types.d.ts +0 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.dom.d.ts +3 -3
- package/dist/types.dom.d.ts.map +1 -1
- package/dist/utils/format.d.ts +1 -2
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js +1 -4
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/runtime.d.ts +3 -2
- package/dist/utils/runtime.d.ts.map +1 -1
- package/dist/utils/runtime.js +5 -2
- package/dist/utils/runtime.js.map +1 -1
- package/dist/utils/vdom.d.ts.map +1 -1
- package/dist/utils/vdom.js +2 -2
- package/dist/utils/vdom.js.map +1 -1
- package/package.json +4 -8
- package/src/components/memo.ts +3 -11
- package/src/context.ts +1 -24
- package/src/dom.ts +145 -96
- package/src/error.ts +2 -4
- package/src/form/index.ts +6 -9
- package/src/globals.ts +1 -1
- package/src/hmr.ts +14 -5
- package/src/hooks/useEffectEvent.ts +0 -1
- package/src/hooks/usePromise.ts +0 -1
- package/src/hooks/utils.ts +12 -12
- package/src/hydration.ts +21 -57
- package/src/reconciler.ts +2 -6
- package/src/recursiveRender.ts +10 -9
- package/src/renderToString.ts +0 -1
- package/src/router/client/index.ts +14 -100
- package/src/router/context.ts +6 -7
- package/src/router/fileRouter.ts +2 -6
- package/src/router/fileRouterController.ts +39 -159
- package/src/router/globals.ts +0 -4
- package/src/router/head.ts +7 -5
- package/src/router/index.ts +1 -12
- package/src/router/link.ts +3 -3
- package/src/router/{ssg → server}/index.ts +10 -17
- package/src/router/types.internal.ts +0 -5
- package/src/router/types.ts +4 -48
- package/src/router/utils/index.ts +16 -79
- package/src/scheduler.ts +83 -70
- package/src/signals/base.ts +0 -8
- package/src/signals/computed.ts +30 -18
- package/src/signals/for.ts +15 -10
- package/src/signals/utils.ts +2 -1
- package/src/signals/watch.ts +27 -22
- package/src/ssr/client.ts +1 -4
- package/src/ssr/server.ts +21 -20
- package/src/types.dom.ts +4 -5
- package/src/types.ts +0 -10
- package/src/utils/format.ts +0 -5
- package/src/utils/runtime.ts +6 -2
- package/src/utils/vdom.ts +2 -7
- package/dist/router/guard.d.ts +0 -17
- package/dist/router/guard.d.ts.map +0 -1
- package/dist/router/guard.js +0 -45
- package/dist/router/guard.js.map +0 -1
- package/dist/router/ssg/index.d.ts.map +0 -1
- package/dist/router/ssg/index.js.map +0 -1
- package/dist/router/ssr/index.d.ts +0 -20
- package/dist/router/ssr/index.d.ts.map +0 -1
- package/dist/router/ssr/index.js +0 -160
- package/dist/router/ssr/index.js.map +0 -1
- package/src/router/guard.ts +0 -72
- 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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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(
|
|
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 =
|
|
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(
|
package/src/router/globals.ts
CHANGED
package/src/router/head.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Signal } from "../signals/base.js"
|
|
2
|
-
import { isValidTextChild, isVNode
|
|
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 =
|
|
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
|
|
33
|
-
const titleNode =
|
|
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 =
|
|
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))
|
package/src/router/index.ts
CHANGED
|
@@ -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"
|
package/src/router/link.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
18
|
+
pages: FormattedViteImportMap
|
|
22
19
|
layouts: FormattedViteImportMap
|
|
23
|
-
guards: FormattedViteImportMap<GuardModule>
|
|
24
20
|
Document: Kiru.FC
|
|
25
21
|
registerModule: (moduleId: string) => void
|
|
26
|
-
|
|
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 =
|
|
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.
|
|
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
|
}
|
package/src/router/types.ts
CHANGED
|
@@ -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
|
|
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:
|
|
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>
|