Releases: burrr-ai/comwit
Release list
v2.2.0 — Local-first resources
Highlights
- Added standalone IndexedDB-backed local resources for durable server-owned snapshots without requiring a client request.
- Added local.query and local.infinite adapters with exact argument restore, stale-time revalidation, and graceful in-memory fallback.
- Added normalized collections with custom entity identity, fragment merge and revision controls, version cleanup, and list/detail fan-out.
- Added static and lazy collection-level scopes for public, user, and tenant cache isolation, including protection against cross-scope response commits.
- Added documentation and agent guidance covering local-first boundaries, server initialization, optimistic updates, and synchronization behavior.
- Fixed selector .load calls on frozen snapshots produced by derived, computed, validation, and history model extensions.
Upgrade
npm install @comwit/state@2.2.0
The deprecated comwit compatibility package is also available at 2.2.0 and re-exports @comwit/state.
Both packages are published under the npm latest tag.
Validation
- 369 library tests passed.
- TypeScript type checking passed.
- Library and documentation production builds passed.
Full changelog: v2.1.0...v2.2.0
v2.1.0 — Selector-owned query loading
Selector-owned query loading
React components can now declare a query and its typed argument directly inside the existing useModel() / create() selector:
const products = useProduct((state) =>
state.products.load({ page, filter })
)
const stats = useProduct((state) => state.stats.load())The argument is inferred from Query<Data, Arg>. Calling .load() is the explicit opt-in; selecting the resource without it remains a passive read and never starts a request.
Behavior
- reports first-load state during the initial render, avoiding the empty → skeleton flash before an effect runs
- starts the request after React commits
- changes cache keys when the serialized argument changes
- does not restart a stable mounted query on unrelated rerenders
- deduplicates concurrent selector loads for the same resource and key
- supports single, infinite, and realtime resources
- keeps call-time query options in imperative actions
Fully backward compatible
Existing action methods remain unchanged:
await this.model.products.query({ page, filter })
await this.model.products.refetch()
this.model.products.set(serverData)useEffect-driven loading continues to work. Use selector .load() for view-owned requests and action .query() for commands, preloads, forced requests, multi-query workflows, and side effects. No additional React hook was added.
Documentation
- rewrote
llms.txtas a concise English domain implementation guide - documented selector-owned versus command-owned query loading
- added cache-aware App Router Suspense fallback guidance using existing
silent()+.set()initialization instead of a new hydration API - added the v2.1.0 release article
Validation
- 25 test files, 345 tests passed
- TypeScript and selector type-contract checks passed
- ESM/CJS bundle and declaration generation passed
- docs production build passed
- published package tarballs were inspected
Packages
@comwit/state@2.1.0comwit@2.1.0compatibility shim →@comwit/state@^2.1.0
v2.0.0 — The package is now @comwit/state
The package is now @comwit/state
comwit is now published on npm as @comwit/state. That's the whole change — there are no API changes, no renamed exports, no behavioral differences. Only two things move:
- The package you install:
comwit→@comwit/state - The specifier you import from:
from 'comwit'→from '@comwit/state'
The ComwitProvider component, the library.comwit.io docs, and this GitHub repo keep their names. Only the npm package identifier changed.
Migration
For most projects this is a two-line change:
yarn remove comwit
yarn add @comwit/state- import { model, action, query, ComwitProvider } from 'comwit'
+ import { model, action, query, ComwitProvider } from '@comwit/state'A project-wide find-and-replace of from 'comwit' → from '@comwit/state' is safe — the export surface is identical.
You don't have to migrate immediately
We took the soft path — nothing breaks on upgrade:
comwit@2.0.0was published as a thin compatibility shim that simply re-exports@comwit/state. Existingimport ... from 'comwit'code keeps working unchanged.- The
comwitpackage is now deprecated on npm with a notice pointing to@comwit/state.
New projects should install @comwit/state directly; existing projects can migrate whenever convenient. The shim is a bridge, not a long-term home.
Why a major version?
The public API is unchanged, but renaming the package is breaking for consumers (install name + import path move), so this ships as 2.0.0. Both @comwit/state and the comwit compatibility shim are published at 2.0.0 and track the same version line going forward.
Links
- 📦 npm: https://www.npmjs.com/package/@comwit/state
- 📖 Migration notes: https://library.comwit.io/blog/v2.0.0-release
- 📚 Docs: https://library.comwit.io
🤖 Generated with Claude Code
v1.3.0
First stable release of the 1.3.x line (supersedes 1.2.0 on the latest tag).
Highlights
- Model history (undo/redo). Built-in undo/redo for models, with a configurable history limit (default 100) and safe handling of concurrent async transactions.
- Observer-based
gcTime(TanStack Query v5 semantics). Garbage collection now starts when a model loses its lastuseModelobserver instead of fromlastFetchedAt. Cache entries are never evicted while a model has active subscribers, which fixesisLoadingflicker on same-key refetches.gcTimenow defaults to 5 minutes, applied only after a model reaches zero observers. - Improved
flush/cancelhelpers for@Debounce/@Throttle.flushDebounce/cancelDebounce/flushThrottle/cancelThrottleare now keyed per instance (two instances of the same class no longer share a window) and return a deferred result, so the surrounding interceptor stack (@OnError,@Retry, …) observes the flushed call's return value or rejection.
Fixes
refetch()always returns a Promise, even when the query has no active entry yet — previously it returnedundefinedand broke.then/.catchcallers (#76).
Breaking / migration
- Removed the
cacheTimeoption (it was an alias forgcTime). UsegcTimeinstead. FieldPlugin.bindStategains an optionalmodelKeyargument and a new optionalonSubscriberChange(modelKey, bag, registryState, hasObservers)hook. External plugins implementing theFieldPlugininterface must accept (or ignore) the extra argument.
Docs
- New History and Utilities API documentation, plus a refreshed
llms.txt.
v1.0.0 — stable
First stable release of comwit.
Highlights since 0.x
Features
computed()primitive for derived state (#44)- Model lifecycle hooks:
onObserve/ cleanup (#43) - Streaming query support via AsyncIterable (#45)
- DevTools integration layer (
__COMWIT_DEVTOOLS__) (#42) toPlain()utility for proxy-to-POJO conversion (#55)- Removed
valtiodependency — inline proxy reactivity engine (#52)
Fixes
- Reset query state when arg changes without
keepPreviousData(#60) - Synchronous
subscribe()to fix IME composition (#56) - Expose
.snapshot()type on nested proxy objects (#64)
Docs
- Full docs site moved to https://library.comwit.io
computed(), lifecycle hooks, dependent queries, suspense docs (#54)- SWC decorator setup step in
llms.txt(#57, #59) - Class-level lazy decorator example (#65)
Install
npm i comwitLLM setup: pass https://library.comwit.io/llms.txt to Claude Code.
v0.2.5
Fix
- fix(proxy): synchronous notification for IME composition support (#48, #49)
- Replaced microtask-based (
Promise.resolve().then()) listener notification with synchronous notification - Fixes Korean/Japanese/Chinese IME composition breaking in controlled inputs
- Fixes cursor jumping to end of input on every keystroke
- React 18's automatic batching handles grouping multiple synchronous updates, so no performance regression
- Matches the approach used by Zustand (synchronous by default) and Valtio (
{ sync: true }option)
- Replaced microtask-based (
Migration
No breaking changes. This is a drop-in upgrade — controlled inputs with CJK IME will now work correctly without needing onCompositionStart/onCompositionEnd workarounds.
v0.2.1
Bug Fix
query().query() no longer throws on second call (#35)
Calling .query() on a resource field threw TypeError: Cannot assign to read only property '0' on subsequent calls. The proxy engine now shallow-clones frozen snapshot objects before wrapping, preventing in-place mutation of cached state.
Fix: #36
Upgrade
yarn add comwit@0.2.1Drop-in replacement. No API changes.
v0.2.0
What's New in v0.2.0
Features
-
Suspense Support —
query()andquery.infinite()에suspense: true옵션 추가. React<Suspense>와 자연스럽게 통합되며, 별도 hook 없이 기존useModel()/create()로 동작. TypeScript에서data가NonNullable<T>로 자동 추론됨 (#32) -
Real-time Subscriptions —
query.realtime()디스크립터 추가. WebSocket, SSE 등 실시간 데이터 소스를query()패턴으로 통합.connectionStatus,isConnected상태 제공,subscribe콜백으로update(),set(),onStatus(),onError()지원 (#30) -
Persist Plugin —
persist()필드 디스크립터 추가.localStorage,sessionStorage기본 어댑터 제공, 커스텀PersistAdapter인터페이스 지원. 크로스탭 동기화, 디바운스 write-back, SSR 안전, 커스텀 직렬화/역직렬화 (#31) -
Decorators —
@Retry,@Queue,@Log,@Validate데코레이터 추가. 글로벌 인터셉터, derived state, model validation 지원
Architecture
-
Plugin System — 모놀리식 구조에서 플러그인 아키텍처로 리팩토링.
FieldPlugin인터페이스를 통해 query, persist, realtime 등 기능이 코어 수정 없이 동적으로 등록됨.registerPlugin()으로 확장 가능 (#33) -
Custom Proxy Layer — valtio 의존성 제거, 자체 프록시 기반 반응성 엔진 구현
Bug Fixes
- query
isLoading계산 순서 수정 — error-retry 시 로딩 상태 정상 표시 (#17) - stale response race condition 수정 — 빠른 query arg 변경 시 최신 응답만 반영 (#17)
set()호출 시 캐시 동기화 — staleTime 내 읽기 시 set 데이터 유지 (#17)nextFetchcursor history 개선 — 다단계 뒤로가기 네비게이션 지원 (#17)- infinite query
withCursor제거,hasMore가드 추가 (#15)
Docs
llm.txt모듈형 레퍼런스 분리 — query, decorator 상세 레퍼런스 추가 (#34)
Full Changelog: v0.0.2...v0.2.0
v0.0.2 — Initial Release
comwit v0.0.2
React state management for vibe coding. Pass llm.txt to Claude Code.
Highlights
model()/action()/create()— core state management APIquery()/query.infinite()— built-in data fetching with cachingsilent()— SSR hydration without re-renders- Decorators:
@OnError,@OnSuccess,@Debounce,@Throttle,@Authorized createInterceptor— reusable decorator factoriesMuchaProvider— React context with default query options- Full
llm.txtsupport — just pass the URL to Claude Code
Links
- npm: https://www.npmjs.com/package/comwit
- Docs: https://comwit.io
- llm.txt: https://comwit.io/llm.txt