@nifrajs/web 2.2.0 → 2.3.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 +3 -3
- package/dist/build-vite.d.ts +4 -4
- package/dist/build-vite.d.ts.map +1 -1
- package/dist/build-vite.js +20 -74
- package/dist/build-vite.js.map +1 -1
- package/dist/build.d.ts +64 -42
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +100 -78
- package/dist/build.js.map +1 -1
- package/dist/bun-dev-entry.d.ts +1 -1
- package/dist/bun-dev-entry.js +1 -1
- package/dist/chunk-names.js +1 -1
- package/dist/client.d.ts +3 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +201 -29
- package/dist/client.js.map +1 -1
- package/dist/conformance.d.ts +2 -2
- package/dist/conformance.js +3 -3
- package/dist/deferred.d.ts +11 -11
- package/dist/deferred.d.ts.map +1 -1
- package/dist/deferred.js +16 -16
- package/dist/dev-error.d.ts +2 -2
- package/dist/dev-error.js +3 -3
- package/dist/dev-port.d.ts +2 -2
- package/dist/dev-port.js +1 -1
- package/dist/dev.d.ts +3 -3
- package/dist/dev.js +9 -9
- package/dist/draft.d.ts +12 -12
- package/dist/draft.js +11 -11
- package/dist/fn-state.d.ts +56 -0
- package/dist/fn-state.d.ts.map +1 -0
- package/dist/fn-state.js +77 -0
- package/dist/fn-state.js.map +1 -0
- package/dist/fn.d.ts +111 -0
- package/dist/fn.d.ts.map +1 -0
- package/dist/fn.js +125 -0
- package/dist/fn.js.map +1 -0
- package/dist/fonts-google.d.ts +9 -9
- package/dist/fonts-google.js +10 -10
- package/dist/fonts.d.ts +7 -7
- package/dist/fonts.js +1 -1
- package/dist/forms.d.ts +8 -8
- package/dist/fs.d.ts +1 -1
- package/dist/fs.js +1 -1
- package/dist/index.d.ts +151 -70
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +317 -139
- package/dist/index.js.map +1 -1
- package/dist/internal/head-attributes.d.ts +15 -0
- package/dist/internal/head-attributes.d.ts.map +1 -0
- package/dist/internal/head-attributes.js +99 -0
- package/dist/internal/head-attributes.js.map +1 -0
- package/dist/internal/script-types.d.ts +14 -0
- package/dist/internal/script-types.d.ts.map +1 -0
- package/dist/internal/script-types.js +17 -0
- package/dist/internal/script-types.js.map +1 -0
- package/dist/internal/server-boundary.d.ts +60 -0
- package/dist/internal/server-boundary.d.ts.map +1 -0
- package/dist/internal/server-boundary.js +174 -0
- package/dist/internal/server-boundary.js.map +1 -0
- package/dist/internal/timing-safe-equal.d.ts +1 -1
- package/dist/internal/timing-safe-equal.js +1 -1
- package/dist/internal/vite-import.d.ts +63 -0
- package/dist/internal/vite-import.d.ts.map +1 -0
- package/dist/internal/vite-import.js +94 -0
- package/dist/internal/vite-import.js.map +1 -0
- package/dist/islands.d.ts +5 -5
- package/dist/islands.js +5 -5
- package/dist/isr.d.ts +15 -15
- package/dist/isr.js +7 -7
- package/dist/manifest.d.ts +73 -35
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +10 -16
- package/dist/manifest.js.map +1 -1
- package/dist/module-graph.d.ts +5 -5
- package/dist/module-graph.js +4 -4
- package/dist/navigation.d.ts +120 -5
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +37 -5
- package/dist/navigation.js.map +1 -1
- package/dist/plugins/css-modules.d.ts +3 -3
- package/dist/plugins/css-modules.js +0 -0
- package/dist/plugins/kit.d.ts +8 -8
- package/dist/plugins/kit.js +9 -9
- package/dist/plugins/scss.js +3 -3
- package/dist/plugins/vite-leak-guard.d.ts +1 -1
- package/dist/plugins/vite-leak-guard.js +1 -1
- package/dist/plugins/vite-server-fn.d.ts +23 -0
- package/dist/plugins/vite-server-fn.d.ts.map +1 -0
- package/dist/plugins/vite-server-fn.js +51 -0
- package/dist/plugins/vite-server-fn.js.map +1 -0
- package/dist/plugins/vite-server-only.d.ts +49 -0
- package/dist/plugins/vite-server-only.d.ts.map +1 -0
- package/dist/plugins/vite-server-only.js +57 -0
- package/dist/plugins/vite-server-only.js.map +1 -0
- package/dist/prerender.d.ts +5 -5
- package/dist/prerender.js +7 -7
- package/dist/query.d.ts +10 -10
- package/dist/query.js +15 -15
- package/dist/route-manifest.d.ts +1 -1
- package/dist/route-manifest.js +2 -2
- package/dist/router.d.ts +30 -21
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +57 -28
- package/dist/router.js.map +1 -1
- package/dist/search.d.ts +94 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +232 -0
- package/dist/search.js.map +1 -0
- package/dist/server-only.d.ts +6 -6
- package/dist/server-only.js +7 -7
- package/dist/service-worker.d.ts +56 -0
- package/dist/service-worker.d.ts.map +1 -0
- package/dist/service-worker.js +127 -0
- package/dist/service-worker.js.map +1 -0
- package/dist/vite.d.ts +15 -13
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +31 -21
- package/dist/vite.js.map +1 -1
- package/package.json +33 -4
- package/server-manifest.d.ts +31 -0
- package/src/build-vite.ts +24 -77
- package/src/build.ts +137 -105
- package/src/bun-dev-entry.ts +1 -1
- package/src/chunk-names.ts +1 -1
- package/src/client.ts +215 -32
- package/src/conformance.ts +3 -3
- package/src/deferred.ts +17 -17
- package/src/dev-error.ts +3 -3
- package/src/dev-port.ts +2 -2
- package/src/dev.ts +12 -12
- package/src/draft.ts +15 -15
- package/src/fn-state.ts +107 -0
- package/src/fn.ts +199 -0
- package/src/fonts-google.ts +13 -13
- package/src/fonts.ts +7 -7
- package/src/forms.ts +8 -8
- package/src/fs.ts +2 -2
- package/src/index.ts +460 -181
- package/src/internal/head-attributes.ts +109 -0
- package/src/internal/script-types.ts +18 -0
- package/src/internal/server-boundary.ts +187 -0
- package/src/internal/timing-safe-equal.ts +1 -1
- package/src/internal/vite-import.ts +92 -0
- package/src/islands.ts +7 -7
- package/src/isr.ts +17 -17
- package/src/manifest.ts +83 -42
- package/src/module-graph.ts +6 -6
- package/src/navigation.ts +151 -5
- package/src/plugins/css-modules.ts +0 -0
- package/src/plugins/kit.ts +11 -11
- package/src/plugins/scss.ts +3 -3
- package/src/plugins/vite-leak-guard.ts +2 -2
- package/src/plugins/vite-server-fn.ts +67 -0
- package/src/plugins/vite-server-only.ts +75 -0
- package/src/prerender.ts +10 -10
- package/src/query.ts +22 -22
- package/src/route-manifest.ts +3 -3
- package/src/router.ts +91 -41
- package/src/search.ts +297 -0
- package/src/server-only.ts +7 -7
- package/src/service-worker.ts +165 -0
- package/src/vite.ts +41 -29
package/dist/prerender.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type RouteEntry } from "./manifest.js";
|
|
2
|
-
/** Minimal app surface the driver needs
|
|
2
|
+
/** Minimal app surface the driver needs - just a fetch handler (a built `createWebApp`). */
|
|
3
3
|
export interface PrerenderApp {
|
|
4
4
|
fetch(req: Request): Response | Promise<Response>;
|
|
5
5
|
}
|
|
@@ -33,7 +33,7 @@ export interface PrerenderResult {
|
|
|
33
33
|
readonly path: string;
|
|
34
34
|
readonly reason: string;
|
|
35
35
|
}[];
|
|
36
|
-
/** Per dynamic route pattern, its `getStaticPaths` `fallback` (`"ssr"` default)
|
|
36
|
+
/** Per dynamic route pattern, its `getStaticPaths` `fallback` (`"ssr"` default) - so the deploy
|
|
37
37
|
* layer knows whether unlisted paths should hit the worker (`"ssr"`) or 404 (`"404"`). */
|
|
38
38
|
readonly fallbacks: Readonly<Record<string, "ssr" | "404">>;
|
|
39
39
|
}
|
|
@@ -44,7 +44,7 @@ export declare function htmlFileFor(pattern: string): string;
|
|
|
44
44
|
export declare function dataFileFor(pattern: string): string;
|
|
45
45
|
/**
|
|
46
46
|
* Render every opted-in static route to a static `index.html` under `outDir`. Run AFTER `buildClient`
|
|
47
|
-
* (so the app references the hashed client entry). Returns a report of what was emitted vs skipped
|
|
47
|
+
* (so the app references the hashed client entry). Returns a report of what was emitted vs skipped -
|
|
48
48
|
* the caller can use `prerendered` to wire a hybrid deploy (e.g. exclude those paths from the SSR
|
|
49
49
|
* worker so the CDN serves the static file). Never throws on a per-route miss: a non-OK response or a
|
|
50
50
|
* non-opted/dynamic route is recorded in `skipped` and the build continues.
|
|
@@ -59,7 +59,7 @@ export interface CloudflarePagesRoutes {
|
|
|
59
59
|
}
|
|
60
60
|
export interface CloudflarePagesRoutesOptions {
|
|
61
61
|
/** Prerendered request paths (e.g. `prerenderRoutes(...).prerendered.map(p => p.path)`, or the
|
|
62
|
-
* build's `prerendered.json`). Each is excluded from the worker
|
|
62
|
+
* build's `prerendered.json`). Each is excluded from the worker - plus its static `_data.json`. */
|
|
63
63
|
readonly prerendered: readonly string[];
|
|
64
64
|
/** Extra globs to keep OFF the worker (CDN-served). Default `["/assets/*"]` (the hashed bundle). */
|
|
65
65
|
readonly staticGlobs?: readonly string[];
|
|
@@ -71,7 +71,7 @@ export interface CloudflarePagesRoutesOptions {
|
|
|
71
71
|
*
|
|
72
72
|
* ⚠️ Cloudflare caps `_routes.json` at **100** include+exclude rules total, and each prerendered path
|
|
73
73
|
* costs 2 (the doc + its `_data.json`). For a large SSG site, exclude by **prefix glob** (e.g.
|
|
74
|
-
* `/blog/*`) instead of listing every path
|
|
74
|
+
* `/blog/*`) instead of listing every path - pass those via `staticGlobs` and a smaller `prerendered`.
|
|
75
75
|
*/
|
|
76
76
|
export declare function cloudflarePagesRoutes(options: CloudflarePagesRoutesOptions): CloudflarePagesRoutes;
|
|
77
77
|
//# sourceMappingURL=prerender.d.ts.map
|
package/dist/prerender.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Build-time SSG driver. Prerendering is framework-agnostic by construction: a nifra SSR page is
|
|
3
3
|
* "just `app.fetch(GET)` returning a streamed `Response`", so prerendering = drive that same handler
|
|
4
4
|
* at build with a synthetic request, drain the body to bytes, and write the HTML to disk. No adapter
|
|
5
|
-
* (React/Solid/Vue/Preact/Svelte) is touched
|
|
5
|
+
* (React/Solid/Vue/Preact/Svelte) is touched - this sits entirely above the render seam.
|
|
6
6
|
*
|
|
7
7
|
* Handles **static** routes (opt in via `export const prerender = true`) and **dynamic** `:param`
|
|
8
8
|
* routes (enumerate concrete params via `export const getStaticPaths`). Catch-all/wildcard (`*`)
|
|
@@ -28,7 +28,7 @@ const outputPath = (root, file) => {
|
|
|
28
28
|
};
|
|
29
29
|
/**
|
|
30
30
|
* Render every opted-in static route to a static `index.html` under `outDir`. Run AFTER `buildClient`
|
|
31
|
-
* (so the app references the hashed client entry). Returns a report of what was emitted vs skipped
|
|
31
|
+
* (so the app references the hashed client entry). Returns a report of what was emitted vs skipped -
|
|
32
32
|
* the caller can use `prerendered` to wire a hybrid deploy (e.g. exclude those paths from the SSR
|
|
33
33
|
* worker so the CDN serves the static file). Never throws on a per-route miss: a non-OK response or a
|
|
34
34
|
* non-opted/dynamic route is recorded in `skipped` and the build continues.
|
|
@@ -44,7 +44,7 @@ export async function prerenderRoutes(options) {
|
|
|
44
44
|
const renderPath = async (path) => {
|
|
45
45
|
const res = await options.app.fetch(new Request(`${origin}${path}`));
|
|
46
46
|
if (!res.ok) {
|
|
47
|
-
// A failed render is a per-route skip, not a build failure
|
|
47
|
+
// A failed render is a per-route skip, not a build failure - surfaced for the caller to log.
|
|
48
48
|
skipped.push({ path, reason: `render returned HTTP ${res.status}` });
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
@@ -59,7 +59,7 @@ export async function prerenderRoutes(options) {
|
|
|
59
59
|
writeFileSync(abs, html);
|
|
60
60
|
// Also emit the loader data as a static `_data.json` next to it, so a client soft-nav into this
|
|
61
61
|
// route fetches a file instead of hitting the worker. Only when the data-mode response is plain
|
|
62
|
-
// JSON
|
|
62
|
+
// JSON - a deferred loader answers with NDJSON, which the static fast-path doesn't cover (the
|
|
63
63
|
// client falls back to the worker for those).
|
|
64
64
|
let dataFile;
|
|
65
65
|
const dataRes = await options.app.fetch(new Request(`${origin}${path}`, { headers: { [DATA_HEADER]: "1" } }));
|
|
@@ -76,13 +76,13 @@ export async function prerenderRoutes(options) {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
else {
|
|
79
|
-
await dataRes.body?.cancel(); // not emitting (non-OK or NDJSON)
|
|
79
|
+
await dataRes.body?.cancel(); // not emitting (non-OK or NDJSON) - release the stream
|
|
80
80
|
}
|
|
81
81
|
prerendered.push({ path, file, bytes: html.length, ...(dataFile ? { dataFile } : {}) });
|
|
82
82
|
};
|
|
83
83
|
for (const route of options.routes) {
|
|
84
84
|
if (route.pattern.includes("*")) {
|
|
85
|
-
skipped.push({ path: route.pattern, reason: "catch-all/wildcard route
|
|
85
|
+
skipped.push({ path: route.pattern, reason: "catch-all/wildcard route - not supported" });
|
|
86
86
|
continue;
|
|
87
87
|
}
|
|
88
88
|
const mod = await route.load();
|
|
@@ -126,7 +126,7 @@ export async function prerenderRoutes(options) {
|
|
|
126
126
|
*
|
|
127
127
|
* ⚠️ Cloudflare caps `_routes.json` at **100** include+exclude rules total, and each prerendered path
|
|
128
128
|
* costs 2 (the doc + its `_data.json`). For a large SSG site, exclude by **prefix glob** (e.g.
|
|
129
|
-
* `/blog/*`) instead of listing every path
|
|
129
|
+
* `/blog/*`) instead of listing every path - pass those via `staticGlobs` and a smaller `prerendered`.
|
|
130
130
|
*/
|
|
131
131
|
export function cloudflarePagesRoutes(options) {
|
|
132
132
|
const exclude = [...(options.staticGlobs ?? ["/assets/*"])];
|
package/dist/query.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The agnostic keyed query-cache
|
|
2
|
+
* The agnostic keyed query-cache - a `query(key, fn)` primitive with in-flight dedup, `staleTime`
|
|
3
3
|
* freshness, prefix `invalidateQueries`, imperative cache read/write, prefetch, SSR dehydrate/hydrate,
|
|
4
4
|
* infinite (paged) queries, and standalone mutations. Pure logic, no `window`, no framework, no
|
|
5
|
-
* `Date.now`/timers (the clock is injected)
|
|
5
|
+
* `Date.now`/timers (the clock is injected) - so it unit-tests deterministically and is safe to import
|
|
6
6
|
* from the SSR core's main entry. A per-adapter binding (`useQuery`/`useMutation`/`createQuery`)
|
|
7
7
|
* subscribes to a query/mutation's `subscribe`/`snapshot` store (the same shape the router + fetchers
|
|
8
8
|
* use).
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
*/
|
|
14
14
|
/** A query's lifecycle status. `pending` = no data yet; `success`/`error` once it has settled once. */
|
|
15
15
|
export type QueryStatus = "pending" | "success" | "error";
|
|
16
|
-
/** A query's observable state
|
|
16
|
+
/** A query's observable state - what a binding renders. A new (frozen) object per transition, so a
|
|
17
17
|
* `useSyncExternalStore`/signal binding can compare by reference. */
|
|
18
18
|
export interface QueryState<T = unknown> {
|
|
19
19
|
readonly status: QueryStatus;
|
|
20
20
|
readonly data: T | undefined;
|
|
21
21
|
readonly error: unknown;
|
|
22
|
-
/** True while a fetch is in flight
|
|
22
|
+
/** True while a fetch is in flight - the initial load OR a background refetch (data may still show). */
|
|
23
23
|
readonly isFetching: boolean;
|
|
24
24
|
/** When `data` was last set (via the injected clock); drives `staleTime`. `-Infinity` until first set. */
|
|
25
25
|
readonly updatedAt: number;
|
|
@@ -41,14 +41,14 @@ export interface QueryOptions {
|
|
|
41
41
|
readonly staleTime?: number;
|
|
42
42
|
}
|
|
43
43
|
export interface QueryClientOptions {
|
|
44
|
-
/** Monotonic clock in ms
|
|
44
|
+
/** Monotonic clock in ms - injected so the core stays deterministic + testable; the adapter binding
|
|
45
45
|
* passes `() => Date.now()`. */
|
|
46
46
|
readonly now: () => number;
|
|
47
47
|
/** Data stays fresh this long after a fetch; older ⇒ refetch on the next `fetch()` (default `0`). */
|
|
48
48
|
readonly staleTime?: number;
|
|
49
49
|
/** Evict an entry this long (ms) after its last subscriber leaves (default 5 min). */
|
|
50
50
|
readonly gcTime?: number;
|
|
51
|
-
/** Hard cap on cached entries
|
|
51
|
+
/** Hard cap on cached entries - LRU-evict the oldest *unsubscribed* entry past it (default 1000). */
|
|
52
52
|
readonly max?: number;
|
|
53
53
|
}
|
|
54
54
|
/** An infinite (paged) query's accumulated data: the fetched `pages` in order + the `pageParam` each
|
|
@@ -58,7 +58,7 @@ export interface InfiniteData<T, P> {
|
|
|
58
58
|
readonly pageParams: readonly P[];
|
|
59
59
|
}
|
|
60
60
|
/** Options for an {@link InfiniteQueryHandle}. `getNextPageParam` (required) derives the param for the
|
|
61
|
-
* next page from the last page
|
|
61
|
+
* next page from the last page - return `undefined`/`null` to signal there is no next page. */
|
|
62
62
|
export interface InfiniteQueryOptions<T, P> extends QueryOptions {
|
|
63
63
|
/** The param the FIRST page is fetched with. */
|
|
64
64
|
readonly initialPageParam: P;
|
|
@@ -85,7 +85,7 @@ export interface InfiniteQueryHandle<T, P> {
|
|
|
85
85
|
/** Whether a page can be prepended (derived from `getPreviousPageParam` of the first page). */
|
|
86
86
|
hasPreviousPage: () => boolean;
|
|
87
87
|
}
|
|
88
|
-
/** A serializable snapshot of the cache's successful queries
|
|
88
|
+
/** A serializable snapshot of the cache's successful queries - the SSR→client bridge payload. */
|
|
89
89
|
export interface DehydratedState {
|
|
90
90
|
readonly queries: ReadonlyArray<{
|
|
91
91
|
readonly key: unknown;
|
|
@@ -119,7 +119,7 @@ export interface QueryClient {
|
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
121
|
* Hash a query key to a stable cache string. Object keys are sorted (so `{a,b}` ≡ `{b,a}`); arrays
|
|
122
|
-
* keep order. Keys must be serializable
|
|
122
|
+
* keep order. Keys must be serializable - a function/symbol in the key throws (it can't be a stable
|
|
123
123
|
* identity). Mirrors TanStack Query's structural hashing.
|
|
124
124
|
*/
|
|
125
125
|
export declare function hashQueryKey(key: unknown): string;
|
|
@@ -154,7 +154,7 @@ export interface MutationHandle<TData, TVariables> {
|
|
|
154
154
|
reset: () => void;
|
|
155
155
|
}
|
|
156
156
|
/**
|
|
157
|
-
* Create a standalone mutation state machine
|
|
157
|
+
* Create a standalone mutation state machine - framework-agnostic, so a per-adapter `useMutation`
|
|
158
158
|
* binding just subscribes to it. Single-flight by a monotonic token: overlapping `mutate` calls each
|
|
159
159
|
* run their `fn`, but only the latest publishes state (an older, slower response can't clobber a newer
|
|
160
160
|
* one). The callbacks fire in TanStack order: `onMutate` (before), then `onSuccess`/`onError`, then
|
package/dist/query.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The agnostic keyed query-cache
|
|
2
|
+
* The agnostic keyed query-cache - a `query(key, fn)` primitive with in-flight dedup, `staleTime`
|
|
3
3
|
* freshness, prefix `invalidateQueries`, imperative cache read/write, prefetch, SSR dehydrate/hydrate,
|
|
4
4
|
* infinite (paged) queries, and standalone mutations. Pure logic, no `window`, no framework, no
|
|
5
|
-
* `Date.now`/timers (the clock is injected)
|
|
5
|
+
* `Date.now`/timers (the clock is injected) - so it unit-tests deterministically and is safe to import
|
|
6
6
|
* from the SSR core's main entry. A per-adapter binding (`useQuery`/`useMutation`/`createQuery`)
|
|
7
7
|
* subscribes to a query/mutation's `subscribe`/`snapshot` store (the same shape the router + fetchers
|
|
8
8
|
* use).
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
/**
|
|
15
15
|
* Hash a query key to a stable cache string. Object keys are sorted (so `{a,b}` ≡ `{b,a}`); arrays
|
|
16
|
-
* keep order. Keys must be serializable
|
|
16
|
+
* keep order. Keys must be serializable - a function/symbol in the key throws (it can't be a stable
|
|
17
17
|
* identity). Mirrors TanStack Query's structural hashing.
|
|
18
18
|
*/
|
|
19
19
|
export function hashQueryKey(key) {
|
|
@@ -54,7 +54,7 @@ export function createQueryClient(options) {
|
|
|
54
54
|
const max = options.max ?? 1000;
|
|
55
55
|
const cache = new Map();
|
|
56
56
|
// Lazily evict entries whose GC timer has elapsed (no subscribers), then enforce the hard cap by
|
|
57
|
-
// dropping the oldest-inserted unsubscribed entries. Called on every `query()`
|
|
57
|
+
// dropping the oldest-inserted unsubscribed entries. Called on every `query()` - no background timer.
|
|
58
58
|
const sweep = () => {
|
|
59
59
|
const t = now();
|
|
60
60
|
for (const [h, e] of cache) {
|
|
@@ -91,8 +91,8 @@ export function createQueryClient(options) {
|
|
|
91
91
|
handle: undefined,
|
|
92
92
|
};
|
|
93
93
|
const emit = () => {
|
|
94
|
-
// Iterate the live set
|
|
95
|
-
// listener must not synchronously subscribe/unsubscribe during notification
|
|
94
|
+
// Iterate the live set - no per-emit copy (the common case is 0-1 subscribers). Contract: a
|
|
95
|
+
// listener must not synchronously subscribe/unsubscribe during notification - `useSyncExternalStore`/
|
|
96
96
|
// signal/store bindings don't (un/subscribe happens in a later effect/cleanup tick).
|
|
97
97
|
if (entry.listeners.size === 0)
|
|
98
98
|
return;
|
|
@@ -105,20 +105,20 @@ export function createQueryClient(options) {
|
|
|
105
105
|
};
|
|
106
106
|
const isStale = () => entry.invalidated || now() - entry.state.updatedAt >= entry.staleTime;
|
|
107
107
|
entry.run = (force) => {
|
|
108
|
-
// Dedup
|
|
108
|
+
// Dedup - but join the in-flight fetch ONLY when it belongs to the current generation. An
|
|
109
109
|
// `invalidateQueries` bumps `generation`, so a fetch that started *before* the invalidation is
|
|
110
110
|
// superseded and must NOT satisfy this call (its data is pre-mutation); fall through and kick a
|
|
111
111
|
// fresh fetch instead of returning the stale in-flight one.
|
|
112
112
|
if (entry.promise !== undefined && entry.promiseGen === entry.generation)
|
|
113
113
|
return entry.promise;
|
|
114
114
|
if (!force && entry.state.status === "success" && !isStale())
|
|
115
|
-
return Promise.resolve(entry.state.data); // fresh cache hit
|
|
115
|
+
return Promise.resolve(entry.state.data); // fresh cache hit - no fn call
|
|
116
116
|
const gen = entry.generation;
|
|
117
117
|
entry.setState({ ...entry.state, isFetching: true }); // show the background/initial fetch
|
|
118
118
|
const promise = (async () => {
|
|
119
119
|
try {
|
|
120
120
|
const data = await entry.fn();
|
|
121
|
-
// A newer generation (a later invalidate/refetch) owns the entry now
|
|
121
|
+
// A newer generation (a later invalidate/refetch) owns the entry now - discard this result
|
|
122
122
|
// rather than publishing pre-mutation data as fresh or clearing `invalidated`. The fetch
|
|
123
123
|
// that superseded this one publishes the post-mutation data.
|
|
124
124
|
if (gen !== entry.generation)
|
|
@@ -148,7 +148,7 @@ export function createQueryClient(options) {
|
|
|
148
148
|
snapshot: () => entry.state,
|
|
149
149
|
subscribe: (listener) => {
|
|
150
150
|
entry.subscribers++;
|
|
151
|
-
entry.gcAt = undefined; // in use again
|
|
151
|
+
entry.gcAt = undefined; // in use again - cancel any pending eviction
|
|
152
152
|
entry.listeners.add(listener);
|
|
153
153
|
return () => {
|
|
154
154
|
entry.listeners.delete(listener);
|
|
@@ -185,7 +185,7 @@ export function createQueryClient(options) {
|
|
|
185
185
|
if (!keyMatchesPrefix(entry.key, keyOrPrefix))
|
|
186
186
|
continue;
|
|
187
187
|
entry.invalidated = true; // next fetch refetches even within staleTime
|
|
188
|
-
// Supersede any in-flight fetch begun before this point
|
|
188
|
+
// Supersede any in-flight fetch begun before this point - its result is pre-mutation and must
|
|
189
189
|
// not resolve as "fresh" or clear `invalidated`. The refetch below (or the next `fetch()`)
|
|
190
190
|
// starts a new generation that publishes the post-mutation data.
|
|
191
191
|
entry.generation++;
|
|
@@ -200,13 +200,13 @@ export function createQueryClient(options) {
|
|
|
200
200
|
: undefined;
|
|
201
201
|
};
|
|
202
202
|
const setQueryData = (key, updater) => {
|
|
203
|
-
// Create a placeholder entry if none exists
|
|
203
|
+
// Create a placeholder entry if none exists - its `fn` throws until a real `query(key, fn)` re-binds
|
|
204
204
|
// it, so a `setQueryData` for a key nobody queries yet never triggers a fetch on its own.
|
|
205
205
|
const entry = upsert(key, cache.get(hashQueryKey(key))?.fn ??
|
|
206
206
|
(() => Promise.reject(new Error("[nifra/web] query has no fetcher (setQueryData-only key)"))), defaultStaleTime);
|
|
207
207
|
const prev = entry.state.status === "success" ? entry.state.data : undefined;
|
|
208
208
|
const data = typeof updater === "function" ? updater(prev) : updater;
|
|
209
|
-
// A direct write is the new truth
|
|
209
|
+
// A direct write is the new truth - bump the generation so any in-flight fetch can't overwrite it,
|
|
210
210
|
// and clear the invalidated flag (the caller just supplied fresh data).
|
|
211
211
|
entry.generation++;
|
|
212
212
|
entry.invalidated = false;
|
|
@@ -391,7 +391,7 @@ const IDLE_MUTATION = Object.freeze({
|
|
|
391
391
|
variables: undefined,
|
|
392
392
|
});
|
|
393
393
|
/**
|
|
394
|
-
* Create a standalone mutation state machine
|
|
394
|
+
* Create a standalone mutation state machine - framework-agnostic, so a per-adapter `useMutation`
|
|
395
395
|
* binding just subscribes to it. Single-flight by a monotonic token: overlapping `mutate` calls each
|
|
396
396
|
* run their `fn`, but only the latest publishes state (an older, slower response can't clobber a newer
|
|
397
397
|
* one). The callbacks fire in TanStack order: `onMutate` (before), then `onSuccess`/`onError`, then
|
|
@@ -427,7 +427,7 @@ export function createMutation(fn, callbacks = {}) {
|
|
|
427
427
|
mutate: async (variables) => {
|
|
428
428
|
const mine = ++token;
|
|
429
429
|
setState({ status: "pending", data: undefined, error: undefined, variables });
|
|
430
|
-
// Only await a callback when one is actually supplied
|
|
430
|
+
// Only await a callback when one is actually supplied - an `await undefined` would insert a
|
|
431
431
|
// needless microtask before the mutationFn runs (and complicates single-flight timing).
|
|
432
432
|
if (cbs.onMutate !== undefined)
|
|
433
433
|
await cbs.onMutate(variables);
|
package/dist/route-manifest.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@nifrajs/web/route-manifest`
|
|
2
|
+
* `@nifrajs/web/route-manifest` - what each route actually DOES, as one artifact.
|
|
3
3
|
*
|
|
4
4
|
* The facts are already in the route modules: `prerender`, `getStaticPaths`, `revalidate`, `hydrate`.
|
|
5
5
|
* What has never existed is anywhere to read them together. To answer "which pages are static?", "which
|
package/dist/route-manifest.js
CHANGED
|
@@ -94,7 +94,7 @@ export function renderRouteManifest(manifest) {
|
|
|
94
94
|
const lines = [];
|
|
95
95
|
lines.push(manifest.target === undefined
|
|
96
96
|
? "nifra route manifest"
|
|
97
|
-
: `nifra route manifest
|
|
97
|
+
: `nifra route manifest - target: ${manifest.target}`);
|
|
98
98
|
lines.push("");
|
|
99
99
|
if (manifest.routes.length === 0) {
|
|
100
100
|
lines.push("no routes found.");
|
|
@@ -120,7 +120,7 @@ export function renderRouteManifest(manifest) {
|
|
|
120
120
|
lines.push("");
|
|
121
121
|
lines.push(`✗ ${manifest.conflicts.length} route(s) the target cannot honour:`);
|
|
122
122
|
for (const conflict of manifest.conflicts) {
|
|
123
|
-
lines.push(` ✗ ${conflict.pattern}
|
|
123
|
+
lines.push(` ✗ ${conflict.pattern} - ${conflict.consequence}`);
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
return lines.join("\n");
|
package/dist/router.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@nifrajs/core/server";
|
|
1
2
|
/**
|
|
2
3
|
* Request header that asks a nifra route's GET to return just the loader data as JSON (instead of
|
|
3
4
|
* the full HTML document). Set by client-side navigation; read by `createWebApp`'s GET handler.
|
|
@@ -6,18 +7,18 @@ export declare const DATA_HEADER = "x-nifra-data";
|
|
|
6
7
|
/**
|
|
7
8
|
* Global the server injects (`createWebApp({ prerenderedPaths })`) listing the SSG-prerendered paths.
|
|
8
9
|
* The client's default data fetch reads it: a soft-nav INTO a prerendered route fetches its static
|
|
9
|
-
* `<path>/_data.json` (a CDN file
|
|
10
|
+
* `<path>/_data.json` (a CDN file - no worker round-trip) instead of the dynamic header-GET.
|
|
10
11
|
*/
|
|
11
12
|
export declare const PRERENDERED_GLOBAL = "__NIFRA_PRERENDERED__";
|
|
12
13
|
/**
|
|
13
14
|
* Response header a data-mode action POST uses to convey a redirect (`redirect(...)`) to the
|
|
14
|
-
* client
|
|
15
|
+
* client - fetch would otherwise silently follow a 3xx to its HTML, losing the target. The
|
|
15
16
|
* client reads this and performs a client-side navigation instead.
|
|
16
17
|
*/
|
|
17
18
|
export declare const REDIRECT_HEADER = "x-nifra-redirect";
|
|
18
19
|
/**
|
|
19
20
|
* Response header an action sets (via the `revalidate(paths, data)` helper) to tell the client which
|
|
20
|
-
* routes the mutation changed
|
|
21
|
+
* routes the mutation changed - a comma-separated list of paths. After the submit, the client marks
|
|
21
22
|
* those cached routes stale (refetching any that are mounted) so a mutation can refresh views beyond
|
|
22
23
|
* the active one. The client validates each path against the manifest matcher before acting on it.
|
|
23
24
|
*/
|
|
@@ -81,7 +82,7 @@ export interface RouteMatch {
|
|
|
81
82
|
readonly routeId: string;
|
|
82
83
|
readonly params: Record<string, string>;
|
|
83
84
|
}
|
|
84
|
-
/** An in-flight client submit
|
|
85
|
+
/** An in-flight client submit - the action it targets + the `FormData` being sent. Set while the
|
|
85
86
|
* submit is pending, cleared when it settles. A component reads `submission.formData` to render an
|
|
86
87
|
* **optimistic** view (the expected result) before the server responds. */
|
|
87
88
|
export interface Submission {
|
|
@@ -105,10 +106,10 @@ export interface RouterState {
|
|
|
105
106
|
/** The path a navigation is transitioning TO while `pending` (cleared when it settles). Lets a
|
|
106
107
|
* `NavLink` know whether its own `to` is the one loading; `undefined` when idle. */
|
|
107
108
|
readonly pendingPath?: string | undefined;
|
|
108
|
-
/** The in-flight submit (set during a `submit`, cleared when it settles)
|
|
109
|
+
/** The in-flight submit (set during a `submit`, cleared when it settles) - for optimistic UI. */
|
|
109
110
|
readonly submission?: Submission;
|
|
110
111
|
}
|
|
111
|
-
/** A route id paired with its nifra pattern (e.g. `":id"` segments)
|
|
112
|
+
/** A route id paired with its nifra pattern (e.g. `":id"` segments) - the matcher input. */
|
|
112
113
|
export interface RoutePattern {
|
|
113
114
|
readonly routeId: string;
|
|
114
115
|
readonly pattern: string;
|
|
@@ -131,7 +132,7 @@ export interface SubmitOptions {
|
|
|
131
132
|
* keep the current `data` and rely on the action's `actionData` alone. */
|
|
132
133
|
readonly revalidate?: boolean;
|
|
133
134
|
}
|
|
134
|
-
/** A fetcher's observable state
|
|
135
|
+
/** A fetcher's observable state - independent of the main router. `pending` covers its in-flight
|
|
135
136
|
* load/submit; `data` is its last `load()` result; `actionData` its last `submit()` result;
|
|
136
137
|
* `submission` the in-flight submit (for optimistic UI). Client-only (never SSR'd). */
|
|
137
138
|
export interface FetcherState {
|
|
@@ -142,7 +143,7 @@ export interface FetcherState {
|
|
|
142
143
|
}
|
|
143
144
|
/**
|
|
144
145
|
* An independent load/submit state machine, retrieved by `router.fetcher(key)`. Runs **concurrently**
|
|
145
|
-
* with the main router and with other fetchers
|
|
146
|
+
* with the main router and with other fetchers - each is single-flight against *itself* (its own
|
|
146
147
|
* monotonic token), so N row-level mutations / side-channel loads can be in flight at once without
|
|
147
148
|
* disturbing the active view. Loads/submits write the shared cache and honor `X-Nifra-Revalidate`.
|
|
148
149
|
*/
|
|
@@ -156,7 +157,7 @@ export interface Fetcher {
|
|
|
156
157
|
load: (path: string) => Promise<void>;
|
|
157
158
|
/** Submit an action into this fetcher's own state; honors `X-Nifra-Revalidate` by refreshing the
|
|
158
159
|
* active route + any mounted fetcher showing a changed path. Rejects on failure (caller falls back).
|
|
159
|
-
* (No `revalidate` opt-out
|
|
160
|
+
* (No `revalidate` opt-out - a fetcher has no active loader of its own to skip.) */
|
|
160
161
|
submit: (action: string, body: NonNullable<RequestInit["body"]>) => Promise<void>;
|
|
161
162
|
}
|
|
162
163
|
/** The agnostic router store consumed by per-adapter Router bindings. */
|
|
@@ -171,7 +172,7 @@ export interface ClientRouter {
|
|
|
171
172
|
* Submit an action (POST `body` to `action` in data mode): a redirect becomes a client
|
|
172
173
|
* navigation; otherwise the data return is published as `actionData` and the active route's
|
|
173
174
|
* loader is revalidated so the mutation is reflected. Pass `{ revalidate: false }` to SKIP that
|
|
174
|
-
* revalidation
|
|
175
|
+
* revalidation - keep the current `data` and just publish the action's `actionData` (useful when
|
|
175
176
|
* the action already returned everything that changed, saving the extra round-trip). A redirect
|
|
176
177
|
* always loads its target regardless. Rejects on failure (caller falls back).
|
|
177
178
|
*/
|
|
@@ -179,28 +180,28 @@ export interface ClientRouter {
|
|
|
179
180
|
/**
|
|
180
181
|
* Mark cached route data stale and refresh the active view. With `paths`, target exactly those
|
|
181
182
|
* (e.g. the routes a mutation changed); without, invalidate the whole cache. The active route
|
|
182
|
-
* refreshes immediately
|
|
183
|
+
* refreshes immediately - refetched + republished - whenever it's in scope (an explicit list that
|
|
183
184
|
* includes it, or an invalidate-all); other stale entries refetch lazily when next read (a
|
|
184
185
|
* fetcher, or the next navigation/access). Rejects if the active refetch fails (like `navigate`).
|
|
185
186
|
* The keyed substrate for targeted revalidation (the `X-Nifra-Revalidate` header) and fetchers.
|
|
186
187
|
*/
|
|
187
188
|
invalidate: (paths?: readonly string[]) => Promise<void>;
|
|
188
189
|
/**
|
|
189
|
-
* Warm a path's chunk + loader data into a bounded one-shot cache without publishing state
|
|
190
|
+
* Warm a path's chunk + loader data into a bounded one-shot cache without publishing state -
|
|
190
191
|
* a later `navigate` to it transitions with no network round-trip. Best-effort: failures and
|
|
191
192
|
* unmatched paths are no-ops. Wired to link hover/focus by `installHistory`.
|
|
192
193
|
*/
|
|
193
194
|
prefetch: (path: string) => Promise<void>;
|
|
194
195
|
/**
|
|
195
|
-
* Get (lazily creating) the stable {@link Fetcher} for `key`
|
|
196
|
+
* Get (lazily creating) the stable {@link Fetcher} for `key` - an independent, concurrent
|
|
196
197
|
* load/submit state machine for row-level mutations or side-channel loads that must not disturb
|
|
197
198
|
* the active view. The same `key` always returns the same fetcher (so a binding can subscribe to a
|
|
198
199
|
* stable store). Keys are app-chosen and typically stable (e.g. a row id).
|
|
199
200
|
*/
|
|
200
201
|
fetcher: (key: string) => Fetcher;
|
|
201
|
-
/** All live fetchers
|
|
202
|
+
/** All live fetchers - for a global busy view (e.g. a `useFetchers` binding). */
|
|
202
203
|
fetchers: () => readonly Fetcher[];
|
|
203
|
-
/** Subscribe to any-fetcher-changed (a transition on any fetcher, or a new one created)
|
|
204
|
+
/** Subscribe to any-fetcher-changed (a transition on any fetcher, or a new one created) - backs a
|
|
204
205
|
* `useFetchers` binding; returns an unsubscribe fn. */
|
|
205
206
|
subscribeFetchers: (listener: () => void) => () => void;
|
|
206
207
|
/** Match a path against the manifest patterns (exposed for history/link wiring). */
|
|
@@ -217,19 +218,27 @@ export interface ClientRouterOptions {
|
|
|
217
218
|
/** Terminal status → client route id. Generated entries populate this from `_404` and
|
|
218
219
|
* `_<status>` files so soft navigation renders the same boundary as a hard request. */
|
|
219
220
|
readonly statusRoutes?: Readonly<Record<number, string>>;
|
|
221
|
+
/** routeId → the route's client-only search keys (its `searchClientKeys` export). When a soft
|
|
222
|
+
* navigation stays on the same route + pathname and changes ONLY these keys, `navigate` publishes the
|
|
223
|
+
* new URL WITHOUT re-running the loader (re-render, not revalidate). Populated lazily by the generated
|
|
224
|
+
* entry's `loadModule` (so a route's keys are present once it has been visited, which is exactly when a
|
|
225
|
+
* same-route nav can consult them). Omit ⇒ every search change revalidates (the safe default). */
|
|
226
|
+
readonly searchClientKeys?: Readonly<Record<string, readonly string[]>>;
|
|
220
227
|
}
|
|
221
228
|
/** Options for a per-adapter `mountRouter` (the Router binding that hydrates + re-renders). */
|
|
222
229
|
export interface MountRouterOptions {
|
|
223
230
|
readonly router: ClientRouter;
|
|
224
231
|
/** routeId → layout chain (outermost layout → page); built by `generateClientEntry`. */
|
|
225
232
|
readonly routes: Record<string, readonly unknown[]>;
|
|
226
|
-
/**
|
|
233
|
+
/** routeId → the route's search-schema CHAIN (its layout chain's `searchSchema` exports, outermost
|
|
234
|
+
* first, then the page's; each entry `undefined` when that module declares none); built by
|
|
235
|
+
* `generateClientEntry`. The mount derives each route's typed `search` from this chain plus the URL via
|
|
236
|
+
* `searchOfChain` (layout keys merged with page keys, page-wins), matching the server's
|
|
237
|
+
* `ctx.search`/`RenderProps.search`. Omitted by callers with no typed search (tests, a hand-built mount)
|
|
238
|
+
* ⇒ every route sees the raw parsed query. */
|
|
239
|
+
readonly searchSchemas?: Readonly<Record<string, readonly (StandardSchemaV1 | undefined)[]>>;
|
|
240
|
+
/** Hydration container (opaque - the adapter casts it to its DOM element type). */
|
|
227
241
|
readonly container: unknown;
|
|
228
242
|
}
|
|
229
|
-
/**
|
|
230
|
-
* Create the agnostic router store. `navigate` is guarded by a monotonic token so that when
|
|
231
|
-
* navigations overlap, only the latest result is applied (rapid clicks don't flash stale data).
|
|
232
|
-
* A failed fetch clears `pending` and rethrows so the caller can fall back to a full-page load.
|
|
233
|
-
*/
|
|
234
243
|
export declare function createClientRouter(options: ClientRouterOptions): ClientRouter;
|
|
235
244
|
//# sourceMappingURL=router.d.ts.map
|
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|