@dxos/app-graph 0.8.4-main.c1de068 → 0.8.4-main.fd6878d
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/lib/browser/index.mjs +186 -133
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +186 -133
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/graph-builder.d.ts +15 -4
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +6 -2
- package/dist/types/src/graph.d.ts.map +1 -1
- package/dist/types/src/node.d.ts +1 -1
- package/dist/types/src/stories/EchoGraph.stories.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +23 -22
- package/src/graph-builder.test.ts +59 -2
- package/src/graph-builder.ts +65 -21
- package/src/graph.test.ts +1 -1
- package/src/graph.ts +16 -17
- package/src/node.ts +1 -1
- package/src/signals-integration.test.ts +1 -1
- package/src/stories/EchoGraph.stories.tsx +8 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/graph.ts
|
|
2
2
|
import { Registry, Rx } from "@effect-rx/rx-react";
|
|
3
|
-
import { Option,
|
|
3
|
+
import { Option, Record, pipe } from "effect";
|
|
4
4
|
import { Event, Trigger } from "@dxos/async";
|
|
5
5
|
import { todo } from "@dxos/debug";
|
|
6
6
|
import { invariant } from "@dxos/invariant";
|
|
@@ -26,90 +26,95 @@ var ROOT_TYPE = "dxos.org/type/GraphRoot";
|
|
|
26
26
|
var ACTION_TYPE = "dxos.org/type/GraphAction";
|
|
27
27
|
var ACTION_GROUP_TYPE = "dxos.org/type/GraphActionGroup";
|
|
28
28
|
var Graph = class {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
29
|
+
onNodeChanged = new Event();
|
|
30
|
+
_onExpand;
|
|
31
|
+
_onInitialize;
|
|
32
|
+
_onRemoveNode;
|
|
33
|
+
_registry;
|
|
34
|
+
_expanded = Record.empty();
|
|
35
|
+
_initialized = Record.empty();
|
|
36
|
+
_initialEdges = Record.empty();
|
|
37
|
+
_initialNodes = Record.fromEntries([
|
|
38
|
+
[
|
|
39
|
+
ROOT_ID,
|
|
40
|
+
this._constructNode({
|
|
41
|
+
id: ROOT_ID,
|
|
42
|
+
type: ROOT_TYPE,
|
|
43
|
+
data: null,
|
|
44
|
+
properties: {}
|
|
45
|
+
})
|
|
46
|
+
]
|
|
47
|
+
]);
|
|
48
|
+
/** @internal */
|
|
49
|
+
_node = Rx.family((id) => {
|
|
50
|
+
const initial = Option.flatten(Record.get(this._initialNodes, id));
|
|
51
|
+
return Rx.make(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:node:${id}`));
|
|
52
|
+
});
|
|
53
|
+
_nodeOrThrow = Rx.family((id) => {
|
|
54
|
+
return Rx.make((get) => {
|
|
55
|
+
const node = get(this._node(id));
|
|
56
|
+
invariant(Option.isSome(node), `Node not available: ${id}`, {
|
|
57
|
+
F: __dxlog_file,
|
|
58
|
+
L: 252,
|
|
59
|
+
S: this,
|
|
60
|
+
A: [
|
|
61
|
+
"Option.isSome(node)",
|
|
62
|
+
"`Node not available: ${id}`"
|
|
63
|
+
]
|
|
63
64
|
});
|
|
65
|
+
return node.value;
|
|
64
66
|
});
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (node.properties.label) {
|
|
95
|
-
obj.label = node.properties.label;
|
|
96
|
-
}
|
|
97
|
-
if (nodes.length) {
|
|
98
|
-
obj.nodes = nodes.map((n) => {
|
|
99
|
-
const nextSeen = [
|
|
100
|
-
...seen,
|
|
101
|
-
node.id
|
|
102
|
-
];
|
|
103
|
-
return nextSeen.includes(n.id) ? void 0 : toJSON(n, nextSeen);
|
|
104
|
-
}).filter(isNonNullable);
|
|
105
|
-
}
|
|
106
|
-
return obj;
|
|
67
|
+
});
|
|
68
|
+
_edges = Rx.family((id) => {
|
|
69
|
+
const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({
|
|
70
|
+
inbound: [],
|
|
71
|
+
outbound: []
|
|
72
|
+
})));
|
|
73
|
+
return Rx.make(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:edges:${id}`));
|
|
74
|
+
});
|
|
75
|
+
// NOTE: Currently the argument to the family needs to be referentially stable for the rx to be referentially stable.
|
|
76
|
+
// TODO(wittjosiah): Rx feature request, support for something akin to `ComplexMap` to allow for complex arguments.
|
|
77
|
+
_connections = Rx.family((key) => {
|
|
78
|
+
return Rx.make((get) => {
|
|
79
|
+
const [id, relation] = key.split("$");
|
|
80
|
+
const edges = get(this._edges(id));
|
|
81
|
+
return edges[relation].map((id2) => get(this._node(id2))).filter(Option.isSome).map((o) => o.value);
|
|
82
|
+
}).pipe(Rx.withLabel(`graph:connections:${key}`));
|
|
83
|
+
});
|
|
84
|
+
_actions = Rx.family((id) => {
|
|
85
|
+
return Rx.make((get) => {
|
|
86
|
+
return get(this._connections(`${id}$outbound`)).filter((node) => node.type === ACTION_TYPE || node.type === ACTION_GROUP_TYPE);
|
|
87
|
+
}).pipe(Rx.withLabel(`graph:actions:${id}`));
|
|
88
|
+
});
|
|
89
|
+
_json = Rx.family((id) => {
|
|
90
|
+
return Rx.make((get) => {
|
|
91
|
+
const toJSON = (node, seen = []) => {
|
|
92
|
+
const nodes = get(this.connections(node.id));
|
|
93
|
+
const obj = {
|
|
94
|
+
id: node.id.length > 32 ? `${node.id.slice(0, 32)}...` : node.id,
|
|
95
|
+
type: node.type
|
|
107
96
|
};
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
97
|
+
if (node.properties.label) {
|
|
98
|
+
obj.label = node.properties.label;
|
|
99
|
+
}
|
|
100
|
+
if (nodes.length) {
|
|
101
|
+
obj.nodes = nodes.map((n) => {
|
|
102
|
+
const nextSeen = [
|
|
103
|
+
...seen,
|
|
104
|
+
node.id
|
|
105
|
+
];
|
|
106
|
+
return nextSeen.includes(n.id) ? void 0 : toJSON(n, nextSeen);
|
|
107
|
+
}).filter(isNonNullable);
|
|
108
|
+
}
|
|
109
|
+
return obj;
|
|
110
|
+
};
|
|
111
|
+
const root = get(this.nodeOrThrow(id));
|
|
112
|
+
return toJSON(root);
|
|
113
|
+
}).pipe(Rx.withLabel(`graph:json:${id}`));
|
|
114
|
+
});
|
|
115
|
+
constructor({ registry, nodes, edges, onInitialize, onExpand, onRemoveNode } = {}) {
|
|
112
116
|
this._registry = registry ?? Registry.make();
|
|
117
|
+
this._onInitialize = onInitialize;
|
|
113
118
|
this._onExpand = onExpand;
|
|
114
119
|
this._onRemoveNode = onRemoveNode;
|
|
115
120
|
if (nodes) {
|
|
@@ -162,15 +167,22 @@ var Graph = class {
|
|
|
162
167
|
getEdges(id) {
|
|
163
168
|
return this._registry.get(this.edges(id));
|
|
164
169
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
170
|
+
async initialize(id) {
|
|
171
|
+
const initialized = Record.get(this._initialized, id).pipe(Option.getOrElse(() => false));
|
|
172
|
+
log("initialize", {
|
|
173
|
+
id,
|
|
174
|
+
initialized
|
|
175
|
+
}, {
|
|
176
|
+
F: __dxlog_file,
|
|
177
|
+
L: 384,
|
|
178
|
+
S: this,
|
|
179
|
+
C: (f, a) => f(...a)
|
|
180
|
+
});
|
|
181
|
+
if (!initialized) {
|
|
182
|
+
await this._onInitialize?.(id);
|
|
183
|
+
Record.set(this._initialized, id, true);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
174
186
|
expand(id, relation = "outbound") {
|
|
175
187
|
const key = `${id}$${relation}`;
|
|
176
188
|
const expanded = Record.get(this._expanded, key).pipe(Option.getOrElse(() => false));
|
|
@@ -179,7 +191,7 @@ var Graph = class {
|
|
|
179
191
|
expanded
|
|
180
192
|
}, {
|
|
181
193
|
F: __dxlog_file,
|
|
182
|
-
L:
|
|
194
|
+
L: 394,
|
|
183
195
|
S: this,
|
|
184
196
|
C: (f, a) => f(...a)
|
|
185
197
|
});
|
|
@@ -209,7 +221,7 @@ var Graph = class {
|
|
|
209
221
|
propertiesChanged
|
|
210
222
|
}, {
|
|
211
223
|
F: __dxlog_file,
|
|
212
|
-
L:
|
|
224
|
+
L: 416,
|
|
213
225
|
S: this,
|
|
214
226
|
C: (f, a) => f(...a)
|
|
215
227
|
});
|
|
@@ -221,7 +233,7 @@ var Graph = class {
|
|
|
221
233
|
properties
|
|
222
234
|
}, {
|
|
223
235
|
F: __dxlog_file,
|
|
224
|
-
L:
|
|
236
|
+
L: 418,
|
|
225
237
|
S: this,
|
|
226
238
|
C: (f, a) => f(...a)
|
|
227
239
|
});
|
|
@@ -249,7 +261,7 @@ var Graph = class {
|
|
|
249
261
|
properties
|
|
250
262
|
}, {
|
|
251
263
|
F: __dxlog_file,
|
|
252
|
-
L:
|
|
264
|
+
L: 425,
|
|
253
265
|
S: this,
|
|
254
266
|
C: (f, a) => f(...a)
|
|
255
267
|
});
|
|
@@ -320,7 +332,7 @@ var Graph = class {
|
|
|
320
332
|
target: edgeArg.target
|
|
321
333
|
}, {
|
|
322
334
|
F: __dxlog_file,
|
|
323
|
-
L:
|
|
335
|
+
L: 480,
|
|
324
336
|
S: this,
|
|
325
337
|
C: (f, a) => f(...a)
|
|
326
338
|
});
|
|
@@ -340,7 +352,7 @@ var Graph = class {
|
|
|
340
352
|
target: edgeArg.target
|
|
341
353
|
}, {
|
|
342
354
|
F: __dxlog_file,
|
|
343
|
-
L:
|
|
355
|
+
L: 487,
|
|
344
356
|
S: this,
|
|
345
357
|
C: (f, a) => f(...a)
|
|
346
358
|
});
|
|
@@ -469,7 +481,7 @@ var Graph = class {
|
|
|
469
481
|
// src/graph-builder.ts
|
|
470
482
|
import { Registry as Registry2, Rx as Rx2 } from "@effect-rx/rx-react";
|
|
471
483
|
import { effect } from "@preact/signals-core";
|
|
472
|
-
import { Array,
|
|
484
|
+
import { Array, Option as Option2, Record as Record2, pipe as pipe2 } from "effect";
|
|
473
485
|
import { log as log2 } from "@dxos/log";
|
|
474
486
|
import { byPosition, getDebugName, isNode, isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
475
487
|
|
|
@@ -483,13 +495,18 @@ var isActionLike = (data) => isAction(data) || isActionGroup(data);
|
|
|
483
495
|
// src/graph-builder.ts
|
|
484
496
|
var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph-builder.ts";
|
|
485
497
|
var createExtension = (extension) => {
|
|
486
|
-
const { id, position = "static", relation = "outbound", connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
|
|
498
|
+
const { id, position = "static", relation = "outbound", resolver: _resolver, connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
|
|
487
499
|
const getId = (key) => `${id}/${key}`;
|
|
500
|
+
const resolver = _resolver && Rx2.family((id2) => _resolver(id2).pipe(Rx2.withLabel(`graph-builder:_resolver:${id2}`)));
|
|
488
501
|
const connector = _connector && Rx2.family((node) => _connector(node).pipe(Rx2.withLabel(`graph-builder:_connector:${id}`)));
|
|
489
502
|
const actionGroups = _actionGroups && Rx2.family((node) => _actionGroups(node).pipe(Rx2.withLabel(`graph-builder:_actionGroups:${id}`)));
|
|
490
503
|
const actions = _actions && Rx2.family((node) => _actions(node).pipe(Rx2.withLabel(`graph-builder:_actions:${id}`)));
|
|
491
504
|
return [
|
|
492
|
-
|
|
505
|
+
resolver ? {
|
|
506
|
+
id: getId("resolver"),
|
|
507
|
+
position,
|
|
508
|
+
resolver
|
|
509
|
+
} : void 0,
|
|
493
510
|
connector ? {
|
|
494
511
|
id: getId("connector"),
|
|
495
512
|
position,
|
|
@@ -503,7 +520,7 @@ var createExtension = (extension) => {
|
|
|
503
520
|
node
|
|
504
521
|
}, {
|
|
505
522
|
F: __dxlog_file2,
|
|
506
|
-
L:
|
|
523
|
+
L: 109,
|
|
507
524
|
S: void 0,
|
|
508
525
|
C: (f, a) => f(...a)
|
|
509
526
|
});
|
|
@@ -528,7 +545,7 @@ var createExtension = (extension) => {
|
|
|
528
545
|
node
|
|
529
546
|
}, {
|
|
530
547
|
F: __dxlog_file2,
|
|
531
|
-
L:
|
|
548
|
+
L: 130,
|
|
532
549
|
S: void 0,
|
|
533
550
|
C: (f, a) => f(...a)
|
|
534
551
|
});
|
|
@@ -552,7 +569,7 @@ var createExtension = (extension) => {
|
|
|
552
569
|
node
|
|
553
570
|
}, {
|
|
554
571
|
F: __dxlog_file2,
|
|
555
|
-
L:
|
|
572
|
+
L: 147,
|
|
556
573
|
S: void 0,
|
|
557
574
|
C: (f, a) => f(...a)
|
|
558
575
|
});
|
|
@@ -576,32 +593,19 @@ var flattenExtensions = (extension, acc = []) => {
|
|
|
576
593
|
}
|
|
577
594
|
};
|
|
578
595
|
var GraphBuilder = class _GraphBuilder {
|
|
596
|
+
// TODO(wittjosiah): Use Context.
|
|
597
|
+
_subscriptions = /* @__PURE__ */ new Map();
|
|
598
|
+
_extensions = Rx2.make(Record2.empty()).pipe(Rx2.keepAlive, Rx2.withLabel("graph-builder:extensions"));
|
|
599
|
+
_initialized = {};
|
|
600
|
+
_registry;
|
|
601
|
+
_graph;
|
|
579
602
|
constructor({ registry, ...params } = {}) {
|
|
580
|
-
// TODO(wittjosiah): Use Context.
|
|
581
|
-
this._connectorSubscriptions = /* @__PURE__ */ new Map();
|
|
582
|
-
this._extensions = Rx2.make(Record2.empty()).pipe(Rx2.keepAlive, Rx2.withLabel("graph-builder:extensions"));
|
|
583
|
-
this._connectors = Rx2.family((key) => {
|
|
584
|
-
return Rx2.make((get) => {
|
|
585
|
-
const [id, relation] = key.split("+");
|
|
586
|
-
const node = this._graph.node(id);
|
|
587
|
-
return pipe2(
|
|
588
|
-
get(this._extensions),
|
|
589
|
-
Record2.values,
|
|
590
|
-
// TODO(wittjosiah): Sort on write rather than read.
|
|
591
|
-
Array.sortBy(byPosition),
|
|
592
|
-
Array.filter(({ relation: _relation = "outbound" }) => _relation === relation),
|
|
593
|
-
Array.map(({ connector }) => connector?.(node)),
|
|
594
|
-
Array.filter(isNonNullable2),
|
|
595
|
-
Array.flatMap((result) => get(result))
|
|
596
|
-
);
|
|
597
|
-
}).pipe(Rx2.withLabel(`graph-builder:connectors:${key}`));
|
|
598
|
-
});
|
|
599
603
|
this._registry = registry ?? Registry2.make();
|
|
600
604
|
this._graph = new Graph({
|
|
601
605
|
...params,
|
|
602
606
|
registry: this._registry,
|
|
603
607
|
onExpand: (id, relation) => this._onExpand(id, relation),
|
|
604
|
-
|
|
608
|
+
onInitialize: (id) => this._onInitialize(id),
|
|
605
609
|
onRemoveNode: (id) => this._onRemoveNode(id)
|
|
606
610
|
});
|
|
607
611
|
}
|
|
@@ -671,9 +675,30 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
671
675
|
}
|
|
672
676
|
}
|
|
673
677
|
destroy() {
|
|
674
|
-
this.
|
|
675
|
-
this.
|
|
678
|
+
this._subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
679
|
+
this._subscriptions.clear();
|
|
676
680
|
}
|
|
681
|
+
_resolvers = Rx2.family((id) => {
|
|
682
|
+
return Rx2.make((get) => {
|
|
683
|
+
return pipe2(get(this._extensions), Record2.values, Array.sortBy(byPosition), Array.map(({ resolver }) => resolver), Array.filter(isNonNullable2), Array.map((resolver) => get(resolver(id))), Array.filter(isNonNullable2), Array.head);
|
|
684
|
+
});
|
|
685
|
+
});
|
|
686
|
+
_connectors = Rx2.family((key) => {
|
|
687
|
+
return Rx2.make((get) => {
|
|
688
|
+
const [id, relation] = key.split("+");
|
|
689
|
+
const node = this._graph.node(id);
|
|
690
|
+
return pipe2(
|
|
691
|
+
get(this._extensions),
|
|
692
|
+
Record2.values,
|
|
693
|
+
// TODO(wittjosiah): Sort on write rather than read.
|
|
694
|
+
Array.sortBy(byPosition),
|
|
695
|
+
Array.filter(({ relation: _relation = "outbound" }) => _relation === relation),
|
|
696
|
+
Array.map(({ connector }) => connector?.(node)),
|
|
697
|
+
Array.filter(isNonNullable2),
|
|
698
|
+
Array.flatMap((result) => get(result))
|
|
699
|
+
);
|
|
700
|
+
}).pipe(Rx2.withLabel(`graph-builder:connectors:${key}`));
|
|
701
|
+
});
|
|
677
702
|
_onExpand(id, relation) {
|
|
678
703
|
log2("onExpand", {
|
|
679
704
|
id,
|
|
@@ -681,7 +706,7 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
681
706
|
registry: getDebugName(this._registry)
|
|
682
707
|
}, {
|
|
683
708
|
F: __dxlog_file2,
|
|
684
|
-
L:
|
|
709
|
+
L: 324,
|
|
685
710
|
S: this,
|
|
686
711
|
C: (f, a) => f(...a)
|
|
687
712
|
});
|
|
@@ -698,7 +723,7 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
698
723
|
removed
|
|
699
724
|
}, {
|
|
700
725
|
F: __dxlog_file2,
|
|
701
|
-
L:
|
|
726
|
+
L: 335,
|
|
702
727
|
S: this,
|
|
703
728
|
C: (f, a) => f(...a)
|
|
704
729
|
});
|
|
@@ -727,15 +752,43 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
727
752
|
}, {
|
|
728
753
|
immediate: true
|
|
729
754
|
});
|
|
730
|
-
this.
|
|
755
|
+
this._subscriptions.set(id, cancel);
|
|
756
|
+
}
|
|
757
|
+
// TODO(wittjosiah): If the same node is added by a connector, the resolver should probably cancel itself?
|
|
758
|
+
async _onInitialize(id) {
|
|
759
|
+
log2("onInitialize", {
|
|
760
|
+
id
|
|
761
|
+
}, {
|
|
762
|
+
F: __dxlog_file2,
|
|
763
|
+
L: 372,
|
|
764
|
+
S: this,
|
|
765
|
+
C: (f, a) => f(...a)
|
|
766
|
+
});
|
|
767
|
+
const resolver = this._resolvers(id);
|
|
768
|
+
const cancel = this._registry.subscribe(resolver, (node) => {
|
|
769
|
+
const trigger = this._initialized[id];
|
|
770
|
+
Option2.match(node, {
|
|
771
|
+
onSome: (node2) => {
|
|
772
|
+
this._graph.addNodes([
|
|
773
|
+
node2
|
|
774
|
+
]);
|
|
775
|
+
trigger?.wake();
|
|
776
|
+
},
|
|
777
|
+
onNone: () => {
|
|
778
|
+
trigger?.wake();
|
|
779
|
+
this._graph.removeNodes([
|
|
780
|
+
id
|
|
781
|
+
]);
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
}, {
|
|
785
|
+
immediate: true
|
|
786
|
+
});
|
|
787
|
+
this._subscriptions.set(id, cancel);
|
|
731
788
|
}
|
|
732
|
-
// TODO(wittjosiah): On initialize to restore state from cache.
|
|
733
|
-
// private async _onInitialize(id: string) {
|
|
734
|
-
// log('onInitialize', { id });
|
|
735
|
-
// }
|
|
736
789
|
_onRemoveNode(id) {
|
|
737
|
-
this.
|
|
738
|
-
this.
|
|
790
|
+
this._subscriptions.get(id)?.();
|
|
791
|
+
this._subscriptions.delete(id);
|
|
739
792
|
}
|
|
740
793
|
};
|
|
741
794
|
var rxFromSignal = (cb) => {
|