@solidjs/router 0.17.0-next.5 → 1.0.0-next.10
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 +526 -716
- package/dist/claims.d.ts +21 -0
- package/dist/claims.js +115 -0
- package/dist/data/action.d.ts +28 -1
- package/dist/data/action.js +218 -52
- package/dist/data/events.d.ts +8 -0
- package/dist/data/events.js +23 -22
- package/dist/data/flash.d.ts +21 -0
- package/dist/data/flash.js +78 -0
- package/dist/data/flashCookie.d.ts +7 -0
- package/dist/data/flashCookie.js +20 -0
- package/dist/data/query.js +11 -4
- package/dist/data/serverForms.d.ts +1 -0
- package/dist/data/serverForms.js +5 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +1548 -683
- package/dist/index.jsx +2 -2
- package/dist/lifecycle.d.ts +29 -4
- package/dist/lifecycle.js +40 -37
- package/dist/paths.d.ts +117 -0
- package/dist/paths.js +41 -0
- package/dist/routers/components.d.ts +10 -21
- package/dist/routers/components.jsx +29 -44
- package/dist/routers/factory.d.ts +66 -0
- package/dist/routers/factory.jsx +151 -0
- package/dist/routers/history.d.ts +26 -0
- package/dist/routers/history.js +180 -0
- package/dist/routers/index.d.ts +4 -11
- package/dist/routers/index.js +2 -6
- package/dist/routers/scrollRestoration.d.ts +33 -0
- package/dist/routers/scrollRestoration.js +135 -0
- package/dist/routing.d.ts +80 -44
- package/dist/routing.js +311 -108
- package/dist/server.d.ts +79 -0
- package/dist/server.js +284 -0
- package/dist/types.d.ts +75 -6
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +2 -0
- package/package.json +10 -8
- package/dist/components.d.ts +0 -31
- package/dist/components.jsx +0 -46
- package/dist/routers/HashRouter.d.ts +0 -9
- package/dist/routers/HashRouter.js +0 -41
- package/dist/routers/MemoryRouter.d.ts +0 -24
- package/dist/routers/MemoryRouter.js +0 -57
- package/dist/routers/Router.d.ts +0 -9
- package/dist/routers/Router.js +0 -45
- package/dist/routers/StaticRouter.d.ts +0 -6
- package/dist/routers/StaticRouter.js +0 -15
- package/dist/routers/createRouter.d.ts +0 -10
- package/dist/routers/createRouter.js +0 -40
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// The no-JS form convention's cookie codec. When a form posts to a server
|
|
2
|
+
// function without the client runtime (no instance header), the server
|
|
3
|
+
// handler redirects back carrying the outcome in a one-shot "flash" cookie;
|
|
4
|
+
// the next SSR pass reads it and seeds the router's submission state so
|
|
5
|
+
// useSubmission() renders the result exactly as a scripted submission would.
|
|
6
|
+
// Both codec halves live in this module so the write (src/server.ts, the
|
|
7
|
+
// handler's handleNoJS) and the read (provided to the router core by
|
|
8
|
+
// data/action.ts) can never drift apart. The cookie's name/clearing live in
|
|
9
|
+
// flashCookie.ts — the only piece the router core itself consumes — so this
|
|
10
|
+
// codec stays out of bundles that never load the action layer.
|
|
11
|
+
import { FLASH_COOKIE, matchFlashCookie } from "./flashCookie.js";
|
|
12
|
+
export { FLASH_COOKIE, hasFlashCookie, clearFlashCookie } from "./flashCookie.js";
|
|
13
|
+
// Form payloads have no JSON encoding, so entries are captured as pair
|
|
14
|
+
// arrays under a marker key ($f / $u) and revived to real FormData /
|
|
15
|
+
// URLSearchParams on the way out. File entries cannot ride a cookie and are
|
|
16
|
+
// dropped.
|
|
17
|
+
function encodeInputValue(value) {
|
|
18
|
+
if (value instanceof FormData)
|
|
19
|
+
return { $f: [...value.entries()].filter(([, v]) => typeof v === "string") };
|
|
20
|
+
if (value instanceof URLSearchParams)
|
|
21
|
+
return { $u: [...value.entries()] };
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
function decodeInputValue(value) {
|
|
25
|
+
if (value && typeof value === "object") {
|
|
26
|
+
if (Array.isArray(value.$f)) {
|
|
27
|
+
const form = new FormData();
|
|
28
|
+
for (const [k, v] of value.$f)
|
|
29
|
+
form.append(k, v);
|
|
30
|
+
return form;
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(value.$u))
|
|
33
|
+
return new URLSearchParams(value.$u);
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Encodes the outcome of a no-JS submission as a Set-Cookie value. `url` is
|
|
39
|
+
* the action url (pathname + search of the server function call) so the
|
|
40
|
+
* seeded submission matches `useSubmission` filters; `thrown` errors land on
|
|
41
|
+
* `error`, returned values on `result` (mirroring the scripted split).
|
|
42
|
+
*/
|
|
43
|
+
export function encodeFlashCookie(url, result, input, thrown) {
|
|
44
|
+
const isError = result instanceof Error;
|
|
45
|
+
const payload = {
|
|
46
|
+
url,
|
|
47
|
+
result: isError ? result.message : result,
|
|
48
|
+
error: isError,
|
|
49
|
+
thrown: !!thrown,
|
|
50
|
+
input: input.map(encodeInputValue)
|
|
51
|
+
};
|
|
52
|
+
return `${FLASH_COOKIE}=${encodeURIComponent(JSON.stringify(payload))}; Secure; HttpOnly; Path=/`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Decodes the flash cookie out of a request's Cookie header. Returns
|
|
56
|
+
* undefined when absent or unreadable (a malformed cookie must never take
|
|
57
|
+
* down SSR — it is cleared either way).
|
|
58
|
+
*/
|
|
59
|
+
export function decodeFlashCookie(cookieHeader) {
|
|
60
|
+
const match = matchFlashCookie(cookieHeader);
|
|
61
|
+
if (!match)
|
|
62
|
+
return;
|
|
63
|
+
try {
|
|
64
|
+
const payload = JSON.parse(decodeURIComponent(match));
|
|
65
|
+
if (!payload || !payload.result)
|
|
66
|
+
return;
|
|
67
|
+
const result = payload.error ? new Error(payload.result) : payload.result;
|
|
68
|
+
return {
|
|
69
|
+
input: Array.isArray(payload.input) ? payload.input.map(decodeInputValue) : [],
|
|
70
|
+
url: payload.url,
|
|
71
|
+
result: payload.thrown ? undefined : result,
|
|
72
|
+
error: payload.thrown ? result : undefined
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error(error);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const FLASH_COOKIE = "flash";
|
|
2
|
+
/** Whether a Cookie header carries a flash cookie (readable or not). */
|
|
3
|
+
export declare function hasFlashCookie(cookieHeader: string | null): boolean;
|
|
4
|
+
/** The raw encoded flash payload out of a Cookie header, if present. */
|
|
5
|
+
export declare function matchFlashCookie(cookieHeader: string | null): string | undefined;
|
|
6
|
+
/** The Set-Cookie value clearing the flash cookie after it has been read. */
|
|
7
|
+
export declare function clearFlashCookie(): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// The flash cookie's name and one-shot clearing — split from the codec in
|
|
2
|
+
// flash.ts so the router core can consume the cookie eagerly (the clear must
|
|
3
|
+
// be appended before streaming flushes the response headers, and an unread
|
|
4
|
+
// outcome must not haunt a later request) without carrying the encode/decode
|
|
5
|
+
// machinery into client bundles that never load the action layer.
|
|
6
|
+
export const FLASH_COOKIE = "flash";
|
|
7
|
+
const FLASH_MATCHER = new RegExp(`(?:^|;\\s*)${FLASH_COOKIE}=([^;]+)`);
|
|
8
|
+
/** Whether a Cookie header carries a flash cookie (readable or not). */
|
|
9
|
+
export function hasFlashCookie(cookieHeader) {
|
|
10
|
+
return !!cookieHeader && FLASH_MATCHER.test(cookieHeader);
|
|
11
|
+
}
|
|
12
|
+
/** The raw encoded flash payload out of a Cookie header, if present. */
|
|
13
|
+
export function matchFlashCookie(cookieHeader) {
|
|
14
|
+
const match = cookieHeader && cookieHeader.match(FLASH_MATCHER);
|
|
15
|
+
return match ? match[1] : undefined;
|
|
16
|
+
}
|
|
17
|
+
/** The Set-Cookie value clearing the flash cookie after it has been read. */
|
|
18
|
+
export function clearFlashCookie() {
|
|
19
|
+
return `${FLASH_COOKIE}=; Max-Age=0; Path=/`;
|
|
20
|
+
}
|
package/dist/data/query.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createSignal, getObserver, getOwner, onCleanup, sharedConfig } from "solid-js";
|
|
2
2
|
import { getRequestEvent, isResponseEnvelope, isServer } from "@solidjs/web";
|
|
3
|
-
import { decodeResponse } from "@solidjs/web/server-functions";
|
|
3
|
+
import { GET, decodeResponse, getServerFunctionMetadata, isServerFunction } from "@solidjs/web/server-functions";
|
|
4
4
|
import { useNavigate, getIntent, getInPreloadFn } from "../routing.js";
|
|
5
5
|
const LocationHeader = "Location";
|
|
6
6
|
const PRELOAD_TIMEOUT = 5000;
|
|
@@ -43,9 +43,16 @@ export function cacheKeyOp(key, fn) {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
export function query(fn, name) {
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
// query implies GET: the router primitive is the declaration site, so a
|
|
47
|
+
// server function handed to query() is wrapped with core `GET(fn)` here,
|
|
48
|
+
// at query-creation (module scope) — the server half records the method
|
|
49
|
+
// declaration for dispatch, the client half swaps in the GET transport.
|
|
50
|
+
// An explicit `GET(fn)` already carries the declaration on the metadata
|
|
51
|
+
// channel (`getServerFunctionMetadata(fn)?.method === "GET"`) and passes
|
|
52
|
+
// through; non-server functions are untouched.
|
|
53
|
+
if (isServerFunction(fn) && !getServerFunctionMetadata(fn)?.method) {
|
|
54
|
+
fn = GET(fn);
|
|
55
|
+
}
|
|
49
56
|
const cachedFn = ((...args) => {
|
|
50
57
|
const cache = getCache();
|
|
51
58
|
const intent = getIntent();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { submitServerForm } from "./action.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// The delegation fallback's lazy entry (see data/events.ts). Nothing imports
|
|
2
|
+
// this module statically — it exists so the dynamic import has a target that
|
|
3
|
+
// bundlers can keep as a split point: router-only apps never load the action
|
|
4
|
+
// machinery unless a server-action form actually submits.
|
|
5
|
+
export { submitServerForm } from "./action.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export * from "./routers/index.js";
|
|
2
|
-
export * from "./components.jsx";
|
|
3
2
|
export * from "./lifecycle.js";
|
|
4
|
-
export { useHref, useIsRouting, useLocation, useMatch,
|
|
3
|
+
export { useHref, useIsRouting, useLinkState, useLocation, useMatch, useNavigate, usePreloadRoute, useParams, useResolvedPath, useRouteMatches, useSearchParams, RouterContextObj as RouterContext } from "./routing.js";
|
|
4
|
+
export type { LinkState } from "./routing.js";
|
|
5
5
|
export { mergeSearchString as _mergeSearchString } from "./utils.js";
|
|
6
|
+
export { int } from "./paths.js";
|
|
7
|
+
export type { RoutePaths, PathParamsOf, PathEnd, TypedMatchFilter, DefaultSearchTypes } from "./paths.js";
|
|
6
8
|
export * from "./data/index.js";
|
|
7
|
-
export type { Location, LocationChange, SearchParams, MatchFilter, MatchFilters, NavigateOptions, Navigator, OutputMatch, Params, PathMatch, RouteSectionProps, RoutePreloadFunc, RoutePreloadFuncArgs, RouteDefinition, RouteDescription, RouteMatch, RouterIntegration, RouterUtils, SetParams, Submission, BeforeLeaveEventArgs } from "./types.js";
|
|
9
|
+
export type { Location, LocationChange, SearchParams, MatchFilter, MatchFilters, NavigateOptions, Navigator, OutputMatch, Params, PathMatch, RouteSectionProps, RoutePreloadFunc, RoutePreloadFuncArgs, RouteDefinition, RouteDescription, RouteMatch, RouterIntegration, RouterUtils, SetParams, SetSearchParams, Submission, BeforeLeaveEventArgs, TypedPath, TypedSearchPath, StandardSchemaV1 } from "./types.js";
|