@echojs-ecosystem/router 0.1.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 +80 -0
- package/dist/index.d.ts +455 -0
- package/dist/index.js +1546 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# @echojs-ecosystem/router
|
|
4
|
+
|
|
5
|
+
**Typed SPA routing — routes as signal-backed objects, not components.**
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@echojs-ecosystem/router)
|
|
8
|
+
[](https://echojs.dev/docs/packages/router)
|
|
9
|
+
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Programmatic router for EchoJS. Syncs **URL ↔ route state** with guards, lazy loading, layouts, and Hyperdom bindings (`Link`, `NavLink`).
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **Route views** — `createRouteView`, `createLayoutView`, `createLazyRouteView`
|
|
19
|
+
- **Signal-backed state** — `$path`, `$params`, `$query`, `$activePage`, `$pending`, `$error`
|
|
20
|
+
- **Guards & redirects** — `authorizationGuard`, `guardRoute`, `redirect`, `chainRoute`
|
|
21
|
+
- **History adapters** — `browser`, `hash`, `memory`, or custom
|
|
22
|
+
- **Hyperdom** — `@echojs-ecosystem/router/hyperdom` for `Link`, `NavLink`, `createRouter`
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @echojs-ecosystem/router @echojs-ecosystem/reactivity @echojs-ecosystem/hyperdom
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { createRouteView, createRoutes, createRouter } from "@echojs-ecosystem/router";
|
|
34
|
+
|
|
35
|
+
const homePage = createRouteView({
|
|
36
|
+
name: "home",
|
|
37
|
+
view: () => "Home",
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const router = createRouter({
|
|
41
|
+
history: "browser",
|
|
42
|
+
routes: createRoutes([{ path: "/", name: "home", routeView: homePage }]),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
router.start();
|
|
46
|
+
router.go("/");
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Hyperdom
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { createRouter, NavLink } from "@echojs-ecosystem/router/hyperdom";
|
|
53
|
+
|
|
54
|
+
const router = createRouter({ history: "browser", routes });
|
|
55
|
+
router.start();
|
|
56
|
+
|
|
57
|
+
NavLink({ to: homePage, activeClass: "active", children: "Home" });
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## API
|
|
61
|
+
|
|
62
|
+
| Export | Description |
|
|
63
|
+
|--------|-------------|
|
|
64
|
+
| `createRouter` | Router instance |
|
|
65
|
+
| `createRoutes` | Route tree builder |
|
|
66
|
+
| `createRouteView` / `createLayoutView` | Page & layout views |
|
|
67
|
+
| `createLazyRouteView` | Code-split routes |
|
|
68
|
+
| `createRoute` | Legacy imperative routes |
|
|
69
|
+
| `guardRoute`, `redirect`, `chainRoute` | Route operators |
|
|
70
|
+
|
|
71
|
+
## Related packages
|
|
72
|
+
|
|
73
|
+
| Package | Role |
|
|
74
|
+
|---------|------|
|
|
75
|
+
| [`@echojs-ecosystem/url-state`](https://www.npmjs.com/package/@echojs-ecosystem/url-state) | Typed search params |
|
|
76
|
+
| [`@echojs-ecosystem/framework`](https://www.npmjs.com/package/@echojs-ecosystem/framework) | App bootstrap with router provider |
|
|
77
|
+
|
|
78
|
+
## Documentation
|
|
79
|
+
|
|
80
|
+
[echojs.dev/docs/packages/router](https://echojs.dev/docs/packages/router)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import { ReadonlySignal } from '@echojs-ecosystem/reactivity';
|
|
2
|
+
import { Child } from '@echojs-ecosystem/hyperdom';
|
|
3
|
+
import { RouterBoundQueryParams } from '@echojs-ecosystem/url-state';
|
|
4
|
+
|
|
5
|
+
type RouterHistoryKind = "browser" | "hash" | "memory";
|
|
6
|
+
type MemoryHistoryConfig = {
|
|
7
|
+
readonly type: "memory";
|
|
8
|
+
readonly initial?: string;
|
|
9
|
+
};
|
|
10
|
+
type RouterHistoryConfig = RouterHistoryKind | MemoryHistoryConfig | RouterHistory;
|
|
11
|
+
declare const resolveHistory: (config: RouterHistoryConfig) => RouterHistory;
|
|
12
|
+
|
|
13
|
+
type RouteViewConfig<P extends string = string, N extends string = string, TRouteView = AnyPage> = {
|
|
14
|
+
readonly path: P;
|
|
15
|
+
readonly name: N;
|
|
16
|
+
readonly routeView: TRouteView;
|
|
17
|
+
};
|
|
18
|
+
type RedirectConfig<P extends string = string, N extends string = string, TRoute = AnyRoute> = {
|
|
19
|
+
readonly path: P;
|
|
20
|
+
readonly name: N;
|
|
21
|
+
readonly route: TRoute;
|
|
22
|
+
readonly children?: readonly RouteTreeNode[];
|
|
23
|
+
};
|
|
24
|
+
type LayoutViewConfig<P extends string = string, N extends string = string, TLayoutView extends LayoutPage = LayoutPage> = {
|
|
25
|
+
readonly path: P;
|
|
26
|
+
readonly name: N;
|
|
27
|
+
readonly layoutView: TLayoutView;
|
|
28
|
+
readonly children: readonly RouteTreeNode[];
|
|
29
|
+
};
|
|
30
|
+
/** Discriminated route-tree node for `createRoutes()`. */
|
|
31
|
+
type RouteTreeNode = RouteViewConfig | LayoutViewConfig | RedirectConfig;
|
|
32
|
+
/** @deprecated Use RouteTreeNode */
|
|
33
|
+
type RouteTreeInput = RouteTreeNode;
|
|
34
|
+
type JoinPaths<Parent extends string, Child extends string> = Child extends "/" | "" ? Parent : Child extends `/${infer Rest}` ? Rest extends "" ? "/" : `/${Rest}` : Parent extends "/" ? `/${Child}` : `${Parent}/${Child}`;
|
|
35
|
+
type EntryPathsFrom<Parent extends string, Entries extends readonly RouteTreeBranch[]> = Entries[number] extends infer Entry ? Entry extends {
|
|
36
|
+
path: infer P extends string;
|
|
37
|
+
} ? JoinPaths<Parent, P> | (Entry extends {
|
|
38
|
+
children: infer C extends readonly RouteTreeBranch[];
|
|
39
|
+
} ? EntryPathsFrom<JoinPaths<Parent, P>, C> : never) : never : never;
|
|
40
|
+
type EntryFullPath<Entry> = Entry extends {
|
|
41
|
+
path: infer P extends string;
|
|
42
|
+
} ? Entry extends {
|
|
43
|
+
children: infer C extends readonly RouteTreeBranch[];
|
|
44
|
+
} ? JoinPaths<"/", P> | EntryPathsFrom<JoinPaths<"/", P>, C> : JoinPaths<"/", P> : never;
|
|
45
|
+
type RouteTreeBranch = RouteTreeEntry | RouteTreeNode;
|
|
46
|
+
type CollectRoutePaths<TRoutes extends readonly RouteTreeBranch[]> = TRoutes[number] extends infer Entry ? EntryFullPath<Entry> : never;
|
|
47
|
+
type UnionToIntersection<U> = (U extends unknown ? (arg: U) => void : never) extends (arg: infer I) => void ? I : never;
|
|
48
|
+
type ConfigNamed<E, T> = E extends {
|
|
49
|
+
readonly name: infer N extends string;
|
|
50
|
+
} ? string extends N ? Record<string, never> : {
|
|
51
|
+
readonly [K in N]: T;
|
|
52
|
+
} : Record<string, never>;
|
|
53
|
+
type RouteViewNamed<E> = E extends {
|
|
54
|
+
routeView: infer V extends AnyRoute;
|
|
55
|
+
} ? ConfigNamed<E, V> : Record<string, never>;
|
|
56
|
+
type LayoutViewNamed<E> = E extends {
|
|
57
|
+
layoutView: infer L extends AnyRoute;
|
|
58
|
+
} ? ConfigNamed<E, L> : Record<string, never>;
|
|
59
|
+
type RedirectRouteNamed<E> = E extends {
|
|
60
|
+
route: infer R extends AnyRoute;
|
|
61
|
+
} ? ConfigNamed<E, R> : Record<string, never>;
|
|
62
|
+
type EntryNames<E> = RouteViewNamed<E> & LayoutViewNamed<E> & RedirectRouteNamed<E>;
|
|
63
|
+
type PrevDepth = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
|
64
|
+
type EntryNamesDeep<E, D extends number> = D extends 0 ? Record<string, never> : EntryNames<E> & (E extends {
|
|
65
|
+
children: readonly RouteTreeBranch[];
|
|
66
|
+
} ? UnionToIntersection<EntryNamesDeep<E["children"][number], PrevDepth[D]>> : Record<string, never>);
|
|
67
|
+
type NamedRoutesFromTree<TRoutes extends readonly RouteTreeBranch[]> = UnionToIntersection<EntryNamesDeep<TRoutes[number], 16>>;
|
|
68
|
+
type CollectNamedRoutes<TRoutes> = TRoutes extends readonly RouteTreeBranch[] ? NamedRoutesFromTree<TRoutes> extends infer R ? keyof R extends never ? Record<string, never> : R : Record<string, never> : Record<string, never>;
|
|
69
|
+
type RouteViewEntry<P extends string = string, N extends string = string, TRouteView = AnyPage> = RouteViewConfig<P, N, TRouteView>;
|
|
70
|
+
type LayoutViewEntry<P extends string = string, N extends string = string, TLayoutView extends LayoutPage = LayoutPage> = LayoutViewConfig<P, N, TLayoutView>;
|
|
71
|
+
type RedirectRouteEntry<P extends string = string, N extends string = string, TRoute = AnyRoute> = RedirectConfig<P, N, TRoute>;
|
|
72
|
+
/** @deprecated Use RouteViewEntry */
|
|
73
|
+
type PageRouteEntry<P extends string = string, N extends string = string, TPage = AnyPage> = RouteViewEntry<P, N, TPage>;
|
|
74
|
+
/** @deprecated Use LayoutViewEntry */
|
|
75
|
+
type LayoutRouteEntry<P extends string = string, N extends string = string> = LayoutViewEntry<P, N>;
|
|
76
|
+
type RouteTreeEntry<P extends string = string, N extends string = string> = RouteViewEntry<P, N, AnyPage> | RedirectRouteEntry<P, N> | LayoutViewEntry<P, N>;
|
|
77
|
+
|
|
78
|
+
type RouteEvent<T> = {
|
|
79
|
+
subscribe(listener: (payload: T) => void): () => void;
|
|
80
|
+
};
|
|
81
|
+
type RouteOpenedPayload<Params, Query> = {
|
|
82
|
+
params: Params;
|
|
83
|
+
query: Query;
|
|
84
|
+
path: string;
|
|
85
|
+
fullPath: string;
|
|
86
|
+
};
|
|
87
|
+
type GoOptions<Query> = {
|
|
88
|
+
query?: Query;
|
|
89
|
+
replace?: boolean;
|
|
90
|
+
};
|
|
91
|
+
/** @deprecated Use GoOptions */
|
|
92
|
+
type OpenOptions<Query> = GoOptions<Query>;
|
|
93
|
+
type NamedRoute<Name extends string, Params = Record<string, never>, Query = Record<string, never>> = Route<Params, Query> & {
|
|
94
|
+
readonly name: Name;
|
|
95
|
+
};
|
|
96
|
+
type NamedPage<Name extends string, Params = Record<string, never>, Query = Record<string, never>, Data = void> = Page<Params, Query, Data> & {
|
|
97
|
+
readonly name: Name;
|
|
98
|
+
};
|
|
99
|
+
type Route<Params = Record<string, never>, Query = Record<string, never>> = {
|
|
100
|
+
readonly name?: string;
|
|
101
|
+
readonly $isOpened: ReadonlySignal<boolean>;
|
|
102
|
+
readonly $params: ReadonlySignal<Params | null>;
|
|
103
|
+
readonly $query: ReadonlySignal<Query>;
|
|
104
|
+
readonly $path: ReadonlySignal<string | null>;
|
|
105
|
+
readonly $fullPath: ReadonlySignal<string | null>;
|
|
106
|
+
go(...args: keyof Params extends never ? [params?: Params, options?: GoOptions<Query>] : [params: Params, options?: GoOptions<Query>]): void;
|
|
107
|
+
/** @deprecated Alias for `go()` */
|
|
108
|
+
open(...args: keyof Params extends never ? [params?: Params, options?: GoOptions<Query>] : [params: Params, options?: GoOptions<Query>]): void;
|
|
109
|
+
close(): void;
|
|
110
|
+
readonly opened: RouteEvent<RouteOpenedPayload<Params, Query>>;
|
|
111
|
+
readonly closed: RouteEvent<void>;
|
|
112
|
+
};
|
|
113
|
+
type PageLoaderContext<Params, Query> = {
|
|
114
|
+
params: Params;
|
|
115
|
+
query: Query;
|
|
116
|
+
navigationId?: number;
|
|
117
|
+
};
|
|
118
|
+
type RouteViewContext<Params = Record<string, unknown>, Query = Record<string, unknown>, Data = void> = {
|
|
119
|
+
params: Params;
|
|
120
|
+
query: Query;
|
|
121
|
+
outlet: () => Child;
|
|
122
|
+
data: Data | null;
|
|
123
|
+
/** Set when the view is used as a router-level or per-route error UI. */
|
|
124
|
+
error?: unknown;
|
|
125
|
+
};
|
|
126
|
+
/** @deprecated Use RouteViewContext */
|
|
127
|
+
type PageRenderContext<Params = Record<string, unknown>, Query = Record<string, unknown>, Data = void> = RouteViewContext<Params, Query, Data>;
|
|
128
|
+
type RouteView<Params = Record<string, unknown>, Query = Record<string, unknown>, Data = void> = (context: RouteViewContext<Params, Query, Data>) => unknown;
|
|
129
|
+
/** @deprecated Use RouteView */
|
|
130
|
+
type PageComponent<Params = Record<string, unknown>, Query = Record<string, unknown>, Data = void> = RouteView<Params, Query, Data>;
|
|
131
|
+
type RouteLoadingView = (context: {
|
|
132
|
+
params: Record<string, unknown>;
|
|
133
|
+
query: Record<string, unknown>;
|
|
134
|
+
}) => unknown;
|
|
135
|
+
/** @deprecated Use RouteLoadingView */
|
|
136
|
+
type PageViewComponent = RouteLoadingView;
|
|
137
|
+
type RouteErrorView = (context: {
|
|
138
|
+
error: unknown;
|
|
139
|
+
params: Record<string, unknown>;
|
|
140
|
+
query: Record<string, unknown>;
|
|
141
|
+
}) => unknown;
|
|
142
|
+
/** @deprecated Use RouteErrorView */
|
|
143
|
+
type PageErrorComponent = RouteErrorView;
|
|
144
|
+
type Page<Params = Record<string, never>, Query = Record<string, never>, Data = void> = Route<Params, Query> & {
|
|
145
|
+
readonly $pending: ReadonlySignal<boolean>;
|
|
146
|
+
readonly $error: ReadonlySignal<unknown | null>;
|
|
147
|
+
readonly $data: ReadonlySignal<Data | null>;
|
|
148
|
+
readonly beforeLoad?: (ctx: PageLoaderContext<Params, Query>) => Data | Promise<Data>;
|
|
149
|
+
/** @deprecated Use `beforeLoad` */
|
|
150
|
+
readonly loader?: (ctx: PageLoaderContext<Params, Query>) => Data | Promise<Data>;
|
|
151
|
+
readonly loadingView?: RouteLoadingView;
|
|
152
|
+
readonly errorView?: RouteErrorView;
|
|
153
|
+
replace(...args: keyof Params extends never ? [params?: Params, options?: GoOptions<Query>] : [params: Params, options?: GoOptions<Query>]): void;
|
|
154
|
+
resolve(params?: Params, options?: {
|
|
155
|
+
query?: Record<string, unknown>;
|
|
156
|
+
}): string;
|
|
157
|
+
isActive(): boolean;
|
|
158
|
+
preload?(): void;
|
|
159
|
+
};
|
|
160
|
+
type PageViewRenderContext<Params = Record<string, unknown>, Query = Record<string, unknown>> = Omit<PageRenderContext<Params, Query, void>, "data">;
|
|
161
|
+
/** @deprecated Use PageComponent */
|
|
162
|
+
type PageViewRenderer<Params = Record<string, unknown>, Query = Record<string, unknown>> = (context: PageViewRenderContext<Params, Query>) => unknown;
|
|
163
|
+
|
|
164
|
+
/** @deprecated Use RouteTreeEntry */
|
|
165
|
+
type RouterRouteDefinition = RouteTreeEntry;
|
|
166
|
+
|
|
167
|
+
type LayoutPage = AnyPage & {
|
|
168
|
+
readonly __layout?: unique symbol;
|
|
169
|
+
};
|
|
170
|
+
type RouteConfig = {
|
|
171
|
+
path: string;
|
|
172
|
+
route: AnyRoute;
|
|
173
|
+
children?: RouteConfig[];
|
|
174
|
+
};
|
|
175
|
+
type RouterHistory = {
|
|
176
|
+
getLocation(): string;
|
|
177
|
+
push(path: string): void;
|
|
178
|
+
replace(path: string): void;
|
|
179
|
+
listen(callback: (path: string) => void): () => void;
|
|
180
|
+
back(): void;
|
|
181
|
+
forward(): void;
|
|
182
|
+
};
|
|
183
|
+
type AuthorizationGuardRedirectContext = {
|
|
184
|
+
readonly pathname: string;
|
|
185
|
+
readonly authorized: boolean;
|
|
186
|
+
};
|
|
187
|
+
/** Resolves a redirect path when the user must leave the current URL. */
|
|
188
|
+
type AuthorizationGuardRedirect<Paths extends string = string> = (context: AuthorizationGuardRedirectContext) => Paths;
|
|
189
|
+
type AuthorizationGuardRedirectTarget<Paths extends string = string> = Paths | AuthorizationGuardRedirect<Paths>;
|
|
190
|
+
type AuthorizationGuardOptions<Paths extends string = string> = {
|
|
191
|
+
isAuthorized: () => boolean;
|
|
192
|
+
allowedUnauthorizedPaths: readonly Paths[];
|
|
193
|
+
allowedAuthorizedPaths?: readonly Paths[];
|
|
194
|
+
redirectTo?: AuthorizationGuardRedirectTarget<Paths>;
|
|
195
|
+
redirectWhenAuthorized?: AuthorizationGuardRedirectTarget<Paths>;
|
|
196
|
+
};
|
|
197
|
+
type CreateRouterOptions<TRoutes extends readonly RouteTreeNode[] = readonly RouteTreeNode[]> = {
|
|
198
|
+
history: RouterHistoryConfig;
|
|
199
|
+
routes: TRoutes;
|
|
200
|
+
authorizationGuard?: AuthorizationGuardOptions<CollectRoutePaths<TRoutes>>;
|
|
201
|
+
loadingView?: RouteLoadingView | AnyPage;
|
|
202
|
+
errorView?: RouteErrorView | AnyPage;
|
|
203
|
+
notFoundView?: RouterNotFoundView | AnyPage;
|
|
204
|
+
};
|
|
205
|
+
type RouterNotFoundView = (context: RouteViewContext<Record<string, unknown>, Record<string, unknown>, void>) => unknown;
|
|
206
|
+
/** @deprecated Use RouterNotFoundView */
|
|
207
|
+
type RouterNotFoundComponent = RouterNotFoundView;
|
|
208
|
+
type AnyRoute = Route<any, any>;
|
|
209
|
+
type AnyPage = Page<any, any, any>;
|
|
210
|
+
type RouterViewComponent = () => unknown;
|
|
211
|
+
/** Default shape of `router.routes` when the route tree is not inferred. */
|
|
212
|
+
type RouterRoutes = Readonly<Record<string, AnyRoute>>;
|
|
213
|
+
type RouterBase = {
|
|
214
|
+
readonly $path: ReadonlySignal<string>;
|
|
215
|
+
readonly $query: ReadonlySignal<Record<string, string>>;
|
|
216
|
+
readonly $fullPath: ReadonlySignal<string>;
|
|
217
|
+
readonly $activeRoute: ReadonlySignal<AnyRoute | null>;
|
|
218
|
+
readonly $activePage: ReadonlySignal<AnyPage | null>;
|
|
219
|
+
readonly $activeRoutes: ReadonlySignal<AnyRoute[]>;
|
|
220
|
+
readonly $matched: ReadonlySignal<AnyRoute[]>;
|
|
221
|
+
readonly $params: ReadonlySignal<Record<string, string>>;
|
|
222
|
+
readonly $pending: ReadonlySignal<boolean>;
|
|
223
|
+
readonly $error: ReadonlySignal<unknown | null>;
|
|
224
|
+
readonly View: RouterViewComponent;
|
|
225
|
+
start(): void;
|
|
226
|
+
stop(): void;
|
|
227
|
+
go(path: string, options?: {
|
|
228
|
+
replace?: boolean;
|
|
229
|
+
}): void;
|
|
230
|
+
/** @deprecated Use `go()` */
|
|
231
|
+
navigate(path: string, options?: {
|
|
232
|
+
replace?: boolean;
|
|
233
|
+
}): void;
|
|
234
|
+
replace(path: string): void;
|
|
235
|
+
back(): void;
|
|
236
|
+
forward(): void;
|
|
237
|
+
reload(): void;
|
|
238
|
+
resolve(route: AnyRoute, params?: Record<string, string>, options?: {
|
|
239
|
+
query?: Record<string, unknown>;
|
|
240
|
+
}): string;
|
|
241
|
+
isActive(route: AnyRoute): boolean;
|
|
242
|
+
view(): RouterViewComponent;
|
|
243
|
+
closeRoute(route: AnyRoute): void;
|
|
244
|
+
};
|
|
245
|
+
type Router<TRoutes extends RouterRoutes = RouterRoutes> = RouterBase & {
|
|
246
|
+
readonly routes: TRoutes;
|
|
247
|
+
};
|
|
248
|
+
type MatchResult = {
|
|
249
|
+
matched: boolean;
|
|
250
|
+
params: Record<string, string>;
|
|
251
|
+
};
|
|
252
|
+
type ChainedRoute<Params, Query, Result = void> = {
|
|
253
|
+
readonly $isOpened: ReadonlySignal<boolean>;
|
|
254
|
+
readonly $pending: ReadonlySignal<boolean>;
|
|
255
|
+
readonly $error: ReadonlySignal<unknown | null>;
|
|
256
|
+
readonly $params: ReadonlySignal<Params | null>;
|
|
257
|
+
readonly $query: ReadonlySignal<Query>;
|
|
258
|
+
readonly $result: ReadonlySignal<Result | null>;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
declare const createRoute: <const Name extends string, Params = Record<string, never>, Query = Record<string, never>>(name: Name) => NamedRoute<Name, Params, Query>;
|
|
262
|
+
|
|
263
|
+
type FlatRouteEntry = {
|
|
264
|
+
path: string;
|
|
265
|
+
route: AnyRoute;
|
|
266
|
+
parent: FlatRouteEntry | null;
|
|
267
|
+
};
|
|
268
|
+
declare const flattenRouteTree: (configs: RouteConfig[], parentPath?: string, parent?: FlatRouteEntry | null) => FlatRouteEntry[];
|
|
269
|
+
type RouteMatchChain = {
|
|
270
|
+
leaf: FlatRouteEntry;
|
|
271
|
+
chain: FlatRouteEntry[];
|
|
272
|
+
leafParams: Record<string, string>;
|
|
273
|
+
};
|
|
274
|
+
declare const matchRouteChain: (pathname: string, flatRoutes: FlatRouteEntry[]) => RouteMatchChain | null;
|
|
275
|
+
|
|
276
|
+
type LazyRouteViewModule<Params = Record<string, unknown>, Query = Record<string, unknown>, Data = void> = {
|
|
277
|
+
default: RouteView<Params, Query, Data>;
|
|
278
|
+
};
|
|
279
|
+
type LazyRouteViewLoader<Params = Record<string, unknown>, Query = Record<string, unknown>, Data = void> = () => Promise<LazyRouteViewModule<Params, Query, Data>>;
|
|
280
|
+
declare const isLazyRouteView: (page: AnyPage) => boolean;
|
|
281
|
+
|
|
282
|
+
type BeforeLoadContext<Params, Query> = PageLoaderContext<Params, Query> & {
|
|
283
|
+
navigationId: number;
|
|
284
|
+
};
|
|
285
|
+
declare const isPage: (value: Route<any, any>) => value is Page<any, any, any>;
|
|
286
|
+
declare const isLayoutPage: (value: Route<any, any>) => value is Page<any, any, any>;
|
|
287
|
+
declare const assertPage: (value: Route<any, any>, label?: string) => Page;
|
|
288
|
+
type CreateRouteViewOptions<Params, Query, Data> = {
|
|
289
|
+
name?: string;
|
|
290
|
+
view?: RouteView<Params, Query, Data>;
|
|
291
|
+
viewLoader?: LazyRouteViewLoader<Params, Query, Data>;
|
|
292
|
+
beforeLoad?: (ctx: BeforeLoadContext<Params, Query>) => Data | Promise<Data>;
|
|
293
|
+
/** @deprecated Use `beforeLoad` */
|
|
294
|
+
loader?: (ctx: PageLoaderContext<Params, Query>) => Data | Promise<Data>;
|
|
295
|
+
loadingView?: RouteLoadingView;
|
|
296
|
+
errorView?: RouteErrorView;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
type RouteViewOptionsConstraint = CreateRouteViewOptions<unknown, unknown, unknown> & {
|
|
300
|
+
readonly name: string;
|
|
301
|
+
};
|
|
302
|
+
type RouteViewNameFromOptions<O extends RouteViewOptionsConstraint> = O extends {
|
|
303
|
+
readonly name: infer N extends string;
|
|
304
|
+
} ? string extends N ? never : N : never;
|
|
305
|
+
type RouteViewParamsFromOptions<O extends RouteViewOptionsConstraint> = O extends CreateRouteViewOptions<infer P, unknown, unknown> ? P : Record<string, never>;
|
|
306
|
+
type RouteViewQueryFromOptions<O extends RouteViewOptionsConstraint> = O extends CreateRouteViewOptions<unknown, infer Q, unknown> ? Q : Record<string, never>;
|
|
307
|
+
type RouteViewDataFromOptions<O extends RouteViewOptionsConstraint> = O extends CreateRouteViewOptions<unknown, unknown, infer D> ? D : void;
|
|
308
|
+
|
|
309
|
+
declare function createRouteView<const O extends RouteViewOptionsConstraint>(options: O): NamedPage<RouteViewNameFromOptions<O>, RouteViewParamsFromOptions<O>, RouteViewQueryFromOptions<O>, RouteViewDataFromOptions<O>>;
|
|
310
|
+
declare function createRouteView<Params = Record<string, never>, Query = Record<string, never>, Data = void>(options: CreateRouteViewOptions<Params, Query, Data> & {
|
|
311
|
+
readonly name: string;
|
|
312
|
+
}): NamedPage<string, Params, Query, Data>;
|
|
313
|
+
|
|
314
|
+
type LazyRouteViewOptionsConstraint = {
|
|
315
|
+
readonly name: string;
|
|
316
|
+
view: LazyRouteViewLoader<unknown, unknown, unknown>;
|
|
317
|
+
beforeLoad?: (ctx: BeforeLoadContext<unknown, unknown>) => unknown | Promise<unknown>;
|
|
318
|
+
loadingView?: CreateRouteViewOptions<unknown, unknown, unknown>["loadingView"];
|
|
319
|
+
errorView?: CreateRouteViewOptions<unknown, unknown, unknown>["errorView"];
|
|
320
|
+
};
|
|
321
|
+
type LazyRouteViewNameFromOptions<O extends LazyRouteViewOptionsConstraint> = O extends {
|
|
322
|
+
readonly name: infer N extends string;
|
|
323
|
+
} ? string extends N ? never : N : never;
|
|
324
|
+
type LazyRouteViewParamsFromOptions<O extends LazyRouteViewOptionsConstraint> = O extends {
|
|
325
|
+
beforeLoad?: (ctx: BeforeLoadContext<infer P, unknown>) => unknown;
|
|
326
|
+
} ? P : Record<string, never>;
|
|
327
|
+
type LazyRouteViewQueryFromOptions<O extends LazyRouteViewOptionsConstraint> = O extends {
|
|
328
|
+
beforeLoad?: (ctx: BeforeLoadContext<unknown, infer Q>) => unknown;
|
|
329
|
+
} ? Q : Record<string, never>;
|
|
330
|
+
type LazyRouteViewDataFromOptions<O extends LazyRouteViewOptionsConstraint> = O extends {
|
|
331
|
+
beforeLoad?: (ctx: BeforeLoadContext<unknown, unknown>) => infer D;
|
|
332
|
+
} ? Awaited<D> : void;
|
|
333
|
+
|
|
334
|
+
type CreateLazyRouteViewOptions<Params = Record<string, never>, Query = Record<string, never>, Data = void> = {
|
|
335
|
+
name?: string;
|
|
336
|
+
/** Dynamic import — module must `export default` a route view function. */
|
|
337
|
+
view: LazyRouteViewLoader<Params, Query, Data>;
|
|
338
|
+
beforeLoad?: (ctx: BeforeLoadContext<Params, Query>) => Data | Promise<Data>;
|
|
339
|
+
loadingView?: RouteLoadingView;
|
|
340
|
+
errorView?: RouteErrorView;
|
|
341
|
+
};
|
|
342
|
+
declare function createLazyRouteView<const O extends LazyRouteViewOptionsConstraint>(options: O): NamedPage<LazyRouteViewNameFromOptions<O>, LazyRouteViewParamsFromOptions<O>, LazyRouteViewQueryFromOptions<O>, LazyRouteViewDataFromOptions<O>>;
|
|
343
|
+
declare function createLazyRouteView<Params = Record<string, never>, Query = Record<string, never>, Data = void>(options: CreateLazyRouteViewOptions<Params, Query, Data> & {
|
|
344
|
+
readonly name: string;
|
|
345
|
+
}): NamedPage<string, Params, Query, Data>;
|
|
346
|
+
|
|
347
|
+
type NamedLayoutView<Name extends string, Params = Record<string, never>, Query = Record<string, never>, Data = void> = LayoutPage & NamedPage<Name, Params, Query, Data>;
|
|
348
|
+
declare const createLayoutView: <const O extends RouteViewOptionsConstraint>(options: O) => NamedLayoutView<RouteViewNameFromOptions<O>, RouteViewParamsFromOptions<O>, RouteViewQueryFromOptions<O>, RouteViewDataFromOptions<O>>;
|
|
349
|
+
|
|
350
|
+
declare const createRouter$1: <const TRoutes extends readonly RouteTreeBranch[]>(options: CreateRouterOptions<TRoutes>) => Router<CollectNamedRoutes<TRoutes>>;
|
|
351
|
+
|
|
352
|
+
type HyperdomRouter<TRoutes extends Router["routes"] = Router["routes"]> = Omit<Router<TRoutes>, "View"> & {
|
|
353
|
+
readonly View: () => Child;
|
|
354
|
+
createQueryParams: RouterBoundQueryParams;
|
|
355
|
+
};
|
|
356
|
+
declare const createRouter: <const TRoutes extends readonly RouteTreeBranch[]>(options: CreateRouterOptions<TRoutes>) => HyperdomRouter<CollectNamedRoutes<TRoutes>>;
|
|
357
|
+
|
|
358
|
+
type QueryPrimitive = string | number | boolean;
|
|
359
|
+
type QueryValue = QueryPrimitive | QueryPrimitive[] | null | undefined;
|
|
360
|
+
type QueryRecord = Record<string, QueryValue>;
|
|
361
|
+
declare const parseQuery: (search: string) => Record<string, string>;
|
|
362
|
+
declare const parseQueryValues: (search: string) => Record<string, string | string[]>;
|
|
363
|
+
declare const stringifyQuery: (query: QueryRecord) => string;
|
|
364
|
+
|
|
365
|
+
type LinkProps<Params = Record<string, string>, Query = QueryRecord> = {
|
|
366
|
+
to?: Route<Params, Query>;
|
|
367
|
+
href?: string;
|
|
368
|
+
params?: Params;
|
|
369
|
+
query?: Query;
|
|
370
|
+
replace?: boolean;
|
|
371
|
+
children?: Child;
|
|
372
|
+
};
|
|
373
|
+
declare const Link: <Params = Record<string, string>, Query = QueryRecord>(props: LinkProps<Params, Query>) => Child;
|
|
374
|
+
|
|
375
|
+
type NavLinkProps<Params = Record<string, string>, Query = QueryRecord> = LinkProps<Params, Query> & {
|
|
376
|
+
activeClass?: string;
|
|
377
|
+
class?: string;
|
|
378
|
+
};
|
|
379
|
+
declare const NavLink: <Params = Record<string, string>, Query = QueryRecord>(props: NavLinkProps<Params, Query>) => Child;
|
|
380
|
+
|
|
381
|
+
declare const ROUTER_KEY: unique symbol;
|
|
382
|
+
type RouterLike = Pick<Router, "View" | "start" | "stop">;
|
|
383
|
+
type RouterProviderHost = {
|
|
384
|
+
provide?<T>(key: symbol, value: T): unknown;
|
|
385
|
+
};
|
|
386
|
+
type RouterProviderOptions = {
|
|
387
|
+
/** @default true */
|
|
388
|
+
autoStart?: boolean;
|
|
389
|
+
};
|
|
390
|
+
/** Provider shape accepted by `createEchoApp().use(...)`. */
|
|
391
|
+
type RouterProvider = {
|
|
392
|
+
name: "router";
|
|
393
|
+
setup: (app: RouterProviderHost) => void;
|
|
394
|
+
resolveRoot: () => Child;
|
|
395
|
+
};
|
|
396
|
+
/** @deprecated Use {@link RouterProvider} */
|
|
397
|
+
type RouterPlugin = RouterProvider;
|
|
398
|
+
declare const isRouterLike: (value: unknown) => value is RouterLike;
|
|
399
|
+
declare const createRouterProvider: (router: RouterLike, options?: RouterProviderOptions) => RouterProvider;
|
|
400
|
+
/** @deprecated Use {@link createRouterProvider} */
|
|
401
|
+
declare const routerPlugin: (router: RouterLike, options?: RouterProviderOptions) => RouterProvider;
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Builds a typed route tree for `createRouter({ routes })`.
|
|
405
|
+
* Use `routeView`, `layoutView`, and `route` (redirect) on each entry.
|
|
406
|
+
*/
|
|
407
|
+
declare function createRoutes<const TRoutes extends readonly RouteTreeNode[]>(routes: TRoutes): TRoutes;
|
|
408
|
+
type RoutesFromConfig<TRoutes extends readonly RouteTreeNode[]> = CollectNamedRoutes<TRoutes>;
|
|
409
|
+
|
|
410
|
+
declare const normalizePathname: (pathname: string) => string;
|
|
411
|
+
declare const joinRoutePaths: (parentPath: string, childPath: string) => string;
|
|
412
|
+
declare const matchPath: (pattern: string, pathname: string) => MatchResult;
|
|
413
|
+
declare const buildPath: (pattern: string, params?: Record<string, string>) => string;
|
|
414
|
+
declare const splitLocation: (location: string) => {
|
|
415
|
+
pathname: string;
|
|
416
|
+
search: string;
|
|
417
|
+
};
|
|
418
|
+
declare const joinLocation: (pathname: string, search: string) => string;
|
|
419
|
+
|
|
420
|
+
type NamedRoutesMap = Readonly<Record<string, AnyRoute>>;
|
|
421
|
+
/** Flat `router.routes` keyed by route config `name` (not URL segments). */
|
|
422
|
+
declare const buildNamedRoutes: (entries: readonly RouteTreeEntry[]) => NamedRoutesMap;
|
|
423
|
+
|
|
424
|
+
declare const createBrowserHistory: () => RouterHistory;
|
|
425
|
+
|
|
426
|
+
declare const createMemoryHistory: (initialPath?: string) => RouterHistory;
|
|
427
|
+
|
|
428
|
+
declare const createHashHistory: () => RouterHistory;
|
|
429
|
+
|
|
430
|
+
type GuardRouteOptions = {
|
|
431
|
+
route: Route<any, any>;
|
|
432
|
+
canOpen: () => boolean;
|
|
433
|
+
otherwise: Route<any, any>;
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
declare const guardRoute: (options: GuardRouteOptions) => (() => void);
|
|
437
|
+
|
|
438
|
+
type RedirectOptions<FromParams = Record<string, unknown>, FromQuery = Record<string, unknown>, ToParams = FromParams, ToQuery = FromQuery> = {
|
|
439
|
+
from: Route<FromParams, FromQuery>;
|
|
440
|
+
to: Route<ToParams, ToQuery>;
|
|
441
|
+
mapParams?: (params: FromParams) => ToParams;
|
|
442
|
+
mapQuery?: (query: FromQuery) => ToQuery;
|
|
443
|
+
};
|
|
444
|
+
declare const redirect: <FromParams = Record<string, unknown>, FromQuery = Record<string, unknown>, ToParams = FromParams, ToQuery = FromQuery>(options: RedirectOptions<FromParams, FromQuery, ToParams, ToQuery>) => (() => void);
|
|
445
|
+
|
|
446
|
+
type ChainRouteOptions<Params, Query, Result = void> = {
|
|
447
|
+
route: Route<Params, Query>;
|
|
448
|
+
beforeOpen: (context: {
|
|
449
|
+
params: Params;
|
|
450
|
+
query: Query;
|
|
451
|
+
}) => Result | Promise<Result>;
|
|
452
|
+
};
|
|
453
|
+
declare const chainRoute: <Params, Query, Result = void>(options: ChainRouteOptions<Params, Query, Result>) => ChainedRoute<Params, Query, Result>;
|
|
454
|
+
|
|
455
|
+
export { type AnyPage, type AuthorizationGuardOptions, type AuthorizationGuardRedirect, type AuthorizationGuardRedirectContext, type AuthorizationGuardRedirectTarget, type BeforeLoadContext, type ChainRouteOptions, type ChainedRoute, type CollectNamedRoutes, type CollectRoutePaths, type CreateLazyRouteViewOptions, type CreateRouteViewOptions, type CreateRouterOptions, type GoOptions, type GuardRouteOptions, type HyperdomRouter, type JoinPaths, type LayoutPage, type LayoutRouteEntry, type LayoutViewConfig, type LayoutViewEntry, type LazyRouteViewLoader, type LazyRouteViewModule, Link, type LinkProps, type MatchResult, type MemoryHistoryConfig, type NamedLayoutView, type NamedPage, type NamedRoute, type NamedRoutesMap, NavLink, type NavLinkProps, type OpenOptions, type Page, type PageComponent, type PageErrorComponent, type PageLoaderContext, type PageRenderContext, type PageRouteEntry, type PageViewComponent, type PageViewRenderer, ROUTER_KEY, type RedirectConfig, type RedirectOptions, type RedirectRouteEntry, type Route, type RouteConfig, type RouteErrorView, type RouteEvent, type RouteLoadingView, type RouteOpenedPayload, type RouteTreeBranch, type RouteTreeEntry, type RouteTreeInput, type RouteTreeNode, type RouteView, type RouteViewConfig, type RouteViewContext, type RouteViewEntry, type Router, type RouterBase, type RouterHistory, type RouterHistoryConfig, type RouterHistoryKind, type RouterLike, type RouterNotFoundComponent, type RouterNotFoundView, type RouterPlugin, type RouterProvider, type RouterRouteDefinition, type RouterRoutes, type RouterViewComponent, type RoutesFromConfig, assertPage, buildNamedRoutes, buildPath, chainRoute, createBrowserHistory, createHashHistory, createLayoutView, createLazyRouteView, createMemoryHistory, createRoute, createRouteView, createRouter, createRouter$1 as createRouterCore, createRouterProvider, createRoutes, flattenRouteTree, guardRoute, isLayoutPage, isLazyRouteView, isPage, isRouterLike, joinLocation, joinRoutePaths, matchPath, matchRouteChain, normalizePathname, parseQuery, parseQueryValues, redirect, resolveHistory, routerPlugin, splitLocation, stringifyQuery };
|