@kudzujs/core 0.16.33 → 0.16.35

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.16.x`: the compiler API and supported TSX surface may change.
16
16
 
17
- **Current release: [0.16.33](https://github.com/kudzujs/kudzu/releases/tag/v0.16.33).** Write reusable components, native event handlers, and pure collection expressions; Kudzu specializes supported source into static content and direct browser updates. Presentation-only conditional branches omit descendant lifecycle traversal when no owner in their runtime family needs it, removing a further 215 raw / 116 aggregate gzip JavaScript bytes from search. Stateful remounts and effect cleanup are preserved; measured search-transition medians remain approximately equal. AI-cost and 1.0 gates remain blocked.
17
+ **Current release: [0.16.35](https://github.com/kudzujs/kudzu/releases/tag/v0.16.35).** Flat evaluator families omit nested context preparation and recursive dependency collection, removing another 172 raw / 50 aggregate gzip JavaScript bytes from search. Nested component-prop evaluators retain current-state reads. The optional `create-kudzu --ai` authoring tools introduced in 0.16.34 remain available; AI-token savings are unmeasured and the AI-cost/1.0 gates remain blocked.
18
18
 
19
19
  - [Documentation](https://kudzujs.cloud/docs)
20
20
  - [Installation guide](https://kudzujs.cloud/docs#install)
@@ -36,6 +36,13 @@ npm run dev
36
36
 
37
37
  The generated project includes reusable components, an interactive state example, a zero-JavaScript static route, metadata, and responsive CSS.
38
38
 
39
+ For optional AI authoring guidance and local developer tools, use
40
+ `npm create kudzu@latest my-app -- --ai`. The generated `AGENTS.md` describes
41
+ `npm run ai -- docs` for installed documentation and `npm run ai -- check` for
42
+ typecheck/build execution with bounded output and full retained logs. These tools
43
+ stay outside default browser output. AI-token savings have not been measured.
44
+ See the [generator guide](https://github.com/kudzujs/kudzu/tree/main/packages/create-kudzu#optional-ai-authoring-guidance).
45
+
39
46
  To add Kudzu to an existing project:
40
47
 
41
48
  ```bash
