@solidjs/router 1.0.0-next.9 → 1.0.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 +715 -531
- package/dist/components.d.ts +31 -0
- package/dist/components.jsx +40 -0
- package/dist/data/action.d.ts +11 -40
- package/dist/data/action.js +100 -293
- package/dist/data/createAsync.d.ts +32 -0
- package/dist/data/createAsync.js +96 -0
- package/dist/data/events.d.ts +0 -8
- package/dist/data/events.js +23 -24
- package/dist/data/index.d.ts +4 -2
- package/dist/data/index.js +4 -2
- package/dist/data/query.d.ts +3 -1
- package/dist/data/query.js +22 -39
- package/dist/data/response.d.ts +4 -0
- package/dist/data/response.js +42 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.js +1024 -1597
- package/dist/index.jsx +2 -2
- package/dist/lifecycle.d.ts +4 -29
- package/dist/lifecycle.js +37 -40
- package/dist/routers/HashRouter.d.ts +9 -0
- package/dist/routers/HashRouter.js +41 -0
- package/dist/routers/MemoryRouter.d.ts +24 -0
- package/dist/routers/MemoryRouter.js +57 -0
- package/dist/routers/Router.d.ts +17 -0
- package/dist/routers/Router.js +59 -0
- package/dist/routers/StaticRouter.d.ts +6 -0
- package/dist/routers/StaticRouter.js +15 -0
- package/dist/routers/components.d.ts +26 -12
- package/dist/routers/components.jsx +54 -68
- package/dist/routers/createRouter.d.ts +10 -0
- package/dist/routers/createRouter.js +41 -0
- package/dist/routers/index.d.ts +11 -4
- package/dist/routers/index.js +6 -2
- package/dist/routers/scrollRestoration.d.ts +32 -0
- package/dist/routers/scrollRestoration.js +96 -0
- package/dist/routing.d.ts +52 -88
- package/dist/routing.js +166 -381
- package/dist/types.d.ts +33 -83
- package/dist/utils.d.ts +0 -2
- package/dist/utils.js +0 -2
- package/package.json +7 -11
- package/dist/claims.d.ts +0 -21
- package/dist/claims.js +0 -115
- package/dist/data/flash.d.ts +0 -21
- package/dist/data/flash.js +0 -78
- package/dist/data/flashCookie.d.ts +0 -7
- package/dist/data/flashCookie.js +0 -20
- package/dist/data/serverForms.d.ts +0 -1
- package/dist/data/serverForms.js +0 -5
- package/dist/paths.d.ts +0 -117
- package/dist/paths.js +0 -41
- package/dist/routers/factory.d.ts +0 -45
- package/dist/routers/factory.jsx +0 -143
- package/dist/routers/history.d.ts +0 -24
- package/dist/routers/history.js +0 -180
- package/dist/server.d.ts +0 -75
- package/dist/server.js +0 -264
package/dist/paths.d.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import type { Params, RouteDefinition, SearchParams, SetSearchParams, StandardSchemaV1, TypedPath, TypedSearchPath } from "./types.js";
|
|
2
|
-
declare const FILTER_TYPE: unique symbol;
|
|
3
|
-
/**
|
|
4
|
-
* A match filter that also declares the TypeScript type accepted for the
|
|
5
|
-
* param at `paths` callsites (the runtime param remains a string).
|
|
6
|
-
*/
|
|
7
|
-
export interface TypedMatchFilter<T> {
|
|
8
|
-
(s: string): boolean;
|
|
9
|
-
readonly [FILTER_TYPE]: T;
|
|
10
|
-
}
|
|
11
|
-
/** Matches integer segments; types the param as `number` in the path proxy. */
|
|
12
|
-
export declare const int: TypedMatchFilter<number>;
|
|
13
|
-
type Flat<T> = {
|
|
14
|
-
[K in keyof T]: T[K];
|
|
15
|
-
} & {};
|
|
16
|
-
type SegmentsOf<P extends string> = P extends `${infer A}/${infer B}` ? [...SegmentsOf<A>, ...SegmentsOf<B>] : P extends "" ? [] : [P];
|
|
17
|
-
type FilterArg<F> = F extends TypedMatchFilter<infer T> ? T : F extends readonly (infer S)[] ? S : string | number;
|
|
18
|
-
type ParamArg<Name extends string, F> = Name extends keyof F ? FilterArg<F[Name]> : string | number;
|
|
19
|
-
/** Collects a maximal run of required params (and a trailing splat) into one call's argument tuple. */
|
|
20
|
-
type ParamRun<Segs extends readonly string[], F, Args extends readonly unknown[] = [], PAcc extends Params = {}> = Segs extends readonly [infer H extends string, ...infer R extends readonly string[]] ? H extends `:${string}?` ? {
|
|
21
|
-
args: Args;
|
|
22
|
-
params: PAcc;
|
|
23
|
-
rest: Segs;
|
|
24
|
-
} : H extends `:${infer N}` ? ParamRun<R, F, [...Args, ParamArg<N, F>], PAcc & {
|
|
25
|
-
[K in N]: string;
|
|
26
|
-
}> : H extends `*${infer N}` ? {
|
|
27
|
-
args: [...Args, string | number];
|
|
28
|
-
params: PAcc & {
|
|
29
|
-
[K in N]: string;
|
|
30
|
-
};
|
|
31
|
-
rest: R;
|
|
32
|
-
} : {
|
|
33
|
-
args: Args;
|
|
34
|
-
params: PAcc;
|
|
35
|
-
rest: Segs;
|
|
36
|
-
} : {
|
|
37
|
-
args: Args;
|
|
38
|
-
params: PAcc;
|
|
39
|
-
rest: Segs;
|
|
40
|
-
};
|
|
41
|
-
/** The search param types a route end carries: input builds URLs, output is what parsing returns. */
|
|
42
|
-
export interface SearchTypes {
|
|
43
|
-
input: any;
|
|
44
|
-
output: any;
|
|
45
|
-
}
|
|
46
|
-
export interface DefaultSearchTypes {
|
|
47
|
-
input: SetSearchParams;
|
|
48
|
-
output: SearchParams;
|
|
49
|
-
}
|
|
50
|
-
/** Terminating calls available on every route end: zero-arg, or search object plus optional hash. */
|
|
51
|
-
export interface PathEnd<Sch extends SearchTypes = DefaultSearchTypes, P extends Params = Params> extends TypedPath<P>, TypedSearchPath<Sch["input"], Sch["output"]> {
|
|
52
|
-
(): string;
|
|
53
|
-
(search: Sch["input"], hash?: string): string;
|
|
54
|
-
}
|
|
55
|
-
type SearchTypesOf<Def> = Def extends {
|
|
56
|
-
search: infer S;
|
|
57
|
-
} ? S extends StandardSchemaV1<any, any> ? {
|
|
58
|
-
input: NonNullable<S["~standard"]["types"]>["input"];
|
|
59
|
-
output: NonNullable<S["~standard"]["types"]>["output"];
|
|
60
|
-
} : DefaultSearchTypes : DefaultSearchTypes;
|
|
61
|
-
type FiltersOf<Def> = Def extends {
|
|
62
|
-
matchFilters: infer F;
|
|
63
|
-
} ? F : {};
|
|
64
|
-
type ChildrenOf<Def> = Def extends {
|
|
65
|
-
children: infer C;
|
|
66
|
-
} ? C : undefined;
|
|
67
|
-
/**
|
|
68
|
-
* Sees through a lazy `children` thunk: the routes the import's promise
|
|
69
|
-
* resolves to (its `default` or `routes` export, matching the runtime) type
|
|
70
|
-
* exactly like inline children. Only tables genuinely built at runtime —
|
|
71
|
-
* where the thunk's return type is a plain `RouteDefinition[]` — degrade to
|
|
72
|
-
* untyped, definitionally.
|
|
73
|
-
*/
|
|
74
|
-
type ResolvedChildren<C> = C extends () => infer R ? Awaited<R> extends infer M ? M extends {
|
|
75
|
-
default: infer D;
|
|
76
|
-
} ? D : M extends {
|
|
77
|
-
routes: infer D;
|
|
78
|
-
} ? D : M : never : C;
|
|
79
|
-
type ChildPaths<C, PAcc extends Params> = [C] extends [undefined] ? {} : ResolvedChildren<C> extends infer RC ? RC extends readonly unknown[] ? TuplePaths<RC, PAcc> : RouteContrib<RC, PAcc> : never;
|
|
80
|
-
type TuplePaths<R extends readonly unknown[], PAcc extends Params> = R extends readonly [
|
|
81
|
-
infer H,
|
|
82
|
-
...infer T extends readonly unknown[]
|
|
83
|
-
] ? RouteContrib<H, PAcc> & TuplePaths<T, PAcc> : {};
|
|
84
|
-
type PathLeaf<Sch extends SearchTypes, C, PAcc extends Params> = PathEnd<Sch, Flat<PAcc>> & ChildPaths<C, PAcc>;
|
|
85
|
-
type PathNode<Segs extends readonly string[], F, Sch extends SearchTypes, C, PAcc extends Params> = Segs extends readonly [infer H extends string, ...infer R extends readonly string[]] ? H extends `:${infer N}?` ? ((arg: ParamArg<N, F>) => PathNode<R, F, Sch, C, PAcc & {
|
|
86
|
-
[K in N]?: string;
|
|
87
|
-
}>) & PathNode<R, F, Sch, C, PAcc & {
|
|
88
|
-
[K in N]?: string;
|
|
89
|
-
}> : H extends `:${string}` | `*${string}` ? ParamCallNode<Segs, F, Sch, C, PAcc> : {
|
|
90
|
-
[K in H]: PathNode<R, F, Sch, C, PAcc>;
|
|
91
|
-
} : PathLeaf<Sch, C, PAcc>;
|
|
92
|
-
type ParamCallNode<Segs extends readonly string[], F, Sch extends SearchTypes, C, PAcc extends Params> = ParamRun<Segs, F> extends {
|
|
93
|
-
args: infer A extends readonly unknown[];
|
|
94
|
-
params: infer P2 extends Params;
|
|
95
|
-
rest: infer R2 extends readonly string[];
|
|
96
|
-
} ? ((...args: A) => PathNode<R2, F, Sch, C, PAcc & P2>) & (R2 extends readonly [] ? {
|
|
97
|
-
(...args: [...A, Sch["input"], string?]): string;
|
|
98
|
-
} : {}) & TypedPath<Flat<PAcc & P2>> : never;
|
|
99
|
-
type RouteContrib<Def, PAcc extends Params> = Def extends {
|
|
100
|
-
path: infer P;
|
|
101
|
-
} ? [P] extends [undefined] ? ChildPaths<ChildrenOf<Def>, PAcc> : P extends readonly string[] ? MultiPathContrib<P, Def, PAcc> : P extends string ? string extends P ? any : PathNode<SegmentsOf<P>, FiltersOf<Def>, SearchTypesOf<Def>, ChildrenOf<Def>, PAcc> : any : ChildPaths<ChildrenOf<Def>, PAcc>;
|
|
102
|
-
type MultiPathContrib<Ps extends readonly string[], Def, PAcc extends Params> = Ps extends readonly [infer H extends string, ...infer T extends readonly string[]] ? PathNode<SegmentsOf<H>, FiltersOf<Def>, SearchTypesOf<Def>, ChildrenOf<Def>, PAcc> & MultiPathContrib<T, Def, PAcc> : {};
|
|
103
|
-
/**
|
|
104
|
-
* The type of a router instance's `paths` proxy for a given route tree.
|
|
105
|
-
* Requires the tree to be a literal tuple (`as const` or a `const` type
|
|
106
|
-
* param); non-literal trees fall back to an untyped proxy.
|
|
107
|
-
*/
|
|
108
|
-
export type RoutePaths<R extends readonly RouteDefinition[]> = number extends R["length"] ? any : PathEnd<DefaultSearchTypes, {}> & TuplePaths<R, {}>;
|
|
109
|
-
/** Extracts the params record a paths node binds, as runtime (string-valued) params. */
|
|
110
|
-
export type PathParamsOf<N> = N extends TypedPath<infer P> ? Flat<P> : Params;
|
|
111
|
-
/**
|
|
112
|
-
* Creates the runtime path proxy. It is instance-scoped: `renderPath` comes
|
|
113
|
-
* from the router's history adapter (eg. hash routing prefixes `#`), and
|
|
114
|
-
* `base` is baked into every produced path.
|
|
115
|
-
*/
|
|
116
|
-
export declare function createPathsProxy(renderPath?: (path: string) => string, base?: string): any;
|
|
117
|
-
export {};
|
package/dist/paths.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { mergeSearchString, normalizePath } from "./utils.js";
|
|
2
|
-
/** Matches integer segments; types the param as `number` in the path proxy. */
|
|
3
|
-
export const int = ((s) => /^-?\d+$/.test(s));
|
|
4
|
-
// ---------------------------------------------------------------------------
|
|
5
|
-
// Runtime
|
|
6
|
-
// ---------------------------------------------------------------------------
|
|
7
|
-
const encodeParam = (value) => String(value).split("/").map(encodeURIComponent).join("/");
|
|
8
|
-
/**
|
|
9
|
-
* Creates the runtime path proxy. It is instance-scoped: `renderPath` comes
|
|
10
|
-
* from the router's history adapter (eg. hash routing prefixes `#`), and
|
|
11
|
-
* `base` is baked into every produced path.
|
|
12
|
-
*/
|
|
13
|
-
export function createPathsProxy(renderPath = p => p, base = "") {
|
|
14
|
-
const toHref = (pathname, suffix = "") => renderPath(pathname || "/") + suffix;
|
|
15
|
-
function node(pathname) {
|
|
16
|
-
const build = (...args) => {
|
|
17
|
-
let path = pathname;
|
|
18
|
-
for (let i = 0; i < args.length; i++) {
|
|
19
|
-
const arg = args[i];
|
|
20
|
-
if (typeof arg === "object" && arg !== null) {
|
|
21
|
-
// a search object terminates; an optional hash string may follow
|
|
22
|
-
const hash = typeof args[i + 1] === "string" ? `#${args[i + 1]}` : "";
|
|
23
|
-
return toHref(path, mergeSearchString("", arg) + hash);
|
|
24
|
-
}
|
|
25
|
-
path += `/${encodeParam(arg)}`;
|
|
26
|
-
}
|
|
27
|
-
// zero-arg calls terminate; param-only calls stay chainable
|
|
28
|
-
return args.length ? node(path) : toHref(path);
|
|
29
|
-
};
|
|
30
|
-
return new Proxy(build, {
|
|
31
|
-
get(_, prop) {
|
|
32
|
-
if (prop === "toString")
|
|
33
|
-
return () => toHref(pathname);
|
|
34
|
-
if (typeof prop === "symbol")
|
|
35
|
-
return prop === Symbol.toPrimitive ? () => toHref(pathname) : undefined;
|
|
36
|
-
return node(`${pathname}/${prop}`);
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
return node(normalizePath(base));
|
|
41
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { JSX } from "@solidjs/web";
|
|
2
|
-
import type { RoutePaths } from "../paths.js";
|
|
3
|
-
import type { OutputMatch, RouteDefinition, RoutePreloadFunc, RouteSectionProps } from "../types.js";
|
|
4
|
-
import type { RouterHistory } from "./history.js";
|
|
5
|
-
/**
|
|
6
|
-
* Identity helper that preserves literal types when the route tree is
|
|
7
|
-
* declared as a separate variable. `createRouter` infers literally from
|
|
8
|
-
* inline arrays, but an extracted `const routes = [...]` widens paths to
|
|
9
|
-
* `string` and silently degrades `paths` and the typed hooks unless it is
|
|
10
|
-
* declared `as const` — `defineRoutes` makes that impossible to forget.
|
|
11
|
-
*/
|
|
12
|
-
export declare function defineRoutes<const R extends readonly RouteDefinition[]>(routes: R): R;
|
|
13
|
-
export interface RouterConfig<R extends readonly RouteDefinition[] = RouteDefinition[]> {
|
|
14
|
-
/** The route tree. Immutable per instance — it is the source of truth for matching *and* types. */
|
|
15
|
-
routes: R;
|
|
16
|
-
base?: string;
|
|
17
|
-
/**
|
|
18
|
-
* Runs once per mount/request (and on single-flight collection passes) to
|
|
19
|
-
* warm app-wide data. Its result is passed to the render-prop child as
|
|
20
|
-
* `props.data`.
|
|
21
|
-
*/
|
|
22
|
-
preload?: RoutePreloadFunc;
|
|
23
|
-
/** History adapter; defaults to browser history on the client and the request URL on the server. */
|
|
24
|
-
history?: RouterHistory;
|
|
25
|
-
singleFlight?: boolean;
|
|
26
|
-
actionBase?: string;
|
|
27
|
-
explicitLinks?: boolean;
|
|
28
|
-
/** Preload route code/data on link hover and focus. Defaults to `true`. */
|
|
29
|
-
preloadLinks?: boolean;
|
|
30
|
-
transformUrl?: (url: string) => string;
|
|
31
|
-
}
|
|
32
|
-
export interface RouterInstance<R extends readonly RouteDefinition[] = RouteDefinition[]> {
|
|
33
|
-
/** The instance is the provider component; the render-prop child receives the matched content as `props.children`. */
|
|
34
|
-
(props: {
|
|
35
|
-
children?: (props: RouteSectionProps) => JSX.Element;
|
|
36
|
-
}): JSX.Element;
|
|
37
|
-
/** Typed path proxy — builds URLs through property access and calls. */
|
|
38
|
-
readonly paths: RoutePaths<R>;
|
|
39
|
-
readonly routes: R;
|
|
40
|
-
/** The config the instance was created with — lets server integrations (flight collector, no-JS handler) consume the instance directly. */
|
|
41
|
-
readonly config: RouterConfig<R>;
|
|
42
|
-
/** Pure matching against an arbitrary URL — no rendering or request context involved. Root→leaf; `[]` when nothing matches. */
|
|
43
|
-
match(url: string): OutputMatch[];
|
|
44
|
-
}
|
|
45
|
-
export declare function createRouter<const R extends readonly RouteDefinition[]>(config: RouterConfig<R>): RouterInstance<R>;
|
package/dist/routers/factory.jsx
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/*@refresh skip*/
|
|
2
|
-
import { createSignal, getOwner, onCleanup, sharedConfig, untrack } from "solid-js";
|
|
3
|
-
import { getRequestEvent, isServer } from "@solidjs/web";
|
|
4
|
-
import { setupLinkClaims } from "../claims.js";
|
|
5
|
-
import { setupNativeEvents } from "../data/events.js";
|
|
6
|
-
import { createPathsProxy } from "../paths.js";
|
|
7
|
-
import { createBranches, createRouterContext, getRouteMatches, registerFlightRouter, RouterContextObj, trackLazySubtrees, useOptionalContext } from "../routing.js";
|
|
8
|
-
import { mockBase } from "../utils.js";
|
|
9
|
-
import { Root, Routes } from "./components.jsx";
|
|
10
|
-
import { browserHistory } from "./history.js";
|
|
11
|
-
/**
|
|
12
|
-
* Identity helper that preserves literal types when the route tree is
|
|
13
|
-
* declared as a separate variable. `createRouter` infers literally from
|
|
14
|
-
* inline arrays, but an extracted `const routes = [...]` widens paths to
|
|
15
|
-
* `string` and silently degrades `paths` and the typed hooks unless it is
|
|
16
|
-
* declared `as const` — `defineRoutes` makes that impossible to forget.
|
|
17
|
-
*/
|
|
18
|
-
export function defineRoutes(routes) {
|
|
19
|
-
return routes;
|
|
20
|
-
}
|
|
21
|
-
/** Wraps a history adapter in the integration signal the router core consumes. Must run under a reactive owner. */
|
|
22
|
-
function createIntegration(history) {
|
|
23
|
-
let ignore = false;
|
|
24
|
-
const wrap = (value) => (typeof value === "string" ? { value } : value);
|
|
25
|
-
const [read, write] = createSignal(wrap(history.get()), {
|
|
26
|
-
equals: (a, b) => a.value === b.value && a.state === b.state,
|
|
27
|
-
ownedWrite: true
|
|
28
|
-
});
|
|
29
|
-
const signal = [
|
|
30
|
-
read,
|
|
31
|
-
(next) => {
|
|
32
|
-
!ignore && history.set(next);
|
|
33
|
-
if (sharedConfig.registry && !sharedConfig.done)
|
|
34
|
-
sharedConfig.done = true;
|
|
35
|
-
write(next);
|
|
36
|
-
}
|
|
37
|
-
];
|
|
38
|
-
history.init &&
|
|
39
|
-
onCleanup(history.init((value = history.get()) => {
|
|
40
|
-
ignore = true;
|
|
41
|
-
signal[1](wrap(value));
|
|
42
|
-
ignore = false;
|
|
43
|
-
}));
|
|
44
|
-
return { signal, utils: history.utils };
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Server default: a static view of the request URL — no signal machinery, a
|
|
48
|
-
* server render never navigates. Without a request event (SSG scripts,
|
|
49
|
-
* server-side tests) the configured history adapter provides the location,
|
|
50
|
-
* so e.g. `memoryHistory("/page")` works isomorphically.
|
|
51
|
-
*/
|
|
52
|
-
function staticIntegration(history) {
|
|
53
|
-
const e = getRequestEvent();
|
|
54
|
-
let value = "";
|
|
55
|
-
if (e) {
|
|
56
|
-
const url = new URL(e.request.url);
|
|
57
|
-
value = url.pathname + url.search;
|
|
58
|
-
}
|
|
59
|
-
else if (history) {
|
|
60
|
-
value = history.get();
|
|
61
|
-
}
|
|
62
|
-
const obj = typeof value === "string" ? { value } : { ...value };
|
|
63
|
-
return { signal: [() => obj, next => Object.assign(obj, next)], utils: history && history.utils };
|
|
64
|
-
}
|
|
65
|
-
export function createRouter(config) {
|
|
66
|
-
const basePath = config.base || "";
|
|
67
|
-
// Routes are immutable per instance, so compilation is shared by every
|
|
68
|
-
// mount, request, and `match()` call — recompiled only when a lazy subtree
|
|
69
|
-
// resolves (append-only: resolution, not mutation). Reading the version
|
|
70
|
-
// inside a computation subscribes it; plain calls just see current state.
|
|
71
|
-
let compiled;
|
|
72
|
-
let compiledVersion = -1;
|
|
73
|
-
const branches = () => {
|
|
74
|
-
const version = trackLazySubtrees();
|
|
75
|
-
if (!compiled || compiledVersion !== version) {
|
|
76
|
-
compiled = createBranches(config.routes, basePath);
|
|
77
|
-
compiledVersion = version;
|
|
78
|
-
}
|
|
79
|
-
return compiled;
|
|
80
|
-
};
|
|
81
|
-
const renderPath = (config.history && config.history.utils && config.history.utils.renderPath) || undefined;
|
|
82
|
-
function RouterComponent(props) {
|
|
83
|
-
// One router per app: the session (location, history, delegation, link
|
|
84
|
-
// claims, preloading) has a single owner, and a second instance would
|
|
85
|
-
// fight it — stale content on click navigations, conflicting link
|
|
86
|
-
// attributes. Compose route trees instead; lazy subtrees are the planned
|
|
87
|
-
// answer for definitions unknown at build time.
|
|
88
|
-
if (useOptionalContext(RouterContextObj)) {
|
|
89
|
-
console.warn("Mounting a router inside another router is not supported. " +
|
|
90
|
-
"Compose route trees in one createRouter config instead.");
|
|
91
|
-
}
|
|
92
|
-
const root = untrack(() => props.children);
|
|
93
|
-
const integration = isServer
|
|
94
|
-
? staticIntegration(config.history)
|
|
95
|
-
: createIntegration(config.history || browserHistory());
|
|
96
|
-
let context;
|
|
97
|
-
const routerState = createRouterContext(integration, branches, () => context, {
|
|
98
|
-
base: basePath,
|
|
99
|
-
singleFlight: config.singleFlight,
|
|
100
|
-
transformUrl: config.transformUrl
|
|
101
|
-
});
|
|
102
|
-
if (!isServer) {
|
|
103
|
-
setupNativeEvents({
|
|
104
|
-
preload: config.preloadLinks,
|
|
105
|
-
explicitLinks: config.explicitLinks,
|
|
106
|
-
actionBase: config.actionBase,
|
|
107
|
-
transformUrl: config.transformUrl
|
|
108
|
-
})(routerState);
|
|
109
|
-
setupLinkClaims(routerState, config.explicitLinks);
|
|
110
|
-
if (routerState.singleFlight)
|
|
111
|
-
onCleanup(registerFlightRouter(routerState));
|
|
112
|
-
}
|
|
113
|
-
return (<RouterContextObj value={routerState}>
|
|
114
|
-
<Root routerState={routerState} root={root} preload={config.preload}>
|
|
115
|
-
{(context = getOwner()) && null}
|
|
116
|
-
<Routes routerState={routerState} branches={branches}/>
|
|
117
|
-
</Root>
|
|
118
|
-
</RouterContextObj>);
|
|
119
|
-
}
|
|
120
|
-
const instance = Object.assign(RouterComponent, {
|
|
121
|
-
routes: config.routes,
|
|
122
|
-
config,
|
|
123
|
-
match(url) {
|
|
124
|
-
const u = new URL(url, mockBase);
|
|
125
|
-
const pathname = config.transformUrl ? config.transformUrl(u.pathname) : u.pathname;
|
|
126
|
-
return getRouteMatches(branches(), pathname).map(({ route, path, params }) => ({
|
|
127
|
-
path: route.originalPath,
|
|
128
|
-
pattern: route.pattern,
|
|
129
|
-
match: path,
|
|
130
|
-
params,
|
|
131
|
-
info: route.info
|
|
132
|
-
}));
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
// Built on first access (a getter via Object.assign would run during the
|
|
136
|
-
// copy) so runtimes without Proxy — some older TVs — can still route as
|
|
137
|
-
// long as they never touch typed paths.
|
|
138
|
-
let paths;
|
|
139
|
-
Object.defineProperty(instance, "paths", {
|
|
140
|
-
get: () => paths || (paths = createPathsProxy(renderPath, basePath))
|
|
141
|
-
});
|
|
142
|
-
return instance;
|
|
143
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { LocationChange, RouterUtils } from "../types.js";
|
|
2
|
-
/**
|
|
3
|
-
* A history adapter: the source of truth for the current URL and how
|
|
4
|
-
* navigations write back to it. Adapters are plain imported values so
|
|
5
|
-
* unused ones never enter the bundle — `createRouter` defaults to browser
|
|
6
|
-
* history on the client and the request URL on the server.
|
|
7
|
-
*/
|
|
8
|
-
export interface RouterHistory {
|
|
9
|
-
get: () => string | LocationChange;
|
|
10
|
-
set: (next: LocationChange) => void;
|
|
11
|
-
init?: (notify: (value?: string | LocationChange) => void) => () => void;
|
|
12
|
-
utils?: Partial<RouterUtils>;
|
|
13
|
-
}
|
|
14
|
-
export declare function browserHistory(): RouterHistory;
|
|
15
|
-
export declare function hashParser(str: string): string;
|
|
16
|
-
export declare function hashHistory(): RouterHistory;
|
|
17
|
-
export interface MemoryHistoryAdapter extends RouterHistory {
|
|
18
|
-
get: () => string;
|
|
19
|
-
go: (delta: number) => void;
|
|
20
|
-
back: () => void;
|
|
21
|
-
forward: () => void;
|
|
22
|
-
listen: (listener: (value: string) => void) => () => void;
|
|
23
|
-
}
|
|
24
|
-
export declare function memoryHistory(initial?: string): MemoryHistoryAdapter;
|
package/dist/routers/history.js
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { isServer } from "@solidjs/web";
|
|
2
|
-
function bindEvent(target, type, handler) {
|
|
3
|
-
target.addEventListener(type, handler);
|
|
4
|
-
return () => target.removeEventListener(type, handler);
|
|
5
|
-
}
|
|
6
|
-
// Depth stamping supports blocking browser-initiated navigation (back/forward)
|
|
7
|
-
// for `useBeforeLeave`. It stays always-on — a couple of history.state writes —
|
|
8
|
-
// so blocking stays exact no matter when the first guard subscribes, while the
|
|
9
|
-
// guard machinery itself lives behind the lazy `beforeLeave` slot.
|
|
10
|
-
let depth;
|
|
11
|
-
function saveCurrentDepth() {
|
|
12
|
-
if (!window.history.state || window.history.state._depth == null) {
|
|
13
|
-
window.history.replaceState({ ...window.history.state, _depth: window.history.length - 1 }, "");
|
|
14
|
-
}
|
|
15
|
-
depth = window.history.state._depth;
|
|
16
|
-
}
|
|
17
|
-
function keepDepth(state) {
|
|
18
|
-
return {
|
|
19
|
-
...state,
|
|
20
|
-
_depth: window.history.state && window.history.state._depth
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
function notifyIfNotBlocked(notify, block) {
|
|
24
|
-
let ignore = false;
|
|
25
|
-
return () => {
|
|
26
|
-
const prevDepth = depth;
|
|
27
|
-
saveCurrentDepth();
|
|
28
|
-
const delta = prevDepth == null ? null : depth - prevDepth;
|
|
29
|
-
if (ignore) {
|
|
30
|
-
ignore = false;
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
if (delta && block(delta)) {
|
|
34
|
-
ignore = true;
|
|
35
|
-
window.history.go(-delta);
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
notify();
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
function scrollToHash(hash, fallbackTop) {
|
|
43
|
-
const el = hash && document.getElementById(hash);
|
|
44
|
-
if (el) {
|
|
45
|
-
el.scrollIntoView();
|
|
46
|
-
}
|
|
47
|
-
else if (fallbackTop) {
|
|
48
|
-
window.scrollTo(0, 0);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
export function browserHistory() {
|
|
52
|
-
const getSource = () => {
|
|
53
|
-
const url = window.location.pathname + window.location.search;
|
|
54
|
-
const state = window.history.state &&
|
|
55
|
-
window.history.state._depth &&
|
|
56
|
-
Object.keys(window.history.state).length === 1
|
|
57
|
-
? undefined
|
|
58
|
-
: window.history.state;
|
|
59
|
-
return {
|
|
60
|
-
value: url + window.location.hash,
|
|
61
|
-
state
|
|
62
|
-
};
|
|
63
|
-
};
|
|
64
|
-
const beforeLeave = {};
|
|
65
|
-
if (!isServer)
|
|
66
|
-
saveCurrentDepth();
|
|
67
|
-
return {
|
|
68
|
-
get: getSource,
|
|
69
|
-
set({ value, replace, scroll, state }) {
|
|
70
|
-
if (replace) {
|
|
71
|
-
window.history.replaceState(keepDepth(state), "", value);
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
window.history.pushState(state, "", value);
|
|
75
|
-
}
|
|
76
|
-
scrollToHash(decodeURIComponent(window.location.hash.slice(1)), scroll);
|
|
77
|
-
saveCurrentDepth();
|
|
78
|
-
},
|
|
79
|
-
init: notify => bindEvent(window, "popstate", notifyIfNotBlocked(notify, delta => {
|
|
80
|
-
const guard = beforeLeave.current;
|
|
81
|
-
if (!guard)
|
|
82
|
-
return false;
|
|
83
|
-
if (delta) {
|
|
84
|
-
return !guard.confirm(delta);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
const s = getSource();
|
|
88
|
-
return !guard.confirm(s.value, { state: s.state });
|
|
89
|
-
}
|
|
90
|
-
})),
|
|
91
|
-
utils: {
|
|
92
|
-
go: delta => window.history.go(delta),
|
|
93
|
-
beforeLeave
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
export function hashParser(str) {
|
|
98
|
-
const to = str.replace(/^.*?#/, "");
|
|
99
|
-
// Hash-only hrefs like `#foo` from plain anchors will come in as `/#foo` whereas a link to
|
|
100
|
-
// `/foo` will be `/#/foo`. Check if the to starts with a `/` and if not append it as a hash
|
|
101
|
-
// to the current path so we can handle these in-page anchors correctly.
|
|
102
|
-
if (!to.startsWith("/")) {
|
|
103
|
-
const [, path = "/"] = window.location.hash.split("#", 2);
|
|
104
|
-
return `${path}#${to}`;
|
|
105
|
-
}
|
|
106
|
-
return to;
|
|
107
|
-
}
|
|
108
|
-
export function hashHistory() {
|
|
109
|
-
const getSource = () => window.location.hash.slice(1);
|
|
110
|
-
const beforeLeave = {};
|
|
111
|
-
if (!isServer)
|
|
112
|
-
saveCurrentDepth();
|
|
113
|
-
return {
|
|
114
|
-
get: getSource,
|
|
115
|
-
set({ value, replace, scroll, state }) {
|
|
116
|
-
if (replace) {
|
|
117
|
-
window.history.replaceState(keepDepth(state), "", "#" + value);
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
window.history.pushState(state, "", "#" + value);
|
|
121
|
-
}
|
|
122
|
-
const hashIndex = value.indexOf("#");
|
|
123
|
-
const hash = hashIndex >= 0 ? value.slice(hashIndex + 1) : "";
|
|
124
|
-
scrollToHash(hash, scroll);
|
|
125
|
-
saveCurrentDepth();
|
|
126
|
-
},
|
|
127
|
-
init: notify => bindEvent(window, "hashchange", notifyIfNotBlocked(notify, delta => {
|
|
128
|
-
const guard = beforeLeave.current;
|
|
129
|
-
return !!guard && !guard.confirm(delta && delta < 0 ? delta : getSource());
|
|
130
|
-
})),
|
|
131
|
-
utils: {
|
|
132
|
-
go: delta => window.history.go(delta),
|
|
133
|
-
renderPath: path => `#${path}`,
|
|
134
|
-
parsePath: hashParser,
|
|
135
|
-
beforeLeave
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
export function memoryHistory(initial = "/") {
|
|
140
|
-
const entries = [initial];
|
|
141
|
-
let index = 0;
|
|
142
|
-
const listeners = [];
|
|
143
|
-
const go = (n) => {
|
|
144
|
-
// https://github.com/remix-run/react-router/blob/682810ca929d0e3c64a76f8d6e465196b7a2ac58/packages/router/history.ts#L245
|
|
145
|
-
index = Math.max(0, Math.min(index + n, entries.length - 1));
|
|
146
|
-
const value = entries[index];
|
|
147
|
-
listeners.forEach(listener => listener(value));
|
|
148
|
-
};
|
|
149
|
-
const listen = (listener) => {
|
|
150
|
-
listeners.push(listener);
|
|
151
|
-
return () => {
|
|
152
|
-
const i = listeners.indexOf(listener);
|
|
153
|
-
listeners.splice(i, 1);
|
|
154
|
-
};
|
|
155
|
-
};
|
|
156
|
-
return {
|
|
157
|
-
get: () => entries[index],
|
|
158
|
-
set: ({ value, scroll, replace }) => {
|
|
159
|
-
if (replace) {
|
|
160
|
-
entries[index] = value;
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
entries.splice(index + 1, entries.length - index, value);
|
|
164
|
-
index++;
|
|
165
|
-
}
|
|
166
|
-
listeners.forEach(listener => listener(value));
|
|
167
|
-
setTimeout(() => {
|
|
168
|
-
if (scroll) {
|
|
169
|
-
scrollToHash(value.split("#")[1] || "", true);
|
|
170
|
-
}
|
|
171
|
-
}, 0);
|
|
172
|
-
},
|
|
173
|
-
back: () => go(-1),
|
|
174
|
-
forward: () => go(1),
|
|
175
|
-
go,
|
|
176
|
-
listen,
|
|
177
|
-
init: listen,
|
|
178
|
-
utils: { go }
|
|
179
|
-
};
|
|
180
|
-
}
|
package/dist/server.d.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type { JSX } from "@solidjs/web";
|
|
2
|
-
import type { CollectFlightDataHook, ServerFunctionOutcome } from "@solidjs/web/server-functions/server";
|
|
3
|
-
import type { RouteDefinition, RoutePreloadFunc } from "./types.js";
|
|
4
|
-
export type { FlashSubmission } from "./data/flash.js";
|
|
5
|
-
export type { CollectFlightDataHook, ServerFunctionOutcome };
|
|
6
|
-
export interface FlightDataCollectorOptions {
|
|
7
|
-
/**
|
|
8
|
-
* The app's route tree — the same config objects the `createRouter`
|
|
9
|
-
* factory receives, an array of them, or a thunk producing either (for
|
|
10
|
-
* lazily/per-request built trees). Flight data is produced by the pure
|
|
11
|
-
* preload runner: the target URL is matched against the tree and the
|
|
12
|
-
* matched routes' `preload` functions run in data-only mode.
|
|
13
|
-
*/
|
|
14
|
-
routes: RouteDefinition | readonly RouteDefinition[] | (() => RouteDefinition | readonly RouteDefinition[]);
|
|
15
|
-
/**
|
|
16
|
-
* The root layout's preload — the same function the app passes to the
|
|
17
|
-
* `createRouter` factory's `preload` option. Runs before the matched
|
|
18
|
-
* routes' preloads with the semantics the root gets during a real server
|
|
19
|
-
* render: the merged params of every match and `intent: "initial"`.
|
|
20
|
-
*/
|
|
21
|
-
rootPreload?: RoutePreloadFunc;
|
|
22
|
-
/** The app's base path, for resolving redirect `Location`s and matching. */
|
|
23
|
-
base?: string;
|
|
24
|
-
}
|
|
25
|
-
/** A `createRouter` instance carries everything the collector needs. */
|
|
26
|
-
interface RouterInstanceLike {
|
|
27
|
-
(props: any): JSX.Element;
|
|
28
|
-
readonly routes: readonly RouteDefinition[];
|
|
29
|
-
readonly config: {
|
|
30
|
-
base?: string;
|
|
31
|
-
preload?: RoutePreloadFunc;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Produces the `collectFlightData` implementation for
|
|
36
|
-
* `configureServerFunctionsServer` (or `handleServerFunctionRequest`
|
|
37
|
-
* options). Accepts a `createRouter` instance directly — its routes, base,
|
|
38
|
-
* and `preload` are the single source of truth — or an options object for
|
|
39
|
-
* trees not created through the factory.
|
|
40
|
-
*
|
|
41
|
-
* Strategy: rerun the route data for the URL the client will show
|
|
42
|
-
* after the mutation — the redirect `Location` when the outcome carries
|
|
43
|
-
* one, the referring page otherwise — collecting each `query` result under
|
|
44
|
-
* its cache key, scoped to the outcome's `X-Revalidate` keys when present
|
|
45
|
-
* (routes newly entered via redirect always collect fully). The returned
|
|
46
|
-
* payload seeds the client router's cache through its registered
|
|
47
|
-
* flight-data consumer.
|
|
48
|
-
*/
|
|
49
|
-
export declare function createFlightDataCollector(options: FlightDataCollectorOptions | RouterInstanceLike): CollectFlightDataHook;
|
|
50
|
-
/**
|
|
51
|
-
* The request headers for the flight-data collection pass: the source
|
|
52
|
-
* request's headers with the mutation's `Set-Cookie` mutations folded into
|
|
53
|
-
* the `Cookie` header, so preloads observe the post-mutation cookie state
|
|
54
|
-
* (deletions honored via Max-Age/Expires).
|
|
55
|
-
*/
|
|
56
|
-
export declare function createSingleFlightHeaders(sourceEvent: {
|
|
57
|
-
request: Request;
|
|
58
|
-
response?: {
|
|
59
|
-
headers?: Headers;
|
|
60
|
-
};
|
|
61
|
-
}): Headers;
|
|
62
|
-
export interface NoJSHandlerOptions {
|
|
63
|
-
/** The app's base path, for resolving redirect `Location`s. */
|
|
64
|
-
base?: string;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Produces the `handleNoJS` implementation for
|
|
68
|
-
* `handleServerFunctionRequest` options: form posts made without the client
|
|
69
|
-
* runtime redirect back to the referring page (or to the result's
|
|
70
|
-
* `Location`) with the outcome riding a one-shot `flash` cookie. The
|
|
71
|
-
* router's SSR initialization reads the cookie into submission state, so
|
|
72
|
-
* `useSubmission()` renders the result exactly as a scripted submission
|
|
73
|
-
* would — progressive enhancement with no app code.
|
|
74
|
-
*/
|
|
75
|
-
export declare function createNoJSHandler(options?: NoJSHandlerOptions): (result: unknown, request: Request, args: unknown[], thrown?: boolean) => Response;
|