@shivaedev/effect-contract 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.0 - 2026-10-19
4
+
5
+ ### Added
6
+
7
+ - Choose a live changed-hint coalescing window per bound query with React's `useQuery(atom, { coalesceWindow })`, keeping the session window as the default. Queries over one connection refetch on their own schedules; changing the option does not reconnect or refetch queries.
8
+ - Configure a bound query's window through its registry with `queryCoalesceWindow(query)` from `@shivaedev/effect-contract/queryCoalesceWindow.ts`.
9
+
10
+ ## 0.9.0 - 2026-10-19
11
+
12
+ ### Added
13
+
14
+ - Contracts include their reserved `<namespace>.$changes` stream in native RPC client types, with the same middleware as declared operations. Subscribe through a client typed from the contract without a cast or a separate Changes group.
15
+
16
+ ### Breaking
17
+
18
+ - Native contract handler builders now require the reserved `$changes` handler. When a Platform host supplies it, build application handlers with `contract.omit("<namespace>.$changes").of(...)` and `.toLayer(...)`, while retaining the full contract for the host and client. Standalone servers and test clients must supply a changes stream handler. Remove hand-built Changes groups and use the contract directly.
19
+
3
20
  ## 0.8.0 - 2026-10-19
4
21
 
5
22
  ### Added
package/README.md CHANGED
@@ -105,7 +105,7 @@ const missing = Get.reject.NoteMissing({ id: 9 });
105
105
  Implement the contract with native `of` and `toLayer`:
106
106
 
107
107
  ```ts
108
- import { Effect, Ref } from "effect";
108
+ import { Effect, Ref, Stream } from "effect";
109
109
  import { Create, Get, Note, Notes, Rename } from "./notes.ts";
110
110
 
111
111
  export const NotesHandlers = Notes.toLayer(Effect.gen(function* () {
@@ -119,6 +119,7 @@ export const NotesHandlers = Notes.toLayer(Effect.gen(function* () {
119
119
  });
120
120
  const save = (note: Note) => Ref.update(stored, (all) => new Map([...all, [note.id, note]])).pipe(Effect.as(note));
121
121
  return Notes.of({
122
+ "notes.$changes": () => Stream.never,
122
123
  "notes.get": ({ id }) => find(id),
123
124
  "notes.list": () => Effect.map(Ref.get(stored), (all) => [...all.values()]),
124
125
  "notes.rename": ({ id, title }) => title.trim() === ""
@@ -131,7 +132,7 @@ export const NotesHandlers = Notes.toLayer(Effect.gen(function* () {
131
132
  }));
132
133
  ```
133
134
 
134
- Save this module as `handlers.ts`. An application can put repository and service calls in these handlers. The contract checks handler result and rejection types; it does not implement persistence, authorization or transactions.
135
+ Save this module as `handlers.ts`. An application can put repository and service calls in these handlers. The contract checks handler result and rejection types; it does not implement persistence, authorization or transactions. This in-memory server keeps the reserved change stream open without publishing hints. When a Platform host supplies that handler, build application handlers from `Notes.omit("notes.$changes")` and keep `Notes` as the host and client group.
135
136
 
136
137
  Native `.middleware(M)` returns a contract that retains its declarations. For example, a native middleware service can supply request identity:
137
138
 
@@ -191,6 +192,8 @@ const readOnce = api.get.run({ id: 1 });
191
192
  const rename = api.rename.run({ id: 1, title: "Uno" });