@@ -286,14 +286,14 @@ export async function loadEvaluator(descriptor) {
286
286
 
287
287
  async function createBindingContext(descriptor) {
288
288
  const scope = Object.fromEntries(Object.entries(descriptor.scope).map(([name, value]) => [name, deserialize(value, id => browserState.get(id))]))
289
- const nested = {}
290
- await Promise.all(Object.entries(descriptor.scopeBindings).map(async ([name, binding]) => {
289
+ const nested = globalThis.__KUDZU_NESTED_EVALUATORS__ !== false && {}
290
+ if (globalThis.__KUDZU_NESTED_EVALUATORS__ !== false) await Promise.all(Object.entries(descriptor.scopeBindings).map(async ([name, binding]) => {
291
291
  const evaluator = await loadEvaluator(binding)
292
292
  nested[name] = evaluator.read
293
293
  }))
294
294
  return {
295
295
  get: name => browserState.get(descriptor.states[name]),
296
- scope: name => name in descriptor.scopeStates ? browserState.get(descriptor.scopeStates[name]) : name in nested ? nested[name]() : scope[name]
296
+ scope: name => name in descriptor.scopeStates ? browserState.get(descriptor.scopeStates[name]) : globalThis.__KUDZU_NESTED_EVALUATORS__ !== false && name in nested ? nested[name]() : scope[name]
297
297
  }
298
298
  }
299
299
 
@@ -302,7 +302,7 @@ function bindingStateIds(descriptor) {
302
302
  ...Object.values(descriptor.states),
303
303
  ...Object.values(descriptor.scopeStates),
304
304
  ...(globalThis.__KUDZU_CAPTURE_STATE__ ? Object.values(descriptor.scope).flatMap(serializedStateIds) : []),
305
- ...Object.values(descriptor.scopeBindings).flatMap(binding => [...bindingStateIds(binding)])
305
+ ...(globalThis.__KUDZU_NESTED_EVALUATORS__ !== false ? Object.values(descriptor.scopeBindings).flatMap(binding => [...bindingStateIds(binding)]) : [])
306
306
  ])
307
307
  }
308
308
 
@@ -15,7 +15,7 @@ export function planRouteCapabilities(records, { navigationRouteCount = 0 } = {}
15
15
  for (const plan of plans) assertRouteIR(plan, { concrete: true })
16
16
  const commandEvents = new Set()
17
17
  const nativeEvents = new Set()
18
- const bindings = { count: 0, text: false, style: false, conditions: false, conditionState: false, conditionMounts: false, svgConditions: false }
18
+ const bindings = { count: 0, text: false, style: false, conditions: false, conditionState: false, conditionMounts: false, svgConditions: false, nestedEvaluators: false }
19
19
  const lists = {
20
20
  count: 0,
21
21
  styleCount: 0,
@@ -57,6 +57,7 @@ export function planRouteCapabilities(records, { navigationRouteCount = 0 } = {}
57
57
  bindings.conditionState ||= plan.conditions.some(condition => Object.values(condition.owned ?? {}).some(states => states.length > 0))
58
58
  bindings.conditionMounts ||= plan.conditions.some(condition => condition.mount)
59
59
  bindings.svgConditions ||= plan.conditions.some(condition => condition.svg)
60
+ bindings.nestedEvaluators ||= [...plan.bindings, ...plan.conditions, ...plan.lists.map(list => list.source)].some(descriptor => Object.keys(descriptor?.scopeBindings ?? {}).length > 0)
60
61
  effects.any ||= plan.effects.length > 0
61
62
  effects.derivedDependencies ||= plan.effects.some(effect => effect.dependencyExpressions?.length)
62
63
  effects.itemDependencies ||= plan.effects.some(effect => effect.itemDependencies?.length)
@@ -127,7 +128,7 @@ export function assertCapabilityIR(capabilityIR, records, options = {}) {
127
128
  if (!sections.every(name => isRecord(capabilityIR[name]))) throw new Error("Invalid CapabilityIR v1 structure")
128
129
  if (!["behaviors", "regularBehaviors", "regularStateSeeds", "dependencyStateSeeds"].every(name => isCount(capabilityIR.routes[name]))) throw new Error("Invalid CapabilityIR v1 route counts")
129
130
  if (!["command", "native"].every(name => Array.isArray(capabilityIR.events[name]) && capabilityIR.events[name].every(event => typeof event === "string")) || typeof capabilityIR.events.hasNativeHandlers !== "boolean") throw new Error("Invalid CapabilityIR v1 events")
130
- if (!isCount(capabilityIR.bindings.count) || !["text", "style", "conditions", "conditionState", "conditionMounts", "svgConditions", "attributes"].every(name => typeof capabilityIR.bindings[name] === "boolean")) throw new Error("Invalid CapabilityIR v1 bindings")
131
+ if (!isCount(capabilityIR.bindings.count) || !["text", "style", "conditions", "conditionState", "conditionMounts", "svgConditions", "nestedEvaluators", "attributes"].every(name => typeof capabilityIR.bindings[name] === "boolean")) throw new Error("Invalid CapabilityIR v1 bindings")
131
132
  if (capabilityIR.bindings.conditionState && !capabilityIR.bindings.conditions) throw new Error("CapabilityIR conditional state requires conditions")
132
133
  if (capabilityIR.bindings.conditionMounts && !capabilityIR.bindings.conditions) throw new Error("CapabilityIR conditional mounts require conditions")
133
134
  if (!Array.isArray(capabilityIR.bindings.properties) || capabilityIR.bindings.properties.some(target => !propertyBindings.includes(target)) || new Set(capabilityIR.bindings.properties).size !== capabilityIR.bindings.properties.length) throw new Error("Invalid CapabilityIR v1 binding properties")
@@ -57,6 +57,7 @@ export function generateBindingRuntime(source, capabilityIR, navigable) {
57
57
  "globalThis.__KUDZU_CONDITION_STATE__": String(capabilityIR.bindings.conditionState),
58
58
  "globalThis.__KUDZU_CONDITION_MOUNTS__": String(capabilityIR.bindings.conditionMounts),
59
59
  "globalThis.__KUDZU_SVG_CONDITIONS__": String(capabilityIR.bindings.svgConditions),
60
+ "globalThis.__KUDZU_NESTED_EVALUATORS__": String(capabilityIR.bindings.nestedEvaluators),
60
61
  "globalThis.__KUDZU_CAPTURE_STATE__": String(capabilityIR.captures.nestedState)
61
62
  }
62
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudzujs/core",
3
- "version": "0.16.33",
3
+ "version": "0.16.35",
4
4
  "description": "HTML-first TSX framework with synchronous state semantics and no virtual DOM",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -50,7 +50,7 @@
50
50
  "check": "tsc --noEmit && tsc -p test/fixtures/tsconfig.json --noEmit && node ./bin/kudzu.mjs build",
51
51
  "test": "node --test test/project-application.test.mjs && node --test --test-skip-pattern='^establishes the 0\\.17\\.0 notification WebSocket ownership contract$' test/*.test.mjs",
52
52
  "test:endurance": "node test/endurance.mjs",
53
- "test:package": "node test/package-smoke.mjs",
53
+ "test:package": "node test/package-smoke.mjs && node test/create-kudzu-smoke.mjs",
54
54
  "benchmark": "node test/performance.mjs",
55
55
  "benchmark:keyed": "node test/keyed-performance.mjs",
56
56
  "benchmark:commerce": "node test/commerce-build-performance.mjs",