@ilha/router 0.10.3 → 0.11.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/README.md +233 -1010
- package/dist/als-key-CVxbuM3z.js +5 -0
- package/dist/als-key.d.ts +1 -0
- package/dist/codegen.d.ts +0 -2
- package/dist/{snapshot-CsEaY6h_.js → head-DpYV3bHH.js} +5 -57
- package/dist/index.d.ts +58 -340
- package/dist/index.js +700 -3
- package/dist/{plugin-DBbbaeFm.js → plugin-C3AAI3e_.js} +67 -193
- package/dist/plugin.d.ts +0 -10
- package/dist/request-scope.d.ts +2 -1
- package/dist/rsbuild.js +1 -1
- package/dist/server-island.d.ts +0 -3
- package/dist/server-island.js +47 -10
- package/dist/server-islands.d.ts +0 -3
- package/dist/snapshot-C0E2OGwL.js +55 -0
- package/dist/snapshot.d.ts +1 -0
- package/dist/{ssr-CTd2quoA.js → ssr-WA3bSsCo.js} +146 -215
- package/dist/ssr.d.ts +29 -64
- package/dist/ssr.js +2 -2
- package/dist/vite.js +1 -1
- package/oxlint.cjs +63 -241
- package/package.json +5 -7
- package/dist/server.d.ts +0 -8
- package/dist/server.js +0 -14
- package/dist/src-B5dHU24f.js +0 -2161
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const REQUEST_ALS_KEY: unique symbol;
|
package/dist/codegen.d.ts
CHANGED
|
@@ -22,8 +22,6 @@ export interface GeneratedPaths {
|
|
|
22
22
|
serverFile: string;
|
|
23
23
|
/** Client module: ?client imports, browser-optimised. `ilha:pages/client` */
|
|
24
24
|
clientFile: string;
|
|
25
|
-
/** Server-only loaders side-effect module. `ilha:loaders` */
|
|
26
|
-
loadersFile: string;
|
|
27
25
|
}
|
|
28
26
|
export declare function resolveGeneratedPaths(outDir: string): GeneratedPaths;
|
|
29
27
|
export declare function generate(pagesDir: string, outDir: string, options?: GenerateOptions): Promise<void>;
|
|
@@ -27,7 +27,10 @@ let _headAlsInit = null;
|
|
|
27
27
|
/** ESM dynamic import — Nitro/Vite SSR workers have no `require`. */
|
|
28
28
|
async function getHeadAlsAsync() {
|
|
29
29
|
if (_headAls) return _headAls;
|
|
30
|
-
if (!_headAlsInit) _headAlsInit = import(
|
|
30
|
+
if (!_headAlsInit) _headAlsInit = import(
|
|
31
|
+
/* @vite-ignore */
|
|
32
|
+
"node:async_hooks"
|
|
33
|
+
).then(({ AsyncLocalStorage }) => {
|
|
31
34
|
_headAls = new AsyncLocalStorage();
|
|
32
35
|
return _headAls;
|
|
33
36
|
});
|
|
@@ -161,10 +164,6 @@ const HEAD_ESC = {
|
|
|
161
164
|
function escapeHeadAttr(value) {
|
|
162
165
|
return String(value).replace(/[&<>"']/g, (c) => HEAD_ESC[c]);
|
|
163
166
|
}
|
|
164
|
-
/** Escape text content for inline HTML (loader error messages etc.). */
|
|
165
|
-
function escapeHtml(value) {
|
|
166
|
-
return String(value).replace(/[&<>]/g, (c) => HEAD_ESC[c]);
|
|
167
|
-
}
|
|
168
167
|
function serializeAttrs(attrs) {
|
|
169
168
|
const parts = [];
|
|
170
169
|
for (const [k, v] of Object.entries(attrs)) {
|
|
@@ -283,55 +282,4 @@ function isSafeRefreshTarget(content) {
|
|
|
283
282
|
}
|
|
284
283
|
|
|
285
284
|
//#endregion
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* Defensive parser for `data-ilha-state` / `data-ilha-props` snapshot
|
|
289
|
-
* attributes on the router side. Mirrors the core ilha guards: size cap,
|
|
290
|
-
* plain-object check, depth cap, and prototype-key stripping. Returns
|
|
291
|
-
* undefined (degrade gracefully) on any failure.
|
|
292
|
-
*/
|
|
293
|
-
const MAX_SNAPSHOT_CHARS = 262144;
|
|
294
|
-
const MAX_SNAPSHOT_DEPTH = 32;
|
|
295
|
-
const UNSAFE_SNAPSHOT_KEYS = /* @__PURE__ */ new Set([
|
|
296
|
-
"__proto__",
|
|
297
|
-
"constructor",
|
|
298
|
-
"prototype"
|
|
299
|
-
]);
|
|
300
|
-
function stripUnsafeKeys(value) {
|
|
301
|
-
if (value === null || typeof value !== "object") return;
|
|
302
|
-
if (Array.isArray(value)) {
|
|
303
|
-
for (const item of value) stripUnsafeKeys(item);
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
for (const key of Object.getOwnPropertyNames(value)) if (UNSAFE_SNAPSHOT_KEYS.has(key)) delete value[key];
|
|
307
|
-
else stripUnsafeKeys(value[key]);
|
|
308
|
-
}
|
|
309
|
-
function exceedsDepth(value, depth) {
|
|
310
|
-
if (depth > MAX_SNAPSHOT_DEPTH) return true;
|
|
311
|
-
if (value === null || typeof value !== "object") return false;
|
|
312
|
-
if (Array.isArray(value)) {
|
|
313
|
-
for (const item of value) if (exceedsDepth(item, depth + 1)) return true;
|
|
314
|
-
return false;
|
|
315
|
-
}
|
|
316
|
-
for (const key in value) {
|
|
317
|
-
if (!Object.hasOwn(value, key)) continue;
|
|
318
|
-
if (exceedsDepth(value[key], depth + 1)) return true;
|
|
319
|
-
}
|
|
320
|
-
return false;
|
|
321
|
-
}
|
|
322
|
-
function parseSnapshotAttr(raw) {
|
|
323
|
-
if (raw.length > MAX_SNAPSHOT_CHARS) return void 0;
|
|
324
|
-
let parsed;
|
|
325
|
-
try {
|
|
326
|
-
parsed = JSON.parse(raw);
|
|
327
|
-
} catch {
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return void 0;
|
|
331
|
-
if (exceedsDepth(parsed, 1)) return void 0;
|
|
332
|
-
stripUnsafeKeys(parsed);
|
|
333
|
-
return parsed;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
//#endregion
|
|
337
|
-
export { escapeHtml as a, withHeadStore as c, escapeHeadAttr as i, applyHeadEntriesToDocument as n, head as o, cssEscapeAttr as r, serializeHead as s, parseSnapshotAttr as t };
|
|
285
|
+
export { withHeadStore as i, head as n, serializeHead as r, applyHeadEntriesToDocument as t };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { Component, View } from "ilha";
|
|
2
|
+
import { type SerializedHead } from "./head";
|
|
3
3
|
import { type HttpResponseOptions } from "./http";
|
|
4
4
|
export { setHistoryMode, getHistoryMode } from "./hash";
|
|
5
5
|
export type { HistoryMode } from "./hash";
|
|
6
|
+
export { head, serializeHead } from "./head";
|
|
7
|
+
export type { HeadInput, SerializedHead } from "./head";
|
|
8
|
+
export { httpResponse, EMPTY_HEAD } from "./http";
|
|
9
|
+
export type { HttpResponseOptions } from "./http";
|
|
10
|
+
export type Page = Component;
|
|
6
11
|
export interface RouteRecord {
|
|
7
12
|
pattern: string;
|
|
8
|
-
|
|
9
|
-
/** Merged loader chain (layouts outer→inner, then page) — `undefined` if no loaders. */
|
|
10
|
-
loader?: Loader<any>;
|
|
11
|
-
/** True when the route has a server-side loader, even if the client only has a marker. */
|
|
12
|
-
hasLoader?: boolean;
|
|
13
|
+
page: Page;
|
|
13
14
|
}
|
|
14
15
|
export interface RouteSnapshot {
|
|
15
16
|
path: string;
|
|
@@ -22,154 +23,46 @@ export interface AppError {
|
|
|
22
23
|
status?: number;
|
|
23
24
|
stack?: string;
|
|
24
25
|
}
|
|
25
|
-
export
|
|
26
|
-
|
|
27
|
-
export interface LoaderContext {
|
|
28
|
-
params: Record<string, string>;
|
|
29
|
-
request: Request;
|
|
30
|
-
url: URL;
|
|
31
|
-
signal: AbortSignal;
|
|
32
|
-
/** Contribute `<head>` data for this route. Safe to call multiple times. */
|
|
33
|
-
head: (input: HeadInput) => void;
|
|
34
|
-
}
|
|
35
|
-
export type Loader<T> = (ctx: LoaderContext) => Promise<T> | T;
|
|
36
|
-
/**
|
|
37
|
-
* Identity function for declaring a loader. Exists purely as a type anchor and
|
|
38
|
-
* a marker for the Vite plugin to detect by export name.
|
|
39
|
-
*
|
|
40
|
-
* Loaders must read `ctx.params`/`ctx.url` rather than `useRoute()` — the
|
|
41
|
-
* route store still holds the previous route while a navigation's loader is
|
|
42
|
-
* in flight, so `useRoute().params()` inside a loader reads stale params.
|
|
43
|
-
*/
|
|
44
|
-
export declare function loader<T>(fn: Loader<T>): Loader<T>;
|
|
45
|
-
export declare namespace loader {
|
|
46
|
-
var client: <T>(fn: Loader<T>) => Loader<T>;
|
|
26
|
+
export interface IslandContext {
|
|
27
|
+
request?: Request;
|
|
47
28
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
value: Awaited<T>;
|
|
53
|
-
error: Error | undefined;
|
|
54
|
-
};
|
|
55
|
-
} : never;
|
|
56
|
-
type InferLoaderValue<L> = L extends Loader<infer T> ? Awaited<T> : never;
|
|
57
|
-
/**
|
|
58
|
-
* Merge multiple loader return types into a single object type.
|
|
59
|
-
* Later loaders override earlier ones on key collision — matching runtime merge.
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* type PageInput = MergeLoaders<[typeof rootLayoutLoad, typeof sectionLayoutLoad, typeof pageLoad]>;
|
|
63
|
-
*/
|
|
64
|
-
export type MergeLoaders<Ls extends readonly Loader<any>[]> = Ls extends readonly [
|
|
65
|
-
infer First extends Loader<any>,
|
|
66
|
-
...infer Rest extends readonly Loader<any>[]
|
|
67
|
-
] ? Rest extends readonly [] ? InferLoaderValue<First> : Omit<InferLoaderValue<First>, keyof MergeLoaders<Rest>> & MergeLoaders<Rest> : {};
|
|
29
|
+
export type LayoutHandler = (props: {
|
|
30
|
+
children?: View;
|
|
31
|
+
} & Record<string, unknown>) => unknown;
|
|
32
|
+
export type ErrorHandler = (error: AppError, route: RouteSnapshot) => Page | View;
|
|
68
33
|
export declare class Redirect {
|
|
69
34
|
readonly __ilhaRedirect: true;
|
|
70
35
|
readonly to: string;
|
|
71
36
|
readonly status: number;
|
|
72
37
|
constructor(to: string, status?: number);
|
|
73
38
|
}
|
|
74
|
-
export declare class
|
|
75
|
-
readonly
|
|
39
|
+
export declare class RouteError {
|
|
40
|
+
readonly __ilhaRouteError: true;
|
|
76
41
|
readonly status: number;
|
|
77
42
|
readonly message: string;
|
|
78
43
|
constructor(status: number, message: string);
|
|
79
44
|
}
|
|
80
45
|
export declare function redirect(to: string, status?: number): never;
|
|
81
46
|
export declare function error(status: number, message: string): never;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
* collision (page loader overrides layout loader for the same key). All loaders
|
|
85
|
-
* run concurrently within a chain since they share the same abort signal and
|
|
86
|
-
* request — re-fetching is cheap with a request-scoped cache (future work).
|
|
87
|
-
*
|
|
88
|
-
* For v1 we run them in parallel via `Promise.all`. If a loader throws a
|
|
89
|
-
* `Redirect` or `LoaderError`, the composed loader re-throws it unchanged.
|
|
90
|
-
*/
|
|
91
|
-
export declare function composeLoaders<Ls extends readonly Loader<any>[]>(loaders: Ls): Loader<MergeLoaders<Ls>>;
|
|
92
|
-
export declare function wrapLayout(layout: LayoutHandler, page: Island<any>): Island<any>;
|
|
93
|
-
export declare function wrapError(handler: ErrorHandler, page: Island<any>): Island<any>;
|
|
47
|
+
export declare function wrapLayout(layout: LayoutHandler, page: Page): Page;
|
|
48
|
+
export declare function wrapError(handler: ErrorHandler, page: Page): Page;
|
|
94
49
|
export declare function defineLayout(layout: LayoutHandler): LayoutHandler;
|
|
95
50
|
export interface NavigateOptions {
|
|
96
51
|
replace?: boolean;
|
|
97
|
-
/**
|
|
98
|
-
* When `false`, keep the current scroll position instead of scrolling to the
|
|
99
|
-
* top (or to the URL hash target) after navigation. Default: `true`.
|
|
100
|
-
*/
|
|
101
52
|
scroll?: boolean;
|
|
102
53
|
}
|
|
103
54
|
export type RouterMode = "spa" | "static";
|
|
104
55
|
export interface RouterOptions {
|
|
105
|
-
/**
|
|
106
|
-
* Client navigation mode.
|
|
107
|
-
* - `spa` — full route graph, SSR/hydration, client-side navigation.
|
|
108
|
-
* - `static` — no route graph bundled; hydrate islands on the current
|
|
109
|
-
* pre-rendered page only.
|
|
110
|
-
* Default: `spa`.
|
|
111
|
-
*/
|
|
112
56
|
mode?: RouterMode;
|
|
113
|
-
/**
|
|
114
|
-
* When `true` (default), internal `<a>` clicks are intercepted and handled
|
|
115
|
-
* by the client router. Set to `false` for MPA-style behavior where links
|
|
116
|
-
* perform full document navigations.
|
|
117
|
-
* Only meaningful in `spa` mode; ignored in `static` mode.
|
|
118
|
-
* Default: `true`.
|
|
119
|
-
*/
|
|
120
57
|
interceptLinks?: boolean;
|
|
121
|
-
/**
|
|
122
|
-
* Island rendered when no route matches the current URL — both on the
|
|
123
|
-
* server (with a 404 status) and in the client `RouterView`.
|
|
124
|
-
*/
|
|
125
|
-
notFound?: Island<any>;
|
|
126
|
-
/**
|
|
127
|
-
* Allow loader `redirect()` targets pointing at other origins. When `false`
|
|
128
|
-
* (default), absolute cross-origin redirect targets are rejected with a 500
|
|
129
|
-
* — redirect targets frequently carry user input (`?next=` params), and
|
|
130
|
-
* rejecting external targets by default prevents open redirects.
|
|
131
|
-
*/
|
|
132
58
|
allowExternalRedirects?: boolean;
|
|
133
|
-
/**
|
|
134
|
-
* Abort a route loader after this many milliseconds during SSR / loader
|
|
135
|
-
* endpoint execution. `0`/`undefined` disables the timeout. The loader's
|
|
136
|
-
* `ctx.signal` also aborts when the incoming `Request`'s signal aborts.
|
|
137
|
-
*/
|
|
138
|
-
loaderTimeout?: number;
|
|
139
|
-
/**
|
|
140
|
-
* Wrap client-side view swaps in `document.startViewTransition()` when the
|
|
141
|
-
* browser supports it (falls back to an instant swap otherwise).
|
|
142
|
-
* Default: `false`.
|
|
143
|
-
*/
|
|
144
59
|
viewTransitions?: boolean;
|
|
145
|
-
|
|
146
|
-
export interface HydratableRenderOptions extends Partial<Omit<HydratableOptions, "name">> {
|
|
147
|
-
/**
|
|
148
|
-
* Base `<head>` data merged before loader and render-time contributions, so
|
|
149
|
-
* route-level head overrides it. Used by host entries rendering routes server-side
|
|
150
|
-
* to supply app-wide title/meta/scripts.
|
|
151
|
-
*/
|
|
152
|
-
baseHead?: HeadInput;
|
|
153
|
-
}
|
|
154
|
-
export interface HydrateOptions {
|
|
155
|
-
root?: Element;
|
|
156
|
-
target?: string | Element;
|
|
157
|
-
/**
|
|
158
|
-
* When `true` (default), internal `<a>` clicks are intercepted for
|
|
159
|
-
* client-side navigation. Set to `false` for MPA-style full-page navigations.
|
|
160
|
-
*/
|
|
161
|
-
interceptLinks?: boolean;
|
|
60
|
+
notFound?: Page;
|
|
162
61
|
}
|
|
163
62
|
export interface MountOptions {
|
|
164
63
|
hydrate?: boolean;
|
|
165
|
-
registry?: Record<string, Island<any>>;
|
|
166
|
-
/**
|
|
167
|
-
* When `true` (default), internal `<a>` clicks are intercepted for
|
|
168
|
-
* client-side navigation. Set to `false` for MPA-style full-page navigations.
|
|
169
|
-
*/
|
|
170
64
|
interceptLinks?: boolean;
|
|
171
65
|
}
|
|
172
|
-
/** Response envelope returned by `renderResponse` — lets the host app handle redirects. */
|
|
173
66
|
export type RenderResponse = {
|
|
174
67
|
kind: "html";
|
|
175
68
|
html: string;
|
|
@@ -186,147 +79,49 @@ export type RenderResponse = {
|
|
|
186
79
|
html: string;
|
|
187
80
|
head?: SerializedHead;
|
|
188
81
|
};
|
|
82
|
+
export interface RespondOptions extends HttpResponseOptions {
|
|
83
|
+
timeout?: number;
|
|
84
|
+
snapshot?: boolean;
|
|
85
|
+
markers?: boolean;
|
|
86
|
+
shell?: (head: SerializedHead, html: string) => string;
|
|
87
|
+
}
|
|
189
88
|
export interface RouterBuilder {
|
|
190
|
-
|
|
191
|
-
* Register a route. The optional `loader` is the merged loader chain
|
|
192
|
-
* (layout loaders outer→inner followed by the page loader) produced by
|
|
193
|
-
* the FS-routing codegen.
|
|
194
|
-
*/
|
|
195
|
-
route(pattern: string, island: Island<any>, loader?: Loader<any>): RouterBuilder;
|
|
196
|
-
/**
|
|
197
|
-
* Attach (or replace) a loader on an already-registered route pattern.
|
|
198
|
-
* Used by the `ilha:loaders` virtual module to wire server-only loaders
|
|
199
|
-
* onto the client-safe `pageRouter` at SSR time. No-op if the pattern
|
|
200
|
-
* was never registered via `.route()`.
|
|
201
|
-
*/
|
|
202
|
-
attachLoader(pattern: string, loader: Loader<any>): RouterBuilder;
|
|
203
|
-
/**
|
|
204
|
-
* Attach a loader that runs **in the browser** on client navigations,
|
|
205
|
-
* instead of fetching from the loader endpoint. Used by the FS-routing
|
|
206
|
-
* codegen for `loader.client` exports; also available for manual routers.
|
|
207
|
-
* When a route has both, the client loader wins on client navigations and
|
|
208
|
-
* the server loader runs during SSR. No-op if the pattern was never
|
|
209
|
-
* registered via `.route()`.
|
|
210
|
-
*/
|
|
211
|
-
clientLoader(pattern: string, loader: Loader<any>): RouterBuilder;
|
|
212
|
-
/**
|
|
213
|
-
* Attach the route's nearest `+error` boundary so **loader** errors render
|
|
214
|
-
* through it (render errors are already handled by `wrapError` inside the
|
|
215
|
-
* island). Used by the FS-routing codegen; also available for manual
|
|
216
|
-
* routers. No-op if the pattern was never registered via `.route()`.
|
|
217
|
-
*/
|
|
89
|
+
route(pattern: string, page: Page): RouterBuilder;
|
|
218
90
|
errorBoundary(pattern: string, handler: ErrorHandler): RouterBuilder;
|
|
219
|
-
/**
|
|
220
|
-
* Mark an already-registered route as having a server-side loader without
|
|
221
|
-
* importing that loader into the client bundle. Used by FS-routing codegen
|
|
222
|
-
* so SPA navigation knows to call the loader endpoint.
|
|
223
|
-
*/
|
|
224
|
-
markLoader(pattern: string): RouterBuilder;
|
|
225
|
-
/**
|
|
226
|
-
* Return a snapshot of every registered route in match order. Useful for
|
|
227
|
-
* prerenderers that need to discover the filesystem routes exposed by
|
|
228
|
-
* `pageRouter` without reaching into router internals.
|
|
229
|
-
*/
|
|
230
91
|
routes(): RouteRecord[];
|
|
231
92
|
prime(): void;
|
|
232
93
|
mount(target: string | Element, options?: MountOptions): () => void;
|
|
233
|
-
render(url: string | URL
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
* redirect sentinel, or an error sentinel.
|
|
246
|
-
*/
|
|
247
|
-
runLoader(urlOrRequest: string | URL | Request, request?: Request): Promise<{
|
|
248
|
-
kind: "data";
|
|
249
|
-
data: Record<string, unknown>;
|
|
250
|
-
head?: SerializedHead;
|
|
251
|
-
} | {
|
|
252
|
-
kind: "redirect";
|
|
253
|
-
to: string;
|
|
254
|
-
status: number;
|
|
255
|
-
} | {
|
|
256
|
-
kind: "error";
|
|
257
|
-
status: number;
|
|
258
|
-
message: string;
|
|
259
|
-
} | {
|
|
260
|
-
kind: "not-found";
|
|
261
|
-
}>;
|
|
262
|
-
/**
|
|
263
|
-
* Render a route to a ready-to-send HTTP `Response`, handling redirects,
|
|
264
|
-
* loader errors, and security headers. `request` (or a URL string) selects
|
|
265
|
-
* the route; the optional `shell` injects `head` tags into a document.
|
|
266
|
-
*/
|
|
267
|
-
respond(urlOrRequest: string | URL | Request, registry: Record<string, Island<any>>, options?: RespondOptions): Promise<Response>;
|
|
268
|
-
/**
|
|
269
|
-
* Hydrate the application - combines prime(), mount(), and router.mount() into one call.
|
|
270
|
-
* @param registry - The island registry from ilha:registry
|
|
271
|
-
* @param options - Optional root element (defaults to document.body) and router target (defaults to root)
|
|
272
|
-
* @returns Cleanup function
|
|
273
|
-
*/
|
|
274
|
-
hydrate(registry: Record<string, Island<any>>, options?: HydrateOptions): () => void;
|
|
275
|
-
/**
|
|
276
|
-
* Hydrate islands on the current pre-rendered page without mounting a route
|
|
277
|
-
* view or enabling client navigation. Intended for `static` mode: each page
|
|
278
|
-
* is a self-contained HTML file; only interactive islands need activation.
|
|
279
|
-
*/
|
|
280
|
-
hydrateStatic(registry: Record<string, Island<any>>, options?: {
|
|
94
|
+
render(url: string | URL | Request, options?: {
|
|
95
|
+
timeout?: number;
|
|
96
|
+
snapshot?: boolean;
|
|
97
|
+
markers?: boolean;
|
|
98
|
+
}): Promise<string>;
|
|
99
|
+
renderResponse(url: string | URL | Request, options?: {
|
|
100
|
+
timeout?: number;
|
|
101
|
+
snapshot?: boolean;
|
|
102
|
+
markers?: boolean;
|
|
103
|
+
}): Promise<RenderResponse>;
|
|
104
|
+
respond(url: string | URL | Request, options?: RespondOptions): Promise<Response>;
|
|
105
|
+
hydrate(options?: {
|
|
281
106
|
root?: Element;
|
|
107
|
+
interceptLinks?: boolean;
|
|
282
108
|
}): () => void;
|
|
283
109
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
* navigation) or is superseded by another prefetch.
|
|
290
|
-
*/
|
|
291
|
-
export declare function prefetch(pathWithSearch: string): void;
|
|
292
|
-
/** @internal Internal reactive route-state accessor; use the aggregate `useRoute()` for the public surface. */
|
|
293
|
-
export declare function routePath(value?: string): string;
|
|
294
|
-
/** @internal Internal reactive route-state accessor; use the aggregate `useRoute()` for the public surface. */
|
|
295
|
-
export declare function routeParams(value?: Record<string, string>): Record<string, string>;
|
|
296
|
-
/** @internal Internal reactive route-state accessor; use the aggregate `useRoute()` for the public surface. */
|
|
297
|
-
export declare function routeSearch(value?: string): string;
|
|
298
|
-
/** @internal Internal reactive route-state accessor; use the aggregate `useRoute()` for the public surface. */
|
|
299
|
-
export declare function routeHash(value?: string): string;
|
|
300
|
-
/** Reactive: `true` while a client navigation (loader fetch + view swap) is in flight. */
|
|
301
|
-
export declare function navigating(): boolean;
|
|
302
|
-
/**
|
|
303
|
-
* Re-run the current route's loader and re-render the view with fresh data —
|
|
304
|
-
* e.g. after a mutation. Resolves when the view has updated. No-op on the
|
|
305
|
-
* server or when no router is mounted.
|
|
306
|
-
*/
|
|
307
|
-
export declare function invalidate(): Promise<void>;
|
|
308
|
-
/**
|
|
309
|
-
* Context seeded for server-owned island renders. Extensible: future entries
|
|
310
|
-
* (route params, app middleware values) land here without moving call sites.
|
|
311
|
-
*/
|
|
312
|
-
export interface IslandContext {
|
|
313
|
-
/**
|
|
314
|
-
* The `Request` seeding this render, when one exists — page SSR passes the
|
|
315
|
-
* incoming request; frame renders pass a synthesized POST with forwarded
|
|
316
|
-
* identity headers (`cookie`, `authorization`, …). Absent in unscoped
|
|
317
|
-
* renders (plain `toString()` in tests).
|
|
318
|
-
*/
|
|
319
|
-
request?: Request;
|
|
110
|
+
export interface Navigation {
|
|
111
|
+
from: string;
|
|
112
|
+
to: string;
|
|
113
|
+
type: "push" | "replace" | "pop";
|
|
114
|
+
cancel?: () => void;
|
|
320
115
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
export declare function
|
|
116
|
+
type BeforeNavigateHook = (nav: Navigation & {
|
|
117
|
+
cancel: () => void;
|
|
118
|
+
}) => void;
|
|
119
|
+
type AfterNavigateHook = (nav: Navigation) => void;
|
|
120
|
+
export declare function routePath(): string;
|
|
121
|
+
export declare function routeParams(): Record<string, string>;
|
|
122
|
+
export declare function routeSearch(): string;
|
|
123
|
+
export declare function routeHash(): string;
|
|
124
|
+
export declare function navigating(): boolean;
|
|
330
125
|
export declare function useRoute(): {
|
|
331
126
|
path: typeof routePath;
|
|
332
127
|
params: typeof routeParams;
|
|
@@ -334,73 +129,20 @@ export declare function useRoute(): {
|
|
|
334
129
|
hash: typeof routeHash;
|
|
335
130
|
navigating: typeof navigating;
|
|
336
131
|
};
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
* render — preventing a mismatch morph that would destroy hydrated bindings.
|
|
341
|
-
*/
|
|
132
|
+
export declare function useContext(): {
|
|
133
|
+
request: Request | undefined;
|
|
134
|
+
};
|
|
342
135
|
export declare function prime(): void;
|
|
343
|
-
export interface Navigation {
|
|
344
|
-
/** Logical URL (path + search + hash) being navigated away from. */
|
|
345
|
-
from: string;
|
|
346
|
-
/** Logical URL being navigated to. */
|
|
347
|
-
to: string;
|
|
348
|
-
/** `"push"`/`"replace"` for programmatic navigations, `"pop"` for history traversal. */
|
|
349
|
-
type: "push" | "replace" | "pop";
|
|
350
|
-
}
|
|
351
|
-
export type BeforeNavigateHook = (nav: Navigation & {
|
|
352
|
-
cancel(): void;
|
|
353
|
-
}) => void;
|
|
354
|
-
export type AfterNavigateHook = (nav: Navigation) => void;
|
|
355
|
-
/**
|
|
356
|
-
* Run before a programmatic navigation commits. Call `nav.cancel()` to keep
|
|
357
|
-
* the current URL (e.g. unsaved-changes guards). Not invoked for browser
|
|
358
|
-
* back/forward — the URL has already changed by the time `popstate` fires.
|
|
359
|
-
* Returns an unsubscribe function.
|
|
360
|
-
*/
|
|
361
136
|
export declare function beforeNavigate(fn: BeforeNavigateHook): () => void;
|
|
362
|
-
/** Run after a navigation (push, replace, or pop) has committed. Returns an unsubscribe function. */
|
|
363
137
|
export declare function afterNavigate(fn: AfterNavigateHook): () => void;
|
|
364
138
|
export declare function navigate(to: string, opts?: NavigateOptions): void;
|
|
365
139
|
export interface LinkInterceptionOptions {
|
|
366
|
-
/**
|
|
367
|
-
* Prefetch loader data on `mouseenter` for eligible links. Links opt in via
|
|
368
|
-
* the `data-prefetch` attribute (set `data-prefetch="false"` to opt out a
|
|
369
|
-
* specific link even when the framework is configured to prefetch by default).
|
|
370
|
-
* Default: `true` — prefetches on hover for any link with `data-prefetch`.
|
|
371
|
-
*/
|
|
372
|
-
prefetch?: boolean;
|
|
373
140
|
}
|
|
374
|
-
export declare function enableLinkInterception(root?: Element | Document,
|
|
375
|
-
export declare const RouterView: Island<unknown>;
|
|
376
|
-
export declare const RouterLink: Island<{
|
|
377
|
-
href?: string;
|
|
378
|
-
label?: string;
|
|
379
|
-
}>;
|
|
141
|
+
export declare function enableLinkInterception(root?: Element | Document, _options?: LinkInterceptionOptions): () => void;
|
|
380
142
|
export interface IsActiveOptions {
|
|
381
|
-
|
|
382
|
-
* When `false`, `isActive("/docs")` also matches nested paths like
|
|
383
|
-
* `/docs/getting-started` (prefix match on the current path).
|
|
384
|
-
* Default: `true` (the matched route's pattern must equal `pattern`).
|
|
385
|
-
*/
|
|
386
|
-
exact?: boolean;
|
|
143
|
+
end?: boolean;
|
|
387
144
|
}
|
|
388
145
|
export declare function isActive(pattern: string, options?: IsActiveOptions): boolean;
|
|
389
|
-
export interface RespondOptions extends HydratableRenderOptions, HttpResponseOptions {
|
|
390
|
-
/**
|
|
391
|
-
* Wrap the rendered body with a document shell. Receives the serialized
|
|
392
|
-
* head (title/meta/link/script tags + html/body attributes) and the inner
|
|
393
|
-
* HTML; return the full document.
|
|
394
|
-
*/
|
|
395
|
-
shell?: (head: SerializedHead, html: string) => string;
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Validate a loader redirect target. Relative paths always pass; same-origin
|
|
399
|
-
* absolute URLs collapse to a path; cross-origin targets (including
|
|
400
|
-
* protocol-relative `//host` URLs) are rejected unless `allowExternal` is set.
|
|
401
|
-
* Non-http(s) schemes, backslash/control-char smuggling, and unparsable
|
|
402
|
-
* targets are always rejected.
|
|
403
|
-
*/
|
|
404
146
|
export declare function resolveRedirectTarget(to: string, base: URL, allowExternal: boolean): {
|
|
405
147
|
ok: true;
|
|
406
148
|
to: string;
|
|
@@ -408,27 +150,3 @@ export declare function resolveRedirectTarget(to: string, base: URL, allowExtern
|
|
|
408
150
|
ok: false;
|
|
409
151
|
};
|
|
410
152
|
export declare function router(options?: RouterOptions): RouterBuilder;
|
|
411
|
-
declare const _default: {
|
|
412
|
-
router: typeof router;
|
|
413
|
-
navigate: typeof navigate;
|
|
414
|
-
useRoute: typeof useRoute;
|
|
415
|
-
isActive: typeof isActive;
|
|
416
|
-
enableLinkInterception: typeof enableLinkInterception;
|
|
417
|
-
prime: typeof prime;
|
|
418
|
-
prefetch: typeof prefetch;
|
|
419
|
-
beforeNavigate: typeof beforeNavigate;
|
|
420
|
-
afterNavigate: typeof afterNavigate;
|
|
421
|
-
RouterView: Island<unknown>;
|
|
422
|
-
RouterLink: Island<{
|
|
423
|
-
href?: string;
|
|
424
|
-
label?: string;
|
|
425
|
-
}>;
|
|
426
|
-
loader: typeof loader;
|
|
427
|
-
redirect: typeof redirect;
|
|
428
|
-
error: typeof error;
|
|
429
|
-
composeLoaders: typeof composeLoaders;
|
|
430
|
-
head: typeof head;
|
|
431
|
-
};
|
|
432
|
-
export default _default;
|
|
433
|
-
export { head, serializeHead, type HeadInput, type SerializedHead } from "./head";
|
|
434
|
-
export { httpResponse, type HttpResponseOptions } from "./http";
|