Skip to content

feat: correct cache identity and schema-form lifecycle - #223

Open
andrewzolotukhin wants to merge 1 commit into
developmentfrom
feat/cache-form-correctness
Open

feat: correct cache identity and schema-form lifecycle#223
andrewzolotukhin wants to merge 1 commit into
developmentfrom
feat/cache-form-correctness

Conversation

@andrewzolotukhin

@andrewzolotukhin andrewzolotukhin commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Description

Implement the Framework phase of the approved cache-correctness and schema-form improvements. This PR targets development. It does not change Xpenser, publish packages, or deploy anything.

Original request

Address items #1 and #2 from the consumer-experience review in Framework, keeping the APIs application-agnostic. Include a changeset, tests, and documentation. After this PR is merged and a beta version is provided, update Xpenser in a separate PR.

The approved plan explicitly selects a new cache-key format everywhere rather than a legacy-compatible mode.

What changed

  • One browser-safe ct2: key encoder shared by the server/client public helpers, response caches, and external invalidation. It sorts properties, tags value types, preserves date milliseconds, and rejects unsupported/cyclic values.
  • Successful mutation invalidation uses tag metadata and generations. Failed writes preserve entries; pre-mutation reads cannot refill invalidated entries or any multi-tag aliases. Existing tag-name-prefix coverage and TTL settings remain.
  • Form values, mounted descriptors, nested/array bindings, and reset baselines are synchronized using stable external-store snapshots. Stale/debounced validation cannot overwrite newer values.
  • Add handleSubmit, reactive read-only submitting/error, duplicate-submit protection, explicit results, inferred success data, and opt-in exception translation. Reset/unmount suppress old callbacks without pretending to cancel network work. Existing submit()/validate() remain.
  • Add defineFieldRenderer<Value, Props> and createFormSystem({ renderers }) for checked variants/custom props and composable registries, retaining legacy exports/providers.
  • Add runtime, HTTP integration, race-condition, SSR/Strict Mode, and strict consumer type tests.
  • Add package documentation, a migration guide, a live local-only form demo, and a changeset.

Reasoning and migration

Cache identity must distinguish types and date instants consistently without parsing delimiter-joined strings. Generation guards cover the empty-cache/in-flight race and alias invalidation while preserving existing invalidation scope.

Breaking cache migration: upgrade all external writers and invalidators together and flush/expire old keys. Even property-free computed keys change; literal base invalidation names do not. There is no legacy fallback. Endpoint response identity and auth/tenant scope remain consumer-owned, and external writers need their own concurrency controls.

Forms centralize reusable mechanics only; UI kits, notifications, navigation, persistence, and expected-error classification remain application-owned. The typed factory's closed registry prevents an untyped parent provider from changing its renderer contract.

The changeset requests major server/client and minor react-form changes. Framework's existing fixed release group consequently advances its published libraries together at major level. No versions have been changed here.

See the migration guide.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Refactor / internal improvement

Blog post

Skipped: internal library/API work, with package docs and a migration guide instead of an Xpenser product announcement.

Screenshots / preview evidence

Actual Chromium verification of the local docs preview at http://127.0.0.1:3217/react-form: empty validation, mounted text/select/checkbox reset, failure with preserved inputs, disabled pending button, and successful retry with cleared controls and confirmation. No browser errors. The demo sends no data to a server.

Successful save clears mounted controls and shows confirmation

A low-contrast inherited demo background was found during browser QA and corrected with theme-aware, demo-scoped styles. Local browser/server processes were stopped afterward.

Validation

  • npm run lint
  • npm run build — 21 tasks succeeded
  • npm run test4,233 tests, 173 files; no type errors
  • npm run typecheck:schema-site
  • npm run typecheck:docs-site
  • npm run docs — generated successfully, 0 errors / 238 TypeDoc warnings about documentation links/internal types
  • npx changeset status --since origin/development — valid release plan; existing website file: dependency warnings
  • Local browser verification described above
  • GitHub Lint, Build & Test (Node 24) — passed on commit f7c65ae
  • Hosted PR preview: skipped; Framework has no PR-preview deployment configured. Local preview was verified.
  • SigNoz: skipped; no Framework preview telemetry is configured.
  • Telegram: skipped; the notifier is unavailable under the session's outbound restrictions. No notification was sent.

Checklist

  • I've added tests for my changes
  • I've run npm run lint and fixed any issues
  • I've run npm run test and all tests pass
  • I've added a changeset for package behavior changes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant