@nifrajs/web 0.1.0-alpha.1

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.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +18 -0
  3. package/css-modules.d.ts +34 -0
  4. package/dist/build.d.ts +110 -0
  5. package/dist/build.d.ts.map +1 -0
  6. package/dist/build.js +238 -0
  7. package/dist/build.js.map +1 -0
  8. package/dist/client.d.ts +32 -0
  9. package/dist/client.d.ts.map +1 -0
  10. package/dist/client.js +204 -0
  11. package/dist/client.js.map +1 -0
  12. package/dist/deferred.d.ts +90 -0
  13. package/dist/deferred.d.ts.map +1 -0
  14. package/dist/deferred.js +310 -0
  15. package/dist/deferred.js.map +1 -0
  16. package/dist/dev-error.d.ts +17 -0
  17. package/dist/dev-error.d.ts.map +1 -0
  18. package/dist/dev-error.js +59 -0
  19. package/dist/dev-error.js.map +1 -0
  20. package/dist/dev.d.ts +25 -0
  21. package/dist/dev.d.ts.map +1 -0
  22. package/dist/dev.js +83 -0
  23. package/dist/dev.js.map +1 -0
  24. package/dist/draft.d.ts +58 -0
  25. package/dist/draft.d.ts.map +1 -0
  26. package/dist/draft.js +55 -0
  27. package/dist/draft.js.map +1 -0
  28. package/dist/fonts-google.d.ts +109 -0
  29. package/dist/fonts-google.d.ts.map +1 -0
  30. package/dist/fonts-google.js +291 -0
  31. package/dist/fonts-google.js.map +1 -0
  32. package/dist/fonts.d.ts +67 -0
  33. package/dist/fonts.d.ts.map +1 -0
  34. package/dist/fonts.js +103 -0
  35. package/dist/fonts.js.map +1 -0
  36. package/dist/fs.d.ts +10 -0
  37. package/dist/fs.d.ts.map +1 -0
  38. package/dist/fs.js +24 -0
  39. package/dist/fs.js.map +1 -0
  40. package/dist/index.d.ts +280 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +784 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/islands.d.ts +37 -0
  45. package/dist/islands.d.ts.map +1 -0
  46. package/dist/islands.js +107 -0
  47. package/dist/islands.js.map +1 -0
  48. package/dist/isr.d.ts +154 -0
  49. package/dist/isr.d.ts.map +1 -0
  50. package/dist/isr.js +331 -0
  51. package/dist/isr.js.map +1 -0
  52. package/dist/manifest.d.ts +178 -0
  53. package/dist/manifest.d.ts.map +1 -0
  54. package/dist/manifest.js +213 -0
  55. package/dist/manifest.js.map +1 -0
  56. package/dist/plugins/css-modules.d.ts +40 -0
  57. package/dist/plugins/css-modules.d.ts.map +1 -0
  58. package/dist/plugins/css-modules.js +0 -0
  59. package/dist/plugins/css-modules.js.map +1 -0
  60. package/dist/plugins/kit.d.ts +44 -0
  61. package/dist/plugins/kit.d.ts.map +1 -0
  62. package/dist/plugins/kit.js +105 -0
  63. package/dist/plugins/kit.js.map +1 -0
  64. package/dist/plugins/scss.d.ts +27 -0
  65. package/dist/plugins/scss.d.ts.map +1 -0
  66. package/dist/plugins/scss.js +78 -0
  67. package/dist/plugins/scss.js.map +1 -0
  68. package/dist/prerender.d.ts +77 -0
  69. package/dist/prerender.d.ts.map +1 -0
  70. package/dist/prerender.js +139 -0
  71. package/dist/prerender.js.map +1 -0
  72. package/dist/query.d.ts +62 -0
  73. package/dist/query.d.ts.map +1 -0
  74. package/dist/query.js +184 -0
  75. package/dist/query.js.map +1 -0
  76. package/dist/router.d.ts +169 -0
  77. package/dist/router.d.ts.map +1 -0
  78. package/dist/router.js +531 -0
  79. package/dist/router.js.map +1 -0
  80. package/dist/vite.d.ts +49 -0
  81. package/dist/vite.d.ts.map +1 -0
  82. package/dist/vite.js +144 -0
  83. package/dist/vite.js.map +1 -0
  84. package/package.json +127 -0
  85. package/src/build.ts +375 -0
  86. package/src/client.ts +218 -0
  87. package/src/deferred.ts +339 -0
  88. package/src/dev-error.ts +62 -0
  89. package/src/dev.ts +108 -0
  90. package/src/draft.ts +82 -0
  91. package/src/fonts-google.ts +397 -0
  92. package/src/fonts.ts +147 -0
  93. package/src/fs.ts +26 -0
  94. package/src/index.ts +1202 -0
  95. package/src/islands.ts +121 -0
  96. package/src/isr.ts +461 -0
  97. package/src/manifest.ts +366 -0
  98. package/src/plugins/css-modules.ts +0 -0
  99. package/src/plugins/kit.ts +123 -0
  100. package/src/plugins/scss.ts +108 -0
  101. package/src/prerender.ts +209 -0
  102. package/src/query.ts +250 -0
  103. package/src/router.ts +676 -0
  104. package/src/vite.ts +212 -0
