Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 12 additions & 0 deletions .changeset/cache-form-correctness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@cleverbrush/server': minor
'@cleverbrush/client': minor
'@cleverbrush/deep': minor
'@cleverbrush/react-form': minor
---

Use one browser-safe, deterministic `ct2:` cache key encoder across server and client helpers, response caches, and external invalidation. Selected properties and plain-object keys are sorted, values retain their types, and dates retain millisecond precision. Unsupported values fail explicitly. **Breaking:** every computed key changes, including property-free tags. Upgrade external cache writers and invalidators together, and flush or expire previous entries; literal base invalidation names and TTL settings remain unchanged. Successful mutations invalidate cached aliases and prevent older in-flight reads from refilling them; failed writes preserve entries.

Synchronize mounted schema-form fields with form/field setters and reset baselines, using descriptor identities and stable external-store subscriptions. Discard obsolete async validation after value changes or reset. Add `handleSubmit`, reactive `submitting`/`error`, duplicate-submit protection, explicit success/failure results and opt-in error translation. Add `defineFieldRenderer` and `createFormSystem` for typed renderer values, variants, props and composable registries while retaining existing form APIs. See the cache/form migration guide for semantics and examples.

Add reusable `deepClone` for plain objects, arrays and Dates with cycle/shared-reference preservation, sparse-array lengths, null prototypes and safe enumerable own string/symbol properties. React forms now use `deepClone` and `deepEqual` from `@cleverbrush/deep` for snapshots and dirty checks. **Breaking:** correct existing `deepEqual` semantics for null/type mismatches, equivalent cycles and shared references, signed zero, invalid Dates, symbol keys and sparse arrays. Opaque values such as Files, Maps, Sets and custom instances compare only by identity and remain references when cloned. Unordered arrays preserve duplicate/hole counts without hash-based matching or input mutation. Review consumers relying on the old outcomes; `deepExtend`, `HashObject` and `Transaction` are unchanged.
5 changes: 5 additions & 0 deletions .changeset/defaulted-form-fields.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cleverbrush/react-form': minor
---

Accept defaulted schema properties in typed Field, headless useField, and renderer schema bounds without losing value inference. Return a named TypedFormSystem so shared UI packages can export inferred registries while emitting declarations.
Binary file added docs/assets/form-lifecycle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
261 changes: 261 additions & 0 deletions docs/cache-form-migration.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 15 additions & 3 deletions libs/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ const client = createClient(api, {
middlewares: [cacheTags({ defaultTtl: 5000 })],
});

// Populates cache entries for 'todo-list' and 'todo:id=1' tags.
// Populates versioned keys for the 'todo-list' and 'todo' tag definitions.
await client.todos.list({ query: { page: 1 } });
await client.todos.get({ params: { id: 1 } });

Expand Down Expand Up @@ -307,8 +307,20 @@ externalCacheTags({ invalidateTag: revalidateTag });
```

The middleware runs after successful `POST`, `PUT`, `PATCH`, and `DELETE`
responses. Dynamic tags invalidate both the base tag name and the computed key
by default, for example `expense` and `expense:id=42`.
responses. Tags invalidate both the literal base tag name and the versioned computed
key by default, for example `expense` and `ct2:["expense",[["id",["number","42"]]]]`.
Property-free tags also have a computed key: `ct2:["expense",[]]`.

Computed keys share a deterministic, type-tagged encoder with the server;
property/object key order is normalized and dates retain millisecond precision.
Only successful mutations invalidate the in-memory cache; older in-flight reads
cannot refill invalidated entries or aliases. Tag-name-prefix coverage and TTLs
are unchanged. Unsupported selected values throw `TypeError`.

**Breaking migration:** upgrade all external cache writers and invalidators together
and retire old entries. Base invalidation labels remain literal names, but all
computed keys changed. Endpoint and auth/tenant scope are still consumer-defined.
See the [migration guide](../../docs/cache-form-migration.md#cache-key-migration-breaking).

## Per-Call Overrides

Expand Down
Loading
Loading