@nifrajs/web-solid 5.1.0 → 5.2.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/CHANGELOG.md ADDED
@@ -0,0 +1,1251 @@
1
+ # @nifrajs/web-solid
2
+
3
+ ## 5.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1d20d1f: An app registers its locale routing once: `export const i18n = urls` (the router `defineI18nRouting()` returns) from `backend/framework.ts`, which `nifra dev`, `nifra build` and the generated server entry pass to `createWebApp({ i18n })`. Every document then takes `<html lang dir>` from the registry's `documentMeta(localeOf(path))` unless the route's meta sets `lang`, on a hard load and after each client navigation, and carries `Content-Language`. Each adapter's new `useLocale()` returns the page's locale key, and `<I18nProvider>` formats in the page's locale when no `locale` is passed, with no loader handing either over. A route under a `[lang]` or `[[lang]]` directory runs `matchSegment()` before any middleware: an unserved locale, or a page missing from it, is a 404 through the app's `_404`, and a non-canonical prefix such as `/en/x` with an unprefixed default is a 308 to `/x`.
8
+
9
+ ### Patch Changes
10
+
11
+ - 9498cf8: The package ships its `CHANGELOG.md`, so the installed package has the notes for every version, as the GitHub release does. Before, the tarball held only the code, `README.md`, `LICENSE` and `package.json`.
12
+ - 281a48e: A production client build (Bun or Vite) moves copy tables (`@nifrajs/i18n/copy`) into one chunk per locale, so a page's JavaScript carries the copy of the locale it renders in and none of the others; the server bundle keeps every table whole. The client manifest lists the chunks as `copyChunks`, the generated server entry passes them to the new `createWebApp({ copyChunks })` option (a hand-written entry passes the manifest's), and each page hands the map to the browser and preloads the chunks it reads: its URL's locale and the one its `<html lang>` names. A client navigation loads the next URL's chunk with the route's code; the router passes the target path to `loadModule` for that. The build reads tables with the app's TypeScript (5.9 or 6) and warns and leaves them whole without one; `buildClient({ copySplit: false })` turns it off. `readSource()` and `addSourceTransform()` in `@nifrajs/web/plugins/kit` let a plugin that claims a file still compile the rewritten source; the Solid and StyleX plugins read through it.
13
+ - Updated dependencies [9498cf8]
14
+ - Updated dependencies [1f3ff32]
15
+ - Updated dependencies [4bb8e52]
16
+ - Updated dependencies [cdff19d]
17
+ - Updated dependencies [5edd0ba]
18
+ - Updated dependencies [000b4cb]
19
+ - Updated dependencies [c5455fb]
20
+ - Updated dependencies [6082ba5]
21
+ - Updated dependencies [fd58beb]
22
+ - Updated dependencies [ea25a61]
23
+ - Updated dependencies [ed13e36]
24
+ - Updated dependencies [281a48e]
25
+ - Updated dependencies [281a48e]
26
+ - Updated dependencies [1d20d1f]
27
+ - Updated dependencies [1d20d1f]
28
+ - Updated dependencies [746ada9]
29
+ - Updated dependencies [1d20d1f]
30
+ - Updated dependencies [b9e7c6b]
31
+ - @nifrajs/core@5.2.0
32
+ - @nifrajs/i18n@5.2.0
33
+ - @nifrajs/image@5.2.0
34
+ - @nifrajs/web@5.2.0
35
+
36
+ ## 5.1.0
37
+
38
+ ### Patch Changes
39
+
40
+ - df50368: When a Solid `<ErrorBoundary>` catches during server rendering, or a resource fails, the page no longer ships the error's message and stack in its inline hydration script. On Bun, that also included the server file path. The browser now receives `Error("Internal Server Error")`. In development and test the error keeps its text. That inline script now also carries the document's CSP nonce on pages rendered in one pass: `RenderAdapter.renderToString` receives `{ nonce }` as `renderToStream` already did. Before, a strict CSP blocked the script and hydration did not match the server's markup.
41
+ - Updated dependencies [78b2a04]
42
+ - Updated dependencies [638efe5]
43
+ - Updated dependencies [2a0a5d3]
44
+ - Updated dependencies [5372e3a]
45
+ - Updated dependencies [b276c67]
46
+ - Updated dependencies [29d6649]
47
+ - Updated dependencies [2a0a5d3]
48
+ - Updated dependencies [72e1b4b]
49
+ - Updated dependencies [7bb8a67]
50
+ - Updated dependencies [513ec28]
51
+ - @nifrajs/web@5.1.0
52
+ - @nifrajs/core@5.1.0
53
+ - @nifrajs/i18n@5.1.0
54
+ - @nifrajs/image@5.1.0
55
+
56
+ ## 5.0.0
57
+
58
+ ### Minor Changes
59
+
60
+ - fc0284a: Add opt-in server components across React, Vue, Svelte, Solid and Preact. Closed schemas project public props, owner GET admission and read capabilities govern every refresh, and private responses bypass shared caches. React uses native Flight; Vue, Svelte, Solid and Preact preserve native island state and owned ranges.
61
+
62
+ Add coordinated Vite builds and development generations, guarded component references, generated Bun/Node/Deno/Workers/Pages/Vercel outputs, typed outlets, router and server-function refresh integration, and release certification for browsers, packaged consumers, resource limits and performance. Existing applications retain their default rendering pipeline.
63
+
64
+ Reuse registered Web middleware continuations across requests while retaining request-local state.
65
+
66
+ ### Patch Changes
67
+
68
+ - Updated dependencies [7169820]
69
+ - Updated dependencies [22e3df7]
70
+ - Updated dependencies [a0a02f4]
71
+ - Updated dependencies [0aed425]
72
+ - Updated dependencies [eaf030b]
73
+ - Updated dependencies [7de0397]
74
+ - Updated dependencies [674c658]
75
+ - Updated dependencies [de27557]
76
+ - Updated dependencies [2173644]
77
+ - Updated dependencies [4d894b0]
78
+ - Updated dependencies [61901cd]
79
+ - Updated dependencies [5e366e2]
80
+ - Updated dependencies [2938a0d]
81
+ - Updated dependencies [dc8439c]
82
+ - Updated dependencies [b19cb37]
83
+ - Updated dependencies [4330e40]
84
+ - Updated dependencies [4199ff3]
85
+ - Updated dependencies [90d9ee6]
86
+ - Updated dependencies [364a234]
87
+ - Updated dependencies [c06cba5]
88
+ - Updated dependencies [f4d3852]
89
+ - Updated dependencies [4a82ae0]
90
+ - Updated dependencies [0ff867a]
91
+ - Updated dependencies [e7391bf]
92
+ - Updated dependencies [0b80a59]
93
+ - Updated dependencies [c64db12]
94
+ - Updated dependencies [3753104]
95
+ - Updated dependencies [4b3b1fa]
96
+ - Updated dependencies [3562557]
97
+ - Updated dependencies [53087f3]
98
+ - Updated dependencies [2def6c7]
99
+ - Updated dependencies [b5b5bc3]
100
+ - Updated dependencies [22e1777]
101
+ - Updated dependencies [3a483cd]
102
+ - Updated dependencies [35f52c7]
103
+ - Updated dependencies [343cb81]
104
+ - Updated dependencies [412a9ee]
105
+ - Updated dependencies [65883e5]
106
+ - Updated dependencies [0e20529]
107
+ - Updated dependencies [d91fd44]
108
+ - Updated dependencies [f7e36ec]
109
+ - Updated dependencies [262e46d]
110
+ - Updated dependencies [b13e071]
111
+ - Updated dependencies [944623d]
112
+ - Updated dependencies [6d9869d]
113
+ - Updated dependencies [077657f]
114
+ - Updated dependencies [b9cc68c]
115
+ - Updated dependencies [de2cc1d]
116
+ - Updated dependencies [a5963cb]
117
+ - Updated dependencies [05aac0e]
118
+ - Updated dependencies [1a6616f]
119
+ - Updated dependencies [ecd738e]
120
+ - Updated dependencies [7775c2b]
121
+ - Updated dependencies [05587e0]
122
+ - Updated dependencies [c75818d]
123
+ - Updated dependencies [3db36b3]
124
+ - Updated dependencies [7775c2b]
125
+ - Updated dependencies [09c47c5]
126
+ - Updated dependencies [326caee]
127
+ - Updated dependencies [f8e0ed5]
128
+ - Updated dependencies [a588c18]
129
+ - Updated dependencies [1cdcfe5]
130
+ - Updated dependencies [e195fe8]
131
+ - Updated dependencies [846e2f6]
132
+ - Updated dependencies [55f4fdb]
133
+ - Updated dependencies [7775c2b]
134
+ - Updated dependencies [d3e79c4]
135
+ - Updated dependencies [d922f65]
136
+ - Updated dependencies [aadd9fc]
137
+ - Updated dependencies [ea16748]
138
+ - Updated dependencies [a1eda0a]
139
+ - Updated dependencies [fc0284a]
140
+ - Updated dependencies [5b22f4d]
141
+ - Updated dependencies [1b94593]
142
+ - Updated dependencies [9f58295]
143
+ - Updated dependencies [2f7299a]
144
+ - Updated dependencies [29e62a0]
145
+ - Updated dependencies [c613e7d]
146
+ - Updated dependencies [5975163]
147
+ - Updated dependencies [b9608ac]
148
+ - Updated dependencies [7a165de]
149
+ - Updated dependencies [4064f36]
150
+ - Updated dependencies [d8f11a5]
151
+ - Updated dependencies [e9e02cf]
152
+ - Updated dependencies [b70b18a]
153
+ - Updated dependencies [6f42b38]
154
+ - Updated dependencies [870227d]
155
+ - Updated dependencies [48aad8c]
156
+ - Updated dependencies [2fbb4f0]
157
+ - Updated dependencies [1d66252]
158
+ - Updated dependencies [a6a6834]
159
+ - Updated dependencies [166a6ff]
160
+ - Updated dependencies [79be5af]
161
+ - Updated dependencies [41050ed]
162
+ - Updated dependencies [fc837cb]
163
+ - Updated dependencies [bf6eeb0]
164
+ - Updated dependencies [5a3c27a]
165
+ - Updated dependencies [15a3a66]
166
+ - Updated dependencies [b80ce77]
167
+ - Updated dependencies [9b971fc]
168
+ - Updated dependencies [2577fc7]
169
+ - Updated dependencies [9b1acc9]
170
+ - Updated dependencies [391ab3c]
171
+ - Updated dependencies [3bf7d6b]
172
+ - Updated dependencies [7775c2b]
173
+ - Updated dependencies [ab1935b]
174
+ - Updated dependencies [740109f]
175
+ - Updated dependencies [e0a25fe]
176
+ - Updated dependencies [3630b6e]
177
+ - Updated dependencies [1290c6d]
178
+ - Updated dependencies [d0a7d58]
179
+ - @nifrajs/web@5.0.0
180
+ - @nifrajs/core@5.0.0
181
+ - @nifrajs/i18n@5.0.0
182
+ - @nifrajs/image@5.0.0
183
+
184
+ ## 4.0.2
185
+
186
+ ### Patch Changes
187
+
188
+ - Updated dependencies [fcd6a5b]
189
+ - @nifrajs/web@4.0.2
190
+ - @nifrajs/core@4.0.2
191
+ - @nifrajs/i18n@4.0.2
192
+ - @nifrajs/image@4.0.2
193
+
194
+ ## 4.0.1
195
+
196
+ ### Patch Changes
197
+
198
+ - Updated dependencies [bbb2b27]
199
+ - Updated dependencies [2957acd]
200
+ - Updated dependencies [4bd292a]
201
+ - Updated dependencies [55e813b]
202
+ - @nifrajs/web@4.0.1
203
+ - @nifrajs/core@4.0.1
204
+ - @nifrajs/i18n@4.0.1
205
+ - @nifrajs/image@4.0.1
206
+
207
+ ## 4.0.0
208
+
209
+ ### Major Changes
210
+
211
+ - a8b33bc: The Solid and Svelte compiler plugins live on their `/plugin` subpaths, and each adapter root exports only the render adapter.
212
+
213
+ - `solidBunPlugin` is imported from `@nifrajs/web-solid/plugin`, matching `@nifrajs/web-svelte/plugin` and `@nifrajs/web-vue/plugin`.
214
+ - `@nifrajs/web-solid` and `@nifrajs/web-svelte` link no build-time or `node:` module, so a server or edge bundle that imports the adapter builds under edge resolve conditions (Cloudflare Workers, Vercel Edge, Deno).
215
+ - Solid site scaffolds import the plugin from the subpath.
216
+
217
+ Breaking: `solidBunPlugin` is no longer exported from `@nifrajs/web-solid`, nor `svelteBunPlugin` from `@nifrajs/web-svelte`. `nifra fix --code NF-C005` rewrites those imports.
218
+
219
+ ### Minor Changes
220
+
221
+ - f70f99b: feat(i18n): selectordinal, fallback catalogs, typed nested catalogs and the locale cookie
222
+
223
+ The formatter supports `selectordinal` (`{n, selectordinal, one {#st} two {#nd} few {#rd} other {#th}}`).
224
+ Inside a `plural` or `selectordinal` case, `#` is now the number in the locale's own format
225
+ (`1,000 items`, `1.000 Artikel`) instead of its plain digits - the output changes for counts of 1,000
226
+ and more and for fractions.
227
+
228
+ `createFormatter(locale, messages, options)` takes `fallback` catalogs, tried in order for a key the
229
+ catalog lacks (`locales.chain()` gives the order); `onMissing(key, locale)`, called once per key when
230
+ no catalog has it; and `timeZone` and `numberingSystem` defaults for `d()`, `n()` and `#`. An invalid
231
+ locale, time zone or numbering system throws at creation. Formatters are cached per catalog and
232
+ options, with bounded caches, so per-request values cannot grow memory.
233
+
234
+ Catalogs may nest: values are messages, lists or blocks, read with dotted keys (`t("home.title")`); a
235
+ flat key that contains a dot is found first, so flat catalogs work unchanged. `get(key)` returns a list
236
+ or block whole. Lookups read own properties only, and an argument named like an `Object.prototype`
237
+ member renders empty unless passed. Declaring `interface Register { messages: typeof en }` on
238
+ `@nifrajs/i18n` types every `t()` and `get()` key, and other locales' catalogs (`Translation`,
239
+ `PartialMessages`) against that shape.
240
+
241
+ `localeCookie(name, locale, { maxAge })` returns the `document.cookie` string for a language switcher,
242
+ byte-identical to the `Set-Cookie` `localeDetector({ persist: true })` writes.
243
+
244
+ Every adapter's `<I18nProvider>` takes `fallback`, `onMissing`, `timeZone` and `numberingSystem`, and
245
+ its `messages` prop is checked against the registered catalog type.
246
+
247
+ - 49f106f: feat(i18n): rich text from catalog messages without HTML
248
+
249
+ `rich(formatter, key, tags, vars)` from the new `@nifrajs/i18n/rich` entry formats a message like
250
+ `t()` and turns its `<name>…</name>` and `<name/>` tags into calls to `tags[name]`, returning the
251
+ message as text and whatever the handlers returned. Tags are bare names (no attributes); a tag
252
+ without an own handler keeps its content as text, an unclosed or stray marker stays literal, and
253
+ interpolated values and `#` are never read for tags. `renderRich(renderer, ...)` is the same for a
254
+ UI framework.
255
+
256
+ React, Preact, Solid and Vue export `rich(t, key, tags, vars)` from `/i18n`, returning one node
257
+ (each handler receives its tag's content as one node, and `<br/>` renders a `<br>` unless `br` is
258
+ given). Svelte exports `<Rich key tags vars>`, which takes one snippet per tag, and `rich()` for the
259
+ parts array. `t()` is unchanged.
260
+
261
+ - 0f6babe: feat(web): a route can export a `handle`, and `useMatches()` reports the rendered chain on every adapter.
262
+
263
+ ```tsx
264
+ // routes/orgs/[org]/_layout.tsx
265
+ import { useMatches } from "@nifrajs/web-react/router";
266
+
267
+ export const handle = { crumb: "Organization" };
268
+
269
+ export default function OrgLayout({
270
+ children,
271
+ }: {
272
+ children: React.ReactNode;
273
+ }) {
274
+ const crumbs = useMatches().flatMap(
275
+ (m) => (m.handle as { crumb?: string } | undefined)?.crumb ?? []
276
+ );
277
+ // ...
278
+ }
279
+ ```
280
+
281
+ `useMatches()` lists the layouts being rendered, outermost first, then the page, each as
282
+ `{ id, pathname, params, data, handle }`: the route file without its extension, the part of the URL
283
+ it covers (never the query), the params it declares, its loader data (`null` without a loader), and
284
+ its `handle` export. The server render and the browser report the same list, so a breadcrumb trail
285
+ hydrates with no mismatch. `handle` is read from the module on each side and never serialized.
286
+
287
+ While a `_loading` page is up it takes the page's place; a nested `_404` reports the layouts it
288
+ renders inside; an `_error` page the server renders reports an empty list. The hook ships from each
289
+ adapter's `/router` entry: an array on React and Preact, a `Ref` on Vue, an accessor on Solid and
290
+ Svelte. An app that never calls it does not bundle it.
291
+
292
+ The Preact, Solid, Vue and Svelte client mounts now pass `params` and `path` to the rendered chain,
293
+ as the server render already did. `UIMatch` and `MatchChain` are exported from `@nifrajs/web`.
294
+
295
+ ### Patch Changes
296
+
297
+ - ee19d29: fix(web-react, web-preact, web-vue, web-solid, web-svelte): a layout keeps its loader data in the
298
+ browser. The mounted router rendered every layout with `data: null` - on the first paint, where the
299
+ server had rendered the layout with its data and the client render no longer matched it, and after
300
+ each client navigation. It now hands each layout the data the router holds for it. On Solid a layout
301
+ also follows a same-route update, so new layout data after a revalidation or a param change arrives
302
+ without the layout remounting.
303
+ - 6393b1e: feat(web): `_loading.tsx` is what the page slot shows while a client navigation loads. A navigation
304
+ still waiting on its data after about 120 ms swaps the page for the target route's nearest
305
+ `_loading` - the innermost one above it whose layouts are already on screen, which are the layouts
306
+ the two pages share; they stay mounted with their data. A `_loading` never renders outside a layout
307
+ above it. A navigation that settles sooner goes straight to the new page, as does one with no
308
+ eligible `_loading`; a change of search on the same path and a form submit keep the page. A newer
309
+ navigation, a form submit, or a refresh of the page on screen takes over from a pending loading
310
+ page, and a superseded navigation that fails later changes nothing. The
311
+ component receives `pending` and no `data`. It is browser-only: the server never renders one, and an
312
+ app without a `_loading` file ships no code for it. Where the browser runs view transitions, a
313
+ navigation's transition ends on the loading page instead of holding the old page until the data
314
+ arrives. `Manifest.loadings` lists the pages (`LoadingEntry`, each with the layouts it sits under)
315
+ and `RouteEntry.loadingIds` the ones above each route. In a `buildClient` build every page links the
316
+ loading pages' stylesheets.
317
+
318
+ A file named `_loading` was an ignored underscore file before; one kept in a routes directory for
319
+ another purpose is now a loading page.
320
+
321
+ fix(web-solid): the mounted router renders the chain the router names while a navigation is pending,
322
+ which is how a `_loading` page reaches the screen. A pending navigation on the same chain is still
323
+ skipped until it settles.
324
+
325
+ - 1ae5543: The MDX runtime's intrinsic components always render their own tag: a `component` prop on a Markdown element no longer replaces the element, and the element's props stay reactive. `useMDXComponents()` now types each component's result as `JSX.Element` instead of `unknown`.
326
+ - 64e7a42: fix(web): pages that `defer()` keep working under a nonce Content-Security-Policy.
327
+ React, Solid and Preact stream inline scripts to reveal a Suspense boundary that resolves after the
328
+ shell, and none of them carried the document's nonce, so a nonce CSP blocked them and the boundary
329
+ stayed on its fallback. `RenderAdapter.renderToStream` now receives `{ nonce }` as an optional third
330
+ argument (`RenderStreamOptions`), and every adapter that streams scripts applies it: React and Solid
331
+ through their own `nonce` option, Preact on the one island-runtime script it streams. A script the
332
+ app renders itself never inherits the nonce. Vue, Svelte and the vanilla adapter stream no scripts.
333
+ - Updated dependencies [dde125b]
334
+ - Updated dependencies [22e2af8]
335
+ - Updated dependencies [72b62fa]
336
+ - Updated dependencies [aa44e93]
337
+ - Updated dependencies [4a3ee60]
338
+ - Updated dependencies [963694f]
339
+ - Updated dependencies [aad6297]
340
+ - Updated dependencies [dad0d41]
341
+ - Updated dependencies [538adc2]
342
+ - Updated dependencies [f47edd1]
343
+ - Updated dependencies [df9530a]
344
+ - Updated dependencies [3e6973f]
345
+ - Updated dependencies [25e8edf]
346
+ - Updated dependencies [2b5e5fc]
347
+ - Updated dependencies [3b090de]
348
+ - Updated dependencies [da7d792]
349
+ - Updated dependencies [612a296]
350
+ - Updated dependencies [fb14dfa]
351
+ - Updated dependencies [8ae97f6]
352
+ - Updated dependencies [4af6f39]
353
+ - Updated dependencies [ca8b50d]
354
+ - Updated dependencies [b00a889]
355
+ - Updated dependencies [b53d64f]
356
+ - Updated dependencies [66fd712]
357
+ - Updated dependencies [9c3d524]
358
+ - Updated dependencies [738e7a1]
359
+ - Updated dependencies [4801cac]
360
+ - Updated dependencies [1b2d53a]
361
+ - Updated dependencies [25fe13d]
362
+ - Updated dependencies [0852290]
363
+ - Updated dependencies [0589dbe]
364
+ - Updated dependencies [2e2d8c0]
365
+ - Updated dependencies [856f5ce]
366
+ - Updated dependencies [18aa5aa]
367
+ - Updated dependencies [cfd86b3]
368
+ - Updated dependencies [8ff96c9]
369
+ - Updated dependencies [4c46199]
370
+ - Updated dependencies [eef4932]
371
+ - Updated dependencies [6de8686]
372
+ - Updated dependencies [86e2d0f]
373
+ - Updated dependencies [a0cfffa]
374
+ - Updated dependencies [d7892ea]
375
+ - Updated dependencies [93e5e7f]
376
+ - Updated dependencies [214d674]
377
+ - Updated dependencies [4936309]
378
+ - Updated dependencies [ff5a779]
379
+ - Updated dependencies [772249a]
380
+ - Updated dependencies [f70f99b]
381
+ - Updated dependencies [49f106f]
382
+ - Updated dependencies [4936309]
383
+ - Updated dependencies [def0172]
384
+ - Updated dependencies [fc2f019]
385
+ - Updated dependencies [a734fba]
386
+ - Updated dependencies [0e9b167]
387
+ - Updated dependencies [bbdc5a1]
388
+ - Updated dependencies [10bc446]
389
+ - Updated dependencies [e8270d9]
390
+ - Updated dependencies [d942c33]
391
+ - Updated dependencies [ef28ef9]
392
+ - Updated dependencies [ff4a062]
393
+ - Updated dependencies [43ba944]
394
+ - Updated dependencies [46c741a]
395
+ - Updated dependencies [7bfa25e]
396
+ - Updated dependencies [216fe27]
397
+ - Updated dependencies [4936309]
398
+ - Updated dependencies [6e257a6]
399
+ - Updated dependencies [4a03d30]
400
+ - Updated dependencies [8e30090]
401
+ - Updated dependencies [28f3aaf]
402
+ - Updated dependencies [6d20355]
403
+ - Updated dependencies [08250bf]
404
+ - Updated dependencies [6907cbe]
405
+ - Updated dependencies [4b8d8de]
406
+ - Updated dependencies [ba5dd1c]
407
+ - Updated dependencies [d50f73e]
408
+ - Updated dependencies [031c33d]
409
+ - Updated dependencies [8fa902c]
410
+ - Updated dependencies [085e852]
411
+ - Updated dependencies [0dac7ec]
412
+ - Updated dependencies [b64c3ee]
413
+ - Updated dependencies [dc2d4d3]
414
+ - Updated dependencies [bda9637]
415
+ - Updated dependencies [81c720e]
416
+ - Updated dependencies [ed60b23]
417
+ - Updated dependencies [0150ed4]
418
+ - Updated dependencies [ae815ab]
419
+ - Updated dependencies [ea2ee87]
420
+ - Updated dependencies [3442e1c]
421
+ - Updated dependencies [85d636b]
422
+ - Updated dependencies [6c978a1]
423
+ - Updated dependencies [bfe29b6]
424
+ - Updated dependencies [8b99424]
425
+ - Updated dependencies [87783f0]
426
+ - Updated dependencies [135aba4]
427
+ - Updated dependencies [47b0d65]
428
+ - Updated dependencies [e32268d]
429
+ - Updated dependencies [432fec3]
430
+ - Updated dependencies [0e14068]
431
+ - Updated dependencies [8f1b780]
432
+ - Updated dependencies [dcc9ff6]
433
+ - Updated dependencies [5a63dd4]
434
+ - Updated dependencies [c49882f]
435
+ - Updated dependencies [dfd19d8]
436
+ - Updated dependencies [28e091f]
437
+ - Updated dependencies [046e79d]
438
+ - Updated dependencies [6393b1e]
439
+ - Updated dependencies [a158b74]
440
+ - Updated dependencies [ee19d29]
441
+ - Updated dependencies [293d3c8]
442
+ - Updated dependencies [7e1e1c3]
443
+ - Updated dependencies [0cd5f6e]
444
+ - Updated dependencies [2245bee]
445
+ - Updated dependencies [feeec4a]
446
+ - Updated dependencies [3eb6339]
447
+ - Updated dependencies [f784c32]
448
+ - Updated dependencies [e3b2b97]
449
+ - Updated dependencies [5934b5d]
450
+ - Updated dependencies [03a3729]
451
+ - Updated dependencies [bd11269]
452
+ - Updated dependencies [579d9a9]
453
+ - Updated dependencies [3554ad8]
454
+ - Updated dependencies [64e7a42]
455
+ - Updated dependencies [ee19d29]
456
+ - Updated dependencies [d6f806f]
457
+ - Updated dependencies [38cf032]
458
+ - Updated dependencies [b94e5cb]
459
+ - Updated dependencies [0f6babe]
460
+ - Updated dependencies [00f18bf]
461
+ - Updated dependencies [a84f546]
462
+ - Updated dependencies [669b6a2]
463
+ - Updated dependencies [ff25d68]
464
+ - @nifrajs/core@4.0.0
465
+ - @nifrajs/web@4.0.0
466
+ - @nifrajs/i18n@4.0.0
467
+ - @nifrajs/image@4.0.0
468
+
469
+ ## 3.5.0
470
+
471
+ ### Patch Changes
472
+
473
+ - Updated dependencies [6046984]
474
+ - Updated dependencies [ac27343]
475
+ - Updated dependencies [d5b7c22]
476
+ - @nifrajs/core@3.5.0
477
+ - @nifrajs/web@3.5.0
478
+ - @nifrajs/image@3.5.0
479
+ - @nifrajs/i18n@3.5.0
480
+
481
+ ## 3.4.0
482
+
483
+ ### Patch Changes
484
+
485
+ - 8d23613: Add the opt-in `@nifrajs/webmcp` package: typed WebMCP registration, core-backed receipts, deterministic predictive-UI reconciliation, and host-independent conformance checks. Also tighten agent execution cancellation cleanup so aborted local work cannot leak into later turns.
486
+ - Updated dependencies [8d23613]
487
+ - Updated dependencies [8d23613]
488
+ - Updated dependencies
489
+ - Updated dependencies [719d82e]
490
+ - @nifrajs/web@3.4.0
491
+ - @nifrajs/core@3.4.0
492
+ - @nifrajs/i18n@3.4.0
493
+ - @nifrajs/image@3.4.0
494
+
495
+ ## 3.3.0
496
+
497
+ ### Patch Changes
498
+
499
+ - @nifrajs/core@3.3.0
500
+ - @nifrajs/i18n@3.3.0
501
+ - @nifrajs/image@3.3.0
502
+ - @nifrajs/web@3.3.0
503
+
504
+ ## 3.2.0
505
+
506
+ ### Patch Changes
507
+
508
+ - c39712e: Move route policy compilation and deploy-target planning behind shared internal seams, pin the Solid adapter's Babel type identity, and add a cleanup-safe cross-runtime contract-lab runner.
509
+ - Updated dependencies [652201a]
510
+ - Updated dependencies [3aefb12]
511
+ - Updated dependencies [8b58d1f]
512
+ - Updated dependencies [c4ed8f7]
513
+ - Updated dependencies [25305bb]
514
+ - Updated dependencies [095c320]
515
+ - Updated dependencies [7504864]
516
+ - Updated dependencies [e88c23a]
517
+ - Updated dependencies [c39712e]
518
+ - Updated dependencies [9010fd3]
519
+ - Updated dependencies [7551709]
520
+ - Updated dependencies [ea2356e]
521
+ - Updated dependencies [a816b87]
522
+ - @nifrajs/web@3.2.0
523
+ - @nifrajs/core@3.2.0
524
+ - @nifrajs/image@3.2.0
525
+ - @nifrajs/i18n@3.2.0
526
+
527
+ ## 3.1.0
528
+
529
+ ### Patch Changes
530
+
531
+ - 8b136ee: Framework bindings now share consistent query and fetcher idle behavior while keeping mounted-router state isolated per adapter.
532
+ - Updated dependencies [5b78473]
533
+ - Updated dependencies [1400f6c]
534
+ - Updated dependencies [8b136ee]
535
+ - Updated dependencies [a7db515]
536
+ - @nifrajs/core@3.1.0
537
+ - @nifrajs/i18n@3.1.0
538
+ - @nifrajs/web@3.1.0
539
+ - @nifrajs/image@3.1.0
540
+
541
+ ## 3.0.0
542
+
543
+ ### Patch Changes
544
+
545
+ - 86a555b: The roadmap contract surfaces are now shipped across the public packages: shared island triggers,
546
+ typed content indexes and joins, client loader/action hooks, and unified static, dynamic, and
547
+ intercepting boundary modes. WebSocket routes also support opt-in synchronous outbound validation
548
+ through `sendSchema` + `validateSend`; invalid or asynchronous outbound frames fail closed while the
549
+ default remains type-level only.
550
+ - Updated dependencies [f3d2a35]
551
+ - Updated dependencies [6e43c15]
552
+ - Updated dependencies [293a7fe]
553
+ - Updated dependencies [485ae60]
554
+ - Updated dependencies [627b0ba]
555
+ - Updated dependencies [f0fd370]
556
+ - Updated dependencies [004deee]
557
+ - Updated dependencies [86a555b]
558
+ - Updated dependencies [8c5f4cf]
559
+ - Updated dependencies [f0fd370]
560
+ - Updated dependencies [381bbf3]
561
+ - Updated dependencies [36801ae]
562
+ - Updated dependencies [9acadba]
563
+ - Updated dependencies [99fc683]
564
+ - Updated dependencies [73d894d]
565
+ - @nifrajs/core@3.0.0
566
+ - @nifrajs/web@3.0.0
567
+ - @nifrajs/i18n@3.0.0
568
+ - @nifrajs/image@3.0.0
569
+
570
+ ## 2.14.1
571
+
572
+ ### Patch Changes
573
+
574
+ - Updated dependencies [bf93902]
575
+ - @nifrajs/core@2.14.1
576
+ - @nifrajs/i18n@2.14.1
577
+ - @nifrajs/web@2.14.1
578
+ - @nifrajs/image@2.14.1
579
+
580
+ ## 2.14.0
581
+
582
+ ### Patch Changes
583
+
584
+ - Updated dependencies [489c6b6]
585
+ - Updated dependencies [701961a]
586
+ - Updated dependencies [62e22e2]
587
+ - Updated dependencies [62e22e2]
588
+ - Updated dependencies [62133bf]
589
+ - Updated dependencies [8dffdf4]
590
+ - Updated dependencies [489c6b6]
591
+ - @nifrajs/web@2.14.0
592
+ - @nifrajs/core@2.14.0
593
+ - @nifrajs/i18n@2.14.0
594
+ - @nifrajs/image@2.14.0
595
+
596
+ ## 2.13.0
597
+
598
+ ### Patch Changes
599
+
600
+ - Updated dependencies [e0b2dd6]
601
+ - Updated dependencies [7535ce1]
602
+ - Updated dependencies [1704308]
603
+ - Updated dependencies [6510fdc]
604
+ - @nifrajs/core@2.13.0
605
+ - @nifrajs/web@2.13.0
606
+ - @nifrajs/i18n@2.13.0
607
+ - @nifrajs/image@2.13.0
608
+
609
+ ## 2.12.1
610
+
611
+ ### Patch Changes
612
+
613
+ - Updated dependencies [fba30c7]
614
+ - @nifrajs/core@2.12.1
615
+ - @nifrajs/i18n@2.12.1
616
+ - @nifrajs/web@2.12.1
617
+ - @nifrajs/image@2.12.1
618
+
619
+ ## 2.12.0
620
+
621
+ ### Patch Changes
622
+
623
+ - Updated dependencies [df100d3]
624
+ - Updated dependencies [0efacea]
625
+ - Updated dependencies [cd1732c]
626
+ - Updated dependencies [df100d3]
627
+ - Updated dependencies [9a9346e]
628
+ - Updated dependencies [b5f47c0]
629
+ - Updated dependencies [fc33c0f]
630
+ - Updated dependencies [fa51aba]
631
+ - Updated dependencies [c4e8bb0]
632
+ - Updated dependencies [11d1658]
633
+ - Updated dependencies [33ee9ff]
634
+ - Updated dependencies [ceda72d]
635
+ - Updated dependencies [2c004ca]
636
+ - Updated dependencies [5f71c23]
637
+ - Updated dependencies [3788b36]
638
+ - Updated dependencies [0863ef0]
639
+ - Updated dependencies [ae5338f]
640
+ - Updated dependencies [8847825]
641
+ - Updated dependencies [9a9346e]
642
+ - Updated dependencies [4c2123d]
643
+ - Updated dependencies [5e4e31a]
644
+ - Updated dependencies [24f1787]
645
+ - Updated dependencies [9a9346e]
646
+ - Updated dependencies [b045f9e]
647
+ - Updated dependencies [df07059]
648
+ - Updated dependencies [9a9346e]
649
+ - Updated dependencies [9a9346e]
650
+ - Updated dependencies [dbc0b79]
651
+ - Updated dependencies [bd5c624]
652
+ - Updated dependencies [a5d3f5b]
653
+ - Updated dependencies [00819c5]
654
+ - Updated dependencies [e2bdd4a]
655
+ - Updated dependencies [e2d1939]
656
+ - Updated dependencies [e83e6eb]
657
+ - Updated dependencies [64d25db]
658
+ - Updated dependencies [c55f7a3]
659
+ - Updated dependencies [f8b0097]
660
+ - @nifrajs/core@2.12.0
661
+ - @nifrajs/i18n@2.12.0
662
+ - @nifrajs/web@2.12.0
663
+ - @nifrajs/image@2.12.0
664
+
665
+ ## 2.11.0
666
+
667
+ ### Minor Changes
668
+
669
+ - ed5e91c: Vue, Solid and Svelte hot-patch a component edit in place on the Bun dev pipeline: the page keeps its scroll position, its open dialogs and the rest of its client state, and only the edited component re-renders. Route modules still full-reload on save, since a route carries the loader and meta the server ran. The wiring is emitted for a dev server's client compile only, so nothing reaches a production bundle.
670
+
671
+ `@nifrajs/web-svelte/plugin` adds `svelteHmrBoundary`, the same boundary for the Vite pipeline - pass it to `@sveltejs/vite-plugin-svelte` as `dynamicCompileOptions`. Svelte's hot-patch wrapper resolves a component through a signal, which reconciles against server markup only where the component is a plain child in a template; a layout or a page is neither, and wrapping one desyncs hydration on first load. The boundary keeps the wrapper on the app's own views. (Svelte recreates the patched component, so its own `$state` restarts - Vue and Solid preserve theirs.)
672
+
673
+ `Router.svelte` now takes `searchOfChain` from `@nifrajs/web/client` rather than the package root, so a client bundle no longer reaches server-only modules through it.
674
+
675
+ ### Patch Changes
676
+
677
+ - 30f5ea3: SSR renders the code that is on disk on the Bun dev pipeline, not just for route files. An edit to anything a route imports - a component, a helper, a `*.server` module, at any depth - now reaches the server-rendered HTML on the next request, so a saved change no longer shows up on the client while the SSR pass still renders the version the server started with. All four frameworks, and both `import "./Counter"` and `import "./Counter.tsx"`.
678
+
679
+ A module nobody edited keeps its identity, so a database client or any other module-scope singleton shared between the backend and a route is still a single instance; editing that module deliberately gives the routes the new code. The Vite pipeline is unchanged - it already owned an SSR module graph.
680
+
681
+ `@nifrajs/web/plugins/kit` adds `rewriteSsrImports`, which a plugin that compiles its own file type passes its `generate: "ssr"` output through - the compiling plugin is the only code that sees that file's imports, so it is the only place they can be re-keyed.
682
+
683
+ - Updated dependencies [ed5e91c]
684
+ - Updated dependencies [30f5ea3]
685
+ - Updated dependencies [c29e0d0]
686
+ - @nifrajs/web@2.11.0
687
+ - @nifrajs/core@2.11.0
688
+ - @nifrajs/i18n@2.11.0
689
+ - @nifrajs/image@2.11.0
690
+
691
+ ## 2.10.0
692
+
693
+ ### Patch Changes
694
+
695
+ - Updated dependencies [5263c4e]
696
+ - Updated dependencies [15bffdd]
697
+ - Updated dependencies [15bffdd]
698
+ - Updated dependencies [15bffdd]
699
+ - @nifrajs/web@2.10.0
700
+ - @nifrajs/core@2.10.0
701
+ - @nifrajs/image@2.10.0
702
+ - @nifrajs/i18n@2.10.0
703
+
704
+ ## 2.9.1
705
+
706
+ ### Patch Changes
707
+
708
+ - Updated dependencies [01e36fb]
709
+ - @nifrajs/core@2.9.1
710
+ - @nifrajs/web@2.9.1
711
+ - @nifrajs/i18n@2.9.1
712
+ - @nifrajs/image@2.9.1
713
+
714
+ ## 2.9.0
715
+
716
+ ### Patch Changes
717
+
718
+ - Updated dependencies [e05e56d]
719
+ - @nifrajs/core@2.9.0
720
+ - @nifrajs/web@2.9.0
721
+ - @nifrajs/i18n@2.9.0
722
+ - @nifrajs/image@2.9.0
723
+
724
+ ## 2.8.2
725
+
726
+ ### Patch Changes
727
+
728
+ - Updated dependencies [f7d68e8]
729
+ - @nifrajs/core@2.8.2
730
+ - @nifrajs/image@2.8.2
731
+ - @nifrajs/web@2.8.2
732
+ - @nifrajs/i18n@2.8.2
733
+
734
+ ## 2.8.1
735
+
736
+ ### Patch Changes
737
+
738
+ - Updated dependencies [78d66a4]
739
+ - Updated dependencies [93fdc89]
740
+ - @nifrajs/core@2.8.1
741
+ - @nifrajs/web@2.8.1
742
+ - @nifrajs/i18n@2.8.1
743
+ - @nifrajs/image@2.8.1
744
+
745
+ ## 2.8.0
746
+
747
+ ### Patch Changes
748
+
749
+ - Updated dependencies [118e4a5]
750
+ - @nifrajs/web@2.8.0
751
+ - @nifrajs/core@2.8.0
752
+ - @nifrajs/i18n@2.8.0
753
+ - @nifrajs/image@2.8.0
754
+
755
+ ## 2.7.1
756
+
757
+ ### Patch Changes
758
+
759
+ - Updated dependencies [52c89e0]
760
+ - @nifrajs/core@2.7.1
761
+ - @nifrajs/web@2.7.1
762
+ - @nifrajs/i18n@2.7.1
763
+ - @nifrajs/image@2.7.1
764
+
765
+ ## 2.7.0
766
+
767
+ ### Patch Changes
768
+
769
+ - @nifrajs/core@2.7.0
770
+ - @nifrajs/i18n@2.7.0
771
+ - @nifrajs/image@2.7.0
772
+ - @nifrajs/web@2.7.0
773
+
774
+ ## 2.6.1
775
+
776
+ ### Patch Changes
777
+
778
+ - Updated dependencies [5840c98]
779
+ - Updated dependencies [80419f5]
780
+ - @nifrajs/core@2.6.1
781
+ - @nifrajs/web@2.6.1
782
+ - @nifrajs/i18n@2.6.1
783
+ - @nifrajs/image@2.6.1
784
+
785
+ ## 2.6.0
786
+
787
+ ### Patch Changes
788
+
789
+ - Updated dependencies [e6349e5]
790
+ - Updated dependencies [08fe221]
791
+ - Updated dependencies [8383063]
792
+ - @nifrajs/web@2.6.0
793
+ - @nifrajs/core@2.6.0
794
+ - @nifrajs/i18n@2.6.0
795
+ - @nifrajs/image@2.6.0
796
+
797
+ ## 2.5.0
798
+
799
+ ### Patch Changes
800
+
801
+ - 02d9aa8: Routing hooks now SSR-render correctly on the dev server. In dev, the adapter is imported by Bun while route modules load through Vite's SSR runner, so the router module could be evaluated twice in one process - two context objects, and `useSearch`/`useParams`/`useLocation` read a context the render never provided. The result was hooks SSR-rendering their empty defaults (`useSearch()` gave `{}`) while the same request's loader saw the validated values; hydration then papered over it on the client, so it surfaced as "the search schema doesn't work in dev". The router context in every adapter is now a `globalThis` singleton (keyed by `Symbol.for`), so both evaluations share the one context React/Vue/Solid/Preact matches providers to readers by. The Vite dev server also mirrors its client `resolve.conditions` into `ssr.resolve.{conditions,externalConditions}`, so dev SSR resolves the same `bun`-conditioned source files Bun does instead of a package's `dist` artifact - which nothing in the dev loop rebuilds, and whose staleness previously 500'd inside framework code.
802
+ - Updated dependencies [02d9aa8]
803
+ - @nifrajs/web@2.5.0
804
+ - @nifrajs/core@2.5.0
805
+ - @nifrajs/i18n@2.5.0
806
+ - @nifrajs/image@2.5.0
807
+
808
+ ## 2.4.0
809
+
810
+ ### Patch Changes
811
+
812
+ - Updated dependencies [1c2bf5a]
813
+ - Updated dependencies [138bfba]
814
+ - Updated dependencies [23e6eb1]
815
+ - @nifrajs/web@2.4.0
816
+ - @nifrajs/core@2.4.0
817
+ - @nifrajs/i18n@2.4.0
818
+ - @nifrajs/image@2.4.0
819
+
820
+ ## 2.3.0
821
+
822
+ ### Minor Changes
823
+
824
+ - 2d9beaa: Preact, Vue, Solid and Svelte gain `useNavigate` and `useBlocker`, from `@nifrajs/web-<framework>/router`.
825
+
826
+ `useNavigate` returns a programmatic navigate (a path pushes or replaces; a number is a history delta),
827
+ matching the React adapter. `useBlocker` is the unsaved-changes guard - pass a boolean or a
828
+ `({ currentLocation, nextLocation }) => boolean` predicate and get back a `{ state, proceed, reset }`
829
+ value in each framework's own reactive shape (a Vue ref, a Solid accessor, a Svelte store, a plain value
830
+ in Preact). When a navigation is intercepted, `state` becomes `"blocked"`; show your own confirmation and
831
+ call `proceed()` or `reset()`. It also arms the native "Leave site?" prompt on tab close and reload.
832
+
833
+ ```svelte
834
+ <script>
835
+ import { useBlocker } from "@nifrajs/web-svelte/router"
836
+ let dirty = false
837
+ const blocker = useBlocker(() => dirty)
838
+ </script>
839
+
840
+ {#if $blocker.state === "blocked"}
841
+ <dialog open>
842
+ <button on:click={$blocker.reset}>Keep editing</button>
843
+ <button on:click={$blocker.proceed}>Discard</button>
844
+ </dialog>
845
+ {/if}
846
+ ```
847
+
848
+ In Vue, Solid and Svelte the hook is created once, so pass a function to track a changing flag
849
+ (`useBlocker(() => dirty)`); a bare boolean is captured as-is. The guarding itself already ran on every
850
+ adapter at the browser layer - this exposes it as a reactive hook.
851
+
852
+ - c823915: Typed, validated search params: a route declares a `searchSchema` and both its loader and its component read the parsed, validated query.
853
+
854
+ Export a Standard Schema as `searchSchema` from a route. The loader's `ctx.search` becomes the parsed URL query validated against it (typed via `LoaderArgs<typeof app, Env, typeof searchSchema>`), and the component reads the same value with `useSearch<typeof searchSchema>()`. Invalid or hostile input fails closed to the schema's defaults (never a 500); without a `searchSchema`, both are the raw parsed query. Validation runs at match time and the value is derived identically on the server and on client navigation, so a component never parses `window.location.search` by hand and the query it renders hydrates with no mismatch.
855
+
856
+ ```tsx
857
+ export const searchSchema = v.object({
858
+ page: v.optional(v.fallback(v.number(), 1), 1),
859
+ });
860
+
861
+ export async function loader({
862
+ search,
863
+ api,
864
+ }: LoaderArgs<typeof backend, unknown, typeof searchSchema>) {
865
+ return { rows: await api.reports.list(search).get() }; // search.page is a number
866
+ }
867
+
868
+ export default function Reports({ data }) {
869
+ const { page } = useSearch<typeof searchSchema>(); // page: number, SSR-correct
870
+ return <Pager page={page} />;
871
+ }
872
+ ```
873
+
874
+ A `_layout` can declare its own `searchSchema` for keys shared across a section (`?org`, `?theme`); the route's effective search merges the layout chain's schemas with the page's, page-wins on a conflict, so both the layout and the page read their validated slice from one object.
875
+
876
+ A route can also list `searchClientKeys` - search keys that are purely client-side UI (`?tab`, a client-side `?sort`, `?modal`). When a client navigation changes only those keys, the URL updates (so `useSearch` re-renders) without re-running the loader; any other key change revalidates as before, so data is never stale.
877
+
878
+ `useSearch` ships on every adapter - React (a value), Preact (a value), Vue (a `Ref`), Solid (an `Accessor`), and Svelte (an accessor), each in that framework's own shape.
879
+
880
+ `navigate` gains an object form on every adapter: `navigate({ to, search, replace })` serializes `search` onto `to` (no hand-built query strings). Run `nifra sync-routes` to generate `nifra-routes.d.ts` (each static route mapped to its schema output) and include it in your tsconfig, and `search` is typed against the target route's `searchSchema` - a wrong shape for a known route is a compile error, while an unmapped path takes a loose `search`. Regenerated from the route files, so a stale shape becomes a `tsc` error. The string-path and history-delta forms are unchanged.
881
+
882
+ ```ts
883
+ navigate({ to: "/reports", search: { page: 2 } }); // search typed against /reports's schema
884
+ ```
885
+
886
+ - 62a8d03: Add `useServerFn` - a server function's pending, data and error state - to all five adapters.
887
+
888
+ ```tsx
889
+ const addTodo = useServerFn(fns.addTodo)
890
+ <button disabled={addTodo.pending} onClick={() => addTodo.call({ text }).catch(() => {})}>add</button>
891
+ ```
892
+
893
+ Calling a server function never needed a binding: the client stub is `(input) => Promise<Output>`.
894
+ This adds only the state a component wants around it.
895
+
896
+ The state machine is `@nifrajs/web`'s `createServerFnStore`, shared by every adapter, so "is it
897
+ pending" has one answer rather than five that drift. Each binding contributes just its subscription
898
+ primitive: `useSyncExternalStore` (React, Preact), a signal (Solid), a `shallowRef` (Vue), a `readable`
899
+ (Svelte).
900
+
901
+ Two behaviours worth knowing:
902
+
903
+ - **The last call wins.** A response that is no longer the newest is discarded rather than written, so
904
+ a slow first call landing after a fast second cannot overwrite fresh data with stale.
905
+ - **`call` still rejects.** The error is recorded for rendering AND the promise rejects, so `await`
906
+ behaves normally. A caller that only renders from state should attach `.catch(() => {})`, as with
907
+ `useFetcher`'s `submit`.
908
+
909
+ `data` is kept while the next call is in flight, so a rendered list does not blank on every refetch.
910
+
911
+ ### Patch Changes
912
+
913
+ - fd04bb5: Solid's and Vue's `useServerFn` seed their reactive state from the store rather than from the idle
914
+ constant.
915
+
916
+ Both values are identical today - the store is created one line above and cannot have moved - so this
917
+ changes no behaviour. It removes the dependence on that staying true. Svelte's binding had the same
918
+ line reading the constant, and because its subscription is lazy the first render showed idle for a
919
+ call that had already finished. Reading the snapshot makes correctness independent of when the
920
+ subscription attaches.
921
+
922
+ - ea0a27f: A server function has one type per half, so both the server call and the hook argument are honest.
923
+
924
+ ```ts
925
+ export type ClientServerFn<Input, Output> = (
926
+ input: Input
927
+ ) => MaybePromise<Output>;
928
+ export type ServerFnReference<Input, Output> =
929
+ | ServerFn<Input, Output>
930
+ | ClientServerFn<Input, Output>;
931
+ ```
932
+
933
+ One type could not describe both halves. `ServerFn` is the SERVER declaration and takes `(input,
934
+ context)`; the client imports a generated stub that takes one argument. Widening the single type so a
935
+ one-argument call compiled made a direct server call type-check while handing the declaration
936
+ `undefined` for a context its implementation requires - a runtime failure the compiler had just been
937
+ told to allow.
938
+
939
+ Now the two are separate and `useServerFn` accepts either through `ServerFnReference`, which is the
940
+ one place the two halves legitimately meet. Calling a declaration from your own server code needs the
941
+ context, and omitting it is a compile error again.
942
+
943
+ - Updated dependencies [6f5b3ad]
944
+ - Updated dependencies [85b354d]
945
+ - Updated dependencies [7293a1c]
946
+ - Updated dependencies [8514caa]
947
+ - Updated dependencies [ea0a27f]
948
+ - Updated dependencies [ea0a27f]
949
+ - Updated dependencies [45b0733]
950
+ - Updated dependencies [c42d777]
951
+ - Updated dependencies [ea0a27f]
952
+ - Updated dependencies [b271164]
953
+ - Updated dependencies [8c77d47]
954
+ - Updated dependencies [ea0a27f]
955
+ - Updated dependencies [ea0a27f]
956
+ - Updated dependencies [d190b1c]
957
+ - Updated dependencies [a4ecca9]
958
+ - Updated dependencies [de8d992]
959
+ - Updated dependencies [a92104e]
960
+ - Updated dependencies [5fe332a]
961
+ - Updated dependencies [c823915]
962
+ - Updated dependencies [d2840ac]
963
+ - Updated dependencies [62a8d03]
964
+ - Updated dependencies [dcacfe7]
965
+ - Updated dependencies [28704d7]
966
+ - Updated dependencies [ea0a27f]
967
+ - Updated dependencies [0c2de22]
968
+ - @nifrajs/core@2.3.0
969
+ - @nifrajs/web@2.3.0
970
+ - @nifrajs/i18n@2.3.0
971
+ - @nifrajs/image@2.3.0
972
+
973
+ ## 2.2.0
974
+
975
+ ### Minor Changes
976
+
977
+ - 1394641: Layout loaders: request data in the component that wraps every page.
978
+
979
+ `routes/_layout.tsx` rendered, but a `loader` it exported never ran, so nothing request-derived could
980
+ reach a layout - host, session, locale, feature flags, tenant. An app hit this and moved its host guard
981
+ out of the component tree into the server entry, where it could not be typechecked with the rest of the
982
+ app. That is the real cost: the gap pushed security-relevant code to the one place nifra's typed-boundary
983
+ promise does not reach. Remix, React Router and SvelteKit all support this; nifra was alone in not.
984
+
985
+ ```tsx
986
+ // routes/orgs/[org]/_layout.tsx
987
+ export const gate = true // optional; see below
988
+ export async function loader({ params, req }) {
989
+ return { org: await findOrg(params.org) } // params is { org } - nothing deeper
990
+ }
991
+ export default function Layout({ data, children }) { … }
992
+ ```
993
+
994
+ **Scoped, not global.** A layout owns the URL prefix it wraps, so it receives only the params inside
995
+ that prefix and its loader is skipped on a navigation that did not change them. Navigating
996
+ `/orgs/acme/a` → `/orgs/acme/b` does not re-run the org layout's loader. Scope is derived at build time
997
+ per `(route, layout)` pair, because one layout can own different params on different expanded patterns:
998
+ `[[lang]]/docs/_layout` owns nothing on `/docs/:slug` and `{lang}` on `/:lang/docs/:slug`. Layouts are
999
+ not router nodes and did not become any - the router is untouched.
1000
+
1001
+ **Execution order is declared, and this matters for security.** By default a layout loader runs in
1002
+ parallel with the page's, which is right for data and wrong for a guard: a page loader running
1003
+ concurrently with a guard has already queried by the time the guard says no. `export const gate = true`
1004
+ makes a layout blocking - nothing beneath it runs until it resolves, and nothing beneath a rejected gate
1005
+ runs at all. **A layout loader without `gate: true` is not an authorization boundary.** Gates also run on
1006
+ the data-only request, so a client navigation cannot bypass one by sending the data header, and a gate is
1007
+ never skipped by the retention hint.
1008
+
1009
+ A layout may throw `notFound()` / `gone()` / `redirect()`. Its errors resolve to the `_error` boundary at
1010
+ or above its OWN segment, never one below it - rendering there would wrap the boundary in the very layout
1011
+ whose loader just failed.
1012
+
1013
+ Every adapter passes each layout its own data. A layout with no loader receives `null`, and an app where
1014
+ no layout has a loader emits byte-identical HTML and unchanged props.
1015
+
1016
+ The data-mode response becomes a versioned envelope when a chain carries layout data. It is recognised
1017
+ by structure, and the bare pre-envelope shape is still accepted - a prerendered `_data.json` is a static
1018
+ file that outlives the deploy that wrote it.
1019
+
1020
+ ### Patch Changes
1021
+
1022
+ - Updated dependencies [39b1670]
1023
+ - Updated dependencies [d428f52]
1024
+ - Updated dependencies [135d0c6]
1025
+ - Updated dependencies [1394641]
1026
+ - Updated dependencies [e713cab]
1027
+ - Updated dependencies [a4645e2]
1028
+ - Updated dependencies [a7d740a]
1029
+ - Updated dependencies [6e996a1]
1030
+ - Updated dependencies [15ad6ca]
1031
+ - Updated dependencies [6aa0aac]
1032
+ - Updated dependencies [1857d39]
1033
+ - Updated dependencies [6ba3173]
1034
+ - Updated dependencies [ca71a2e]
1035
+ - Updated dependencies [0fc215b]
1036
+ - Updated dependencies [2ff661f]
1037
+ - Updated dependencies [a1327a4]
1038
+ - Updated dependencies [2500705]
1039
+ - @nifrajs/web@2.2.0
1040
+ - @nifrajs/i18n@2.2.0
1041
+ - @nifrajs/image@2.2.0
1042
+
1043
+ ## 2.1.0
1044
+
1045
+ ### Patch Changes
1046
+
1047
+ - Updated dependencies [bd294bb]
1048
+ - @nifrajs/web@2.1.0
1049
+ - @nifrajs/i18n@2.1.0
1050
+ - @nifrajs/image@2.1.0
1051
+
1052
+ ## 2.0.0
1053
+
1054
+ ### Minor Changes
1055
+
1056
+ - 3620546: Extend `import Icon from "./icon.svg?component"` to the Solid, Svelte, and Vue adapters (`@nifrajs/web-solid/svg`, `@nifrajs/web-svelte/svg`, `@nifrajs/web-vue/svg`), joining the React/Preact plugin.
1057
+
1058
+ Each is a Bun build plugin that turns a `?component` SVG import into a framework component with the caller's props/attrs spread onto the root `<svg>`, using that framework's own compiler: Solid emits `class`-form JSX through `babel-preset-solid`; Svelte wraps the raw SVG in a Svelte 5 component (compiled by `svelte/compiler`); Vue wraps it in a single-root template so Vue's attribute inheritance forwards props to the `<svg>` (compiled by `@vue/compiler-sfc`). A plain `import "./icon.svg"` asset URL is untouched - only `?component` is intercepted. The shared `svgToJsx` transform gained a `classProp` option.
1059
+
1060
+ ### Patch Changes
1061
+
1062
+ - Updated dependencies [ade0c7a]
1063
+ - Updated dependencies [d91a45b]
1064
+ - Updated dependencies [d91a45b]
1065
+ - Updated dependencies [e97a92f]
1066
+ - Updated dependencies [e8e49d1]
1067
+ - Updated dependencies [a7d34e5]
1068
+ - @nifrajs/web@2.0.0
1069
+ - @nifrajs/i18n@2.0.0
1070
+ - @nifrajs/image@2.0.0
1071
+
1072
+ ## 1.13.0
1073
+
1074
+ ### Patch Changes
1075
+
1076
+ - Updated dependencies [5b6127a]
1077
+ - @nifrajs/web@1.13.0
1078
+ - @nifrajs/i18n@1.13.0
1079
+ - @nifrajs/image@1.13.0
1080
+
1081
+ ## 1.12.0
1082
+
1083
+ ### Patch Changes
1084
+
1085
+ - @nifrajs/web@1.12.0
1086
+ - @nifrajs/i18n@1.12.0
1087
+ - @nifrajs/image@1.12.0
1088
+
1089
+ ## 1.11.0
1090
+
1091
+ ### Patch Changes
1092
+
1093
+ - Updated dependencies [5638ada]
1094
+ - @nifrajs/web@1.11.0
1095
+ - @nifrajs/i18n@1.11.0
1096
+ - @nifrajs/image@1.11.0
1097
+
1098
+ ## 1.10.0
1099
+
1100
+ ### Patch Changes
1101
+
1102
+ - @nifrajs/web@1.10.0
1103
+ - @nifrajs/i18n@1.10.0
1104
+ - @nifrajs/image@1.10.0
1105
+
1106
+ ## 1.9.1
1107
+
1108
+ ### Patch Changes
1109
+
1110
+ - Updated dependencies [3eb27ae]
1111
+ - @nifrajs/web@1.9.1
1112
+ - @nifrajs/i18n@1.9.1
1113
+ - @nifrajs/image@1.9.1
1114
+
1115
+ ## 1.9.0
1116
+
1117
+ ### Patch Changes
1118
+
1119
+ - Updated dependencies [0e1b4cc]
1120
+ - Updated dependencies [6b67833]
1121
+ - @nifrajs/web@1.9.0
1122
+ - @nifrajs/i18n@1.9.0
1123
+ - @nifrajs/image@1.9.0
1124
+
1125
+ ## 1.8.0
1126
+
1127
+ ### Patch Changes
1128
+
1129
+ - Updated dependencies [1ffd48b]
1130
+ - @nifrajs/web@1.8.0
1131
+ - @nifrajs/i18n@1.8.0
1132
+ - @nifrajs/image@1.8.0
1133
+
1134
+ ## 1.7.0
1135
+
1136
+ ### Patch Changes
1137
+
1138
+ - Updated dependencies [9f23e90]
1139
+ - @nifrajs/web@1.7.0
1140
+ - @nifrajs/i18n@1.7.0
1141
+ - @nifrajs/image@1.7.0
1142
+
1143
+ ## 1.6.0
1144
+
1145
+ ### Patch Changes
1146
+
1147
+ - @nifrajs/i18n@1.6.0
1148
+ - @nifrajs/image@1.6.0
1149
+ - @nifrajs/web@1.6.0
1150
+
1151
+ ## 1.5.0
1152
+
1153
+ ### Patch Changes
1154
+
1155
+ - @nifrajs/web@1.5.0
1156
+ - @nifrajs/i18n@1.5.0
1157
+ - @nifrajs/image@1.5.0
1158
+
1159
+ ## 1.4.0
1160
+
1161
+ ### Patch Changes
1162
+
1163
+ - Updated dependencies [4d25970]
1164
+ - @nifrajs/web@1.4.0
1165
+ - @nifrajs/i18n@1.4.0
1166
+ - @nifrajs/image@1.4.0
1167
+
1168
+ ## 1.3.1
1169
+
1170
+ ### Patch Changes
1171
+
1172
+ - @nifrajs/i18n@1.3.1
1173
+ - @nifrajs/image@1.3.1
1174
+ - @nifrajs/web@1.3.1
1175
+
1176
+ ## 1.3.0
1177
+
1178
+ ### Patch Changes
1179
+
1180
+ - Updated dependencies [4a4b1c4]
1181
+ - @nifrajs/web@1.3.0
1182
+ - @nifrajs/i18n@1.3.0
1183
+ - @nifrajs/image@1.3.0
1184
+
1185
+ ## 1.2.2
1186
+
1187
+ ### Patch Changes
1188
+
1189
+ - @nifrajs/i18n@1.2.2
1190
+ - @nifrajs/image@1.2.2
1191
+ - @nifrajs/web@1.2.2
1192
+
1193
+ ## 1.2.1
1194
+
1195
+ ### Patch Changes
1196
+
1197
+ - Updated dependencies [c3ebd73]
1198
+ - @nifrajs/web@1.2.1
1199
+ - @nifrajs/i18n@1.2.1
1200
+ - @nifrajs/image@1.2.1
1201
+
1202
+ ## 1.2.0
1203
+
1204
+ ### Patch Changes
1205
+
1206
+ - @nifrajs/web@1.2.0
1207
+ - @nifrajs/i18n@1.2.0
1208
+ - @nifrajs/image@1.2.0
1209
+
1210
+ ## 1.1.0
1211
+
1212
+ ### Patch Changes
1213
+
1214
+ - Updated dependencies [37d2383]
1215
+ - @nifrajs/web@1.1.0
1216
+ - @nifrajs/i18n@1.1.0
1217
+ - @nifrajs/image@1.1.0
1218
+
1219
+ ## 1.0.0
1220
+
1221
+ ### Patch Changes
1222
+
1223
+ - Updated dependencies [f1f0e18]
1224
+ - @nifrajs/web@1.0.0
1225
+ - @nifrajs/i18n@1.0.0
1226
+ - @nifrajs/image@1.0.0
1227
+
1228
+ ## 1.0.0-beta.4
1229
+
1230
+ ### Patch Changes
1231
+
1232
+ - @nifrajs/i18n@1.0.0-beta.4
1233
+ - @nifrajs/image@1.0.0-beta.4
1234
+ - @nifrajs/web@1.0.0-beta.4
1235
+
1236
+ ## 1.0.0-beta.3
1237
+
1238
+ ### Patch Changes
1239
+
1240
+ - @nifrajs/i18n@1.0.0-beta.3
1241
+ - @nifrajs/image@1.0.0-beta.3
1242
+ - @nifrajs/web@1.0.0-beta.3
1243
+
1244
+ ## 0.1.0-beta.2
1245
+
1246
+ ### Patch Changes
1247
+
1248
+ - Updated dependencies [5018546]
1249
+ - @nifrajs/web@0.1.0-beta.2
1250
+ - @nifrajs/i18n@0.1.0-beta.2
1251
+ - @nifrajs/image@0.1.0-beta.2