192
193
  ```
193
194
 
195
+ `queryCoalesceWindow(query)` from `@shivaedev/effect-contract/queryCoalesceWindow.ts` returns a writable native atom for that bound query's live changed-hint window. Set it through the query's registry to a Duration, or `undefined` to use the live connection's default. Changing it does not refetch or reconnect; the next window uses the new value. React consumers can set it with `useQuery(query, { coalesceWindow: "2 seconds" })`.
196
+
194
197
  `one` and `list` are native query atoms. `readOnce` and `rename` are Effects for individual calls. A query's Effect requires `NotesClient`; a command's Effect also requires native `Reactivity`. Commands expose `run`, and have no `query` member.
195
198
 
196
199
  Mount the atoms and run commands through the service's atom runtime in the same registry:
@@ -232,6 +235,20 @@ Client invalidation follows RPC success. Platform database hosts also publish de
232
235
 
233
236
  Platform database hosts serve the contract's reserved `<contract>.$changes` stream automatically. With NDJSON transport, `bind` and a React `SessionBoundary` connect query atoms without an application subscribe operation or `live()` call. The boundary finds bound APIs returned directly by `connect` or as properties such as `client.api`. See [automatic changes](https://github.com/ShivaeDev/platform/blob/main/docs/framework/changes.md) for defaults.
234
237
 
238
+ For a direct subscription, configure the server and `NotesClient` with `RpcSerialization.layerNdjson` and use the client already typed from `Notes`:
239
+
240
+ ```ts
241
+ import { Effect, Stream } from "effect";
242
+ import { NotesClient } from "./client.ts";
243
+ import { notes } from "./notes.ts";
244
+
245
+ const changes = Stream.unwrap(NotesClient.use((client) =>
246
+ Effect.succeed(client("notes.$changes", { keys: [notes.item(1)] })),
247
+ ));
248
+ ```
249
+
250
+ The contract includes the reserved stream's payload, `LiveHint` elements and middleware failures in its native RPC type. The subscription uses the contract's middleware and needs no separate RPC group or cast. The caller owns stream consumption and interruption.
251
+
235
252
  For a custom transport or explicit pause/status controls, the native live APIs remain available:
236
253
 
237
254
  Declare subscriptions with `stream` in the same contract. Its `success` schema describes each element, and its `rejections` become the native stream error schema. `bind` exposes `run(payload)` as a native `Stream`, preserving declared rejections, middleware errors and RPC client errors. Completion and client interruption release the server subscription. The compiler rejects a unary client for a streaming operation.
@@ -1,6 +1,7 @@
1
1
  import { type Schema } from "effect";
2
2
  import { Rpc, RpcGroup, type RpcMiddleware, type RpcSchema } from "effect/rpc";
3
3
  import type { CommandShape, OperationShape, QueryShape, StreamShape } from "./operation.ts";
4
+ import { changesRpc } from "./serverMetadata.ts";
4
5
  export type Tag<TContract extends string, TName extends string> = `${TContract}.${TName}`;
5
6
  export type OperationRpc<TContract extends string, TOperation> = TOperation extends OperationShape ? TOperation extends StreamShape ? Rpc.Rpc<Tag<TContract, TOperation["name"]>, TOperation["payload"], RpcSchema.Stream<TOperation["success"], TOperation["error"]>, Schema.Never> : Rpc.Rpc<Tag<TContract, TOperation["name"]>, TOperation["payload"], TOperation["success"], TOperation["error"]> : never;
6
7
  export interface Declared<TName extends string, TQueries extends readonly QueryShape[], TCommands extends readonly CommandShape[], TStreams extends readonly StreamShape[] = readonly []> {
@@ -9,7 +10,7 @@ export interface Declared<TName extends string, TQueries extends readonly QueryS
9
10
  readonly queries: TQueries;
10
11
  readonly streams: TStreams;
11
12
  }
12
- export interface Contract<TName extends string, TQueries extends readonly QueryShape[], TCommands extends readonly CommandShape[], TRpcs extends Rpc.Any = OperationRpc<TName, TQueries[number] | TCommands[number]>, TStreams extends readonly StreamShape[] = readonly []> extends RpcGroup.RpcGroup<TRpcs> {
13
+ export interface Contract<TName extends string, TQueries extends readonly QueryShape[], TCommands extends readonly CommandShape[], TRpcs extends Rpc.Any = OperationRpc<TName, TQueries[number] | TCommands[number]> | ReturnType<typeof changesRpc<TName>>, TStreams extends readonly StreamShape[] = readonly []> extends RpcGroup.RpcGroup<TRpcs> {
13
14
  readonly declaration: Declared<TName, TQueries, TCommands, TStreams>;
14
15
  middleware: <TM extends RpcMiddleware.AnyService>(middleware: TM) => Contract<TName, TQueries, TCommands, Rpc.AddMiddleware<TRpcs, TM>, TStreams>;
15
16
  }
@@ -22,6 +23,6 @@ export declare function contract<const TName extends string, const TQueries exte
22
23
  readonly queries?: TQueries & Unique<TQueries>;
23
24
  readonly commands?: TCommands & Unique<[...TQueries, ...TCommands]>;
24
25
  readonly streams?: TStreams & Unique<[...TQueries, ...TCommands, ...TStreams]>;
25
- }): Contract<TName, TQueries, TCommands, OperationRpc<TName, TQueries[number] | TCommands[number] | TStreams[number]>, TStreams>;
26
+ }): Contract<TName, TQueries, TCommands, OperationRpc<TName, TQueries[number] | TCommands[number] | TStreams[number]> | ReturnType<typeof changesRpc<TName>>, TStreams>;
26
27
  export {};
27
28
  //# sourceMappingURL=contract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5F,OAAO,EAAuB,UAAU,EAAc,MAAM,qBAAqB,CAAC;AAElF,MAAM,MAAM,GAAG,CAAC,SAAS,SAAS,MAAM,EAAE,KAAK,SAAS,MAAM,IAAI,GAAG,SAAS,IAAI,KAAK,EAAE,CAAC;AAE1F,MAAM,MAAM,YAAY,CAAC,SAAS,SAAS,MAAM,EAAE,UAAU,IAAI,UAAU,SAAS,cAAc,GAC/F,UAAU,SAAS,WAAW,GAC7B,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,GAC9I,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,GAC/G,KAAK,CAAC;AAET,MAAM,WAAW,QAAQ,CACxB,KAAK,SAAS,MAAM,EACpB,QAAQ,SAAS,SAAS,UAAU,EAAE,EACtC,SAAS,SAAS,SAAS,YAAY,EAAE,EACzC,QAAQ,SAAS,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE;IAErD,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ,CACxB,KAAK,SAAS,MAAM,EACpB,QAAQ,SAAS,SAAS,UAAU,EAAE,EACtC,SAAS,SAAS,SAAS,YAAY,EAAE,EACzC,KAAK,SAAS,GAAG,CAAC,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,EACxH,QAAQ,SAAS,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE,CACpD,SAAQ,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrE,UAAU,EAAE,CAAC,EAAE,SAAS,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,EAAE,KAAK,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;CAClJ;AAED,KAAK,UAAU,CAAC,WAAW,SAAS,SAAS,cAAc,EAAE,EAAE,KAAK,SAAS,MAAM,GAAG,KAAK,IAAI,WAAW,SAAS,SAAS;IAC3H,MAAM,KAAK,SAAS,cAAc;IAClC,GAAG,MAAM,KAAK,SAAS,SAAS,cAAc,EAAE;CAChD,GACE,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAChG,KAAK,CAAC;AAET,KAAK,MAAM,CAAC,WAAW,SAAS,SAAS,cAAc,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GACnG,OAAO,GACP,+CAA+C,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;AAkC5E,wBAAgB,QAAQ,CACvB,KAAK,CAAC,KAAK,SAAS,MAAM,EAC1B,KAAK,CAAC,QAAQ,SAAS,SAAS,UAAU,EAAE,GAAG,SAAS,EAAE,EAC1D,KAAK,CAAC,SAAS,SAAS,SAAS,YAAY,EAAE,GAAG,SAAS,EAAE,EAC7D,KAAK,CAAC,QAAQ,SAAS,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE,EAE3D,IAAI,EAAE,KAAK,EACX,UAAU,EAAE;IACX,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;IACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;CAC/E,GACC,QAAQ,CACV,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,EACnH,QAAQ,CACR,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAsC,MAAM,YAAY,CAAC;AAE/E,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AA4ClF,SAAS,YAAY,CAAC,UAAqC;IAC1D,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;IACpH,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvG,CAAC;AACF,CAAC;AAED,SAAS,WAAW,CAAC,SAAkD;IACtE,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAClC,OAAO,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;AACjG,CAAC;AAYD,SAAS,eAAe,CAAC,KAAY,EAAE,WAAwB;IAC9D,MAAM,gBAAgB,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE;QAC3B,WAAW;QACX,UAAU,EAAE,CAAC,UAAoC,EAAE,EAAE,CAAC,eAAe,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC;KAChH,CAAC,CAAC;AACJ,CAAC;AAeD,MAAM,UAAU,QAAQ,CACvB,IAAY,EACZ,UAAgJ;IAEhJ,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,UAAU,CAAC;IACjE,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CACpE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE;QACrC,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,OAAO,EAAE,SAAS,CAAC,OAAO;QAC1B,MAAM,EAAE,SAAS,CAAC,IAAI,KAAK,QAAQ;QACnC,OAAO,EAAE,SAAS,CAAC,OAAO;KAC1B,CAAC,CAAC,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CACxC,CAAC;IACF,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AACxG,CAAC"}
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAsC,MAAM,YAAY,CAAC;AAE/E,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AA4ClF,SAAS,YAAY,CAAC,UAAqC;IAC1D,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;IACpH,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvG,CAAC;AACF,CAAC;AAED,SAAS,WAAW,CAAC,SAAkD;IACtE,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAClC,OAAO,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;AACjG,CAAC;AAYD,SAAS,eAAe,CAAC,KAAY,EAAE,WAAwB;IAC9D,MAAM,gBAAgB,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE;QAC3B,WAAW;QACX,UAAU,EAAE,CAAC,UAAoC,EAAE,EAAE,CAAC,eAAe,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC;KAChH,CAAC,CAAC;AACJ,CAAC;AAqBD,MAAM,UAAU,QAAQ,CACvB,IAAY,EACZ,UAAgJ;IAEhJ,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,UAAU,CAAC;IACjE,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CACpE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE;QACrC,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,OAAO,EAAE,SAAS,CAAC,OAAO;QAC1B,MAAM,EAAE,SAAS,CAAC,IAAI,KAAK,QAAQ;QACnC,OAAO,EAAE,SAAS,CAAC,OAAO;KAC1B,CAAC,CAAC,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CACxC,CAAC;IACF,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AACxG,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Duration } from "effect";
2
+ import type * as Reactivity from "effect/reactivity/Reactivity";
3
+ interface Batch {
4
+ readonly active: () => boolean;
5
+ readonly seen: Set<() => void>;
6
+ readonly window: Duration.Input | undefined;
7
+ }
8
+ export declare const liveBatches: WeakMap<Reactivity.Reactivity, Batch>;
9
+ export declare function liveKeys(keys: readonly string[]): string[];
10
+ export declare function invalidateLive(reactivity: Reactivity.Reactivity, keys: readonly string[], active: () => boolean, window?: Duration.Input): void;
11
+ export {};
12
+ //# sourceMappingURL=liveInvalidation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveInvalidation.d.ts","sourceRoot":"","sources":["../../src/internal/liveInvalidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAEhE,UAAU,KAAK;IACd,QAAQ,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAC;CAC5C;AACD,eAAO,MAAM,WAAW,uCAA8C,CAAC;AACvE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,YAE/C;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,OAAO,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,KAAK,QAOxI"}
@@ -0,0 +1,14 @@
1
+ export const liveBatches = new WeakMap();
2
+ export function liveKeys(keys) {
3
+ return keys.map((key) => `@shivaedev/live:${key}`);
4
+ }
5
+ export function invalidateLive(reactivity, keys, active, window) {
6
+ liveBatches.set(reactivity, { active, seen: new Set(), window });
7
+ try {
8
+ reactivity.invalidateUnsafe(window === undefined ? keys : liveKeys(keys));
9
+ }
10
+ finally {
11
+ liveBatches.delete(reactivity);
12
+ }
13
+ }
14
+ //# sourceMappingURL=liveInvalidation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveInvalidation.js","sourceRoot":"","sources":["../../src/internal/liveInvalidation.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,EAAgC,CAAC;AACvE,MAAM,UAAU,QAAQ,CAAC,IAAuB;IAC/C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,UAAiC,EAAE,IAAuB,EAAE,MAAqB,EAAE,MAAuB;IACxI,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC;QACJ,UAAU,CAAC,gBAAgB,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC;YAAS,CAAC;QACV,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;AACF,CAAC"}
@@ -1,6 +1,4 @@
1
1
  import * as AsyncResult from "effect/reactivity/AsyncResult";
2
2
  import * as Atom from "effect/reactivity/Atom";
3
- import * as Reactivity from "effect/reactivity/Reactivity";
4
- export declare function invalidateLive(reactivity: Reactivity.Reactivity, keys: readonly string[], active: () => boolean): void;
5
3
  export declare function queryReactivity<R, E>(runtime: Atom.AtomRuntime<R, E>): (atom: Atom.Atom<AsyncResult.AsyncResult<unknown, unknown>>, keys: readonly string[]) => Atom.Atom<AsyncResult.AsyncResult<unknown, unknown>>;
6
4
  //# sourceMappingURL=queryReactivity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queryReactivity.d.ts","sourceRoot":"","sources":["../../src/internal/queryReactivity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,WAAW,MAAM,+BAA+B,CAAC;AAC7D,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAQ3D,wBAAgB,cAAc,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,OAAO,QAO/G;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,sEAIzC,SAAS,MAAM,EAAE,0DA2D5C"}
1
+ {"version":3,"file":"queryReactivity.d.ts","sourceRoot":"","sources":["../../src/internal/queryReactivity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,WAAW,MAAM,+BAA+B,CAAC;AAC7D,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAK/C,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,sEAIzC,SAAS,MAAM,EAAE,0DAuF5C"}
@@ -1,17 +1,9 @@
1
- import { Effect } from "effect";
1
+ import { Duration, Effect } from "effect";
2
2
  import * as AsyncResult from "effect/reactivity/AsyncResult";
3
3
  import * as Atom from "effect/reactivity/Atom";
4
4
  import * as Reactivity from "effect/reactivity/Reactivity";
5
- const batches = new WeakMap();
6
- export function invalidateLive(reactivity, keys, active) {
7
- batches.set(reactivity, { active, seen: new Set() });
8
- try {
9
- reactivity.invalidateUnsafe(keys);
10
- }
11
- finally {
12
- batches.delete(reactivity);
13
- }
14
- }
5
+ import { queryCoalesceWindow } from "#queryCoalesceWindow.ts";
6
+ import { liveBatches, liveKeys } from "./liveInvalidation.js";
15
7
  export function queryReactivity(runtime) {
16
8
  const service = runtime.atom(Effect.service(Reactivity.Reactivity));
17
9
  const cached = new WeakMap();
@@ -28,22 +20,50 @@ export function queryReactivity(runtime) {
28
20
  }
29
21
  const reactivity = context.value;
30
22
  let pending;
31
- function invalidate() {
32
- const batch = batches.get(reactivity);
33
- if (batch !== undefined) {
34
- if (batch.seen.has(invalidate)) {
35
- return;
36
- }
37
- batch.seen.add(invalidate);
38
- if (get.once(source).waiting) {
39
- pending = batch.active;
40
- return;
41
- }
42
- }
23
+ let timer;
24
+ function clear() {
25
+ clearTimeout(timer);
26
+ timer = undefined;
43
27
  pending = undefined;
44
- get.refresh(source);
45
28
  }
46
- get.addFinalizer(reactivity.registerUnsafe(keys, invalidate));
29
+ function refresh(active) {
30
+ if (!active()) {
31
+ return;
32
+ }
33
+ if (get.once(source).waiting) {
34
+ pending = active;
35
+ }
36
+ else {
37
+ pending = undefined;
38
+ get.refresh(source);
39
+ }
40
+ }
41
+ function changed() {
42
+ const batch = liveBatches.get(reactivity);
43
+ if (batch === undefined || batch.seen.has(changed)) {
44
+ return;
45
+ }
46
+ batch.seen.add(changed);
47
+ const delay = Duration.toMillis(Duration.fromInputUnsafe(get.once(queryCoalesceWindow(wrapped)) ?? batch.window ?? 0));
48
+ if (delay === 0) {
49
+ clear();
50
+ get.refresh(source);
51
+ }
52
+ else {
53
+ timer ??= setTimeout(() => {
54
+ timer = undefined;
55
+ refresh(batch.active);
56
+ }, delay);
57
+ }
58
+ }
59
+ get.addFinalizer(clear);
60
+ get.addFinalizer(reactivity.registerUnsafe(liveKeys(keys), changed));
61
+ get.addFinalizer(reactivity.registerUnsafe(keys, () => {
62
+ if (!liveBatches.has(reactivity)) {
63
+ clear();
64
+ get.refresh(source);
65
+ }
66
+ }));
47
67
  get.subscribe(source, (value) => {
48
68
  get.setSelf(value);
49
69
  if (pending !== undefined && !value.waiting) {
@@ -1 +1 @@
1
- {"version":3,"file":"queryReactivity.js","sourceRoot":"","sources":["../../src/internal/queryReactivity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queryReactivity.js","sourceRoot":"","sources":["../../src/internal/queryReactivity.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,QAAQ,EAAU,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9E,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAG/C,OAAO,EAAoB,GAAG,EAAY,MAAM,WAAW,CAAC;AAE5D,eAAO,MAAM,QAAQ;;;;;;;;;;;;IAGnB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAC;AAC5C,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,YAAY,GAAG,MAAM,GAAG,cAAc,CAAC;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AACD,MAAM,WAAW,WAAW,CAAC,CAAC,EAAE,CAAC;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,SAAS,GAAG,EAAE,GAAG,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC;IAC7D,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAC/C;AAID,wBAAgB,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;;;;;EAwFhH"}
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,QAAQ,EAAU,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9E,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAG/C,OAAO,EAAoB,GAAG,EAAY,MAAM,WAAW,CAAC;AAE5D,eAAO,MAAM,QAAQ;;;;;;;;;;;;IAGnB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAC;AAC5C,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,YAAY,GAAG,MAAM,GAAG,cAAc,CAAC;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AACD,MAAM,WAAW,WAAW,CAAC,CAAC,EAAE,CAAC;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,SAAS,GAAG,EAAE,GAAG,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC;IAC7D,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAC/C;AAID,wBAAgB,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;;;;;EA2FhH"}
package/dist/live.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Duration, Effect, Option, Schema, Stream } from "effect";
2
2
  import * as Atom from "effect/reactivity/Atom";
3
3
  import * as Reactivity from "effect/reactivity/Reactivity";
4
- import { invalidateLive } from "#internal/queryReactivity.ts";
4
+ import { invalidateLive } from "#internal/liveInvalidation.ts";
5
5
  import { invalidationKeys, Key, readKeys } from "./keys.js";
6
6
  export const LiveHint = Schema.Union([
7
7
  Schema.Struct({ _tag: Schema.Literal("Changed"), keys: Schema.Array(Key) }),
@@ -32,19 +32,22 @@ export function live(runtime, options) {
32
32
  clear();
33
33
  });
34
34
  function changed(changedKeys) {
35
- const delay = Duration.toMillis(Duration.fromInputUnsafe(get.once(coalesceWindow)));
35
+ const window = get.once(coalesceWindow);
36
+ const keys = invalidationKeys(changedKeys);
37
+ invalidateLive(reactivity, keys, () => active && !get.once(paused), window);
38
+ const delay = Duration.toMillis(Duration.fromInputUnsafe(window));
36
39
  if (delay === 0) {
37
- reactivity.invalidateUnsafe(invalidationKeys(changedKeys));
40
+ invalidateLive(reactivity, keys, () => active && !get.once(paused));
38
41
  return;
39
42
  }
40
43
  for (const key of invalidationKeys(changedKeys)) {
41
44
  pending.add(key);
42
45
  }
43
46
  timer ??= setTimeout(() => {
44
- const keys = [...pending];
47
+ const queued = [...pending];
45
48
  clear();
46
49
  if (!get.once(paused)) {
47
- invalidateLive(reactivity, keys, () => active && !get.once(paused));
50
+ invalidateLive(reactivity, queued, () => active && !get.once(paused));
48
51
  }
49
52
  }, delay);
50
53
  }
package/dist/live.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"live.js","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Duration } from "effect";
2
+ import * as Atom from "effect/reactivity/Atom";
3
+ export declare function queryCoalesceWindow<A>(query: Atom.Atom<A>): Atom.Writable<Duration.Input | undefined>;
4
+ //# sourceMappingURL=queryCoalesceWindow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryCoalesceWindow.d.ts","sourceRoot":"","sources":["../src/queryCoalesceWindow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAI/C,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAC,CAOrG"}
@@ -0,0 +1,11 @@
1
+ import * as Atom from "effect/reactivity/Atom";
2
+ const windows = new WeakMap();
3
+ export function queryCoalesceWindow(query) {
4
+ let window = windows.get(query);
5
+ if (window === undefined) {
6
+ window = Atom.keepAlive(Atom.make(undefined));
7
+ windows.set(query, window);
8
+ }
9
+ return window;
10
+ }
11
+ //# sourceMappingURL=queryCoalesceWindow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryCoalesceWindow.js","sourceRoot":"","sources":["../src/queryCoalesceWindow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAE/C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAiE,CAAC;AAE7F,MAAM,UAAU,mBAAmB,CAAI,KAAmB;IACzD,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAA6B,SAAS,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/effect-contract",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Typed query and command contracts over native Effect RPC and reactivity",
5
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/effect-contract#readme",
6
6
  "bugs": {
@@ -47,9 +47,9 @@
47
47
  "@effect/platform-node": "4.0.4",
48
48
  "@effect/vitest": "4.0.4",
49
49
  "@shivaedev/effect-test": "0.7.1",
50
- "@shivaedev/effect-test-sql": "0.7.4",
51
- "@shivaedev/quality": "0.29.1",
52
- "@shivaedev/test-story": "0.16.0",
50
+ "@shivaedev/effect-test-sql": "0.8.1",
51
+ "@shivaedev/quality": "0.31.0",
52
+ "@shivaedev/test-story": "0.17.0",
53
53
  "@types/node": "24.19.2",
54
54
  "effect": "4.0.4",
55
55
  "esbuild": "0.28.2",
package/src/contract.ts CHANGED
@@ -27,7 +27,7 @@ export interface Contract<
27
27
  TName extends string,
28
28
  TQueries extends readonly QueryShape[],
29
29
  TCommands extends readonly CommandShape[],
30
- TRpcs extends Rpc.Any = OperationRpc<TName, TQueries[number] | TCommands[number]>,
30
+ TRpcs extends Rpc.Any = OperationRpc<TName, TQueries[number] | TCommands[number]> | ReturnType<typeof changesRpc<TName>>,
31
31
  TStreams extends readonly StreamShape[] = readonly [],
32
32
  > extends RpcGroup.RpcGroup<TRpcs> {
33
33
  readonly declaration: Declared<TName, TQueries, TCommands, TStreams>;
@@ -89,7 +89,13 @@ export function contract<
89
89
  readonly commands?: TCommands & Unique<[...TQueries, ...TCommands]>;
90
90
  readonly streams?: TStreams & Unique<[...TQueries, ...TCommands, ...TStreams]>;
91
91
  },
92
- ): Contract<TName, TQueries, TCommands, OperationRpc<TName, TQueries[number] | TCommands[number] | TStreams[number]>, TStreams>;
92
+ ): Contract<
93
+ TName,
94
+ TQueries,
95
+ TCommands,
96
+ OperationRpc<TName, TQueries[number] | TCommands[number] | TStreams[number]> | ReturnType<typeof changesRpc<TName>>,
97
+ TStreams
98
+ >;
93
99
  export function contract(
94
100
  name: string,
95
101
  operations: { readonly queries?: readonly QueryShape[]; readonly commands?: readonly CommandShape[]; readonly streams?: readonly StreamShape[] },
@@ -0,0 +1,21 @@
1
+ import type { Duration } from "effect";
2
+ import type * as Reactivity from "effect/reactivity/Reactivity";
3
+
4
+ interface Batch {
5
+ readonly active: () => boolean;
6
+ readonly seen: Set<() => void>;
7
+ readonly window: Duration.Input | undefined;
8
+ }
9
+ export const liveBatches = new WeakMap<Reactivity.Reactivity, Batch>();
10
+ export function liveKeys(keys: readonly string[]) {
11
+ return keys.map((key) => `@shivaedev/live:${key}`);
12
+ }
13
+
14
+ export function invalidateLive(reactivity: Reactivity.Reactivity, keys: readonly string[], active: () => boolean, window?: Duration.Input) {
15
+ liveBatches.set(reactivity, { active, seen: new Set(), window });
16
+ try {
17
+ reactivity.invalidateUnsafe(window === undefined ? keys : liveKeys(keys));
18
+ } finally {
19
+ liveBatches.delete(reactivity);
20
+ }
21
+ }
@@ -1,22 +1,9 @@
1
- import { Effect } from "effect";
1
+ import { Duration, Effect } from "effect";
2
2
  import * as AsyncResult from "effect/reactivity/AsyncResult";
3
3
  import * as Atom from "effect/reactivity/Atom";
4
4
  import * as Reactivity from "effect/reactivity/Reactivity";
5
-
6
- interface Batch {
7
- readonly active: () => boolean;
8
- readonly seen: Set<() => void>;
9
- }
10
- const batches = new WeakMap<Reactivity.Reactivity, Batch>();
11
-
12
- export function invalidateLive(reactivity: Reactivity.Reactivity, keys: readonly string[], active: () => boolean) {
13
- batches.set(reactivity, { active, seen: new Set() });
14
- try {
15
- reactivity.invalidateUnsafe(keys);
16
- } finally {
17
- batches.delete(reactivity);
18
- }
19
- }
5
+ import { queryCoalesceWindow } from "#queryCoalesceWindow.ts";
6
+ import { liveBatches, liveKeys } from "./liveInvalidation.ts";
20
7
 
21
8
  export function queryReactivity<R, E>(runtime: Atom.AtomRuntime<R, E>) {
22
9
  const service = runtime.atom(Effect.service(Reactivity.Reactivity));
@@ -40,22 +27,50 @@ export function queryReactivity<R, E>(runtime: Atom.AtomRuntime<R, E>) {
40
27
  }
41
28
  const reactivity = context.value;
42
29
  let pending: (() => boolean) | undefined;
43
- function invalidate() {
44
- const batch = batches.get(reactivity);
45
- if (batch !== undefined) {
46
- if (batch.seen.has(invalidate)) {
47
- return;
48
- }
49
- batch.seen.add(invalidate);
50
- if (get.once(source).waiting) {
51
- pending = batch.active;
52
- return;
53
- }
54
- }
30
+ let timer: ReturnType<typeof setTimeout> | undefined;
31
+ function clear() {
32
+ clearTimeout(timer);
33
+ timer = undefined;
55
34
  pending = undefined;
56
- get.refresh(source);
57
35
  }
58
- get.addFinalizer(reactivity.registerUnsafe(keys, invalidate));
36
+ function refresh(active: () => boolean) {
37
+ if (!active()) {
38
+ return;
39
+ }
40
+ if (get.once(source).waiting) {
41
+ pending = active;
42
+ } else {
43
+ pending = undefined;
44
+ get.refresh(source);
45
+ }
46
+ }
47
+ function changed() {
48
+ const batch = liveBatches.get(reactivity);
49
+ if (batch === undefined || batch.seen.has(changed)) {
50
+ return;
51
+ }
52
+ batch.seen.add(changed);
53
+ const delay = Duration.toMillis(Duration.fromInputUnsafe(get.once(queryCoalesceWindow(wrapped)) ?? batch.window ?? 0));
54
+ if (delay === 0) {
55
+ clear();
56
+ get.refresh(source);
57
+ } else {
58
+ timer ??= setTimeout(() => {
59
+ timer = undefined;
60
+ refresh(batch.active);
61
+ }, delay);
62
+ }
63
+ }
64
+ get.addFinalizer(clear);
65
+ get.addFinalizer(reactivity.registerUnsafe(liveKeys(keys), changed));
66
+ get.addFinalizer(
67
+ reactivity.registerUnsafe(keys, () => {
68
+ if (!liveBatches.has(reactivity)) {
69
+ clear();
70
+ get.refresh(source);
71
+ }
72
+ }),
73
+ );
59
74
  get.subscribe(source, (value) => {
60
75
  get.setSelf(value);
61
76
  if (pending !== undefined && !value.waiting) {
package/src/live.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { type Cause, Duration, Effect, Option, Schema, Stream } from "effect";
2
2
  import * as Atom from "effect/reactivity/Atom";
3
3
  import * as Reactivity from "effect/reactivity/Reactivity";
4
- import { invalidateLive } from "#internal/queryReactivity.ts";
4
+ import { invalidateLive } from "#internal/liveInvalidation.ts";
5
5
  import { invalidationKeys, Key, readKeys } from "./keys.ts";
6
6
 
7
7
  export const LiveHint = Schema.Union([
@@ -50,19 +50,22 @@ export function live<R, E, TRuntimeError>(runtime: Atom.AtomRuntime<R, TRuntimeE
50
50
  clear();
51
51
  });
52
52
  function changed(changedKeys: readonly Key[]) {
53
- const delay = Duration.toMillis(Duration.fromInputUnsafe(get.once(coalesceWindow)));
53
+ const window = get.once(coalesceWindow);
54
+ const keys = invalidationKeys(changedKeys);
55
+ invalidateLive(reactivity, keys, () => active && !get.once(paused), window);
56
+ const delay = Duration.toMillis(Duration.fromInputUnsafe(window));
54
57
  if (delay === 0) {
55
- reactivity.invalidateUnsafe(invalidationKeys(changedKeys));
58
+ invalidateLive(reactivity, keys, () => active && !get.once(paused));
56
59
  return;
57
60
  }
58
61
  for (const key of invalidationKeys(changedKeys)) {
59
62
  pending.add(key);
60
63
  }
61
64
  timer ??= setTimeout(() => {
62
- const keys = [...pending];
65
+ const queued = [...pending];
63
66
  clear();
64
67
  if (!get.once(paused)) {
65
- invalidateLive(reactivity, keys, () => active && !get.once(paused));
68
+ invalidateLive(reactivity, queued, () => active && !get.once(paused));
66
69
  }
67
70
  }, delay);
68
71
  }
@@ -0,0 +1,13 @@
1
+ import type { Duration } from "effect";
2
+ import * as Atom from "effect/reactivity/Atom";
3
+
4
+ const windows = new WeakMap<Atom.Atom<unknown>, Atom.Writable<Duration.Input | undefined>>();
5
+
6
+ export function queryCoalesceWindow<A>(query: Atom.Atom<A>): Atom.Writable<Duration.Input | undefined> {
7
+ let window = windows.get(query);
8
+ if (window === undefined) {
9
+ window = Atom.keepAlive(Atom.make<Duration.Input | undefined>(undefined));
10
+ windows.set(query, window);
11
+ }
12
+ return window;
13
+ }