Skip to content

3.0.0

Choose a tag to compare

@unadlib unadlib released this 12 Jul 18:49
· 176 commits to main since this release

Coaction 3.0.0

Coaction 3.0 rebuilds the shared runtime around a strict JSON contract, a versioned wire protocol, and explicit runtime entry points. Worker, SharedWorker, and custom-transport deployments are now safer and more resilient, while local-only stores remain free from shared-mode data restrictions and transport code.

Highlights

  • Introduced a lossless JSON-only contract for shared state, action arguments and results, patches, and snapshots.
  • Added a versioned string wire protocol with authority epochs, contiguous sequences, gap recovery, and atomic full synchronization.
  • Added dedicated coaction/local, coaction/shared, and coaction/adapter entry points.
  • Added transportPolicy for action allowlists, request authorization, and safe public error mapping.
  • Improved protected computed-read and native shared-update performance without weakening public validation boundaries.
  • Added a complete bilingual documentation website in English and Chinese.

Breaking Changes and Migration

Shared mode now requires JSON data

Every value crossing a Worker, SharedWorker, or injected transport boundary must be a lossless JSON tree:

  • null, booleans, strings, and finite numbers other than negative zero;
  • dense arrays;
  • plain records with safe string keys.

Coaction now rejects values that JSON cannot preserve reliably, including:

  • undefined, BigInt, NaN, infinity, and -0;
  • functions used as data, symbols, and accessors;
  • Date, URL, Map, Set, typed arrays, DOM objects, and other platform objects;
  • sparse arrays, circular references, and repeated object references.

Store methods and computed getters remain runtime behavior and are not transported. Local stores are not subject to this restriction.

See the Shared JSON contract for supported values and migration examples.

Select the appropriate entry point

Entry point Intended use
coaction/local Transport-free local vanilla stores
coaction/shared Shared authorities, Worker clients, and client mirrors
coaction/adapter External-store adapter and low-level middleware authors
coaction Compatibility entry with shared-capable create()

Adapter-authoring helpers have moved from the root entry:

- import { defineExternalStoreAdapter } from 'coaction';
+ import { defineExternalStoreAdapter } from 'coaction/adapter';

This also applies to createBinder, mutable-adapter snapshot and patch helpers, reactive tracking helpers, and other adapter-only utilities.

Official adapters now expose plain JSON transport snapshots without pulling adapter internals into the core runtime.

Upgrade shared deployments as one cohort

Coaction 2.x and 3.x wire protocols are incompatible. An authority and every client connected to it must use the same Coaction major.

When upgrading a Worker, SharedWorker, or custom transport:

  1. Stop or drain writes.
  2. Destroy old client stores and close their ports.
  3. Stop the old authority.
  4. Deploy the authority and clients from the same immutable build.
  5. Verify full sync, one action, one update, and one reconnect before resuming traffic.

Do not run 2.x and 3.x authorities concurrently against the same logical state. Version Worker URLs, SharedWorker names, and custom transport channels where appropriate.

Review remote error handling

Unexpected remote action failures are now redacted to Remote action failed. Use transportPolicy.mapError only for messages that are explicitly safe to expose to connected clients.

If the authority changes while an action is in flight, the client now rejects the stale response with ActionAuthorityChangedError. Its outcome is unknown, because the previous authority may already have completed the action. Do not automatically retry non-idempotent work.

See Workers, policies, and reconnect for policy and recovery examples.

Shared Runtime

  • Validates message shapes, action paths, patch paths, epochs, and sequence numbers before committing state.
  • Limits remote execution to methods declared by the authority store, with optional action allowlists and authorization.
  • Ignores duplicate or stale updates and requests a full snapshot after sequence gaps or authority changes.
  • Applies snapshots and updates atomically, preserving the previous client state if validation fails.
  • Prevents reconnect callbacks from older connection generations from overwriting newer state.
  • Cleans up listeners and pending work after failed initialization or store destruction.

Performance and Packaging

  • Cached computed values now read from an incrementally updated frozen snapshot, preserving deep mutation guards without the previous per-field readonly-proxy overhead.
  • Native shared updates use a prepared internal patch path to avoid repeated cloning, sanitization, and scanning.
  • Public apply(), custom updaters, patch hooks, middleware, and adapter overrides retain their complete validation boundaries.
  • coaction/local provides a static bundle boundary that excludes the protocol, epoch, reconnect, and transport runtime.

Full Changelog: v2.1.0...v3.0.0