feat(chord): Watchable, the common interface of values that can be watched

This commit is contained in:
Mario Zechner 2026-10-23 09:31:09 +00:00
parent 14c8118412
commit a2fd25f56c
3 changed files with 20 additions and 1 deletions

View file

@ -10,6 +10,7 @@
- `WatchHandle<T>` and `WatchEnd`, the one watch API, moved from Durable: a serialized exact-frame observation with `value`, `start(listener)`, `stop()`, and `closed`. `WatchEnd` reasons are `stopped`, `cancelled`, `retired`, `ended`, `listener_error`, and `failed`.
- `Watch<T>`, the one watch handle implementation, moved from Durable: a source creates one per watch and feeds it with `advance(value, ops, context)`, `retire(context)` (last frame `[["r", null]]`, then `retired`), `end()` or `end({ error })`, and `observeCancellation(signal)`. More than 100 undelivered frames collapse to one root replacement `[["r", newest]]`; termination drops the listener and every reference into the source.
- `Watchable<T>`: a value that changes and can be watched (`value`, `watch(context)` returning a `WatchHandle<T>`), the common interface of documents, derives and other observable values.
- `NativeWatchHandle<T>` and its implementation `NativeWatch<T>`: the same lifecycle for in-process values, with listener `(value, context)` and no ops; an overflow collapses to the newest value.
## [1.4.0] - 2026-10-21

View file

@ -78,6 +78,13 @@ export {
replicatedState,
} from "./state.ts";
export type { Ctx, GetOptions, Readable, RefStatus, Shape, StateEvent } from "./types.ts";
export { NativeWatch, type NativeWatchHandle, Watch, type WatchEnd, type WatchHandle } from "./watch.ts";
export {
NativeWatch,
type NativeWatchHandle,
Watch,
type Watchable,
type WatchEnd,
type WatchHandle,
} from "./watch.ts";
export { acceptWebSockets, type WebSocketAcceptOptions, type WebSocketServerLike } from "./websocket.ts";
export { type Frame, PROTOCOL_VERSION } from "./wire.ts";

View file

@ -30,6 +30,17 @@ export interface WatchHandle<T> {
readonly closed: Promise<WatchEnd>;
}
/**
* A value that changes and can be watched: documents, derives, members of references. Values are immutable by
* convention (JSON for state); each watch starts at the current value and then gets one frame per change.
*/
export interface Watchable<T> {
/** The current value. */
readonly value: T;
/** A watch holding the current value, then one frame per change; the context's cancellation ends it. */
watch(context: Context): Promise<WatchHandle<T>>;
}
/** Serialized observation of an in-process value: as `WatchHandle`, but a change is a new value without ops. */
export interface NativeWatchHandle<T> {
/** Acquisition value before start; latest delivered value afterward. */