@derivation/rpc 0.6.0 → 0.8.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/dist/index.cjs CHANGED
@@ -52,6 +52,7 @@ var ReactiveSourceAdapter = class {
52
52
  var ReactiveSinkAdapter = class {
53
53
  constructor(graph, snapshotIso, changeIso, ops, snapshot) {
54
54
  this.graph = graph;
55
+ this.snapshotIso = snapshotIso;
55
56
  this.changeIso = changeIso;
56
57
  this.ops = ops;
57
58
  this.initialValue = snapshotIso.from(snapshot);
@@ -59,6 +60,10 @@ var ReactiveSinkAdapter = class {
59
60
  apply(change, input) {
60
61
  input.push(this.changeIso.from(change));
61
62
  }
63
+ reset(snapshot, input) {
64
+ const snapshotValue = this.snapshotIso.from(snapshot);
65
+ input.push((0, import_composable.asBase)(this.ops).replaceCommand(snapshotValue));
66
+ }
62
67
  build() {
63
68
  const ops = this.ops;
64
69
  const input = new import_composable.ChangeInput(this.graph, ops);
@@ -104,6 +109,9 @@ var StreamSinkAdapter = class {
104
109
  apply(change, input) {
105
110
  input.push(this.iso.from(change));
106
111
  }
112
+ reset(snapshot, input) {
113
+ input.push(this.iso.from(snapshot));
114
+ }
107
115
  build() {
108
116
  const stream = (0, import_derivation.inputValue)(this.graph, this.initialValue);
109
117
  return { stream, input: stream };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/reactive-adapter.ts","../src/stream-adapter.ts"],"sourcesContent":["// Main index exports shared APIs that are transport-agnostic.\nexport * from \"./stream-types.js\";\nexport {\n ReactiveSourceAdapter,\n ReactiveSinkAdapter,\n sink as reactiveSink,\n} from \"./reactive-adapter.js\";\nexport {\n StreamSourceAdapter,\n StreamSinkAdapter,\n sink as streamSink,\n} from \"./stream-adapter.js\";\nexport type { PresenceHandler } from \"./presence-manager.js\";\n","import { Graph } from \"derivation\";\nimport {\n Reactive,\n ChangeInput,\n Changes,\n OperationsBase,\n Operations,\n asBase,\n} from \"@derivation/composable\";\nimport { Source, Sink } from \"./stream-types.js\";\nimport { Iso } from \"./iso.js\";\n\nexport class ReactiveSourceAdapter<T> implements Source<Reactive<T>> {\n constructor(\n private readonly stream: Reactive<T>,\n private readonly snapshotIso: Iso<T, object>,\n private readonly changeIso: Iso<Changes<T>, object>,\n ) {}\n\n get Snapshot(): object {\n return this.snapshotIso.to(this.stream.snapshot);\n }\n\n get LastChange(): object | null {\n const change = this.stream.changes.value;\n if (change === null) return null;\n return this.changeIso.to(change);\n }\n\n get Stream(): Reactive<T> {\n return this.stream;\n }\n}\n\nexport class ReactiveSinkAdapter<T>\n implements Sink<Reactive<T>, ChangeInput<T>>\n{\n private readonly initialValue: T;\n\n constructor(\n private readonly graph: Graph,\n snapshotIso: Iso<T, object>,\n private readonly changeIso: Iso<Changes<T>, object>,\n private readonly ops: Operations<T>,\n snapshot: object,\n ) {\n this.initialValue = snapshotIso.from(snapshot);\n }\n\n apply(change: object, input: ChangeInput<T>): void {\n input.push(this.changeIso.from(change));\n }\n\n build(): { stream: Reactive<T>; input: ChangeInput<T> } {\n const ops = this.ops;\n const input = new ChangeInput<T>(this.graph, ops);\n const stream = Reactive.create(this.graph, ops, input, this.initialValue);\n return { stream, input };\n }\n}\n\nexport function sink<T>(\n graph: Graph,\n snapshotIso: Iso<T, object>,\n changeIso: Iso<Changes<T>, object>,\n ops: Operations<T>,\n): (snapshot: object) => Sink<Reactive<T>, ChangeInput<T>> {\n return (snapshot: object) => {\n return new ReactiveSinkAdapter<T>(\n graph,\n snapshotIso,\n changeIso,\n ops,\n snapshot,\n );\n };\n}\n","import { Graph, ReactiveValue, Input, inputValue } from \"derivation\";\nimport { Source, Sink } from \"./stream-types.js\";\nimport { Iso } from \"./iso.js\";\n\nexport class StreamSourceAdapter<T extends object> implements Source<ReactiveValue<T>> {\n private readonly iso: Iso<T, object>;\n\n constructor(private readonly stream: ReactiveValue<T>, iso: Iso<T, object>) {\n this.iso = iso;\n }\n\n get Snapshot(): object {\n return this.iso.to(this.stream.value);\n }\n\n get LastChange(): object | null {\n return this.iso.to(this.stream.value);\n }\n\n get Stream(): ReactiveValue<T> {\n return this.stream;\n }\n}\n\nexport class StreamSinkAdapter<T extends object> implements Sink<Input<T>, Input<T>> {\n private readonly graph: Graph;\n private readonly iso: Iso<T, object>;\n private readonly initialValue: T;\n\n constructor(graph: Graph, iso: Iso<T, object>, snapshot: object) {\n this.graph = graph;\n this.iso = iso;\n this.initialValue = iso.from(snapshot);\n }\n\n apply(change: object, input: Input<T>): void {\n input.push(this.iso.from(change));\n }\n\n build(): { stream: Input<T>; input: Input<T> } {\n const stream = inputValue(this.graph, this.initialValue);\n return { stream, input: stream };\n }\n}\n\nexport function sink<T extends object>(graph: Graph, iso: Iso<T, object>): (snapshot: object) => Sink<Input<T>, Input<T>> {\n return (snapshot: object) => {\n return new StreamSinkAdapter<T>(graph, iso, snapshot);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAAA;AAAA;AAAA;;;ACCA,wBAOO;AAIA,IAAM,wBAAN,MAA8D;AAAA,EACnE,YACmB,QACA,aACA,WACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAEH,IAAI,WAAmB;AACrB,WAAO,KAAK,YAAY,GAAG,KAAK,OAAO,QAAQ;AAAA,EACjD;AAAA,EAEA,IAAI,aAA4B;AAC9B,UAAM,SAAS,KAAK,OAAO,QAAQ;AACnC,QAAI,WAAW,KAAM,QAAO;AAC5B,WAAO,KAAK,UAAU,GAAG,MAAM;AAAA,EACjC;AAAA,EAEA,IAAI,SAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AACF;AAEO,IAAM,sBAAN,MAEP;AAAA,EAGE,YACmB,OACjB,aACiB,WACA,KACjB,UACA;AALiB;AAEA;AACA;AAGjB,SAAK,eAAe,YAAY,KAAK,QAAQ;AAAA,EAC/C;AAAA,EAEA,MAAM,QAAgB,OAA6B;AACjD,UAAM,KAAK,KAAK,UAAU,KAAK,MAAM,CAAC;AAAA,EACxC;AAAA,EAEA,QAAwD;AACtD,UAAM,MAAM,KAAK;AACjB,UAAM,QAAQ,IAAI,8BAAe,KAAK,OAAO,GAAG;AAChD,UAAM,SAAS,2BAAS,OAAO,KAAK,OAAO,KAAK,OAAO,KAAK,YAAY;AACxE,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB;AACF;AAEO,SAAS,KACd,OACA,aACA,WACA,KACyD;AACzD,SAAO,CAAC,aAAqB;AAC3B,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AC5EA,wBAAwD;AAIjD,IAAM,sBAAN,MAAgF;AAAA,EAGrF,YAA6B,QAA0B,KAAqB;AAA/C;AAC3B,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK;AAAA,EACtC;AAAA,EAEA,IAAI,aAA4B;AAC9B,WAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK;AAAA,EACtC;AAAA,EAEA,IAAI,SAA2B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AAEO,IAAM,oBAAN,MAA8E;AAAA,EAKnF,YAAY,OAAc,KAAqB,UAAkB;AAC/D,SAAK,QAAQ;AACb,SAAK,MAAM;AACX,SAAK,eAAe,IAAI,KAAK,QAAQ;AAAA,EACvC;AAAA,EAEA,MAAM,QAAgB,OAAuB;AAC3C,UAAM,KAAK,KAAK,IAAI,KAAK,MAAM,CAAC;AAAA,EAClC;AAAA,EAEA,QAA+C;AAC7C,UAAM,aAAS,8BAAW,KAAK,OAAO,KAAK,YAAY;AACvD,WAAO,EAAE,QAAQ,OAAO,OAAO;AAAA,EACjC;AACF;AAEO,SAASC,MAAuB,OAAc,KAAqE;AACxH,SAAO,CAAC,aAAqB;AAC3B,WAAO,IAAI,kBAAqB,OAAO,KAAK,QAAQ;AAAA,EACtD;AACF;","names":["sink","sink"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/reactive-adapter.ts","../src/stream-adapter.ts"],"sourcesContent":["// Main index exports shared APIs that are transport-agnostic.\nexport * from \"./stream-types.js\";\nexport {\n ReactiveSourceAdapter,\n ReactiveSinkAdapter,\n sink as reactiveSink,\n} from \"./reactive-adapter.js\";\nexport {\n StreamSourceAdapter,\n StreamSinkAdapter,\n sink as streamSink,\n} from \"./stream-adapter.js\";\nexport type { PresenceHandler } from \"./presence-manager.js\";\n","import { Graph } from \"derivation\";\nimport {\n Reactive,\n ChangeInput,\n Changes,\n Operations,\n asBase,\n} from \"@derivation/composable\";\nimport { Source, Sink } from \"./stream-types.js\";\nimport { Iso } from \"./iso.js\";\n\nexport class ReactiveSourceAdapter<T> implements Source<Reactive<T>> {\n constructor(\n private readonly stream: Reactive<T>,\n private readonly snapshotIso: Iso<T, object>,\n private readonly changeIso: Iso<Changes<T>, object>,\n ) {}\n\n get Snapshot(): object {\n return this.snapshotIso.to(this.stream.snapshot);\n }\n\n get LastChange(): object | null {\n const change = this.stream.changes.value;\n if (change === null) return null;\n return this.changeIso.to(change);\n }\n\n get Stream(): Reactive<T> {\n return this.stream;\n }\n}\n\nexport class ReactiveSinkAdapter<T>\n implements Sink<Reactive<T>, ChangeInput<T>>\n{\n private readonly initialValue: T;\n\n constructor(\n private readonly graph: Graph,\n private readonly snapshotIso: Iso<T, object>,\n private readonly changeIso: Iso<Changes<T>, object>,\n private readonly ops: Operations<T>,\n snapshot: object,\n ) {\n this.initialValue = snapshotIso.from(snapshot);\n }\n\n apply(change: object, input: ChangeInput<T>): void {\n input.push(this.changeIso.from(change));\n }\n\n reset(snapshot: object, input: ChangeInput<T>): void {\n const snapshotValue = this.snapshotIso.from(snapshot);\n input.push(asBase(this.ops).replaceCommand(snapshotValue));\n }\n\n build(): { stream: Reactive<T>; input: ChangeInput<T> } {\n const ops = this.ops;\n const input = new ChangeInput<T>(this.graph, ops);\n const stream = Reactive.create(this.graph, ops, input, this.initialValue);\n return { stream, input };\n }\n}\n\nexport function sink<T>(\n graph: Graph,\n snapshotIso: Iso<T, object>,\n changeIso: Iso<Changes<T>, object>,\n ops: Operations<T>,\n): (snapshot: object) => Sink<Reactive<T>, ChangeInput<T>> {\n return (snapshot: object) => {\n return new ReactiveSinkAdapter<T>(\n graph,\n snapshotIso,\n changeIso,\n ops,\n snapshot,\n );\n };\n}\n","import { Graph, ReactiveValue, Input, inputValue } from \"derivation\";\nimport { Source, Sink } from \"./stream-types.js\";\nimport { Iso } from \"./iso.js\";\n\nexport class StreamSourceAdapter<T extends object> implements Source<ReactiveValue<T>> {\n private readonly iso: Iso<T, object>;\n\n constructor(private readonly stream: ReactiveValue<T>, iso: Iso<T, object>) {\n this.iso = iso;\n }\n\n get Snapshot(): object {\n return this.iso.to(this.stream.value);\n }\n\n get LastChange(): object | null {\n return this.iso.to(this.stream.value);\n }\n\n get Stream(): ReactiveValue<T> {\n return this.stream;\n }\n}\n\nexport class StreamSinkAdapter<T extends object> implements Sink<Input<T>, Input<T>> {\n private readonly graph: Graph;\n private readonly iso: Iso<T, object>;\n private readonly initialValue: T;\n\n constructor(graph: Graph, iso: Iso<T, object>, snapshot: object) {\n this.graph = graph;\n this.iso = iso;\n this.initialValue = iso.from(snapshot);\n }\n\n apply(change: object, input: Input<T>): void {\n input.push(this.iso.from(change));\n }\n\n reset(snapshot: object, input: Input<T>): void {\n input.push(this.iso.from(snapshot));\n }\n\n build(): { stream: Input<T>; input: Input<T> } {\n const stream = inputValue(this.graph, this.initialValue);\n return { stream, input: stream };\n }\n}\n\nexport function sink<T extends object>(graph: Graph, iso: Iso<T, object>): (snapshot: object) => Sink<Input<T>, Input<T>> {\n return (snapshot: object) => {\n return new StreamSinkAdapter<T>(graph, iso, snapshot);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAAA;AAAA;AAAA;;;ACCA,wBAMO;AAIA,IAAM,wBAAN,MAA8D;AAAA,EACnE,YACmB,QACA,aACA,WACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAEH,IAAI,WAAmB;AACrB,WAAO,KAAK,YAAY,GAAG,KAAK,OAAO,QAAQ;AAAA,EACjD;AAAA,EAEA,IAAI,aAA4B;AAC9B,UAAM,SAAS,KAAK,OAAO,QAAQ;AACnC,QAAI,WAAW,KAAM,QAAO;AAC5B,WAAO,KAAK,UAAU,GAAG,MAAM;AAAA,EACjC;AAAA,EAEA,IAAI,SAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AACF;AAEO,IAAM,sBAAN,MAEP;AAAA,EAGE,YACmB,OACA,aACA,WACA,KACjB,UACA;AALiB;AACA;AACA;AACA;AAGjB,SAAK,eAAe,YAAY,KAAK,QAAQ;AAAA,EAC/C;AAAA,EAEA,MAAM,QAAgB,OAA6B;AACjD,UAAM,KAAK,KAAK,UAAU,KAAK,MAAM,CAAC;AAAA,EACxC;AAAA,EAEA,MAAM,UAAkB,OAA6B;AACnD,UAAM,gBAAgB,KAAK,YAAY,KAAK,QAAQ;AACpD,UAAM,SAAK,0BAAO,KAAK,GAAG,EAAE,eAAe,aAAa,CAAC;AAAA,EAC3D;AAAA,EAEA,QAAwD;AACtD,UAAM,MAAM,KAAK;AACjB,UAAM,QAAQ,IAAI,8BAAe,KAAK,OAAO,GAAG;AAChD,UAAM,SAAS,2BAAS,OAAO,KAAK,OAAO,KAAK,OAAO,KAAK,YAAY;AACxE,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB;AACF;AAEO,SAAS,KACd,OACA,aACA,WACA,KACyD;AACzD,SAAO,CAAC,aAAqB;AAC3B,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AChFA,wBAAwD;AAIjD,IAAM,sBAAN,MAAgF;AAAA,EAGrF,YAA6B,QAA0B,KAAqB;AAA/C;AAC3B,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK;AAAA,EACtC;AAAA,EAEA,IAAI,aAA4B;AAC9B,WAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK;AAAA,EACtC;AAAA,EAEA,IAAI,SAA2B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AAEO,IAAM,oBAAN,MAA8E;AAAA,EAKnF,YAAY,OAAc,KAAqB,UAAkB;AAC/D,SAAK,QAAQ;AACb,SAAK,MAAM;AACX,SAAK,eAAe,IAAI,KAAK,QAAQ;AAAA,EACvC;AAAA,EAEA,MAAM,QAAgB,OAAuB;AAC3C,UAAM,KAAK,KAAK,IAAI,KAAK,MAAM,CAAC;AAAA,EAClC;AAAA,EAEA,MAAM,UAAkB,OAAuB;AAC7C,UAAM,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC;AAAA,EACpC;AAAA,EAEA,QAA+C;AAC7C,UAAM,aAAS,8BAAW,KAAK,OAAO,KAAK,YAAY;AACvD,WAAO,EAAE,QAAQ,OAAO,OAAO;AAAA,EACjC;AACF;AAEO,SAASC,MAAuB,OAAc,KAAqE;AACxH,SAAO,CAAC,aAAqB;AAC3B,WAAO,IAAI,kBAAqB,OAAO,KAAK,QAAQ;AAAA,EACtD;AACF;","names":["sink","sink"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as Sink, a as Source } from './stream-types-Q_EqNLtO.cjs';
2
- export { M as MutationDefinition, b as MutationDefinitions, c as MutationEndpoints, d as MutationResult, R as RPCDefinition, e as StreamDefinition, f as StreamDefinitions, g as StreamEndpoints, h as StreamSinks } from './stream-types-Q_EqNLtO.cjs';
1
+ import { S as Sink, a as Source } from './stream-types-Cn-LsIb9.cjs';
2
+ export { M as MutationDefinition, b as MutationDefinitions, c as MutationEndpoints, d as MutationResult, R as RPCDefinition, e as StreamDefinition, f as StreamDefinitions, g as StreamEndpoints, h as StreamSinks } from './stream-types-Cn-LsIb9.cjs';
3
3
  import { Graph, Input, ReactiveValue } from 'derivation';
4
4
  import { Reactive, ChangeInput, Changes, Operations } from '@derivation/composable';
5
5
  import { Iso } from './iso.cjs';
@@ -17,11 +17,13 @@ declare class ReactiveSourceAdapter<T> implements Source<Reactive<T>> {
17
17
  }
18
18
  declare class ReactiveSinkAdapter<T> implements Sink<Reactive<T>, ChangeInput<T>> {
19
19
  private readonly graph;
20
+ private readonly snapshotIso;
20
21
  private readonly changeIso;
21
22
  private readonly ops;
22
23
  private readonly initialValue;
23
24
  constructor(graph: Graph, snapshotIso: Iso<T, object>, changeIso: Iso<Changes<T>, object>, ops: Operations<T>, snapshot: object);
24
25
  apply(change: object, input: ChangeInput<T>): void;
26
+ reset(snapshot: object, input: ChangeInput<T>): void;
25
27
  build(): {
26
28
  stream: Reactive<T>;
27
29
  input: ChangeInput<T>;
@@ -43,6 +45,7 @@ declare class StreamSinkAdapter<T extends object> implements Sink<Input<T>, Inpu
43
45
  private readonly initialValue;
44
46
  constructor(graph: Graph, iso: Iso<T, object>, snapshot: object);
45
47
  apply(change: object, input: Input<T>): void;
48
+ reset(snapshot: object, input: Input<T>): void;
46
49
  build(): {
47
50
  stream: Input<T>;
48
51
  input: Input<T>;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as Sink, a as Source } from './stream-types-Q_EqNLtO.js';
2
- export { M as MutationDefinition, b as MutationDefinitions, c as MutationEndpoints, d as MutationResult, R as RPCDefinition, e as StreamDefinition, f as StreamDefinitions, g as StreamEndpoints, h as StreamSinks } from './stream-types-Q_EqNLtO.js';
1
+ import { S as Sink, a as Source } from './stream-types-Cn-LsIb9.js';
2
+ export { M as MutationDefinition, b as MutationDefinitions, c as MutationEndpoints, d as MutationResult, R as RPCDefinition, e as StreamDefinition, f as StreamDefinitions, g as StreamEndpoints, h as StreamSinks } from './stream-types-Cn-LsIb9.js';
3
3
  import { Graph, Input, ReactiveValue } from 'derivation';
4
4
  import { Reactive, ChangeInput, Changes, Operations } from '@derivation/composable';
5
5
  import { Iso } from './iso.js';
@@ -17,11 +17,13 @@ declare class ReactiveSourceAdapter<T> implements Source<Reactive<T>> {
17
17
  }
18
18
  declare class ReactiveSinkAdapter<T> implements Sink<Reactive<T>, ChangeInput<T>> {
19
19
  private readonly graph;
20
+ private readonly snapshotIso;
20
21
  private readonly changeIso;
21
22
  private readonly ops;
22
23
  private readonly initialValue;
23
24
  constructor(graph: Graph, snapshotIso: Iso<T, object>, changeIso: Iso<Changes<T>, object>, ops: Operations<T>, snapshot: object);
24
25
  apply(change: object, input: ChangeInput<T>): void;
26
+ reset(snapshot: object, input: ChangeInput<T>): void;
25
27
  build(): {
26
28
  stream: Reactive<T>;
27
29
  input: ChangeInput<T>;
@@ -43,6 +45,7 @@ declare class StreamSinkAdapter<T extends object> implements Sink<Input<T>, Inpu
43
45
  private readonly initialValue;
44
46
  constructor(graph: Graph, iso: Iso<T, object>, snapshot: object);
45
47
  apply(change: object, input: Input<T>): void;
48
+ reset(snapshot: object, input: Input<T>): void;
46
49
  build(): {
47
50
  stream: Input<T>;
48
51
  input: Input<T>;
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  // src/reactive-adapter.ts
2
2
  import {
3
3
  Reactive,
4
- ChangeInput
4
+ ChangeInput,
5
+ asBase
5
6
  } from "@derivation/composable";
6
7
  var ReactiveSourceAdapter = class {
7
8
  constructor(stream, snapshotIso, changeIso) {
@@ -24,6 +25,7 @@ var ReactiveSourceAdapter = class {
24
25
  var ReactiveSinkAdapter = class {
25
26
  constructor(graph, snapshotIso, changeIso, ops, snapshot) {
26
27
  this.graph = graph;
28
+ this.snapshotIso = snapshotIso;
27
29
  this.changeIso = changeIso;
28
30
  this.ops = ops;
29
31
  this.initialValue = snapshotIso.from(snapshot);
@@ -31,6 +33,10 @@ var ReactiveSinkAdapter = class {
31
33
  apply(change, input) {
32
34
  input.push(this.changeIso.from(change));
33
35
  }
36
+ reset(snapshot, input) {
37
+ const snapshotValue = this.snapshotIso.from(snapshot);
38
+ input.push(asBase(this.ops).replaceCommand(snapshotValue));
39
+ }
34
40
  build() {
35
41
  const ops = this.ops;
36
42
  const input = new ChangeInput(this.graph, ops);
@@ -76,6 +82,9 @@ var StreamSinkAdapter = class {
76
82
  apply(change, input) {
77
83
  input.push(this.iso.from(change));
78
84
  }
85
+ reset(snapshot, input) {
86
+ input.push(this.iso.from(snapshot));
87
+ }
79
88
  build() {
80
89
  const stream = inputValue(this.graph, this.initialValue);
81
90
  return { stream, input: stream };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/reactive-adapter.ts","../src/stream-adapter.ts"],"sourcesContent":["import { Graph } from \"derivation\";\nimport {\n Reactive,\n ChangeInput,\n Changes,\n OperationsBase,\n Operations,\n asBase,\n} from \"@derivation/composable\";\nimport { Source, Sink } from \"./stream-types.js\";\nimport { Iso } from \"./iso.js\";\n\nexport class ReactiveSourceAdapter<T> implements Source<Reactive<T>> {\n constructor(\n private readonly stream: Reactive<T>,\n private readonly snapshotIso: Iso<T, object>,\n private readonly changeIso: Iso<Changes<T>, object>,\n ) {}\n\n get Snapshot(): object {\n return this.snapshotIso.to(this.stream.snapshot);\n }\n\n get LastChange(): object | null {\n const change = this.stream.changes.value;\n if (change === null) return null;\n return this.changeIso.to(change);\n }\n\n get Stream(): Reactive<T> {\n return this.stream;\n }\n}\n\nexport class ReactiveSinkAdapter<T>\n implements Sink<Reactive<T>, ChangeInput<T>>\n{\n private readonly initialValue: T;\n\n constructor(\n private readonly graph: Graph,\n snapshotIso: Iso<T, object>,\n private readonly changeIso: Iso<Changes<T>, object>,\n private readonly ops: Operations<T>,\n snapshot: object,\n ) {\n this.initialValue = snapshotIso.from(snapshot);\n }\n\n apply(change: object, input: ChangeInput<T>): void {\n input.push(this.changeIso.from(change));\n }\n\n build(): { stream: Reactive<T>; input: ChangeInput<T> } {\n const ops = this.ops;\n const input = new ChangeInput<T>(this.graph, ops);\n const stream = Reactive.create(this.graph, ops, input, this.initialValue);\n return { stream, input };\n }\n}\n\nexport function sink<T>(\n graph: Graph,\n snapshotIso: Iso<T, object>,\n changeIso: Iso<Changes<T>, object>,\n ops: Operations<T>,\n): (snapshot: object) => Sink<Reactive<T>, ChangeInput<T>> {\n return (snapshot: object) => {\n return new ReactiveSinkAdapter<T>(\n graph,\n snapshotIso,\n changeIso,\n ops,\n snapshot,\n );\n };\n}\n","import { Graph, ReactiveValue, Input, inputValue } from \"derivation\";\nimport { Source, Sink } from \"./stream-types.js\";\nimport { Iso } from \"./iso.js\";\n\nexport class StreamSourceAdapter<T extends object> implements Source<ReactiveValue<T>> {\n private readonly iso: Iso<T, object>;\n\n constructor(private readonly stream: ReactiveValue<T>, iso: Iso<T, object>) {\n this.iso = iso;\n }\n\n get Snapshot(): object {\n return this.iso.to(this.stream.value);\n }\n\n get LastChange(): object | null {\n return this.iso.to(this.stream.value);\n }\n\n get Stream(): ReactiveValue<T> {\n return this.stream;\n }\n}\n\nexport class StreamSinkAdapter<T extends object> implements Sink<Input<T>, Input<T>> {\n private readonly graph: Graph;\n private readonly iso: Iso<T, object>;\n private readonly initialValue: T;\n\n constructor(graph: Graph, iso: Iso<T, object>, snapshot: object) {\n this.graph = graph;\n this.iso = iso;\n this.initialValue = iso.from(snapshot);\n }\n\n apply(change: object, input: Input<T>): void {\n input.push(this.iso.from(change));\n }\n\n build(): { stream: Input<T>; input: Input<T> } {\n const stream = inputValue(this.graph, this.initialValue);\n return { stream, input: stream };\n }\n}\n\nexport function sink<T extends object>(graph: Graph, iso: Iso<T, object>): (snapshot: object) => Sink<Input<T>, Input<T>> {\n return (snapshot: object) => {\n return new StreamSinkAdapter<T>(graph, iso, snapshot);\n };\n}\n"],"mappings":";AACA;AAAA,EACE;AAAA,EACA;AAAA,OAKK;AAIA,IAAM,wBAAN,MAA8D;AAAA,EACnE,YACmB,QACA,aACA,WACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAEH,IAAI,WAAmB;AACrB,WAAO,KAAK,YAAY,GAAG,KAAK,OAAO,QAAQ;AAAA,EACjD;AAAA,EAEA,IAAI,aAA4B;AAC9B,UAAM,SAAS,KAAK,OAAO,QAAQ;AACnC,QAAI,WAAW,KAAM,QAAO;AAC5B,WAAO,KAAK,UAAU,GAAG,MAAM;AAAA,EACjC;AAAA,EAEA,IAAI,SAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AACF;AAEO,IAAM,sBAAN,MAEP;AAAA,EAGE,YACmB,OACjB,aACiB,WACA,KACjB,UACA;AALiB;AAEA;AACA;AAGjB,SAAK,eAAe,YAAY,KAAK,QAAQ;AAAA,EAC/C;AAAA,EAEA,MAAM,QAAgB,OAA6B;AACjD,UAAM,KAAK,KAAK,UAAU,KAAK,MAAM,CAAC;AAAA,EACxC;AAAA,EAEA,QAAwD;AACtD,UAAM,MAAM,KAAK;AACjB,UAAM,QAAQ,IAAI,YAAe,KAAK,OAAO,GAAG;AAChD,UAAM,SAAS,SAAS,OAAO,KAAK,OAAO,KAAK,OAAO,KAAK,YAAY;AACxE,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB;AACF;AAEO,SAAS,KACd,OACA,aACA,WACA,KACyD;AACzD,SAAO,CAAC,aAAqB;AAC3B,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AC5EA,SAAsC,kBAAkB;AAIjD,IAAM,sBAAN,MAAgF;AAAA,EAGrF,YAA6B,QAA0B,KAAqB;AAA/C;AAC3B,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK;AAAA,EACtC;AAAA,EAEA,IAAI,aAA4B;AAC9B,WAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK;AAAA,EACtC;AAAA,EAEA,IAAI,SAA2B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AAEO,IAAM,oBAAN,MAA8E;AAAA,EAKnF,YAAY,OAAc,KAAqB,UAAkB;AAC/D,SAAK,QAAQ;AACb,SAAK,MAAM;AACX,SAAK,eAAe,IAAI,KAAK,QAAQ;AAAA,EACvC;AAAA,EAEA,MAAM,QAAgB,OAAuB;AAC3C,UAAM,KAAK,KAAK,IAAI,KAAK,MAAM,CAAC;AAAA,EAClC;AAAA,EAEA,QAA+C;AAC7C,UAAM,SAAS,WAAW,KAAK,OAAO,KAAK,YAAY;AACvD,WAAO,EAAE,QAAQ,OAAO,OAAO;AAAA,EACjC;AACF;AAEO,SAASA,MAAuB,OAAc,KAAqE;AACxH,SAAO,CAAC,aAAqB;AAC3B,WAAO,IAAI,kBAAqB,OAAO,KAAK,QAAQ;AAAA,EACtD;AACF;","names":["sink"]}
1
+ {"version":3,"sources":["../src/reactive-adapter.ts","../src/stream-adapter.ts"],"sourcesContent":["import { Graph } from \"derivation\";\nimport {\n Reactive,\n ChangeInput,\n Changes,\n Operations,\n asBase,\n} from \"@derivation/composable\";\nimport { Source, Sink } from \"./stream-types.js\";\nimport { Iso } from \"./iso.js\";\n\nexport class ReactiveSourceAdapter<T> implements Source<Reactive<T>> {\n constructor(\n private readonly stream: Reactive<T>,\n private readonly snapshotIso: Iso<T, object>,\n private readonly changeIso: Iso<Changes<T>, object>,\n ) {}\n\n get Snapshot(): object {\n return this.snapshotIso.to(this.stream.snapshot);\n }\n\n get LastChange(): object | null {\n const change = this.stream.changes.value;\n if (change === null) return null;\n return this.changeIso.to(change);\n }\n\n get Stream(): Reactive<T> {\n return this.stream;\n }\n}\n\nexport class ReactiveSinkAdapter<T>\n implements Sink<Reactive<T>, ChangeInput<T>>\n{\n private readonly initialValue: T;\n\n constructor(\n private readonly graph: Graph,\n private readonly snapshotIso: Iso<T, object>,\n private readonly changeIso: Iso<Changes<T>, object>,\n private readonly ops: Operations<T>,\n snapshot: object,\n ) {\n this.initialValue = snapshotIso.from(snapshot);\n }\n\n apply(change: object, input: ChangeInput<T>): void {\n input.push(this.changeIso.from(change));\n }\n\n reset(snapshot: object, input: ChangeInput<T>): void {\n const snapshotValue = this.snapshotIso.from(snapshot);\n input.push(asBase(this.ops).replaceCommand(snapshotValue));\n }\n\n build(): { stream: Reactive<T>; input: ChangeInput<T> } {\n const ops = this.ops;\n const input = new ChangeInput<T>(this.graph, ops);\n const stream = Reactive.create(this.graph, ops, input, this.initialValue);\n return { stream, input };\n }\n}\n\nexport function sink<T>(\n graph: Graph,\n snapshotIso: Iso<T, object>,\n changeIso: Iso<Changes<T>, object>,\n ops: Operations<T>,\n): (snapshot: object) => Sink<Reactive<T>, ChangeInput<T>> {\n return (snapshot: object) => {\n return new ReactiveSinkAdapter<T>(\n graph,\n snapshotIso,\n changeIso,\n ops,\n snapshot,\n );\n };\n}\n","import { Graph, ReactiveValue, Input, inputValue } from \"derivation\";\nimport { Source, Sink } from \"./stream-types.js\";\nimport { Iso } from \"./iso.js\";\n\nexport class StreamSourceAdapter<T extends object> implements Source<ReactiveValue<T>> {\n private readonly iso: Iso<T, object>;\n\n constructor(private readonly stream: ReactiveValue<T>, iso: Iso<T, object>) {\n this.iso = iso;\n }\n\n get Snapshot(): object {\n return this.iso.to(this.stream.value);\n }\n\n get LastChange(): object | null {\n return this.iso.to(this.stream.value);\n }\n\n get Stream(): ReactiveValue<T> {\n return this.stream;\n }\n}\n\nexport class StreamSinkAdapter<T extends object> implements Sink<Input<T>, Input<T>> {\n private readonly graph: Graph;\n private readonly iso: Iso<T, object>;\n private readonly initialValue: T;\n\n constructor(graph: Graph, iso: Iso<T, object>, snapshot: object) {\n this.graph = graph;\n this.iso = iso;\n this.initialValue = iso.from(snapshot);\n }\n\n apply(change: object, input: Input<T>): void {\n input.push(this.iso.from(change));\n }\n\n reset(snapshot: object, input: Input<T>): void {\n input.push(this.iso.from(snapshot));\n }\n\n build(): { stream: Input<T>; input: Input<T> } {\n const stream = inputValue(this.graph, this.initialValue);\n return { stream, input: stream };\n }\n}\n\nexport function sink<T extends object>(graph: Graph, iso: Iso<T, object>): (snapshot: object) => Sink<Input<T>, Input<T>> {\n return (snapshot: object) => {\n return new StreamSinkAdapter<T>(graph, iso, snapshot);\n };\n}\n"],"mappings":";AACA;AAAA,EACE;AAAA,EACA;AAAA,EAGA;AAAA,OACK;AAIA,IAAM,wBAAN,MAA8D;AAAA,EACnE,YACmB,QACA,aACA,WACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAEH,IAAI,WAAmB;AACrB,WAAO,KAAK,YAAY,GAAG,KAAK,OAAO,QAAQ;AAAA,EACjD;AAAA,EAEA,IAAI,aAA4B;AAC9B,UAAM,SAAS,KAAK,OAAO,QAAQ;AACnC,QAAI,WAAW,KAAM,QAAO;AAC5B,WAAO,KAAK,UAAU,GAAG,MAAM;AAAA,EACjC;AAAA,EAEA,IAAI,SAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AACF;AAEO,IAAM,sBAAN,MAEP;AAAA,EAGE,YACmB,OACA,aACA,WACA,KACjB,UACA;AALiB;AACA;AACA;AACA;AAGjB,SAAK,eAAe,YAAY,KAAK,QAAQ;AAAA,EAC/C;AAAA,EAEA,MAAM,QAAgB,OAA6B;AACjD,UAAM,KAAK,KAAK,UAAU,KAAK,MAAM,CAAC;AAAA,EACxC;AAAA,EAEA,MAAM,UAAkB,OAA6B;AACnD,UAAM,gBAAgB,KAAK,YAAY,KAAK,QAAQ;AACpD,UAAM,KAAK,OAAO,KAAK,GAAG,EAAE,eAAe,aAAa,CAAC;AAAA,EAC3D;AAAA,EAEA,QAAwD;AACtD,UAAM,MAAM,KAAK;AACjB,UAAM,QAAQ,IAAI,YAAe,KAAK,OAAO,GAAG;AAChD,UAAM,SAAS,SAAS,OAAO,KAAK,OAAO,KAAK,OAAO,KAAK,YAAY;AACxE,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB;AACF;AAEO,SAAS,KACd,OACA,aACA,WACA,KACyD;AACzD,SAAO,CAAC,aAAqB;AAC3B,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AChFA,SAAsC,kBAAkB;AAIjD,IAAM,sBAAN,MAAgF;AAAA,EAGrF,YAA6B,QAA0B,KAAqB;AAA/C;AAC3B,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK;AAAA,EACtC;AAAA,EAEA,IAAI,aAA4B;AAC9B,WAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK;AAAA,EACtC;AAAA,EAEA,IAAI,SAA2B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AAEO,IAAM,oBAAN,MAA8E;AAAA,EAKnF,YAAY,OAAc,KAAqB,UAAkB;AAC/D,SAAK,QAAQ;AACb,SAAK,MAAM;AACX,SAAK,eAAe,IAAI,KAAK,QAAQ;AAAA,EACvC;AAAA,EAEA,MAAM,QAAgB,OAAuB;AAC3C,UAAM,KAAK,KAAK,IAAI,KAAK,MAAM,CAAC;AAAA,EAClC;AAAA,EAEA,MAAM,UAAkB,OAAuB;AAC7C,UAAM,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC;AAAA,EACpC;AAAA,EAEA,QAA+C;AAC7C,UAAM,SAAS,WAAW,KAAK,OAAO,KAAK,YAAY;AACvD,WAAO,EAAE,QAAQ,OAAO,OAAO;AAAA,EACjC;AACF;AAEO,SAASA,MAAuB,OAAc,KAAqE;AACxH,SAAO,CAAC,aAAqB;AAC3B,WAAO,IAAI,kBAAqB,OAAO,KAAK,QAAQ;AAAA,EACtD;AACF;","names":["sink"]}
package/dist/iso.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var iso_exports = {};
22
22
  __export(iso_exports, {
23
23
  array: () => array,
24
+ cellIso: () => cellIso,
24
25
  compose: () => compose,
25
26
  flip: () => flip,
26
27
  id: () => id,
@@ -38,6 +39,7 @@ __export(iso_exports, {
38
39
  module.exports = __toCommonJS(iso_exports);
39
40
  var import_immutable = require("immutable");
40
41
  var import_immutable2 = require("immutable");
42
+ var import_composable = require("@derivation/composable");
41
43
  function id() {
42
44
  return {
43
45
  to: (x) => x,
@@ -131,9 +133,16 @@ function immutableMap(keyIso, valueIso) {
131
133
  }
132
134
  };
133
135
  }
136
+ function cellIso(valueIso) {
137
+ return {
138
+ to: (cell) => valueIso.to(cell.value),
139
+ from: (value) => new import_composable.Cell(valueIso.from(value))
140
+ };
141
+ }
134
142
  // Annotate the CommonJS export names for ESM import in node:
135
143
  0 && (module.exports = {
136
144
  array,
145
+ cellIso,
137
146
  compose,
138
147
  flip,
139
148
  id,
package/dist/iso.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/iso.ts"],"sourcesContent":["import { Record as ImmutableRecord, RecordOf } from \"immutable\";\nimport { List, Set as ImmutableSet, Map as ImmutableMap } from \"immutable\";\n\nexport interface Iso<In, Out> {\n to(x: In): Out;\n from(x: Out): In;\n}\n\nexport function id<A>(): Iso<A, A> {\n return {\n to: (x: A) => x,\n from: (x: A) => x,\n };\n}\n\nexport function unknown<A>(): Iso<A, unknown> {\n return {\n to: (x: A) => x,\n from: (x: unknown) => x as A,\n };\n}\n\nexport function flip<A, B>(iso: Iso<A, B>): Iso<B, A> {\n return {\n to: (x: B) => iso.from(x),\n from: (x: A) => iso.to(x),\n };\n}\n\nexport function compose<A, B, C>(\n first: Iso<A, B>,\n second: Iso<B, C>,\n): Iso<A, C> {\n return {\n to: (x: A) => second.to(first.to(x)),\n from: (x: C) => first.from(second.from(x)),\n };\n}\n\nexport function array<A, B>(itemIso: Iso<A, B>): Iso<Array<A>, Array<B>> {\n return {\n to: (xs: Array<A>) => xs.map(itemIso.to),\n from: (xs: Array<B>) => xs.map(itemIso.from),\n };\n}\n\n\nexport type IsoIn<T> = T extends Iso<infer A, unknown> ? A : never;\nexport type IsoOut<T> = T extends Iso<unknown, infer B> ? B : never;\n\ntype ObjectIsos = Record<string, Iso<unknown, unknown>>;\ntype ObjectIn<T extends ObjectIsos> = { [K in keyof T]: IsoIn<T[K]> };\ntype ObjectOut<T extends ObjectIsos> = { [K in keyof T]: IsoOut<T[K]> };\n\nexport function object<T extends ObjectIsos>(\n spec: T,\n): Iso<ObjectIn<T>, ObjectOut<T>> {\n return {\n to: (x) => {\n const result = {} as ObjectOut<T>;\n for (const key in spec) {\n result[key] = spec[key].to(x[key]) as IsoOut<\n T[Extract<keyof T, string>]\n >;\n }\n return result;\n },\n from: (x) => {\n const result = {} as ObjectIn<T>;\n for (const key in spec) {\n result[key] = spec[key].from(x[key]) as IsoIn<\n T[Extract<keyof T, string>]\n >;\n }\n return result;\n },\n };\n}\n\nexport function shallowRecord<T extends Record<string, unknown>>(): Iso<\n RecordOf<T>,\n T\n> {\n return {\n to: (x: RecordOf<T>): T => x.toObject(),\n from: (x: T): RecordOf<T> => ImmutableRecord<T>(x)(x),\n };\n}\n\nexport function record<T extends ObjectIsos>(\n spec: T,\n): Iso<RecordOf<ObjectIn<T>>, ObjectOut<T>> {\n return compose(shallowRecord(), object(spec));\n}\n\ntype TupleIsos = Array<Iso<unknown, unknown>>;\ntype TupleIn<T extends TupleIsos> = { [K in keyof T]: IsoIn<T[K]> };\ntype TupleOut<T extends TupleIsos> = { [K in keyof T]: IsoOut<T[K]> };\n\nexport function tuple<T extends TupleIsos>(\n ...isos: T\n): Iso<TupleIn<T>, TupleOut<T>> {\n return {\n to: (x) => x.map((xi, i) => isos[i].to(xi)) as TupleOut<T>,\n from: (x) => x.map((xi, i) => isos[i].from(xi)) as TupleIn<T>,\n };\n}\n\nexport function map<K, V, K2, V2>(\n keyIso: Iso<K, K2>,\n valueIso: Iso<V, V2>,\n): Iso<Map<K, V>, Array<[K2, V2]>> {\n return {\n to: (m) => [...m.entries()].map(([k, v]) => [keyIso.to(k), valueIso.to(v)]),\n from: (entries) =>\n new Map(entries.map(([k, v]) => [keyIso.from(k), valueIso.from(v)])),\n };\n}\n\n\n/**\n * A shallow isomorphism between an Immutable.js List and a standard Array.\n */\nexport function shallowList<A>(): Iso<List<A>, Array<A>> {\n return {\n to: (x: List<A>): Array<A> => x.toArray(),\n from: (x: Array<A>): List<A> => List(x),\n };\n}\n\n/**\n * A deep isomorphism that converts a List to an Array and\n * applies an itemIso to every element.\n */\nexport function list<A, B>(itemIso: Iso<A, B>): Iso<List<A>, Array<B>> {\n return compose(shallowList<A>(), array(itemIso));\n}\n\n/**\n * Deep conversion: ImmutableSet<A> <-> Array<B>\n * Note: Converting to Array is usually safer for serialization than native Set.\n */\nexport function immutableSet<A, B>(\n itemIso: Iso<A, B>,\n): Iso<ImmutableSet<A>, Array<B>> {\n return {\n to: (xs: ImmutableSet<A>) => xs.toArray().map(itemIso.to),\n from: (xs: Array<B>) => ImmutableSet(xs.map(itemIso.from)),\n };\n}\n\n/**\n * Deep conversion: ImmutableMap<K, V> <-> Array<[K2, V2]>\n */\nexport function immutableMap<K, V, K2, V2>(\n keyIso: Iso<K, K2>,\n valueIso: Iso<V, V2>,\n): Iso<ImmutableMap<K, V>, Array<[K2, V2]>> {\n const entryIso = tuple(keyIso, valueIso);\n return {\n to: (m) =>\n m\n .entrySeq()\n .toArray()\n .map((e) => entryIso.to([...e] as [K, V])),\n from: (entries) => {\n return ImmutableMap(entries.map((e) => entryIso.from(e)));\n },\n };\n}\n"],"mappings":"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","names":["import_immutable","ImmutableRecord","ImmutableSet","ImmutableMap"]}
1
+ {"version":3,"sources":["../src/iso.ts"],"sourcesContent":["import { Record as ImmutableRecord, RecordOf } from \"immutable\";\nimport { List, Set as ImmutableSet, Map as ImmutableMap } from \"immutable\";\nimport { Cell } from \"@derivation/composable\";\n\nexport interface Iso<In, Out> {\n to(x: In): Out;\n from(x: Out): In;\n}\n\nexport function id<A>(): Iso<A, A> {\n return {\n to: (x: A) => x,\n from: (x: A) => x,\n };\n}\n\nexport function unknown<A>(): Iso<A, unknown> {\n return {\n to: (x: A) => x,\n from: (x: unknown) => x as A,\n };\n}\n\nexport function flip<A, B>(iso: Iso<A, B>): Iso<B, A> {\n return {\n to: (x: B) => iso.from(x),\n from: (x: A) => iso.to(x),\n };\n}\n\nexport function compose<A, B, C>(\n first: Iso<A, B>,\n second: Iso<B, C>,\n): Iso<A, C> {\n return {\n to: (x: A) => second.to(first.to(x)),\n from: (x: C) => first.from(second.from(x)),\n };\n}\n\nexport function array<A, B>(itemIso: Iso<A, B>): Iso<Array<A>, Array<B>> {\n return {\n to: (xs: Array<A>) => xs.map(itemIso.to),\n from: (xs: Array<B>) => xs.map(itemIso.from),\n };\n}\n\n\nexport type IsoIn<T> = T extends Iso<infer A, unknown> ? A : never;\nexport type IsoOut<T> = T extends Iso<unknown, infer B> ? B : never;\n\ntype ObjectIsos = Record<string, Iso<unknown, unknown>>;\ntype ObjectIn<T extends ObjectIsos> = { [K in keyof T]: IsoIn<T[K]> };\ntype ObjectOut<T extends ObjectIsos> = { [K in keyof T]: IsoOut<T[K]> };\n\nexport function object<T extends ObjectIsos>(\n spec: T,\n): Iso<ObjectIn<T>, ObjectOut<T>> {\n return {\n to: (x) => {\n const result = {} as ObjectOut<T>;\n for (const key in spec) {\n result[key] = spec[key].to(x[key]) as IsoOut<\n T[Extract<keyof T, string>]\n >;\n }\n return result;\n },\n from: (x) => {\n const result = {} as ObjectIn<T>;\n for (const key in spec) {\n result[key] = spec[key].from(x[key]) as IsoIn<\n T[Extract<keyof T, string>]\n >;\n }\n return result;\n },\n };\n}\n\nexport function shallowRecord<T extends Record<string, unknown>>(): Iso<\n RecordOf<T>,\n T\n> {\n return {\n to: (x: RecordOf<T>): T => x.toObject(),\n from: (x: T): RecordOf<T> => ImmutableRecord<T>(x)(x),\n };\n}\n\nexport function record<T extends ObjectIsos>(\n spec: T,\n): Iso<RecordOf<ObjectIn<T>>, ObjectOut<T>> {\n return compose(shallowRecord(), object(spec));\n}\n\ntype TupleIsos = Array<Iso<unknown, unknown>>;\ntype TupleIn<T extends TupleIsos> = { [K in keyof T]: IsoIn<T[K]> };\ntype TupleOut<T extends TupleIsos> = { [K in keyof T]: IsoOut<T[K]> };\n\nexport function tuple<T extends TupleIsos>(\n ...isos: T\n): Iso<TupleIn<T>, TupleOut<T>> {\n return {\n to: (x) => x.map((xi, i) => isos[i].to(xi)) as TupleOut<T>,\n from: (x) => x.map((xi, i) => isos[i].from(xi)) as TupleIn<T>,\n };\n}\n\nexport function map<K, V, K2, V2>(\n keyIso: Iso<K, K2>,\n valueIso: Iso<V, V2>,\n): Iso<Map<K, V>, Array<[K2, V2]>> {\n return {\n to: (m) => [...m.entries()].map(([k, v]) => [keyIso.to(k), valueIso.to(v)]),\n from: (entries) =>\n new Map(entries.map(([k, v]) => [keyIso.from(k), valueIso.from(v)])),\n };\n}\n\n\n/**\n * A shallow isomorphism between an Immutable.js List and a standard Array.\n */\nexport function shallowList<A>(): Iso<List<A>, Array<A>> {\n return {\n to: (x: List<A>): Array<A> => x.toArray(),\n from: (x: Array<A>): List<A> => List(x),\n };\n}\n\n/**\n * A deep isomorphism that converts a List to an Array and\n * applies an itemIso to every element.\n */\nexport function list<A, B>(itemIso: Iso<A, B>): Iso<List<A>, Array<B>> {\n return compose(shallowList<A>(), array(itemIso));\n}\n\n/**\n * Deep conversion: ImmutableSet<A> <-> Array<B>\n * Note: Converting to Array is usually safer for serialization than native Set.\n */\nexport function immutableSet<A, B>(\n itemIso: Iso<A, B>,\n): Iso<ImmutableSet<A>, Array<B>> {\n return {\n to: (xs: ImmutableSet<A>) => xs.toArray().map(itemIso.to),\n from: (xs: Array<B>) => ImmutableSet(xs.map(itemIso.from)),\n };\n}\n\n/**\n * Deep conversion: ImmutableMap<K, V> <-> Array<[K2, V2]>\n */\nexport function immutableMap<K, V, K2, V2>(\n keyIso: Iso<K, K2>,\n valueIso: Iso<V, V2>,\n): Iso<ImmutableMap<K, V>, Array<[K2, V2]>> {\n const entryIso = tuple(keyIso, valueIso);\n return {\n to: (m) =>\n m\n .entrySeq()\n .toArray()\n .map((e) => entryIso.to([...e] as [K, V])),\n from: (entries) => {\n return ImmutableMap(entries.map((e) => entryIso.from(e)));\n },\n };\n}\n\n/**\n * Deep conversion: Cell<A> <-> B\n */\nexport function cellIso<A extends NonNullable<unknown>, B>(\n valueIso: Iso<A, B>,\n): Iso<Cell<A>, B> {\n return {\n to: (cell: Cell<A>) => valueIso.to(cell.value),\n from: (value: B) => new Cell(valueIso.from(value)),\n };\n}\n"],"mappings":"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","names":["import_immutable","ImmutableRecord","ImmutableSet","ImmutableMap"]}
package/dist/iso.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Map as Map$1, Set, List, RecordOf } from 'immutable';
2
+ import { Cell } from '@derivation/composable';
2
3
 
3
4
  interface Iso<In, Out> {
4
5
  to(x: In): Out;
@@ -48,5 +49,9 @@ declare function immutableSet<A, B>(itemIso: Iso<A, B>): Iso<Set<A>, Array<B>>;
48
49
  * Deep conversion: ImmutableMap<K, V> <-> Array<[K2, V2]>
49
50
  */
50
51
  declare function immutableMap<K, V, K2, V2>(keyIso: Iso<K, K2>, valueIso: Iso<V, V2>): Iso<Map$1<K, V>, Array<[K2, V2]>>;
52
+ /**
53
+ * Deep conversion: Cell<A> <-> B
54
+ */
55
+ declare function cellIso<A extends NonNullable<unknown>, B>(valueIso: Iso<A, B>): Iso<Cell<A>, B>;
51
56
 
52
- export { type Iso, type IsoIn, type IsoOut, array, compose, flip, id, immutableMap, immutableSet, list, map, object, record, shallowList, shallowRecord, tuple, unknown };
57
+ export { type Iso, type IsoIn, type IsoOut, array, cellIso, compose, flip, id, immutableMap, immutableSet, list, map, object, record, shallowList, shallowRecord, tuple, unknown };
package/dist/iso.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Map as Map$1, Set, List, RecordOf } from 'immutable';
2
+ import { Cell } from '@derivation/composable';
2
3
 
3
4
  interface Iso<In, Out> {
4
5
  to(x: In): Out;
@@ -48,5 +49,9 @@ declare function immutableSet<A, B>(itemIso: Iso<A, B>): Iso<Set<A>, Array<B>>;
48
49
  * Deep conversion: ImmutableMap<K, V> <-> Array<[K2, V2]>
49
50
  */
50
51
  declare function immutableMap<K, V, K2, V2>(keyIso: Iso<K, K2>, valueIso: Iso<V, V2>): Iso<Map$1<K, V>, Array<[K2, V2]>>;
52
+ /**
53
+ * Deep conversion: Cell<A> <-> B
54
+ */
55
+ declare function cellIso<A extends NonNullable<unknown>, B>(valueIso: Iso<A, B>): Iso<Cell<A>, B>;
51
56
 
52
- export { type Iso, type IsoIn, type IsoOut, array, compose, flip, id, immutableMap, immutableSet, list, map, object, record, shallowList, shallowRecord, tuple, unknown };
57
+ export { type Iso, type IsoIn, type IsoOut, array, cellIso, compose, flip, id, immutableMap, immutableSet, list, map, object, record, shallowList, shallowRecord, tuple, unknown };
package/dist/iso.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // src/iso.ts
2
2
  import { Record as ImmutableRecord } from "immutable";
3
3
  import { List, Set as ImmutableSet, Map as ImmutableMap } from "immutable";
4
+ import { Cell } from "@derivation/composable";
4
5
  function id() {
5
6
  return {
6
7
  to: (x) => x,
@@ -94,8 +95,15 @@ function immutableMap(keyIso, valueIso) {
94
95
  }
95
96
  };
96
97
  }
98
+ function cellIso(valueIso) {
99
+ return {
100
+ to: (cell) => valueIso.to(cell.value),
101
+ from: (value) => new Cell(valueIso.from(value))
102
+ };
103
+ }
97
104
  export {
98
105
  array,
106
+ cellIso,
99
107
  compose,
100
108
  flip,
101
109
  id,
package/dist/iso.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/iso.ts"],"sourcesContent":["import { Record as ImmutableRecord, RecordOf } from \"immutable\";\nimport { List, Set as ImmutableSet, Map as ImmutableMap } from \"immutable\";\n\nexport interface Iso<In, Out> {\n to(x: In): Out;\n from(x: Out): In;\n}\n\nexport function id<A>(): Iso<A, A> {\n return {\n to: (x: A) => x,\n from: (x: A) => x,\n };\n}\n\nexport function unknown<A>(): Iso<A, unknown> {\n return {\n to: (x: A) => x,\n from: (x: unknown) => x as A,\n };\n}\n\nexport function flip<A, B>(iso: Iso<A, B>): Iso<B, A> {\n return {\n to: (x: B) => iso.from(x),\n from: (x: A) => iso.to(x),\n };\n}\n\nexport function compose<A, B, C>(\n first: Iso<A, B>,\n second: Iso<B, C>,\n): Iso<A, C> {\n return {\n to: (x: A) => second.to(first.to(x)),\n from: (x: C) => first.from(second.from(x)),\n };\n}\n\nexport function array<A, B>(itemIso: Iso<A, B>): Iso<Array<A>, Array<B>> {\n return {\n to: (xs: Array<A>) => xs.map(itemIso.to),\n from: (xs: Array<B>) => xs.map(itemIso.from),\n };\n}\n\n\nexport type IsoIn<T> = T extends Iso<infer A, unknown> ? A : never;\nexport type IsoOut<T> = T extends Iso<unknown, infer B> ? B : never;\n\ntype ObjectIsos = Record<string, Iso<unknown, unknown>>;\ntype ObjectIn<T extends ObjectIsos> = { [K in keyof T]: IsoIn<T[K]> };\ntype ObjectOut<T extends ObjectIsos> = { [K in keyof T]: IsoOut<T[K]> };\n\nexport function object<T extends ObjectIsos>(\n spec: T,\n): Iso<ObjectIn<T>, ObjectOut<T>> {\n return {\n to: (x) => {\n const result = {} as ObjectOut<T>;\n for (const key in spec) {\n result[key] = spec[key].to(x[key]) as IsoOut<\n T[Extract<keyof T, string>]\n >;\n }\n return result;\n },\n from: (x) => {\n const result = {} as ObjectIn<T>;\n for (const key in spec) {\n result[key] = spec[key].from(x[key]) as IsoIn<\n T[Extract<keyof T, string>]\n >;\n }\n return result;\n },\n };\n}\n\nexport function shallowRecord<T extends Record<string, unknown>>(): Iso<\n RecordOf<T>,\n T\n> {\n return {\n to: (x: RecordOf<T>): T => x.toObject(),\n from: (x: T): RecordOf<T> => ImmutableRecord<T>(x)(x),\n };\n}\n\nexport function record<T extends ObjectIsos>(\n spec: T,\n): Iso<RecordOf<ObjectIn<T>>, ObjectOut<T>> {\n return compose(shallowRecord(), object(spec));\n}\n\ntype TupleIsos = Array<Iso<unknown, unknown>>;\ntype TupleIn<T extends TupleIsos> = { [K in keyof T]: IsoIn<T[K]> };\ntype TupleOut<T extends TupleIsos> = { [K in keyof T]: IsoOut<T[K]> };\n\nexport function tuple<T extends TupleIsos>(\n ...isos: T\n): Iso<TupleIn<T>, TupleOut<T>> {\n return {\n to: (x) => x.map((xi, i) => isos[i].to(xi)) as TupleOut<T>,\n from: (x) => x.map((xi, i) => isos[i].from(xi)) as TupleIn<T>,\n };\n}\n\nexport function map<K, V, K2, V2>(\n keyIso: Iso<K, K2>,\n valueIso: Iso<V, V2>,\n): Iso<Map<K, V>, Array<[K2, V2]>> {\n return {\n to: (m) => [...m.entries()].map(([k, v]) => [keyIso.to(k), valueIso.to(v)]),\n from: (entries) =>\n new Map(entries.map(([k, v]) => [keyIso.from(k), valueIso.from(v)])),\n };\n}\n\n\n/**\n * A shallow isomorphism between an Immutable.js List and a standard Array.\n */\nexport function shallowList<A>(): Iso<List<A>, Array<A>> {\n return {\n to: (x: List<A>): Array<A> => x.toArray(),\n from: (x: Array<A>): List<A> => List(x),\n };\n}\n\n/**\n * A deep isomorphism that converts a List to an Array and\n * applies an itemIso to every element.\n */\nexport function list<A, B>(itemIso: Iso<A, B>): Iso<List<A>, Array<B>> {\n return compose(shallowList<A>(), array(itemIso));\n}\n\n/**\n * Deep conversion: ImmutableSet<A> <-> Array<B>\n * Note: Converting to Array is usually safer for serialization than native Set.\n */\nexport function immutableSet<A, B>(\n itemIso: Iso<A, B>,\n): Iso<ImmutableSet<A>, Array<B>> {\n return {\n to: (xs: ImmutableSet<A>) => xs.toArray().map(itemIso.to),\n from: (xs: Array<B>) => ImmutableSet(xs.map(itemIso.from)),\n };\n}\n\n/**\n * Deep conversion: ImmutableMap<K, V> <-> Array<[K2, V2]>\n */\nexport function immutableMap<K, V, K2, V2>(\n keyIso: Iso<K, K2>,\n valueIso: Iso<V, V2>,\n): Iso<ImmutableMap<K, V>, Array<[K2, V2]>> {\n const entryIso = tuple(keyIso, valueIso);\n return {\n to: (m) =>\n m\n .entrySeq()\n .toArray()\n .map((e) => entryIso.to([...e] as [K, V])),\n from: (entries) => {\n return ImmutableMap(entries.map((e) => entryIso.from(e)));\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/iso.ts"],"sourcesContent":["import { Record as ImmutableRecord, RecordOf } from \"immutable\";\nimport { List, Set as ImmutableSet, Map as ImmutableMap } from \"immutable\";\nimport { Cell } from \"@derivation/composable\";\n\nexport interface Iso<In, Out> {\n to(x: In): Out;\n from(x: Out): In;\n}\n\nexport function id<A>(): Iso<A, A> {\n return {\n to: (x: A) => x,\n from: (x: A) => x,\n };\n}\n\nexport function unknown<A>(): Iso<A, unknown> {\n return {\n to: (x: A) => x,\n from: (x: unknown) => x as A,\n };\n}\n\nexport function flip<A, B>(iso: Iso<A, B>): Iso<B, A> {\n return {\n to: (x: B) => iso.from(x),\n from: (x: A) => iso.to(x),\n };\n}\n\nexport function compose<A, B, C>(\n first: Iso<A, B>,\n second: Iso<B, C>,\n): Iso<A, C> {\n return {\n to: (x: A) => second.to(first.to(x)),\n from: (x: C) => first.from(second.from(x)),\n };\n}\n\nexport function array<A, B>(itemIso: Iso<A, B>): Iso<Array<A>, Array<B>> {\n return {\n to: (xs: Array<A>) => xs.map(itemIso.to),\n from: (xs: Array<B>) => xs.map(itemIso.from),\n };\n}\n\n\nexport type IsoIn<T> = T extends Iso<infer A, unknown> ? A : never;\nexport type IsoOut<T> = T extends Iso<unknown, infer B> ? B : never;\n\ntype ObjectIsos = Record<string, Iso<unknown, unknown>>;\ntype ObjectIn<T extends ObjectIsos> = { [K in keyof T]: IsoIn<T[K]> };\ntype ObjectOut<T extends ObjectIsos> = { [K in keyof T]: IsoOut<T[K]> };\n\nexport function object<T extends ObjectIsos>(\n spec: T,\n): Iso<ObjectIn<T>, ObjectOut<T>> {\n return {\n to: (x) => {\n const result = {} as ObjectOut<T>;\n for (const key in spec) {\n result[key] = spec[key].to(x[key]) as IsoOut<\n T[Extract<keyof T, string>]\n >;\n }\n return result;\n },\n from: (x) => {\n const result = {} as ObjectIn<T>;\n for (const key in spec) {\n result[key] = spec[key].from(x[key]) as IsoIn<\n T[Extract<keyof T, string>]\n >;\n }\n return result;\n },\n };\n}\n\nexport function shallowRecord<T extends Record<string, unknown>>(): Iso<\n RecordOf<T>,\n T\n> {\n return {\n to: (x: RecordOf<T>): T => x.toObject(),\n from: (x: T): RecordOf<T> => ImmutableRecord<T>(x)(x),\n };\n}\n\nexport function record<T extends ObjectIsos>(\n spec: T,\n): Iso<RecordOf<ObjectIn<T>>, ObjectOut<T>> {\n return compose(shallowRecord(), object(spec));\n}\n\ntype TupleIsos = Array<Iso<unknown, unknown>>;\ntype TupleIn<T extends TupleIsos> = { [K in keyof T]: IsoIn<T[K]> };\ntype TupleOut<T extends TupleIsos> = { [K in keyof T]: IsoOut<T[K]> };\n\nexport function tuple<T extends TupleIsos>(\n ...isos: T\n): Iso<TupleIn<T>, TupleOut<T>> {\n return {\n to: (x) => x.map((xi, i) => isos[i].to(xi)) as TupleOut<T>,\n from: (x) => x.map((xi, i) => isos[i].from(xi)) as TupleIn<T>,\n };\n}\n\nexport function map<K, V, K2, V2>(\n keyIso: Iso<K, K2>,\n valueIso: Iso<V, V2>,\n): Iso<Map<K, V>, Array<[K2, V2]>> {\n return {\n to: (m) => [...m.entries()].map(([k, v]) => [keyIso.to(k), valueIso.to(v)]),\n from: (entries) =>\n new Map(entries.map(([k, v]) => [keyIso.from(k), valueIso.from(v)])),\n };\n}\n\n\n/**\n * A shallow isomorphism between an Immutable.js List and a standard Array.\n */\nexport function shallowList<A>(): Iso<List<A>, Array<A>> {\n return {\n to: (x: List<A>): Array<A> => x.toArray(),\n from: (x: Array<A>): List<A> => List(x),\n };\n}\n\n/**\n * A deep isomorphism that converts a List to an Array and\n * applies an itemIso to every element.\n */\nexport function list<A, B>(itemIso: Iso<A, B>): Iso<List<A>, Array<B>> {\n return compose(shallowList<A>(), array(itemIso));\n}\n\n/**\n * Deep conversion: ImmutableSet<A> <-> Array<B>\n * Note: Converting to Array is usually safer for serialization than native Set.\n */\nexport function immutableSet<A, B>(\n itemIso: Iso<A, B>,\n): Iso<ImmutableSet<A>, Array<B>> {\n return {\n to: (xs: ImmutableSet<A>) => xs.toArray().map(itemIso.to),\n from: (xs: Array<B>) => ImmutableSet(xs.map(itemIso.from)),\n };\n}\n\n/**\n * Deep conversion: ImmutableMap<K, V> <-> Array<[K2, V2]>\n */\nexport function immutableMap<K, V, K2, V2>(\n keyIso: Iso<K, K2>,\n valueIso: Iso<V, V2>,\n): Iso<ImmutableMap<K, V>, Array<[K2, V2]>> {\n const entryIso = tuple(keyIso, valueIso);\n return {\n to: (m) =>\n m\n .entrySeq()\n .toArray()\n .map((e) => entryIso.to([...e] as [K, V])),\n from: (entries) => {\n return ImmutableMap(entries.map((e) => entryIso.from(e)));\n },\n };\n}\n\n/**\n * Deep conversion: Cell<A> <-> B\n */\nexport function cellIso<A extends NonNullable<unknown>, B>(\n valueIso: Iso<A, B>,\n): Iso<Cell<A>, B> {\n return {\n to: (cell: Cell<A>) => valueIso.to(cell.value),\n from: (value: B) => new Cell(valueIso.from(value)),\n };\n}\n"],"mappings":"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","names":[]}
@@ -105,11 +105,13 @@ var SharedWorkerClient = class {
105
105
  this.pendingStreams = /* @__PURE__ */ new Map();
106
106
  this.pendingMutations = /* @__PURE__ */ new Map();
107
107
  this.activeStreams = /* @__PURE__ */ new Map();
108
+ this.activeStreamSnapshots = /* @__PURE__ */ new Map();
108
109
  this.registry = new FinalizationRegistry(
109
110
  ([id, name]) => {
110
111
  console.log(`\u{1F9F9} Stream ${id} (${name}) collected \u2014 unsubscribing`);
111
112
  this.sendMessage(ClientMessage.unsubscribe(id));
112
113
  this.activeStreams.delete(id);
114
+ this.activeStreamSnapshots.delete(id);
113
115
  }
114
116
  );
115
117
  this.port.onmessage = (event) => {
@@ -126,6 +128,19 @@ var SharedWorkerClient = class {
126
128
  if (resolve) {
127
129
  resolve(message.snapshot);
128
130
  this.pendingStreams.delete(message.id);
131
+ break;
132
+ }
133
+ const active = this.activeStreamSnapshots.get(message.id);
134
+ if (active) {
135
+ const input = active.input.deref();
136
+ if (input) {
137
+ active.sink.reset(message.snapshot, input);
138
+ this.graph.step();
139
+ } else {
140
+ this.sendMessage(ClientMessage.unsubscribe(message.id));
141
+ this.activeStreams.delete(message.id);
142
+ this.activeStreamSnapshots.delete(message.id);
143
+ }
129
144
  }
130
145
  break;
131
146
  }
@@ -143,6 +158,7 @@ var SharedWorkerClient = class {
143
158
  console.log(`\u{1F9F9} Sink ${id} GC'd \u2014 auto-unsubscribing`);
144
159
  this.sendMessage(ClientMessage.unsubscribe(id));
145
160
  this.activeStreams.delete(id);
161
+ this.activeStreamSnapshots.delete(id);
146
162
  }
147
163
  }
148
164
  console.log("[Client] Stepping graph");
@@ -190,6 +206,10 @@ var SharedWorkerClient = class {
190
206
  const { stream, input } = sinkAdapter.build();
191
207
  const inputRef = new WeakRef(input);
192
208
  this.activeStreams.set(id, changer(sinkAdapter, inputRef));
209
+ this.activeStreamSnapshots.set(id, {
210
+ sink: sinkAdapter,
211
+ input: inputRef
212
+ });
193
213
  this.registry.register(input, [id, String(key)]);
194
214
  return stream;
195
215
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared-worker/index.ts","../src/client-message.ts","../src/shared-worker/shared-worker-client.ts","../src/server-message.ts","../src/shared-worker/shared-worker-client-handler.ts","../src/weak-list.ts","../src/shared-worker/shared-worker-server.ts"],"sourcesContent":["export * from \"./shared-worker-client.js\";\nexport * from \"./shared-worker-server.js\";\n","import { z } from \"zod\";\n\nexport const SubscribeMessageSchema = z.object({\n type: z.literal(\"subscribe\"),\n id: z.number(),\n name: z.string(),\n args: z.looseObject({}),\n});\nexport type SubscribeMessage = z.infer<typeof SubscribeMessageSchema>;\n\nexport const UnsubscribeMessageSchema = z.object({\n type: z.literal(\"unsubscribe\"),\n id: z.number(),\n});\nexport type UnsubscribeMessage = z.infer<typeof UnsubscribeMessageSchema>;\n\nexport const HeartbeatMessageSchema = z.object({\n type: z.literal(\"heartbeat\"),\n});\nexport type HeartbeatMessage = z.infer<typeof HeartbeatMessageSchema>;\n\nexport const CallMessageSchema = z.object({\n type: z.literal(\"call\"),\n id: z.number(),\n name: z.string(),\n args: z.looseObject({}),\n});\nexport type CallMessage = z.infer<typeof CallMessageSchema>;\n\nexport const PresenceMessageSchema = z.object({\n type: z.literal(\"presence\"),\n data: z.looseObject({}),\n});\nexport type PresenceMessage = z.infer<typeof PresenceMessageSchema>;\n\nexport const ClientMessageSchema = z.discriminatedUnion(\"type\", [\n SubscribeMessageSchema,\n UnsubscribeMessageSchema,\n HeartbeatMessageSchema,\n CallMessageSchema,\n PresenceMessageSchema,\n]);\nexport type ClientMessage = z.infer<typeof ClientMessageSchema>;\n\nexport function parseClientMessage(data: unknown): ClientMessage {\n return ClientMessageSchema.parse(data);\n}\n\nexport const ClientMessage = {\n subscribe: (\n id: number,\n name: string,\n args: object,\n ): SubscribeMessage => ({\n type: \"subscribe\",\n id,\n name,\n args: args as Record<string, unknown>,\n }),\n unsubscribe: (id: number): UnsubscribeMessage => ({\n type: \"unsubscribe\",\n id,\n }),\n call: (\n id: number,\n name: string,\n args: object,\n ): CallMessage => ({\n type: \"call\",\n id,\n name,\n args: args as Record<string, unknown>,\n }),\n heartbeat: (): HeartbeatMessage => ({\n type: \"heartbeat\",\n }),\n presence: (data: object): PresenceMessage => ({\n type: \"presence\",\n data: data as Record<string, unknown>,\n }),\n};\n","import { ClientMessage } from \"../client-message.js\";\nimport { ServerMessage } from \"../server-message.js\";\nimport type { Graph } from \"derivation\";\nimport type {\n Sink,\n StreamSinks,\n RPCDefinition,\n MutationResult,\n} from \"../stream-types.js\";\n\nfunction changer<T extends object, I extends object>(\n sink: Sink<T, I>,\n input: WeakRef<I>,\n): (change: object) => void {\n return (change) => {\n const i = input.deref();\n if (i) {\n sink.apply(change, i);\n }\n };\n}\n\nexport class SharedWorkerClient<Defs extends RPCDefinition> {\n private nextId = 1;\n private pendingStreams = new Map<number, (snapshot: object) => void>();\n private pendingMutations = new Map<\n number,\n (result: MutationResult<unknown>) => void\n >();\n private activeStreams = new Map<number, (change: object) => void>();\n\n private registry = new FinalizationRegistry<[number, string]>(\n ([id, name]) => {\n console.log(`🧹 Stream ${id} (${name}) collected — unsubscribing`);\n this.sendMessage(ClientMessage.unsubscribe(id));\n this.activeStreams.delete(id);\n },\n );\n\n constructor(\n private port: MessagePort,\n private sinks: StreamSinks<Defs[\"streams\"]>,\n private graph: Graph,\n ) {\n this.port.onmessage = (event: MessageEvent) => {\n const message = JSON.parse(event.data as string) as ServerMessage;\n this.handleMessage(message);\n };\n this.port.start();\n }\n\n private handleMessage(message: ServerMessage) {\n switch (message.type) {\n case \"snapshot\": {\n console.log(`[Client] Received snapshot for stream ${message.id}`);\n const resolve = this.pendingStreams.get(message.id);\n if (resolve) {\n resolve(message.snapshot as object);\n this.pendingStreams.delete(message.id);\n }\n break;\n }\n case \"delta\": {\n const changeCount = Object.keys(message.changes).length;\n console.log(\n `[Client] Received delta with ${changeCount} changes for streams: ${Object.keys(message.changes).join(\", \")}`,\n );\n for (const [idStr, change] of Object.entries(message.changes)) {\n const id = Number(idStr);\n const sink = this.activeStreams.get(id);\n\n if (sink && change && typeof change === \"object\") {\n sink(change);\n } else if (!sink) {\n console.log(`🧹 Sink ${id} GC'd — auto-unsubscribing`);\n this.sendMessage(ClientMessage.unsubscribe(id));\n this.activeStreams.delete(id);\n }\n }\n console.log(\"[Client] Stepping graph\");\n this.graph.step();\n break;\n }\n case \"result\": {\n console.log(\n `[Client] Received mutation result for call ${message.id}:`,\n message.success ? \"success\" : \"error\",\n );\n const resolve = this.pendingMutations.get(message.id);\n if (resolve) {\n if (message.success) {\n resolve({ success: true, value: message.value });\n } else {\n resolve({\n success: false,\n error: message.error || \"Unknown error\",\n });\n }\n this.pendingMutations.delete(message.id);\n }\n break;\n }\n case \"heartbeat\":\n console.log(\"[Client] Received heartbeat\");\n break;\n }\n }\n\n private sendMessage(message: ClientMessage) {\n this.port.postMessage(JSON.stringify(message));\n }\n\n async run<Key extends keyof Defs[\"streams\"]>(\n key: Key,\n args: Defs[\"streams\"][Key][\"args\"],\n ): Promise<Defs[\"streams\"][Key][\"returnType\"]> {\n console.log(\n `Running stream ${String(key)} with args ${JSON.stringify(args)}`,\n );\n const id = this.nextId++;\n\n this.sendMessage(ClientMessage.subscribe(id, String(key), args));\n\n const snapshot = await new Promise<object>((resolve) => {\n this.pendingStreams.set(id, resolve);\n });\n\n const endpoint = this.sinks[key];\n const sinkAdapter = endpoint(snapshot);\n const { stream, input } = sinkAdapter.build();\n const inputRef = new WeakRef(input);\n this.activeStreams.set(id, changer(sinkAdapter, inputRef));\n this.registry.register(input, [id, String(key)]);\n\n return stream;\n }\n\n async call<Key extends keyof Defs[\"mutations\"]>(\n key: Key,\n args: Defs[\"mutations\"][Key][\"args\"],\n ): Promise<MutationResult<Defs[\"mutations\"][Key][\"result\"]>> {\n console.log(\n `Calling mutation ${String(key)} with args ${JSON.stringify(args)}`,\n );\n const id = this.nextId++;\n\n this.sendMessage(\n ClientMessage.call(id, String(key), args as Record<string, unknown>),\n );\n\n const result = await new Promise<\n MutationResult<Defs[\"mutations\"][Key][\"result\"]>\n >((resolve) => {\n this.pendingMutations.set(\n id,\n resolve as (result: MutationResult<unknown>) => void,\n );\n });\n\n return result;\n }\n\n close() {\n this.port.close();\n }\n\n setPresence(value: Record<string, unknown>): void {\n this.sendMessage(ClientMessage.presence(value));\n }\n}\n\n/**\n * Create a client connected to a SharedWorker.\n *\n * @example\n * ```typescript\n * // main.ts\n * const graph = new Graph();\n * const worker = new SharedWorker('/worker.js');\n *\n * const client = createSharedWorkerClient(worker.port, {\n * streams: {\n * todos: setSink(graph, todoIso),\n * },\n * }, graph);\n *\n * const todos = await client.run('todos', { filter: 'active' });\n * ```\n */\nexport function createSharedWorkerClient<Defs extends RPCDefinition>(\n port: MessagePort,\n sinks: StreamSinks<Defs[\"streams\"]>,\n graph: Graph,\n): SharedWorkerClient<Defs> {\n return new SharedWorkerClient<Defs>(port, sinks, graph);\n}\n","import { z } from \"zod\";\n\nexport const HeartbeatMessageSchema = z.object({\n type: z.literal(\"heartbeat\"),\n});\nexport type HeartbeatMessage = z.infer<typeof HeartbeatMessageSchema>;\n\nexport const SubscribedSchema = z.object({\n type: z.literal(\"snapshot\"),\n id: z.number(),\n snapshot: z.unknown(),\n});\nexport type SubscribedMessage = z.infer<typeof SubscribedSchema>;\n\nexport const DeltaMessageSchema = z.object({\n type: z.literal(\"delta\"),\n changes: z.record(z.number(), z.unknown()),\n});\nexport type DeltaMessage = z.infer<typeof DeltaMessageSchema>;\n\nexport const ResultMessageSchema = z.object({\n type: z.literal(\"result\"),\n id: z.number(),\n success: z.boolean(),\n value: z.unknown().optional(),\n error: z.string().optional(),\n});\nexport type ResultMessage = z.infer<typeof ResultMessageSchema>;\n\nexport const ServerMessageSchema = z.discriminatedUnion(\"type\", [\n HeartbeatMessageSchema,\n SubscribedSchema,\n DeltaMessageSchema,\n ResultMessageSchema,\n]);\nexport type ServerMessage = z.infer<typeof ServerMessageSchema>;\n\nexport const ServerMessage = {\n heartbeat: (): HeartbeatMessage => ({\n type: \"heartbeat\",\n }),\n subscribed: (id: number, snapshot: unknown): SubscribedMessage => ({\n type: \"snapshot\",\n id,\n snapshot,\n }),\n delta: (changes: Record<string, unknown>): DeltaMessage => ({\n type: \"delta\",\n changes: changes,\n }),\n resultSuccess: (id: number, value: unknown): ResultMessage => ({\n type: \"result\",\n id,\n success: true,\n value,\n }),\n resultError: (id: number, error: string): ResultMessage => ({\n type: \"result\",\n id,\n success: false,\n error,\n }),\n};\n","import { parseClientMessage, ClientMessage } from \"../client-message.js\";\nimport { ServerMessage } from \"../server-message.js\";\nimport {\n Source,\n StreamEndpoints,\n MutationEndpoints,\n RPCDefinition,\n} from \"../stream-types.js\";\nimport { PresenceHandler } from \"../presence-manager.js\";\n\n/**\n * Client handler for SharedWorker connections (browser-only).\n * Simplified version without rate limiting, heartbeats, or inactivity timeouts.\n * Designed for same-origin trusted connections.\n */\nexport class SharedWorkerClientHandler<Defs extends RPCDefinition, Ctx = void> {\n private readonly port: MessagePort;\n private readonly context: Ctx;\n private readonly streamEndpoints: StreamEndpoints<Defs[\"streams\"], Ctx>;\n private readonly mutationEndpoints: MutationEndpoints<Defs[\"mutations\"], Ctx>;\n private readonly presenceHandler?: PresenceHandler;\n private currentPresence?: Record<string, unknown>;\n private closed = false;\n private readonly streams = new Map<number, Source<unknown>>();\n\n constructor(\n port: MessagePort,\n context: Ctx,\n streamEndpoints: StreamEndpoints<Defs[\"streams\"], Ctx>,\n mutationEndpoints: MutationEndpoints<Defs[\"mutations\"], Ctx>,\n presenceHandler?: PresenceHandler,\n ) {\n this.port = port;\n this.context = context;\n this.streamEndpoints = streamEndpoints;\n this.mutationEndpoints = mutationEndpoints;\n this.presenceHandler = presenceHandler;\n\n console.log(\"new client connected\");\n\n // Set up transport handlers\n this.port.onmessage = (event: MessageEvent) => {\n this.handleMessage(event.data as string);\n };\n this.port.onmessageerror = () => this.handleDisconnect();\n }\n\n handleMessage(message: string) {\n let data: object;\n try {\n data = JSON.parse(message);\n } catch {\n console.error(\"Invalid JSON received:\", message);\n return this.close();\n }\n\n let parsed: ClientMessage;\n try {\n parsed = parseClientMessage(data);\n } catch (error) {\n console.error(\"Invalid client message:\", error);\n return this.close();\n }\n\n this.handleClientMessage(parsed);\n }\n\n async handleClientMessage(message: ClientMessage) {\n switch (message.type) {\n case \"subscribe\": {\n const { id, name, args } = message;\n\n if (!(name in this.streamEndpoints)) {\n console.error(`Unknown stream: ${name}`);\n this.close();\n return;\n }\n\n const endpoint = this.streamEndpoints[name as keyof Defs[\"streams\"]];\n\n try {\n const source = await endpoint(\n args as Defs[\"streams\"][keyof Defs[\"streams\"]][\"args\"],\n this.context,\n );\n this.streams.set(id, source);\n this.sendMessage(ServerMessage.subscribed(id, source.Snapshot));\n console.log(`Client subscribed to \"${name}\" (${id})`);\n } catch (err) {\n console.error(`Error building stream ${name}:`, err);\n this.close();\n }\n break;\n }\n\n case \"unsubscribe\": {\n const { id } = message;\n this.streams.delete(id);\n console.log(`Client unsubscribed from ${id}`);\n break;\n }\n\n case \"call\": {\n const { id, name, args } = message;\n\n if (!(name in this.mutationEndpoints)) {\n console.error(`Unknown mutation: ${name}`);\n this.close();\n return;\n }\n\n const endpoint =\n this.mutationEndpoints[name as keyof Defs[\"mutations\"]];\n\n endpoint(\n args as Defs[\"mutations\"][keyof Defs[\"mutations\"]][\"args\"],\n this.context,\n )\n .then((result) => {\n if (result.success) {\n this.sendMessage(ServerMessage.resultSuccess(id, result.value));\n console.log(`Mutation \"${name}\" (${id}) completed successfully`);\n } else {\n this.sendMessage(ServerMessage.resultError(id, result.error));\n console.log(\n `Mutation \"${name}\" (${id}) returned error: ${result.error}`,\n );\n }\n })\n .catch((err) => {\n console.error(\n `Unhandled exception in mutation \"${name}\" (${id}):`,\n err,\n );\n this.close();\n });\n break;\n }\n\n case \"heartbeat\":\n break;\n\n case \"presence\": {\n if (!this.presenceHandler) {\n console.error(\"Presence not configured\");\n this.close();\n return;\n }\n\n const { data } = message;\n\n if (this.currentPresence !== undefined) {\n this.presenceHandler.update(this.currentPresence, data);\n } else {\n this.presenceHandler.add(data);\n }\n\n this.currentPresence = data;\n break;\n }\n }\n }\n\n handleStep() {\n if (this.closed) return;\n const changes: Record<number, unknown> = {};\n\n for (const [id, source] of this.streams) {\n const change = source.LastChange;\n if (change === null) continue;\n changes[id] = change;\n }\n\n if (Object.keys(changes).length > 0) {\n console.log(\n `[ClientHandler] Sending delta with ${Object.keys(changes).length} changes for streams: ${Object.keys(changes).join(\", \")}`,\n );\n this.sendMessage(ServerMessage.delta(changes));\n }\n }\n\n sendMessage(message: ServerMessage) {\n if (this.closed) return;\n this.port.postMessage(JSON.stringify(message));\n }\n\n private handleDisconnect() {\n this.close();\n }\n\n close() {\n if (this.closed) return;\n console.log(\"[ClientHandler] Closing client connection\");\n this.closed = true;\n\n if (this.presenceHandler && this.currentPresence) {\n this.presenceHandler.remove(this.currentPresence);\n }\n\n console.log(\n `[ClientHandler] Cleaning up ${this.streams.size} active streams`,\n );\n this.streams.clear();\n\n try {\n this.port.close();\n } catch {}\n }\n}\n","export default class WeakList<T extends object> implements Iterable<T> {\n private items: WeakRef<T>[] = [];\n\n add(value: T): void {\n this.items.push(new WeakRef(value));\n }\n\n *[Symbol.iterator](): Iterator<T> {\n const newItems: WeakRef<T>[] = [];\n\n for (const ref of this.items) {\n const value = ref.deref();\n if (value !== undefined) {\n yield value;\n newItems.push(ref);\n }\n }\n\n this.items = newItems;\n }\n}\n","import { Graph } from \"derivation\";\nimport { SharedWorkerClientHandler } from \"./shared-worker-client-handler.js\";\nimport WeakList from \"../weak-list.js\";\nimport {\n StreamEndpoints,\n MutationEndpoints,\n RPCDefinition,\n} from \"../stream-types.js\";\nimport { PresenceHandler } from \"../presence-manager.js\";\n\nexport type SharedWorkerServerOptions<\n Defs extends RPCDefinition,\n Ctx = void,\n> = {\n streams: StreamEndpoints<Defs[\"streams\"], Ctx>;\n mutations: MutationEndpoints<Defs[\"mutations\"], Ctx>;\n createContext: (port: MessagePort) => Ctx | Promise<Ctx>;\n presenceHandler?: PresenceHandler;\n};\n\n/**\n * Set up a SharedWorker server for RPC communication.\n * This creates a shared Graph that all connected tabs can interact with.\n *\n * @example\n * ```typescript\n * // worker.ts\n * const { graph } = setupSharedWorker({\n * streams: {\n * todos: async (args, ctx) => new ReactiveSourceAdapter(source, iso),\n * },\n * mutations: {\n * addTodo: async (args, ctx) => ({ success: true, value: newTodo }),\n * },\n * createContext: (port) => ({ portId: crypto.randomUUID() }),\n * });\n * ```\n */\nexport function setupSharedWorker<Defs extends RPCDefinition, Ctx = void>(\n options: SharedWorkerServerOptions<Defs, Ctx>,\n graph: Graph,\n) {\n const { streams, mutations, createContext, presenceHandler } = options;\n\n const clients = new WeakList<SharedWorkerClientHandler<Defs, Ctx>>();\n\n // After each graph step, broadcast deltas to all connected clients\n graph.afterStep(() => {\n console.log(\"[SharedWorker] Broadcasting deltas to clients\");\n for (const client of clients) {\n client.handleStep();\n }\n });\n\n // Handle SharedWorker connections\n const globalScope = self as unknown as SharedWorkerGlobalScope;\n globalScope.onconnect = (event: MessageEvent) => {\n console.log(\"[SharedWorker] New client connecting...\");\n const port = event.ports[0];\n const messageBuffer: string[] = [];\n let client: SharedWorkerClientHandler<Defs, Ctx> | null = null;\n\n // Set up temporary message handler to buffer messages\n const tempMessageHandler = (e: MessageEvent) => {\n console.log(\"[SharedWorker] Buffering message during setup:\", e.data);\n messageBuffer.push(e.data);\n };\n port.onmessage = tempMessageHandler;\n\n // Create context (handle both sync and async)\n Promise.resolve(createContext(port))\n .then((context) => {\n console.log(\"[SharedWorker] Context created, setting up client handler\");\n // Create client handler\n client = new SharedWorkerClientHandler<Defs, Ctx>(\n port,\n context,\n streams,\n mutations,\n presenceHandler,\n );\n clients.add(client);\n console.log(\"[SharedWorker] Client handler registered\");\n\n // Process buffered messages\n console.log(`[SharedWorker] Processing ${messageBuffer.length} buffered messages`);\n for (const msg of messageBuffer) {\n client.handleMessage(msg);\n }\n messageBuffer.length = 0;\n\n // Start the port\n port.start();\n console.log(\"[SharedWorker] Client connection ready\");\n })\n .catch((err) => {\n console.error(\"[SharedWorker] Error creating context:\", err);\n port.close();\n });\n };\n}\n"],"mappings":"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","names":["import_zod","HeartbeatMessageSchema"]}
1
+ {"version":3,"sources":["../src/shared-worker/index.ts","../src/client-message.ts","../src/shared-worker/shared-worker-client.ts","../src/server-message.ts","../src/shared-worker/shared-worker-client-handler.ts","../src/weak-list.ts","../src/shared-worker/shared-worker-server.ts"],"sourcesContent":["export * from \"./shared-worker-client.js\";\nexport * from \"./shared-worker-server.js\";\n","import { z } from \"zod\";\n\nexport const SubscribeMessageSchema = z.object({\n type: z.literal(\"subscribe\"),\n id: z.number(),\n name: z.string(),\n args: z.looseObject({}),\n});\nexport type SubscribeMessage = z.infer<typeof SubscribeMessageSchema>;\n\nexport const UnsubscribeMessageSchema = z.object({\n type: z.literal(\"unsubscribe\"),\n id: z.number(),\n});\nexport type UnsubscribeMessage = z.infer<typeof UnsubscribeMessageSchema>;\n\nexport const HeartbeatMessageSchema = z.object({\n type: z.literal(\"heartbeat\"),\n});\nexport type HeartbeatMessage = z.infer<typeof HeartbeatMessageSchema>;\n\nexport const CallMessageSchema = z.object({\n type: z.literal(\"call\"),\n id: z.number(),\n name: z.string(),\n args: z.looseObject({}),\n});\nexport type CallMessage = z.infer<typeof CallMessageSchema>;\n\nexport const PresenceMessageSchema = z.object({\n type: z.literal(\"presence\"),\n data: z.looseObject({}),\n});\nexport type PresenceMessage = z.infer<typeof PresenceMessageSchema>;\n\nexport const ClientMessageSchema = z.discriminatedUnion(\"type\", [\n SubscribeMessageSchema,\n UnsubscribeMessageSchema,\n HeartbeatMessageSchema,\n CallMessageSchema,\n PresenceMessageSchema,\n]);\nexport type ClientMessage = z.infer<typeof ClientMessageSchema>;\n\nexport function parseClientMessage(data: unknown): ClientMessage {\n return ClientMessageSchema.parse(data);\n}\n\nexport const ClientMessage = {\n subscribe: (\n id: number,\n name: string,\n args: object,\n ): SubscribeMessage => ({\n type: \"subscribe\",\n id,\n name,\n args: args as Record<string, unknown>,\n }),\n unsubscribe: (id: number): UnsubscribeMessage => ({\n type: \"unsubscribe\",\n id,\n }),\n call: (\n id: number,\n name: string,\n args: object,\n ): CallMessage => ({\n type: \"call\",\n id,\n name,\n args: args as Record<string, unknown>,\n }),\n heartbeat: (): HeartbeatMessage => ({\n type: \"heartbeat\",\n }),\n presence: (data: object): PresenceMessage => ({\n type: \"presence\",\n data: data as Record<string, unknown>,\n }),\n};\n","import { ClientMessage } from \"../client-message.js\";\nimport { ServerMessage } from \"../server-message.js\";\nimport type { Graph } from \"derivation\";\nimport type {\n Sink,\n StreamSinks,\n RPCDefinition,\n MutationResult,\n} from \"../stream-types.js\";\n\nfunction changer<T extends object, I extends object>(\n sink: Sink<T, I>,\n input: WeakRef<I>,\n): (change: object) => void {\n return (change) => {\n const i = input.deref();\n if (i) {\n sink.apply(change, i);\n }\n };\n}\n\nexport class SharedWorkerClient<Defs extends RPCDefinition> {\n private nextId = 1;\n private pendingStreams = new Map<number, (snapshot: object) => void>();\n private pendingMutations = new Map<\n number,\n (result: MutationResult<unknown>) => void\n >();\n private activeStreams = new Map<number, (change: object) => void>();\n private activeStreamSnapshots = new Map<\n number,\n { sink: Sink<object, object>; input: WeakRef<object> }\n >();\n\n private registry = new FinalizationRegistry<[number, string]>(\n ([id, name]) => {\n console.log(`🧹 Stream ${id} (${name}) collected — unsubscribing`);\n this.sendMessage(ClientMessage.unsubscribe(id));\n this.activeStreams.delete(id);\n this.activeStreamSnapshots.delete(id);\n },\n );\n\n constructor(\n private port: MessagePort,\n private sinks: StreamSinks<Defs[\"streams\"]>,\n private graph: Graph,\n ) {\n this.port.onmessage = (event: MessageEvent) => {\n const message = JSON.parse(event.data as string) as ServerMessage;\n this.handleMessage(message);\n };\n this.port.start();\n }\n\n private handleMessage(message: ServerMessage) {\n switch (message.type) {\n case \"snapshot\": {\n console.log(`[Client] Received snapshot for stream ${message.id}`);\n const resolve = this.pendingStreams.get(message.id);\n if (resolve) {\n resolve(message.snapshot as object);\n this.pendingStreams.delete(message.id);\n break;\n }\n\n const active = this.activeStreamSnapshots.get(message.id);\n if (active) {\n const input = active.input.deref();\n if (input) {\n active.sink.reset(message.snapshot as object, input);\n this.graph.step();\n } else {\n this.sendMessage(ClientMessage.unsubscribe(message.id));\n this.activeStreams.delete(message.id);\n this.activeStreamSnapshots.delete(message.id);\n }\n }\n break;\n }\n case \"delta\": {\n const changeCount = Object.keys(message.changes).length;\n console.log(\n `[Client] Received delta with ${changeCount} changes for streams: ${Object.keys(message.changes).join(\", \")}`,\n );\n for (const [idStr, change] of Object.entries(message.changes)) {\n const id = Number(idStr);\n const sink = this.activeStreams.get(id);\n\n if (sink && change && typeof change === \"object\") {\n sink(change);\n } else if (!sink) {\n console.log(`🧹 Sink ${id} GC'd — auto-unsubscribing`);\n this.sendMessage(ClientMessage.unsubscribe(id));\n this.activeStreams.delete(id);\n this.activeStreamSnapshots.delete(id);\n }\n }\n console.log(\"[Client] Stepping graph\");\n this.graph.step();\n break;\n }\n case \"result\": {\n console.log(\n `[Client] Received mutation result for call ${message.id}:`,\n message.success ? \"success\" : \"error\",\n );\n const resolve = this.pendingMutations.get(message.id);\n if (resolve) {\n if (message.success) {\n resolve({ success: true, value: message.value });\n } else {\n resolve({\n success: false,\n error: message.error || \"Unknown error\",\n });\n }\n this.pendingMutations.delete(message.id);\n }\n break;\n }\n case \"heartbeat\":\n console.log(\"[Client] Received heartbeat\");\n break;\n }\n }\n\n private sendMessage(message: ClientMessage) {\n this.port.postMessage(JSON.stringify(message));\n }\n\n async run<Key extends keyof Defs[\"streams\"]>(\n key: Key,\n args: Defs[\"streams\"][Key][\"args\"],\n ): Promise<Defs[\"streams\"][Key][\"returnType\"]> {\n console.log(\n `Running stream ${String(key)} with args ${JSON.stringify(args)}`,\n );\n const id = this.nextId++;\n\n this.sendMessage(ClientMessage.subscribe(id, String(key), args));\n\n const snapshot = await new Promise<object>((resolve) => {\n this.pendingStreams.set(id, resolve);\n });\n\n const endpoint = this.sinks[key];\n const sinkAdapter = endpoint(snapshot);\n const { stream, input } = sinkAdapter.build();\n const inputRef = new WeakRef(input);\n this.activeStreams.set(id, changer(sinkAdapter, inputRef));\n this.activeStreamSnapshots.set(id, {\n sink: sinkAdapter as Sink<object, object>,\n input: inputRef as WeakRef<object>,\n });\n this.registry.register(input, [id, String(key)]);\n\n return stream;\n }\n\n async call<Key extends keyof Defs[\"mutations\"]>(\n key: Key,\n args: Defs[\"mutations\"][Key][\"args\"],\n ): Promise<MutationResult<Defs[\"mutations\"][Key][\"result\"]>> {\n console.log(\n `Calling mutation ${String(key)} with args ${JSON.stringify(args)}`,\n );\n const id = this.nextId++;\n\n this.sendMessage(\n ClientMessage.call(id, String(key), args as Record<string, unknown>),\n );\n\n const result = await new Promise<\n MutationResult<Defs[\"mutations\"][Key][\"result\"]>\n >((resolve) => {\n this.pendingMutations.set(\n id,\n resolve as (result: MutationResult<unknown>) => void,\n );\n });\n\n return result;\n }\n\n close() {\n this.port.close();\n }\n\n setPresence(value: Record<string, unknown>): void {\n this.sendMessage(ClientMessage.presence(value));\n }\n}\n\n/**\n * Create a client connected to a SharedWorker.\n *\n * @example\n * ```typescript\n * // main.ts\n * const graph = new Graph();\n * const worker = new SharedWorker('/worker.js');\n *\n * const client = createSharedWorkerClient(worker.port, {\n * streams: {\n * todos: setSink(graph, todoIso),\n * },\n * }, graph);\n *\n * const todos = await client.run('todos', { filter: 'active' });\n * ```\n */\nexport function createSharedWorkerClient<Defs extends RPCDefinition>(\n port: MessagePort,\n sinks: StreamSinks<Defs[\"streams\"]>,\n graph: Graph,\n): SharedWorkerClient<Defs> {\n return new SharedWorkerClient<Defs>(port, sinks, graph);\n}\n","import { z } from \"zod\";\n\nexport const HeartbeatMessageSchema = z.object({\n type: z.literal(\"heartbeat\"),\n});\nexport type HeartbeatMessage = z.infer<typeof HeartbeatMessageSchema>;\n\nexport const SubscribedSchema = z.object({\n type: z.literal(\"snapshot\"),\n id: z.number(),\n snapshot: z.unknown(),\n});\nexport type SubscribedMessage = z.infer<typeof SubscribedSchema>;\n\nexport const DeltaMessageSchema = z.object({\n type: z.literal(\"delta\"),\n changes: z.record(z.number(), z.unknown()),\n});\nexport type DeltaMessage = z.infer<typeof DeltaMessageSchema>;\n\nexport const ResultMessageSchema = z.object({\n type: z.literal(\"result\"),\n id: z.number(),\n success: z.boolean(),\n value: z.unknown().optional(),\n error: z.string().optional(),\n});\nexport type ResultMessage = z.infer<typeof ResultMessageSchema>;\n\nexport const ServerMessageSchema = z.discriminatedUnion(\"type\", [\n HeartbeatMessageSchema,\n SubscribedSchema,\n DeltaMessageSchema,\n ResultMessageSchema,\n]);\nexport type ServerMessage = z.infer<typeof ServerMessageSchema>;\n\nexport const ServerMessage = {\n heartbeat: (): HeartbeatMessage => ({\n type: \"heartbeat\",\n }),\n subscribed: (id: number, snapshot: unknown): SubscribedMessage => ({\n type: \"snapshot\",\n id,\n snapshot,\n }),\n delta: (changes: Record<string, unknown>): DeltaMessage => ({\n type: \"delta\",\n changes: changes,\n }),\n resultSuccess: (id: number, value: unknown): ResultMessage => ({\n type: \"result\",\n id,\n success: true,\n value,\n }),\n resultError: (id: number, error: string): ResultMessage => ({\n type: \"result\",\n id,\n success: false,\n error,\n }),\n};\n","import { parseClientMessage, ClientMessage } from \"../client-message.js\";\nimport { ServerMessage } from \"../server-message.js\";\nimport {\n Source,\n StreamEndpoints,\n MutationEndpoints,\n RPCDefinition,\n} from \"../stream-types.js\";\nimport { PresenceHandler } from \"../presence-manager.js\";\n\n/**\n * Client handler for SharedWorker connections (browser-only).\n * Simplified version without rate limiting, heartbeats, or inactivity timeouts.\n * Designed for same-origin trusted connections.\n */\nexport class SharedWorkerClientHandler<Defs extends RPCDefinition, Ctx = void> {\n private readonly port: MessagePort;\n private readonly context: Ctx;\n private readonly streamEndpoints: StreamEndpoints<Defs[\"streams\"], Ctx>;\n private readonly mutationEndpoints: MutationEndpoints<Defs[\"mutations\"], Ctx>;\n private readonly presenceHandler?: PresenceHandler;\n private currentPresence?: Record<string, unknown>;\n private closed = false;\n private readonly streams = new Map<number, Source<unknown>>();\n\n constructor(\n port: MessagePort,\n context: Ctx,\n streamEndpoints: StreamEndpoints<Defs[\"streams\"], Ctx>,\n mutationEndpoints: MutationEndpoints<Defs[\"mutations\"], Ctx>,\n presenceHandler?: PresenceHandler,\n ) {\n this.port = port;\n this.context = context;\n this.streamEndpoints = streamEndpoints;\n this.mutationEndpoints = mutationEndpoints;\n this.presenceHandler = presenceHandler;\n\n console.log(\"new client connected\");\n\n // Set up transport handlers\n this.port.onmessage = (event: MessageEvent) => {\n this.handleMessage(event.data as string);\n };\n this.port.onmessageerror = () => this.handleDisconnect();\n }\n\n handleMessage(message: string) {\n let data: object;\n try {\n data = JSON.parse(message);\n } catch {\n console.error(\"Invalid JSON received:\", message);\n return this.close();\n }\n\n let parsed: ClientMessage;\n try {\n parsed = parseClientMessage(data);\n } catch (error) {\n console.error(\"Invalid client message:\", error);\n return this.close();\n }\n\n this.handleClientMessage(parsed);\n }\n\n async handleClientMessage(message: ClientMessage) {\n switch (message.type) {\n case \"subscribe\": {\n const { id, name, args } = message;\n\n if (!(name in this.streamEndpoints)) {\n console.error(`Unknown stream: ${name}`);\n this.close();\n return;\n }\n\n const endpoint = this.streamEndpoints[name as keyof Defs[\"streams\"]];\n\n try {\n const source = await endpoint(\n args as Defs[\"streams\"][keyof Defs[\"streams\"]][\"args\"],\n this.context,\n );\n this.streams.set(id, source);\n this.sendMessage(ServerMessage.subscribed(id, source.Snapshot));\n console.log(`Client subscribed to \"${name}\" (${id})`);\n } catch (err) {\n console.error(`Error building stream ${name}:`, err);\n this.close();\n }\n break;\n }\n\n case \"unsubscribe\": {\n const { id } = message;\n this.streams.delete(id);\n console.log(`Client unsubscribed from ${id}`);\n break;\n }\n\n case \"call\": {\n const { id, name, args } = message;\n\n if (!(name in this.mutationEndpoints)) {\n console.error(`Unknown mutation: ${name}`);\n this.close();\n return;\n }\n\n const endpoint =\n this.mutationEndpoints[name as keyof Defs[\"mutations\"]];\n\n endpoint(\n args as Defs[\"mutations\"][keyof Defs[\"mutations\"]][\"args\"],\n this.context,\n )\n .then((result) => {\n if (result.success) {\n this.sendMessage(ServerMessage.resultSuccess(id, result.value));\n console.log(`Mutation \"${name}\" (${id}) completed successfully`);\n } else {\n this.sendMessage(ServerMessage.resultError(id, result.error));\n console.log(\n `Mutation \"${name}\" (${id}) returned error: ${result.error}`,\n );\n }\n })\n .catch((err) => {\n console.error(\n `Unhandled exception in mutation \"${name}\" (${id}):`,\n err,\n );\n this.close();\n });\n break;\n }\n\n case \"heartbeat\":\n break;\n\n case \"presence\": {\n if (!this.presenceHandler) {\n console.error(\"Presence not configured\");\n this.close();\n return;\n }\n\n const { data } = message;\n\n if (this.currentPresence !== undefined) {\n this.presenceHandler.update(this.currentPresence, data);\n } else {\n this.presenceHandler.add(data);\n }\n\n this.currentPresence = data;\n break;\n }\n }\n }\n\n handleStep() {\n if (this.closed) return;\n const changes: Record<number, unknown> = {};\n\n for (const [id, source] of this.streams) {\n const change = source.LastChange;\n if (change === null) continue;\n changes[id] = change;\n }\n\n if (Object.keys(changes).length > 0) {\n console.log(\n `[ClientHandler] Sending delta with ${Object.keys(changes).length} changes for streams: ${Object.keys(changes).join(\", \")}`,\n );\n this.sendMessage(ServerMessage.delta(changes));\n }\n }\n\n sendMessage(message: ServerMessage) {\n if (this.closed) return;\n this.port.postMessage(JSON.stringify(message));\n }\n\n private handleDisconnect() {\n this.close();\n }\n\n close() {\n if (this.closed) return;\n console.log(\"[ClientHandler] Closing client connection\");\n this.closed = true;\n\n if (this.presenceHandler && this.currentPresence) {\n this.presenceHandler.remove(this.currentPresence);\n }\n\n console.log(\n `[ClientHandler] Cleaning up ${this.streams.size} active streams`,\n );\n this.streams.clear();\n\n try {\n this.port.close();\n } catch {}\n }\n}\n","export default class WeakList<T extends object> implements Iterable<T> {\n private items: WeakRef<T>[] = [];\n\n add(value: T): void {\n this.items.push(new WeakRef(value));\n }\n\n *[Symbol.iterator](): Iterator<T> {\n const newItems: WeakRef<T>[] = [];\n\n for (const ref of this.items) {\n const value = ref.deref();\n if (value !== undefined) {\n yield value;\n newItems.push(ref);\n }\n }\n\n this.items = newItems;\n }\n}\n","import { Graph } from \"derivation\";\nimport { SharedWorkerClientHandler } from \"./shared-worker-client-handler.js\";\nimport WeakList from \"../weak-list.js\";\nimport {\n StreamEndpoints,\n MutationEndpoints,\n RPCDefinition,\n} from \"../stream-types.js\";\nimport { PresenceHandler } from \"../presence-manager.js\";\n\nexport type SharedWorkerServerOptions<\n Defs extends RPCDefinition,\n Ctx = void,\n> = {\n streams: StreamEndpoints<Defs[\"streams\"], Ctx>;\n mutations: MutationEndpoints<Defs[\"mutations\"], Ctx>;\n createContext: (port: MessagePort) => Ctx | Promise<Ctx>;\n presenceHandler?: PresenceHandler;\n};\n\n/**\n * Set up a SharedWorker server for RPC communication.\n * This creates a shared Graph that all connected tabs can interact with.\n *\n * @example\n * ```typescript\n * // worker.ts\n * const { graph } = setupSharedWorker({\n * streams: {\n * todos: async (args, ctx) => new ReactiveSourceAdapter(source, iso),\n * },\n * mutations: {\n * addTodo: async (args, ctx) => ({ success: true, value: newTodo }),\n * },\n * createContext: (port) => ({ portId: crypto.randomUUID() }),\n * });\n * ```\n */\nexport function setupSharedWorker<Defs extends RPCDefinition, Ctx = void>(\n options: SharedWorkerServerOptions<Defs, Ctx>,\n graph: Graph,\n) {\n const { streams, mutations, createContext, presenceHandler } = options;\n\n const clients = new WeakList<SharedWorkerClientHandler<Defs, Ctx>>();\n\n // After each graph step, broadcast deltas to all connected clients\n graph.afterStep(() => {\n console.log(\"[SharedWorker] Broadcasting deltas to clients\");\n for (const client of clients) {\n client.handleStep();\n }\n });\n\n // Handle SharedWorker connections\n const globalScope = self as unknown as SharedWorkerGlobalScope;\n globalScope.onconnect = (event: MessageEvent) => {\n console.log(\"[SharedWorker] New client connecting...\");\n const port = event.ports[0];\n const messageBuffer: string[] = [];\n let client: SharedWorkerClientHandler<Defs, Ctx> | null = null;\n\n // Set up temporary message handler to buffer messages\n const tempMessageHandler = (e: MessageEvent) => {\n console.log(\"[SharedWorker] Buffering message during setup:\", e.data);\n messageBuffer.push(e.data);\n };\n port.onmessage = tempMessageHandler;\n\n // Create context (handle both sync and async)\n Promise.resolve(createContext(port))\n .then((context) => {\n console.log(\"[SharedWorker] Context created, setting up client handler\");\n // Create client handler\n client = new SharedWorkerClientHandler<Defs, Ctx>(\n port,\n context,\n streams,\n mutations,\n presenceHandler,\n );\n clients.add(client);\n console.log(\"[SharedWorker] Client handler registered\");\n\n // Process buffered messages\n console.log(`[SharedWorker] Processing ${messageBuffer.length} buffered messages`);\n for (const msg of messageBuffer) {\n client.handleMessage(msg);\n }\n messageBuffer.length = 0;\n\n // Start the port\n port.start();\n console.log(\"[SharedWorker] Client connection ready\");\n })\n .catch((err) => {\n console.error(\"[SharedWorker] Error creating context:\", err);\n port.close();\n });\n };\n}\n"],"mappings":"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","names":["import_zod","HeartbeatMessageSchema"]}
@@ -1,5 +1,5 @@
1
1
  import { Graph } from 'derivation';
2
- import { R as RPCDefinition, h as StreamSinks, d as MutationResult, g as StreamEndpoints, c as MutationEndpoints } from './stream-types-Q_EqNLtO.cjs';
2
+ import { R as RPCDefinition, h as StreamSinks, d as MutationResult, g as StreamEndpoints, c as MutationEndpoints } from './stream-types-Cn-LsIb9.cjs';
3
3
  import { P as PresenceHandler } from './presence-manager-4LlEyuGp.cjs';
4
4
 
5
5
  declare class SharedWorkerClient<Defs extends RPCDefinition> {
@@ -10,6 +10,7 @@ declare class SharedWorkerClient<Defs extends RPCDefinition> {
10
10
  private pendingStreams;
11
11
  private pendingMutations;
12
12
  private activeStreams;
13
+ private activeStreamSnapshots;
13
14
  private registry;
14
15
  constructor(port: MessagePort, sinks: StreamSinks<Defs["streams"]>, graph: Graph);
15
16
  private handleMessage;
@@ -1,5 +1,5 @@
1
1
  import { Graph } from 'derivation';
2
- import { R as RPCDefinition, h as StreamSinks, d as MutationResult, g as StreamEndpoints, c as MutationEndpoints } from './stream-types-Q_EqNLtO.js';
2
+ import { R as RPCDefinition, h as StreamSinks, d as MutationResult, g as StreamEndpoints, c as MutationEndpoints } from './stream-types-Cn-LsIb9.js';
3
3
  import { P as PresenceHandler } from './presence-manager-4LlEyuGp.js';
4
4
 
5
5
  declare class SharedWorkerClient<Defs extends RPCDefinition> {
@@ -10,6 +10,7 @@ declare class SharedWorkerClient<Defs extends RPCDefinition> {
10
10
  private pendingStreams;
11
11
  private pendingMutations;
12
12
  private activeStreams;
13
+ private activeStreamSnapshots;
13
14
  private registry;
14
15
  constructor(port: MessagePort, sinks: StreamSinks<Defs["streams"]>, graph: Graph);
15
16
  private handleMessage;