@kudzujs/core 0.8.10 → 0.8.11

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 CHANGED
@@ -14,7 +14,7 @@ Kudzu compiles ordinary React-shaped TypeScript and TSX into complete static HTM
14
14
 
15
15
  > Experimental `0.8.x`: the compiler API and supported TSX surface may change.
16
16
 
17
- **Latest release: 0.8.10 - Native dialog migration.** A reduced shadcn/Radix-shaped dialog now proves how AI migration can preserve `forwardRef`, props, children, refs, and handlers while replacing package-owned Portal and Context behavior with native `<dialog>`. Read the [release notes](./RELEASES.md#0810---native-dialog-migration) or open the [release page](https://kudzujs.cloud/releases/0.8.10).
17
+ **Latest release: 0.8.11 - Stale-safe data migration.** Build-known query data moves to async pages, browser-only reads move to route effects, and superseded promise or fetch setters can no longer overwrite newer state. Read the [release notes](./RELEASES.md#0811---stale-safe-data-migration) or open the [release page](https://kudzujs.cloud/releases/0.8.11).
18
18
 
19
19
  - [Documentation](https://kudzujs.cloud/docs)
20
20
  - [Installation guide](https://kudzujs.cloud/docs#install)
package/RELEASES.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Kudzu Releases
2
2
 
3
+ ## 0.8.11 - Stale-safe data migration
4
+
5
+ Kudzu 0.8.11 proves source migration paths for TanStack Query-shaped data and React Hook Form-shaped forms while strengthening dependency-effect stale-write isolation.
6
+
7
+ ### New in 0.8.11
8
+
9
+ - Build-known query data moves to async pages and emits complete zero-JavaScript HTML.
10
+ - Browser-only query data uses one dependency effect with application-owned loading, error, result, and primitive refetch state.
11
+ - Superseded unowned dependency effects invalidate their invocation before cleanup, so late promise or fetch setters cannot overwrite newer state.
12
+ - A deterministic Chrome race verifies that a fast refetch remains visible after a delayed prior response arrives, followed by HTTP failure and recovery.
13
+ - React Hook Form-shaped signup source migrates to native controls, constraint validation, `FormData`, one async submit handler, accessible server errors, and retained uncontrolled values.
14
+ - Static sibling routes remain JavaScript-free, with no TanStack Query or React Hook Form runtime in deploy output.
15
+
16
+ ### Fixed in 0.8.11
17
+
18
+ - Mobile documentation now uses a true 100% layout wrapper with explicit inner gutters instead of a reduced outer width.
19
+ - The complete suite passes 142/142 tests.
20
+
21
+ ### Boundary
22
+
23
+ This release does not execute TanStack Query or React Hook Form. Query clients, Providers, caches, retries, deduplication, optimistic cache updates, query-key arrays, Suspense, controllers, watchers, resolvers, and dynamic field registration remain source migration work.
24
+
25
+ ### Upgrade
26
+
27
+ ```bash
28
+ npm install @kudzujs/core@^0.8.11
29
+ ```
30
+
3
31
  ## 0.8.10 - Native dialog migration
4
32
 
5
33
  Kudzu 0.8.10 proves a source migration path from a shadcn/Radix-shaped dialog to the native `<dialog>` element without adding package compatibility runtime.
@@ -581,7 +581,7 @@ addEventListener("pagehide", event => {
581
581
  if (hasDependencies) return `${imports.join("\n")}
582
582
  const effects = ${inlineJson(effects)}
583
583
  const modules = new Map([${entries}])
584
- const records = effects.map((effect, index) => ({ effect, index, values: undefined, cleanup: undefined }))
584
+ const records = effects.map((effect, index) => ({ effect, index, values: undefined, cleanup: undefined, token: undefined }))
585
585
  const dependencies = new Map()
586
586
  const pending = new Set()
587
587
  let scheduled = false
@@ -649,7 +649,9 @@ ${hasDependencyExpressions ? printDerivedDependencyRead("browserState") : ""}
649
649
  function invoke(record) {
650
650
  try {
651
651
  const effect = record.effect
652
- const result = modules.get(effect.module)[effect.handler](createEffectContext(browserState, effect.states, commitDom, effect.scope))
652
+ const token = { active: true }
653
+ record.token = token
654
+ const result = modules.get(effect.module)[effect.handler](createEffectContext(browserState, effect.states, commitDom, effect.scope, () => active && token.active && record.token === token))
653
655
  if (effect.cleanup && typeof result === "function") record.cleanup = result
654
656
  else if (result && typeof result.then === "function") result.catch(error => console.error(error))
655
657
  } catch (error) {
@@ -657,6 +659,8 @@ function invoke(record) {
657
659
  }
658
660
  }
659
661
  async function invokeCleanup(record) {
662
+ if (record.token) record.token.active = false
663
+ record.token = undefined
660
664
  const cleanup = record.cleanup
661
665
  record.cleanup = undefined
662
666
  if (!cleanup) return
@@ -1352,6 +1356,7 @@ const effect = ${inlineJson(effect)}
1352
1356
  const dependency = effect.dependencies[0]
1353
1357
  let value
1354
1358
  let cleanup
1359
+ let token
1355
1360
  let active = true
1356
1361
  let pending = false
1357
1362
  let scheduled = false
@@ -1402,7 +1407,9 @@ function readDependency() {
1402
1407
  }
1403
1408
  function invoke() {
1404
1409
  try {
1405
- const result = __kEffectModule0[effect.handler](createEffectContext(browserState, effect.states, commitDom, effect.scope))
1410
+ const current = { active: true }
1411
+ token = current
1412
+ const result = __kEffectModule0[effect.handler](createEffectContext(browserState, effect.states, commitDom, effect.scope, () => active && current.active && token === current))
1406
1413
  if (effect.cleanup && typeof result === "function") cleanup = result
1407
1414
  else if (result && typeof result.then === "function") result.catch(error => console.error(error))
1408
1415
  } catch (error) {
@@ -1410,6 +1417,8 @@ function invoke() {
1410
1417
  }
1411
1418
  }
1412
1419
  async function invokeCleanup() {
1420
+ if (token) token.active = false
1421
+ token = undefined
1413
1422
  const current = cleanup
1414
1423
  cleanup = undefined
1415
1424
  if (!current) return
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudzujs/core",
3
- "version": "0.8.10",
3
+ "version": "0.8.11",
4
4
  "description": "HTML-first TSX framework with synchronous state semantics and no virtual DOM",
5
5
  "type": "module",
6
6
  "license": "MIT",