kiru 0.51.0-preview.1 → 0.51.0-preview.2
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/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/router/cache.d.ts +71 -0
- package/dist/router/cache.d.ts.map +1 -0
- package/dist/router/cache.js +325 -0
- package/dist/router/cache.js.map +1 -0
- package/dist/router/client/index.d.ts.map +1 -1
- package/dist/router/client/index.js +15 -1
- package/dist/router/client/index.js.map +1 -1
- package/dist/router/context.d.ts +8 -0
- package/dist/router/context.d.ts.map +1 -1
- package/dist/router/context.js.map +1 -1
- package/dist/router/fileRouterController.d.ts +1 -0
- package/dist/router/fileRouterController.d.ts.map +1 -1
- package/dist/router/fileRouterController.js +124 -36
- package/dist/router/fileRouterController.js.map +1 -1
- package/dist/router/globals.d.ts +4 -0
- package/dist/router/globals.d.ts.map +1 -1
- package/dist/router/globals.js +3 -0
- package/dist/router/globals.js.map +1 -1
- package/dist/router/index.d.ts +3 -0
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +6 -0
- package/dist/router/index.js.map +1 -1
- package/dist/router/server/index.d.ts.map +1 -1
- package/dist/router/server/index.js +20 -14
- package/dist/router/server/index.js.map +1 -1
- package/dist/router/types.d.ts +31 -3
- package/dist/router/types.d.ts.map +1 -1
- package/dist/router/types.internal.d.ts +9 -8
- package/dist/router/types.internal.d.ts.map +1 -1
- package/dist/router/utils/index.d.ts +1 -6
- package/dist/router/utils/index.d.ts.map +1 -1
- package/dist/router/utils/index.js +1 -1
- package/dist/router/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +1 -0
- package/src/router/cache.ts +385 -0
- package/src/router/client/index.ts +18 -1
- package/src/router/context.ts +8 -0
- package/src/router/fileRouterController.ts +140 -47
- package/src/router/globals.ts +5 -0
- package/src/router/index.ts +8 -0
- package/src/router/server/index.ts +30 -14
- package/src/router/types.internal.ts +10 -8
- package/src/router/types.ts +43 -13
- package/src/router/utils/index.ts +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Signal } from "../signals/base.js"
|
|
2
|
-
import { flushSync } from "../scheduler.js"
|
|
2
|
+
import { flushSync, nextIdle } from "../scheduler.js"
|
|
3
3
|
import { __DEV__ } from "../env.js"
|
|
4
4
|
import { type FileRouterContextType } from "./context.js"
|
|
5
5
|
import { FileRouterDataLoadError } from "./errors.js"
|
|
6
|
-
import { fileRouterInstance, fileRouterRoute } from "./globals.js"
|
|
6
|
+
import { fileRouterInstance, fileRouterRoute, routerCache } from "./globals.js"
|
|
7
7
|
import type {
|
|
8
8
|
FileRouterConfig,
|
|
9
9
|
PageConfig,
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
parseQuery,
|
|
27
27
|
wrapWithLayouts,
|
|
28
28
|
} from "./utils/index.js"
|
|
29
|
+
import { RouterCache, type CacheKey } from "./cache.js"
|
|
29
30
|
|
|
30
31
|
interface PageConfigWithLoader<T = unknown> extends PageConfig {
|
|
31
32
|
loader: PageDataLoaderConfig<T>
|
|
@@ -34,7 +35,7 @@ interface PageConfigWithLoader<T = unknown> extends PageConfig {
|
|
|
34
35
|
export class FileRouterController {
|
|
35
36
|
public contextValue: FileRouterContextType
|
|
36
37
|
private enableTransitions: boolean
|
|
37
|
-
private pages: FormattedViteImportMap
|
|
38
|
+
private pages: FormattedViteImportMap<PageModule>
|
|
38
39
|
private layouts: FormattedViteImportMap
|
|
39
40
|
private abortController: AbortController
|
|
40
41
|
private currentPage: Signal<{
|
|
@@ -53,6 +54,7 @@ export class FileRouterController {
|
|
|
53
54
|
private pageRouteToConfig?: Map<string, PageConfig>
|
|
54
55
|
|
|
55
56
|
constructor() {
|
|
57
|
+
routerCache.current ??= new RouterCache()
|
|
56
58
|
this.enableTransitions = false
|
|
57
59
|
this.pages = {}
|
|
58
60
|
this.layouts = {}
|
|
@@ -68,6 +70,7 @@ export class FileRouterController {
|
|
|
68
70
|
}
|
|
69
71
|
const __this = this
|
|
70
72
|
this.contextValue = {
|
|
73
|
+
invalidate: this.invalidate.bind(this),
|
|
71
74
|
get state() {
|
|
72
75
|
return __this.state
|
|
73
76
|
},
|
|
@@ -114,11 +117,12 @@ export class FileRouterController {
|
|
|
114
117
|
route,
|
|
115
118
|
params,
|
|
116
119
|
query,
|
|
120
|
+
cacheData,
|
|
117
121
|
} = preloaded
|
|
118
122
|
this.state = {
|
|
119
123
|
params,
|
|
120
124
|
query,
|
|
121
|
-
path:
|
|
125
|
+
path: window.location.pathname,
|
|
122
126
|
signal: this.abortController.signal,
|
|
123
127
|
}
|
|
124
128
|
this.currentPage.value = {
|
|
@@ -139,20 +143,30 @@ export class FileRouterController {
|
|
|
139
143
|
validateRoutes(this.pages)
|
|
140
144
|
}
|
|
141
145
|
const loader = page.config?.loader
|
|
142
|
-
if (
|
|
143
|
-
if (
|
|
146
|
+
if (loader && loader.mode !== "static" && pageProps.loading === true) {
|
|
147
|
+
if (cacheData === null) {
|
|
144
148
|
this.loadRouteData(
|
|
145
149
|
page.config as PageConfigWithLoader,
|
|
146
150
|
pageProps,
|
|
147
151
|
this.state
|
|
148
152
|
)
|
|
153
|
+
} else {
|
|
154
|
+
nextIdle(() => {
|
|
155
|
+
const props = {
|
|
156
|
+
...pageProps,
|
|
157
|
+
data: cacheData.value,
|
|
158
|
+
error: null,
|
|
159
|
+
loading: false,
|
|
160
|
+
}
|
|
161
|
+
let transition = this.enableTransitions
|
|
162
|
+
if (loader.transition !== undefined) {
|
|
163
|
+
transition = loader.transition
|
|
164
|
+
}
|
|
165
|
+
handleStateTransition(this.state.signal, transition, () => {
|
|
166
|
+
this.currentPageProps.value = props
|
|
167
|
+
})
|
|
168
|
+
})
|
|
149
169
|
}
|
|
150
|
-
} else if (loader && loader.mode !== "static") {
|
|
151
|
-
this.loadRouteData(
|
|
152
|
-
page.config as PageConfigWithLoader,
|
|
153
|
-
pageProps,
|
|
154
|
-
this.state
|
|
155
|
-
)
|
|
156
170
|
}
|
|
157
171
|
} else {
|
|
158
172
|
this.pages = formatViteImportMap(
|
|
@@ -182,28 +196,55 @@ export class FileRouterController {
|
|
|
182
196
|
return
|
|
183
197
|
}
|
|
184
198
|
const curPage = this.currentPage.value
|
|
185
|
-
|
|
199
|
+
const loader = config.loader
|
|
200
|
+
if (curPage?.route === existing.route && loader) {
|
|
186
201
|
const p = this.currentPageProps.value
|
|
187
202
|
let transition = this.enableTransitions
|
|
188
|
-
if (
|
|
189
|
-
transition =
|
|
203
|
+
if (loader.mode !== "static" && loader.transition !== undefined) {
|
|
204
|
+
transition = loader.transition
|
|
190
205
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
206
|
+
|
|
207
|
+
// Check cache first if caching is enabled
|
|
208
|
+
let cachedData = null
|
|
209
|
+
if (loader.mode !== "static" && loader.cache) {
|
|
210
|
+
const cacheKey: CacheKey = {
|
|
211
|
+
path: this.state.path,
|
|
212
|
+
params: this.state.params,
|
|
213
|
+
query: this.state.query,
|
|
214
|
+
}
|
|
215
|
+
cachedData = routerCache.current!.get(cacheKey, loader.cache)
|
|
196
216
|
}
|
|
197
|
-
handleStateTransition(this.state.signal, transition, () => {
|
|
198
|
-
this.currentPageProps.value = props
|
|
199
|
-
})
|
|
200
217
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
props
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
218
|
+
if (cachedData !== null) {
|
|
219
|
+
// Use cached data immediately - no loading state needed
|
|
220
|
+
const props = {
|
|
221
|
+
...p,
|
|
222
|
+
data: cachedData.value,
|
|
223
|
+
error: null,
|
|
224
|
+
loading: false,
|
|
225
|
+
}
|
|
226
|
+
handleStateTransition(this.state.signal, transition, () => {
|
|
227
|
+
this.currentPageProps.value = props
|
|
228
|
+
})
|
|
229
|
+
} else {
|
|
230
|
+
// No cached data - show loading state and load data
|
|
231
|
+
const props = {
|
|
232
|
+
...p,
|
|
233
|
+
loading: true,
|
|
234
|
+
data: null,
|
|
235
|
+
error: null,
|
|
236
|
+
}
|
|
237
|
+
handleStateTransition(this.state.signal, transition, () => {
|
|
238
|
+
this.currentPageProps.value = props
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
this.loadRouteData(
|
|
242
|
+
config as PageConfigWithLoader,
|
|
243
|
+
props,
|
|
244
|
+
this.state,
|
|
245
|
+
transition
|
|
246
|
+
)
|
|
247
|
+
}
|
|
207
248
|
}
|
|
208
249
|
|
|
209
250
|
this.pageRouteToConfig?.set(existing.route, config)
|
|
@@ -269,7 +310,7 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
|
|
|
269
310
|
)
|
|
270
311
|
|
|
271
312
|
const [page, ...layouts] = await Promise.all([
|
|
272
|
-
pagePromise
|
|
313
|
+
pagePromise,
|
|
273
314
|
...layoutPromises,
|
|
274
315
|
])
|
|
275
316
|
|
|
@@ -301,19 +342,41 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
|
|
|
301
342
|
|
|
302
343
|
if (loader) {
|
|
303
344
|
if (loader.mode !== "static" || __DEV__) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
345
|
+
// Check cache first if caching is enabled
|
|
346
|
+
let cachedData = null
|
|
347
|
+
if (loader.mode !== "static" && loader.cache) {
|
|
348
|
+
const cacheKey: CacheKey = {
|
|
349
|
+
path: routerState.path,
|
|
350
|
+
params: routerState.params,
|
|
351
|
+
query: routerState.query,
|
|
352
|
+
}
|
|
353
|
+
cachedData = routerCache.current!.get(cacheKey, loader.cache)
|
|
354
|
+
}
|
|
310
355
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
props
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
356
|
+
if (cachedData !== null) {
|
|
357
|
+
// Use cached data immediately - no loading state needed
|
|
358
|
+
props = {
|
|
359
|
+
...props,
|
|
360
|
+
data: cachedData.value,
|
|
361
|
+
error: null,
|
|
362
|
+
loading: false,
|
|
363
|
+
} satisfies PageProps<PageConfig<unknown>>
|
|
364
|
+
} else {
|
|
365
|
+
// No cached data - show loading state and load data
|
|
366
|
+
props = {
|
|
367
|
+
...props,
|
|
368
|
+
loading: true,
|
|
369
|
+
data: null,
|
|
370
|
+
error: null,
|
|
371
|
+
} satisfies PageProps<PageConfig<unknown>>
|
|
372
|
+
|
|
373
|
+
this.loadRouteData(
|
|
374
|
+
config as PageConfigWithLoader,
|
|
375
|
+
props,
|
|
376
|
+
routerState,
|
|
377
|
+
enableTransition
|
|
378
|
+
)
|
|
379
|
+
}
|
|
317
380
|
} else {
|
|
318
381
|
const staticProps = page.__KIRU_STATIC_PROPS__?.[path]
|
|
319
382
|
if (!staticProps) {
|
|
@@ -355,15 +418,28 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
|
|
|
355
418
|
enableTransition = this.enableTransitions
|
|
356
419
|
) {
|
|
357
420
|
const { loader } = config
|
|
421
|
+
|
|
422
|
+
// Load data from loader (cache check is now done earlier in loadRoute)
|
|
358
423
|
loader
|
|
359
424
|
.load(routerState)
|
|
360
425
|
.then(
|
|
361
|
-
(data) =>
|
|
362
|
-
|
|
426
|
+
(data) => {
|
|
427
|
+
// Cache the data if caching is enabled
|
|
428
|
+
if (loader.mode !== "static" && loader.cache) {
|
|
429
|
+
const cacheKey: CacheKey = {
|
|
430
|
+
path: routerState.path,
|
|
431
|
+
params: routerState.params,
|
|
432
|
+
query: routerState.query,
|
|
433
|
+
}
|
|
434
|
+
routerCache.current!.set(cacheKey, data, loader.cache)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return {
|
|
363
438
|
data,
|
|
364
439
|
error: null,
|
|
365
440
|
loading: false,
|
|
366
|
-
} satisfies PageProps<PageConfig<unknown>>
|
|
441
|
+
} satisfies PageProps<PageConfig<unknown>>
|
|
442
|
+
},
|
|
367
443
|
(error) =>
|
|
368
444
|
({
|
|
369
445
|
data: null,
|
|
@@ -375,7 +451,7 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
|
|
|
375
451
|
if (routerState.signal.aborted) return
|
|
376
452
|
|
|
377
453
|
let transition = enableTransition
|
|
378
|
-
if (loader.transition !== undefined) {
|
|
454
|
+
if (loader.mode !== "static" && loader.transition !== undefined) {
|
|
379
455
|
transition = loader.transition
|
|
380
456
|
}
|
|
381
457
|
|
|
@@ -388,6 +464,23 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`
|
|
|
388
464
|
})
|
|
389
465
|
}
|
|
390
466
|
|
|
467
|
+
private invalidate(...paths: string[]) {
|
|
468
|
+
// Invalidate cache entries
|
|
469
|
+
routerCache.current!.invalidate(...paths)
|
|
470
|
+
|
|
471
|
+
// Check if current page matches any invalidated paths
|
|
472
|
+
const currentPath = this.state.path
|
|
473
|
+
const shouldRefresh = routerCache.current!.pathMatchesPattern(
|
|
474
|
+
currentPath,
|
|
475
|
+
paths
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
if (shouldRefresh) {
|
|
479
|
+
// Refresh the current page to get fresh data
|
|
480
|
+
this.loadRoute(currentPath, {}, this.enableTransitions)
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
391
484
|
private async navigate(
|
|
392
485
|
path: string,
|
|
393
486
|
options?: {
|
|
@@ -482,7 +575,7 @@ function validateRoutes(pageMap: FormattedViteImportMap) {
|
|
|
482
575
|
let warning = "[kiru/router]: Route conflicts detected:\n"
|
|
483
576
|
warning += routeConflicts
|
|
484
577
|
.map(([route1, route2]) => {
|
|
485
|
-
return ` - "${route1.
|
|
578
|
+
return ` - "${route1.absolutePath}" conflicts with "${route2.absolutePath}"\n`
|
|
486
579
|
})
|
|
487
580
|
.join("")
|
|
488
581
|
warning += "Routes are ordered by specificity (higher specificity wins)"
|
package/src/router/globals.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RouterCache } from "./cache"
|
|
1
2
|
import type { FileRouterController } from "./fileRouterController"
|
|
2
3
|
|
|
3
4
|
export const fileRouterInstance = {
|
|
@@ -7,3 +8,7 @@ export const fileRouterInstance = {
|
|
|
7
8
|
export const fileRouterRoute = {
|
|
8
9
|
current: null as string | null,
|
|
9
10
|
}
|
|
11
|
+
|
|
12
|
+
export const routerCache = {
|
|
13
|
+
current: null as RouterCache | null,
|
|
14
|
+
}
|
package/src/router/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createElement } from "../element.js"
|
|
2
|
+
|
|
1
3
|
export { useFileRouter, type FileRouterContextType } from "./context.js"
|
|
2
4
|
export * from "./errors.js"
|
|
3
5
|
export { FileRouter, type FileRouterProps } from "./fileRouter.js"
|
|
@@ -11,3 +13,9 @@ export const Head = {
|
|
|
11
13
|
Content,
|
|
12
14
|
Outlet,
|
|
13
15
|
}
|
|
16
|
+
|
|
17
|
+
export const Body = {
|
|
18
|
+
Outlet: function BodyOutlet() {
|
|
19
|
+
return createElement("kiru-body-outlet")
|
|
20
|
+
},
|
|
21
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createElement } from "../../element.js"
|
|
1
|
+
import { createElement, Fragment } from "../../element.js"
|
|
2
2
|
import { renderToReadableStream } from "../../ssr/server.js"
|
|
3
3
|
import {
|
|
4
4
|
matchLayouts,
|
|
@@ -72,7 +72,7 @@ export async function render(
|
|
|
72
72
|
|
|
73
73
|
if (__DEV__) {
|
|
74
74
|
;[pageEntry, ...layoutEntries].forEach((e) => {
|
|
75
|
-
ctx.registerModule(e.
|
|
75
|
+
ctx.registerModule(e.absolutePath!)
|
|
76
76
|
})
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -131,8 +131,21 @@ export async function render(
|
|
|
131
131
|
props
|
|
132
132
|
)
|
|
133
133
|
|
|
134
|
+
let { immediate: documentShell } = renderToReadableStream(
|
|
135
|
+
createElement(ctx.Document)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
if (
|
|
139
|
+
documentShell.includes("</body>") ||
|
|
140
|
+
!documentShell.includes("<kiru-body-outlet>")
|
|
141
|
+
) {
|
|
142
|
+
throw new Error(
|
|
143
|
+
"[kiru/router]: Document is expected to contain a <Body.Outlet> element. See https://kirujs.dev/docs/api/file-router#ssg"
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
134
147
|
const app = createElement(RouterContext.Provider, {
|
|
135
|
-
children:
|
|
148
|
+
children: Fragment({ children }),
|
|
136
149
|
value: {
|
|
137
150
|
state: {
|
|
138
151
|
params,
|
|
@@ -143,35 +156,38 @@ export async function render(
|
|
|
143
156
|
},
|
|
144
157
|
})
|
|
145
158
|
|
|
146
|
-
let { immediate, stream } = renderToReadableStream(app)
|
|
147
|
-
const
|
|
148
|
-
const
|
|
159
|
+
let { immediate: pageOutletContent, stream } = renderToReadableStream(app)
|
|
160
|
+
const hasHeadContent = pageOutletContent.includes("<kiru-head-content>")
|
|
161
|
+
const hasHeadOutlet = documentShell.includes("<kiru-head-outlet>")
|
|
149
162
|
|
|
150
163
|
if (hasHeadOutlet && hasHeadContent) {
|
|
151
164
|
let [preHeadContent = "", headContentInner = "", postHeadContent = ""] =
|
|
152
|
-
|
|
165
|
+
pageOutletContent.split(/<kiru-head-content>|<\/kiru-head-content>/)
|
|
153
166
|
|
|
154
|
-
|
|
167
|
+
documentShell = documentShell.replace(
|
|
155
168
|
"<kiru-head-outlet>",
|
|
156
169
|
headContentInner
|
|
157
170
|
)
|
|
158
|
-
|
|
171
|
+
pageOutletContent = `${preHeadContent}${postHeadContent}`
|
|
159
172
|
} else if (hasHeadContent) {
|
|
160
173
|
// remove head content element and everything within it
|
|
161
|
-
|
|
174
|
+
pageOutletContent = pageOutletContent.replace(
|
|
162
175
|
/<kiru-head-content>(.*?)<\/kiru-head-content>/,
|
|
163
176
|
""
|
|
164
177
|
)
|
|
165
178
|
} else if (hasHeadOutlet) {
|
|
166
179
|
// remove head outlet element and everything within it
|
|
167
|
-
|
|
180
|
+
documentShell = documentShell.replaceAll("<kiru-head-outlet>", "")
|
|
168
181
|
}
|
|
169
182
|
|
|
183
|
+
const [prePageOutlet, postPageOutlet] =
|
|
184
|
+
documentShell.split("<kiru-body-outlet>")
|
|
185
|
+
|
|
170
186
|
// console.log("immediate", immediate)
|
|
171
187
|
|
|
172
188
|
return {
|
|
173
189
|
status: is404Route ? 404 : result?.status ?? 200,
|
|
174
|
-
immediate:
|
|
190
|
+
immediate: `<!doctype html>${prePageOutlet}<body>${pageOutletContent}</body>${postPageOutlet}`,
|
|
175
191
|
stream,
|
|
176
192
|
}
|
|
177
193
|
}
|
|
@@ -190,7 +206,7 @@ export async function generateStaticPaths(pages: FormattedViteImportMap) {
|
|
|
190
206
|
|
|
191
207
|
const hasDynamic = urlSegments.some((s) => s.startsWith(":"))
|
|
192
208
|
if (!hasDynamic) {
|
|
193
|
-
results[basePath === "" ? "/" : basePath] = entry.
|
|
209
|
+
results[basePath === "" ? "/" : basePath] = entry.absolutePath
|
|
194
210
|
continue
|
|
195
211
|
}
|
|
196
212
|
try {
|
|
@@ -206,7 +222,7 @@ export async function generateStaticPaths(pages: FormattedViteImportMap) {
|
|
|
206
222
|
const value = params[key]
|
|
207
223
|
p = p.replace(`:${key}*`, value).replace(`:${key}`, value)
|
|
208
224
|
}
|
|
209
|
-
results[p] = entry.
|
|
225
|
+
results[p] = entry.absolutePath
|
|
210
226
|
}
|
|
211
227
|
} catch {}
|
|
212
228
|
}
|
|
@@ -17,18 +17,20 @@ export interface ViteImportMap {
|
|
|
17
17
|
[fp: string]: () => Promise<DefaultComponentModule>
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export interface
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
export interface FormattedViteImportMapEntry<T = DefaultComponentModule> {
|
|
21
|
+
load: () => Promise<T>
|
|
22
|
+
specificity: number
|
|
23
|
+
segments: string[]
|
|
24
|
+
absolutePath: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface FormattedViteImportMap<T = DefaultComponentModule> {
|
|
28
|
+
[key: string]: FormattedViteImportMapEntry<T>
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
export interface RouteMatch {
|
|
30
32
|
route: string
|
|
31
|
-
pageEntry:
|
|
33
|
+
pageEntry: FormattedViteImportMapEntry<PageModule>
|
|
32
34
|
params: Record<string, string>
|
|
33
35
|
routeSegments: string[]
|
|
34
36
|
}
|
package/src/router/types.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface FileRouterPreloadConfig {
|
|
|
15
15
|
params: RouteParams
|
|
16
16
|
query: RouteQuery
|
|
17
17
|
route: string
|
|
18
|
+
cacheData: null | { value: unknown }
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export interface FileRouterConfig {
|
|
@@ -91,25 +92,54 @@ export interface RouterState {
|
|
|
91
92
|
|
|
92
93
|
type PageDataLoaderContext = RouterState & {}
|
|
93
94
|
|
|
95
|
+
export interface PageDataLoaderCacheConfig {
|
|
96
|
+
type: "memory" | "localStorage" | "sessionStorage"
|
|
97
|
+
ttl: number
|
|
98
|
+
}
|
|
99
|
+
|
|
94
100
|
export type PageDataLoaderConfig<T = unknown> = {
|
|
95
101
|
/**
|
|
96
102
|
* The function to load the page data
|
|
97
103
|
*/
|
|
98
104
|
load: (context: PageDataLoaderContext) => Promise<T>
|
|
105
|
+
} & (
|
|
106
|
+
| {
|
|
107
|
+
/**
|
|
108
|
+
* The mode to use for the page data loader
|
|
109
|
+
* @default "client"
|
|
110
|
+
* @description
|
|
111
|
+
* - **static**: The page data is loaded at build time and never updated
|
|
112
|
+
* - **client**: The page data is loaded upon navigation and updated on subsequent navigations
|
|
113
|
+
*/
|
|
114
|
+
mode?: "client"
|
|
115
|
+
/**
|
|
116
|
+
* Enable transitions when swapping between "load", "error" and "data" states
|
|
117
|
+
*/
|
|
118
|
+
transition?: boolean
|
|
99
119
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Configure caching for this loader
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* cache: {
|
|
125
|
+
* type: "memory", // or "localStorage" / "sessionStorage"
|
|
126
|
+
* ttl: 1000 * 60 * 5, // 5 minutes
|
|
127
|
+
}
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
cache?: PageDataLoaderCacheConfig
|
|
131
|
+
}
|
|
132
|
+
| {
|
|
133
|
+
/**
|
|
134
|
+
* The mode to use for the page data loader
|
|
135
|
+
* @default "client"
|
|
136
|
+
* @description
|
|
137
|
+
* - **static**: The page data is loaded at build time and never updated
|
|
138
|
+
* - **client**: The page data is loaded upon navigation and updated on subsequent navigations
|
|
139
|
+
*/
|
|
140
|
+
mode: "static"
|
|
141
|
+
}
|
|
142
|
+
)
|
|
113
143
|
|
|
114
144
|
export interface PageConfig<T = unknown> {
|
|
115
145
|
/**
|