@kudzujs/core 0.8.9 → 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
@@ -8,9 +8,13 @@ HTML-first TSX framework with synchronous state semantics and no virtual DOM.
8
8
 
9
9
  Kudzu compiles ordinary React-shaped TypeScript and TSX into complete static HTML, CSS, and only the route-specific ESM capabilities actually used. Static pages ship zero JavaScript. React, hydration, a VDOM, and a retained browser component tree are not part of the output.
10
10
 
11
+ [![Watch the 22-second Kudzu compiler overview](https://raw.githubusercontent.com/kudzujs/kudzu/main/media/kudzu-demo-cover.png)](https://github.com/kudzujs/kudzu/blob/main/media/kudzu-demo.mp4)
12
+
13
+ *Watch: React-shaped TSX to static HTML and route-specific ESM in 22 seconds.*
14
+
11
15
  > Experimental `0.8.x`: the compiler API and supported TSX surface may change.
12
16
 
13
- **Latest release: 0.8.9 - Context-backed CRUD actions.** A relative custom hook may directly return `useContext(Context)` for one analyzable Provider whose state-backed actions compile into existing route handler ESM, without a browser Context tree. Read the [release notes](./RELEASES.md#089---context-backed-crud-actions) or open the [release page](https://kudzujs.cloud/releases/0.8.9).
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).
14
18
 
15
19
  - [Documentation](https://kudzujs.cloud/docs)
16
20
  - [Installation guide](https://kudzujs.cloud/docs#install)
package/RELEASES.md CHANGED
@@ -1,5 +1,61 @@
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
+
31
+ ## 0.8.10 - Native dialog migration
32
+
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.
34
+
35
+ ### New in 0.8.10
36
+
37
+ - A reduced migration fixture preserves a relative `forwardRef` component, props, children, object refs, and ordinary JSX event handlers.
38
+ - Package-owned Portal and Context behavior becomes native `showModal()`, `close()`, and cancel handling.
39
+ - Complete accessible dialog markup is pre-rendered while route output includes only the `click` and `cancel` events it uses.
40
+ - Chrome coverage verifies modal top-layer behavior, initial focus, confirm and cancel paths, and explicit trigger-focus restoration.
41
+ - Public documentation now includes the migration recipe and its deliberate library boundary.
42
+
43
+ ### Fixed in 0.8.10
44
+
45
+ - Mobile documentation code blocks stay within the content grid and scroll horizontally instead of widening the viewport.
46
+ - Browser tests allow slower CI Chrome startup and report process timeouts directly instead of failing later against empty DOM output.
47
+ - The complete suite passes 140/140 tests.
48
+
49
+ ### Boundary
50
+
51
+ This release does not execute Radix or arbitrary React UI packages. `Portal`, `asChild`/`Slot`, element cloning, and arbitrary compound-component Context must be removed during source migration. Applications remain responsible for dialog labeling and explicit focus restoration.
52
+
53
+ ### Upgrade
54
+
55
+ ```bash
56
+ npm install @kudzujs/core@^0.8.10
57
+ ```
58
+
3
59
  ## 0.8.9 - Context-backed CRUD actions
4
60
 
5
61
  Kudzu 0.8.9 specializes state-backed actions exposed through one conventional Context Provider and relative custom hook.
@@ -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.9",
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",