package/dist/router.js ADDED
@@ -0,0 +1,531 @@
1
+ /**
2
+ * The agnostic client-side router core — pure logic, no `window`, no framework. A per-adapter
3
+ * Router binding subscribes via `subscribe`/`snapshot` and renders the matched chain; a
4
+ * browser-only `installHistory` (history + link interception) wires on top. Kept DOM-free so it
5
+ * unit-tests without a browser and is safe to import from the SSR core's main entry.
6
+ */
7
+ import { parseNdjsonData } from "./deferred.js";
8
+ /**
9
+ * Request header that asks a nifra route's GET to return just the loader data as JSON (instead of
10
+ * the full HTML document). Set by client-side navigation; read by `createWebApp`'s GET handler.
11
+ */
12
+ export const DATA_HEADER = "x-nifra-data";
13
+ /**
14
+ * Global the server injects (`createWebApp({ prerenderedPaths })`) listing the SSG-prerendered paths.
15
+ * The client's default data fetch reads it: a soft-nav INTO a prerendered route fetches its static
16
+ * `<path>/_data.json` (a CDN file — no worker round-trip) instead of the dynamic header-GET.
17
+ */
18
+ export const PRERENDERED_GLOBAL = "__NIFRA_PRERENDERED__";
19
+ /**
20
+ * Response header a data-mode action POST uses to convey a redirect (`redirect(...)`) to the
21
+ * client — fetch would otherwise silently follow a 3xx to its HTML, losing the target. The
22
+ * client reads this and performs a client-side navigation instead.
23
+ */
24
+ export const REDIRECT_HEADER = "x-nifra-redirect";
25
+ /**
26
+ * Response header an action sets (via the `revalidate(paths, data)` helper) to tell the client which
27
+ * routes the mutation changed — a comma-separated list of paths. After the submit, the client marks
28
+ * those cached routes stale (refetching any that are mounted) so a mutation can refresh views beyond
29
+ * the active one. The client validates each path against the manifest matcher before acting on it.
30
+ */
31
+ export const REVALIDATE_HEADER = "x-nifra-revalidate";
32
+ function compile(pattern) {
33
+ const keys = [];
34
+ const src = pattern
35
+ .split("/")
36
+ .map((seg) => {
37
+ if (seg.startsWith(":")) {
38
+ keys.push(seg.slice(1));
39
+ return "([^/]+)";
40
+ }
41
+ if (seg.startsWith("*")) {
42
+ // Catch-all (`*slug`, or bare `*` → key "*"): capture the rest of the path, slashes included.
43
+ // Always the final segment (the manifest/core enforce it), so the greedy `.` is safe.
44
+ keys.push(seg.length === 1 ? "*" : seg.slice(1));
45
+ return "(.+)";
46
+ }
47
+ // Escape regex-special chars. `$`/`{`/`}` are ordered so no literal `${` appears (it can
48
+ // trip tooling that scans for template-literal interpolation, e.g. coverage sourcemaps).
49
+ return seg.replace(/[.*+?^()|[\]\\{}$]/g, "\\$&");
50
+ })
51
+ .join("/");
52
+ return { regex: new RegExp(`^${src}/?$`), keys };
53
+ }
54
+ /**
55
+ * Build a matcher from route patterns (built from the SAME manifest the server routes from, so
56
+ * client and server agree). Returns the first matching route + decoded params, or null. The
57
+ * query string is ignored for matching (it is not part of the route pattern).
58
+ */
59
+ export function createMatcher(patterns) {
60
+ const compiled = patterns.map((p) => ({ routeId: p.routeId, ...compile(p.pattern) }));
61
+ return (path) => {
62
+ // Strip the query without allocating a `split("?")` array — matcher runs per match.
63
+ const q = path.indexOf("?");
64
+ const clean = q === -1 ? path : path.slice(0, q);
65
+ for (const c of compiled) {
66
+ const m = c.regex.exec(clean);
67
+ if (m === null)
68
+ continue;
69
+ const params = {};
70
+ // for-of (no per-match `forEach` closure); `i` indexes the capture groups (`m[0]` is the match).
71
+ let i = 0;
72
+ for (const k of c.keys) {
73
+ params[k] = decodeURIComponent(m[i + 1] ?? "");
74
+ i++;
75
+ }
76
+ return { routeId: c.routeId, params };
77
+ }
78
+ return null;
79
+ };
80
+ }
81
+ /** Read a nifra data response: a deferred loader/action streams NDJSON (parse line 1 + settle
82
+ * `<Await>` markers as resolution lines arrive); a non-deferred one returns a single JSON. Shared by
83
+ * navigation fetches and action submits — both transports are identical. */
84
+ const readResponseData = (res, signal) => (res.headers.get("content-type") ?? "").includes("application/x-ndjson") && res.body !== null
85
+ ? parseNdjsonData(res.body, signal)
86
+ : res.json();
87
+ // The static `_data.json` URL for a prerendered path: `/` → `/_data.json`, `/users/7` →
88
+ // `/users/7/_data.json` (mirrors the build's `dataFileFor`).
89
+ const dataUrlFor = (pathname) => pathname === "/" ? "/_data.json" : `${pathname.replace(/\/+$/, "")}/_data.json`;
90
+ const defaultFetchData = async (path, _match, signal) => {
91
+ // SSG fast path: if this path was prerendered, its loader data is a static file — fetch that (no
92
+ // worker). Falls through to the dynamic header-GET on any miss (file absent, e.g. a deferred route,
93
+ // or a stale set), so it's always safe. Non-SSG apps have no global → the dynamic path, unchanged.
94
+ const prerendered = globalThis[PRERENDERED_GLOBAL];
95
+ if (Array.isArray(prerendered)) {
96
+ const pathname = path.replace(/[?#].*$/, "");
97
+ if (prerendered.includes(pathname)) {
98
+ const staticRes = await fetch(dataUrlFor(pathname), { signal: signal ?? null });
99
+ if (staticRes.ok)
100
+ return readResponseData(staticRes, signal);
101
+ }
102
+ }
103
+ const res = await fetch(path, { headers: { [DATA_HEADER]: "1" }, signal: signal ?? null });
104
+ if (!res.ok)
105
+ throw new Error(`[nifra/web] navigation data fetch failed (${res.status}): ${path}`);
106
+ return readResponseData(res, signal);
107
+ };
108
+ /**
109
+ * Create the agnostic router store. `navigate` is guarded by a monotonic token so that when
110
+ * navigations overlap, only the latest result is applied (rapid clicks don't flash stale data).
111
+ * A failed fetch clears `pending` and rethrows so the caller can fall back to a full-page load.
112
+ */
113
+ export function createClientRouter(options) {
114
+ const match = createMatcher(options.patterns);
115
+ const fetchData = options.fetchData ?? defaultFetchData;
116
+ const loadModule = options.loadModule;
117
+ let state = options.initial;
118
+ const listeners = new Set();
119
+ let token = 0;
120
+ // Snapshot listeners to defend against accidental un/subscribe during notification. The adapters
121
+ // don't do this (un/subscribe runs in effect/cleanup ticks), so the overhead is negligible
122
+ // (5-20 listeners typically), and the defensiveness is valuable.
123
+ const emit = () => {
124
+ if (listeners.size === 0)
125
+ return;
126
+ for (const listener of [...listeners])
127
+ listener();
128
+ };
129
+ // Bounded one-shot prefetch cache (path → loader data) + an in-flight guard so hover spam
130
+ // doesn't double-fetch. Consumed (and dropped) by the next navigate to that path.
131
+ const MAX_PREFETCH = 10;
132
+ const prefetched = new Map();
133
+ const inflight = new Set();
134
+ // Keyed data cache (path → latest loader data + freshness). Written on every published data
135
+ // (navigate/submit), read by `invalidate` (+ targeted revalidation and fetchers in later F16
136
+ // increments). Bounded — evict the oldest-inserted past the cap (route data is small; this just
137
+ // caps memory). `status` is the staleness ledger: `invalidate` flips entries to `stale`; readers
138
+ // refetch stale ones. Client-only — never serialized/hydrated.
139
+ const MAX_CACHE = 50;
140
+ const cache = new Map();
141
+ const cachePut = (path, data) => {
142
+ if (!cache.has(path) && cache.size >= MAX_CACHE) {
143
+ const oldest = cache.keys().next().value;
144
+ if (oldest !== undefined)
145
+ cache.delete(oldest);
146
+ }
147
+ cache.set(path, { data, status: "fresh" });
148
+ };
149
+ // Flip cached entries to stale (a no-op for paths not in the cache). Shared by `invalidate` and the
150
+ // `X-Nifra-Revalidate` handling in `submit`.
151
+ const markStale = (paths) => {
152
+ for (const p of paths) {
153
+ const entry = cache.get(p);
154
+ if (entry !== undefined)
155
+ cache.set(p, { data: entry.data, status: "stale" });
156
+ }
157
+ };
158
+ // Parse the `X-Nifra-Revalidate` response header into validated paths. The header is response data
159
+ // (a trust boundary), so each path must match a real manifest pattern — unknown/garbage is dropped
160
+ // and never triggers a fetch.
161
+ const parseRevalidate = (header) => header === null
162
+ ? []
163
+ : header
164
+ .split(",")
165
+ .map((s) => s.trim())
166
+ .filter((s) => s.length > 0 && match(s) !== null);
167
+ // Aborts the in-flight navigation's fetch + deferred stream when a newer navigation supersedes it
168
+ // (so a superseded route's NDJSON stream stops reading instead of draining in the background).
169
+ let navAbort;
170
+ // Refetch the active route + republish, single-flight via the shared `token`. Shared by `invalidate`
171
+ // and targeted revalidation. Rejects if the fetch fails (clearing its own `pending` first).
172
+ const refetchActive = async () => {
173
+ const mine = ++token;
174
+ navAbort?.abort();
175
+ const ac = new AbortController();
176
+ navAbort = ac;
177
+ state = { ...state, pending: true };
178
+ emit();
179
+ try {
180
+ const data = await fetchData(state.path, { routeId: state.routeId, params: state.params }, ac.signal);
181
+ if (mine !== token)
182
+ return; // superseded — drop the stale result
183
+ cachePut(state.path, data);
184
+ state = { ...state, data, pending: false };
185
+ emit();
186
+ }
187
+ catch (err) {
188
+ if (mine === token) {
189
+ state = { ...state, pending: false };
190
+ emit();
191
+ }
192
+ throw err;
193
+ }
194
+ };
195
+ const fetchers = new Map();
196
+ const fetcherListeners = new Set();
197
+ // Cached list of live fetchers, rebuilt (new array ref) on every fetcher change/creation. A stable
198
+ // ref between changes is what lets a `useFetchers` binding read it via `useSyncExternalStore`
199
+ // without looping; a fresh ref on each change is what makes it re-render.
200
+ let fetchersArr = [];
201
+ const emitFetchers = () => {
202
+ fetchersArr = [...fetchers.values()].map((e) => e.fetcher); // snapshot ref (intentional)
203
+ if (fetcherListeners.size === 0)
204
+ return;
205
+ for (const l of [...fetcherListeners])
206
+ l(); // snapshot for defensiveness
207
+ };
208
+ // Best-effort refresh of every MOUNTED reader of `paths`: the active route (unless `skipActive`,
209
+ // when the caller already refetched it) + any fetcher that loaded one of these paths. Errors are
210
+ // swallowed — a failed targeted refresh must not fail the mutation that triggered it.
211
+ const refreshMounted = async (paths, skipActive) => {
212
+ const jobs = [];
213
+ if (!skipActive && paths.includes(state.path))
214
+ jobs.push(refetchActive().catch(() => { }));
215
+ for (const entry of fetchers.values())
216
+ jobs.push(entry.refreshIfShowing(paths));
217
+ await Promise.all(jobs);
218
+ };
219
+ const createFetcher = () => {
220
+ let fState = { pending: false, data: undefined };
221
+ let fToken = 0;
222
+ let fAbort;
223
+ let loadedPath;
224
+ const fListeners = new Set();
225
+ const fEmit = () => {
226
+ if (fListeners.size > 0)
227
+ for (const l of [...fListeners])
228
+ l(); // snapshot for defensiveness
229
+ emitFetchers();
230
+ };
231
+ const runLoad = async (path) => {
232
+ const matched = match(path);
233
+ if (matched === null)
234
+ return; // unmatched path → no-op
235
+ const mine = ++fToken;
236
+ fAbort?.abort();
237
+ const ac = new AbortController();
238
+ fAbort = ac;
239
+ fState = { ...fState, pending: true };
240
+ fEmit();
241
+ try {
242
+ const [, data] = await Promise.all([
243
+ loadModule?.(matched.routeId),
244
+ fetchData(path, matched, ac.signal),
245
+ ]);
246
+ if (mine !== fToken)
247
+ return; // a newer load/submit on THIS fetcher superseded us
248
+ // Record the loaded path only on SUCCESS — a thrown or superseded load must not
249
+ // leave `loadedPath` pointing at a path this fetcher never actually showed, or a later
250
+ // `X-Nifra-Revalidate` for it would spuriously refetch onto unexpected data.
251
+ loadedPath = path;
252
+ cachePut(path, data);
253
+ fState = { ...fState, data, pending: false };
254
+ fEmit();
255
+ }
256
+ catch (err) {
257
+ if (mine === fToken) {
258
+ fState = { ...fState, pending: false };
259
+ fEmit();
260
+ }
261
+ throw err;
262
+ }
263
+ };
264
+ const fetcher = {
265
+ snapshot: () => fState,
266
+ subscribe: (l) => {
267
+ fListeners.add(l);
268
+ return () => {
269
+ fListeners.delete(l);
270
+ };
271
+ },
272
+ load: runLoad,
273
+ submit: async (action, body) => {
274
+ const mine = ++fToken;
275
+ // Abort any prior in-flight load/submit on THIS fetcher (its fetch + NDJSON drain) — like
276
+ // `runLoad` does for a superseding load. The mutation POST is left to complete; the
277
+ // signal cancels the follow-up data drain if a newer op supersedes this one.
278
+ fAbort?.abort();
279
+ const ac = new AbortController();
280
+ fAbort = ac;
281
+ // Expose the in-flight submission (FormData) for optimistic UI; a new submit supersedes any
282
+ // prior actionData (dropped here, set again on success).
283
+ fState = {
284
+ pending: true,
285
+ data: fState.data,
286
+ ...(body instanceof FormData ? { submission: { action, formData: body } } : {}),
287
+ };
288
+ fEmit();
289
+ try {
290
+ const res = await fetch(action, { method: "POST", body, headers: { [DATA_HEADER]: "1" } });
291
+ if (!res.ok)
292
+ throw new Error(`[nifra/web] fetcher action failed (${res.status}): ${action}`);
293
+ const actionData = res.status === 204 ? undefined : await readResponseData(res, ac.signal);
294
+ const changed = parseRevalidate(res.headers.get(REVALIDATE_HEADER));
295
+ if (mine !== fToken)
296
+ return;
297
+ // Publish the fetcher's actionData; clear `submission` (the optimistic window is over).
298
+ fState = { pending: false, data: fState.data, actionData };
299
+ fEmit();
300
+ // A fetcher has no loader of its own — its mutation's freshness flows through the cache:
301
+ // mark the changed routes stale + refresh every mounted reader (active route + fetchers).
302
+ if (changed.length > 0) {
303
+ markStale(changed);
304
+ await refreshMounted(changed, false);
305
+ }
306
+ }
307
+ catch (err) {
308
+ if (mine === fToken) {
309
+ fState = { pending: false, data: fState.data };
310
+ fEmit();
311
+ }
312
+ throw err;
313
+ }
314
+ },
315
+ };
316
+ return {
317
+ fetcher,
318
+ refreshIfShowing: async (paths) => {
319
+ // Best-effort: a failed targeted refresh of a fetcher must not reject the triggering flow.
320
+ if (loadedPath !== undefined && paths.includes(loadedPath))
321
+ await runLoad(loadedPath).catch(() => { });
322
+ },
323
+ };
324
+ };
325
+ return {
326
+ match,
327
+ snapshot: () => state,
328
+ subscribe: (listener) => {
329
+ listeners.add(listener);
330
+ return () => {
331
+ listeners.delete(listener);
332
+ };
333
+ },
334
+ navigate: async (path) => {
335
+ const matched = match(path);
336
+ if (matched === null)
337
+ return;
338
+ const mine = ++token;
339
+ navAbort?.abort(); // abandon any in-flight navigation's stream
340
+ const ac = new AbortController();
341
+ navAbort = ac;
342
+ state = { ...state, pending: true };
343
+ emit();
344
+ try {
345
+ // Use prefetched data when present (one-shot — drop it); else fetch. The chunk is loaded
346
+ // either way (cached + instant after a prefetch), so pending covers both.
347
+ const hit = prefetched.has(path);
348
+ const dataPromise = hit
349
+ ? Promise.resolve(prefetched.get(path))
350
+ : fetchData(path, matched, ac.signal);
351
+ if (hit)
352
+ prefetched.delete(path);
353
+ const [, data] = await Promise.all([loadModule?.(matched.routeId), dataPromise]);
354
+ if (mine !== token)
355
+ return; // a newer navigation superseded this one — drop the stale result
356
+ cachePut(path, data); // keep the keyed cache coherent with what we publish
357
+ state = {
358
+ routeId: matched.routeId,
359
+ params: matched.params,
360
+ path,
361
+ data,
362
+ actionData: undefined, // a fresh navigation has no action result
363
+ pending: false,
364
+ };
365
+ emit();
366
+ }
367
+ catch (err) {
368
+ // Clear our pending flag (only if still current) and rethrow — the caller decides how to
369
+ // recover (the history layer falls back to a full-page navigation).
370
+ if (mine === token) {
371
+ state = { ...state, pending: false };
372
+ emit();
373
+ }
374
+ throw err;
375
+ }
376
+ },
377
+ submit: async (action, body, opts) => {
378
+ const mine = ++token;
379
+ // A superseding navigation/submit aborts this submit's FOLLOW-UP reads (revalidation / redirect
380
+ // fetch + their NDJSON drains) — not the mutation POST itself, which should complete.
381
+ // Wire into `navAbort` like `navigate`/`refetchActive`, so a later nav cancels the in-flight read.
382
+ navAbort?.abort();
383
+ const ac = new AbortController();
384
+ navAbort = ac;
385
+ // Expose the in-flight submission (when it's FormData) so components can render an optimistic
386
+ // view from it while pending; cleared when the submit settles below.
387
+ state = {
388
+ ...state,
389
+ pending: true,
390
+ ...(body instanceof FormData ? { submission: { action, formData: body } } : {}),
391
+ };
392
+ emit();
393
+ try {
394
+ const res = await fetch(action, { method: "POST", body, headers: { [DATA_HEADER]: "1" } });
395
+ if (!res.ok)
396
+ throw new Error(`[nifra/web] action failed (${res.status}): ${action}`);
397
+ const redirectTo = res.headers.get(REDIRECT_HEADER);
398
+ if (redirectTo !== null) {
399
+ // The action redirected (Post/Redirect/Get) — treat it as a client navigation.
400
+ const target = match(redirectTo);
401
+ if (target === null)
402
+ throw new Error(`[nifra/web] action redirect off-route: ${redirectTo}`);
403
+ const [, data] = await Promise.all([
404
+ loadModule?.(target.routeId),
405
+ fetchData(redirectTo, target, ac.signal),
406
+ ]);
407
+ if (mine !== token)
408
+ return;
409
+ cachePut(redirectTo, data);
410
+ state = {
411
+ routeId: target.routeId,
412
+ params: target.params,
413
+ path: redirectTo,
414
+ data,
415
+ actionData: undefined,
416
+ pending: false,
417
+ };
418
+ emit();
419
+ return;
420
+ }
421
+ // The action's data — streamed NDJSON if it `defer()`'d slow parts (markers settle as lines
422
+ // arrive, for `<Await actionData>`), else one JSON. Abortable so a superseding nav cancels the
423
+ // drain.
424
+ const actionData = res.status === 204 ? undefined : await readResponseData(res, ac.signal);
425
+ // Routes the action declared changed (via the `revalidate()` helper → `X-Nifra-Revalidate`),
426
+ // validated against the manifest.
427
+ const changed = parseRevalidate(res.headers.get(REVALIDATE_HEADER));
428
+ // Revalidate the active route's loader so the mutation is reflected — unless the caller opted
429
+ // out (`revalidate: false`). A server-declared revalidate of the active path overrides the
430
+ // opt-out (the server says it changed, so stale data would be wrong). Default is to revalidate.
431
+ const skipActive = opts?.revalidate === false && !changed.includes(state.path);
432
+ const data = skipActive
433
+ ? state.data
434
+ : await fetchData(state.path, { routeId: state.routeId, params: state.params }, ac.signal);
435
+ if (mine !== token)
436
+ return;
437
+ cachePut(state.path, data); // the revalidated (or kept) data is now the cache's truth
438
+ // Mark the OTHER changed routes stale so the next access refetches.
439
+ markStale(changed.filter((p) => p !== state.path));
440
+ // Reconcile: publish the revalidated data + actionData; omit `submission` (the optimistic
441
+ // window is over — the real data now drives the view).
442
+ state = {
443
+ routeId: state.routeId,
444
+ params: state.params,
445
+ path: state.path,
446
+ data,
447
+ actionData,
448
+ pending: false,
449
+ };
450
+ emit();
451
+ // Refresh any mounted fetcher showing one of the changed routes (the active route was just
452
+ // revalidated inline above, so skip it here). Best-effort — never rejects the submit.
453
+ await refreshMounted(changed, true);
454
+ }
455
+ catch (err) {
456
+ if (mine === token) {
457
+ // Revert: clear `submission` (the optimistic view vanishes) leaving `data` untouched, so the
458
+ // pre-submit data shows through.
459
+ state = {
460
+ routeId: state.routeId,
461
+ params: state.params,
462
+ path: state.path,
463
+ data: state.data,
464
+ actionData: state.actionData,
465
+ pending: false,
466
+ };
467
+ emit();
468
+ }
469
+ throw err;
470
+ }
471
+ },
472
+ invalidate: async (paths) => {
473
+ // Mark targeted cache entries stale (all entries when no `paths`) — unmounted ones refetch
474
+ // lazily on next access.
475
+ const targets = paths ?? [...cache.keys()];
476
+ markStale(targets);
477
+ // Refresh mounted readers now: the active route (when in scope — an explicit list including it,
478
+ // or an invalidate-all) + any fetcher showing a targeted path. The active refetch rejects on
479
+ // failure (the caller asked to refresh); fetcher refreshes are best-effort (swallowed).
480
+ const jobs = [];
481
+ if (paths === undefined || paths.includes(state.path))
482
+ jobs.push(refetchActive());
483
+ for (const entry of fetchers.values())
484
+ jobs.push(entry.refreshIfShowing(targets));
485
+ await Promise.all(jobs);
486
+ },
487
+ prefetch: async (path) => {
488
+ if (prefetched.has(path) || inflight.has(path))
489
+ return;
490
+ const matched = match(path);
491
+ if (matched === null)
492
+ return;
493
+ inflight.add(path);
494
+ try {
495
+ const [, data] = await Promise.all([
496
+ loadModule?.(matched.routeId),
497
+ fetchData(path, matched),
498
+ ]);
499
+ if (prefetched.size >= MAX_PREFETCH) {
500
+ const oldest = prefetched.keys().next().value;
501
+ if (oldest !== undefined)
502
+ prefetched.delete(oldest);
503
+ }
504
+ prefetched.set(path, data);
505
+ }
506
+ catch {
507
+ // Best-effort: a failed prefetch just means the eventual navigate fetches normally.
508
+ }
509
+ finally {
510
+ inflight.delete(path);
511
+ }
512
+ },
513
+ fetcher: (key) => {
514
+ const existing = fetchers.get(key);
515
+ if (existing !== undefined)
516
+ return existing.fetcher;
517
+ const entry = createFetcher();
518
+ fetchers.set(key, entry);
519
+ emitFetchers(); // a new fetcher appeared — wake any `useFetchers` subscriber
520
+ return entry.fetcher;
521
+ },
522
+ fetchers: () => fetchersArr,
523
+ subscribeFetchers: (listener) => {
524
+ fetcherListeners.add(listener);
525
+ return () => {
526
+ fetcherListeners.delete(listener);
527
+ };
528
+ },
529
+ };
530
+ }
531
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
package/dist/vite.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ /** Minimal app surface — `createWebApp(...)` satisfies it. */
2
+ interface FetchApp {
3
+ fetch(request: Request): Response | Promise<Response>;
4
+ }
5
+ export interface ViteDevServerOptions {
6
+ /** Absolute (or cwd-relative) path to the `routes/` dir. */
7
+ readonly routesDir: string;
8
+ /** Client runtime module providing `mountRouter` (e.g. `"@nifrajs/web-react/client"`). */
9
+ readonly clientModule: string;
10
+ /**
11
+ * Build the nifra app for the given dev client-entry URL. `importQuery` changes when a route file
12
+ * changes — thread it into `discoverRoutes(routesDir, { importQuery })` so a hard reload SSRs edited
13
+ * modules (HMR handles the live client update; this keeps server-render fresh).
14
+ */
15
+ readonly createApp: (clientEntry: string, importQuery: string) => FetchApp | Promise<FetchApp>;
16
+ /** Vite plugins — inject your framework's official plugin, e.g. `[react()]`. */
17
+ readonly plugins?: readonly unknown[];
18
+ /**
19
+ * Extra `resolve.conditions` prepended ahead of nifra's defaults — some frameworks need their own
20
+ * (e.g. Solid's `"solid"` condition routes `solid-js` to its source/JSX-dev build).
21
+ */
22
+ readonly conditions?: readonly string[];
23
+ /**
24
+ * Compile-time `define` replacements (e.g. Vue's `__VUE_OPTIONS_API__` flags). Vite already sets
25
+ * `process.env.NODE_ENV` in dev; this is for framework feature flags the plugin doesn't inject.
26
+ */
27
+ readonly define?: Readonly<Record<string, string>>;
28
+ /** Vite project root (default `process.cwd()`). */
29
+ readonly root?: string;
30
+ /** Port (default 3000). */
31
+ readonly port?: number;
32
+ /**
33
+ * Use polling for the file watcher. Native fs events (fsevents/inotify) are unreliable inside
34
+ * containers, networked filesystems, and some sandboxes — there, HMR silently never fires. Set
35
+ * `true` (or the env var `CHOKIDAR_USEPOLLING=1`) to poll instead. Default: off (native events).
36
+ */
37
+ readonly poll?: boolean;
38
+ }
39
+ export interface ViteDevServer {
40
+ readonly port: number;
41
+ stop(): Promise<void>;
42
+ }
43
+ /**
44
+ * Start the Vite-backed dev server: Vite serves/HMRs the client; nifra SSRs each request and Vite
45
+ * injects its HMR client + the framework refresh preamble via `transformIndexHtml`.
46
+ */
47
+ export declare function createViteDevServer(options: ViteDevServerOptions): Promise<ViteDevServer>;
48
+ export {};
49
+ //# sourceMappingURL=vite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAuBA,8DAA8D;AAC9D,UAAU,QAAQ;IAChB,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtD;AAiBD,MAAM,WAAW,oBAAoB;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,0FAA0F;IAC1F,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC9F,gFAAgF;IAChF,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;IACrC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAClD,mDAAmD;IACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,2BAA2B;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAgCD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CA8F/F"}