@dxos/app-graph 0.8.4-main.a4bbb77 → 0.8.4-main.abd8ff62ef

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.
Files changed (60) hide show
  1. package/dist/lib/browser/chunk-3T75MQOS.mjs +1480 -0
  2. package/dist/lib/browser/chunk-3T75MQOS.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +27 -842
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +39 -0
  7. package/dist/lib/browser/testing/index.mjs.map +7 -0
  8. package/dist/lib/node-esm/chunk-UEXRLXMS.mjs +1481 -0
  9. package/dist/lib/node-esm/chunk-UEXRLXMS.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +27 -843
  11. package/dist/lib/node-esm/index.mjs.map +4 -4
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/testing/index.mjs +40 -0
  14. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  15. package/dist/types/src/atoms.d.ts +8 -0
  16. package/dist/types/src/atoms.d.ts.map +1 -0
  17. package/dist/types/src/graph-builder.d.ts +113 -67
  18. package/dist/types/src/graph-builder.d.ts.map +1 -1
  19. package/dist/types/src/graph.d.ts +188 -222
  20. package/dist/types/src/graph.d.ts.map +1 -1
  21. package/dist/types/src/index.d.ts +7 -3
  22. package/dist/types/src/index.d.ts.map +1 -1
  23. package/dist/types/src/node-matcher.d.ts +244 -0
  24. package/dist/types/src/node-matcher.d.ts.map +1 -0
  25. package/dist/types/src/node-matcher.test.d.ts +2 -0
  26. package/dist/types/src/node-matcher.test.d.ts.map +1 -0
  27. package/dist/types/src/node.d.ts +50 -5
  28. package/dist/types/src/node.d.ts.map +1 -1
  29. package/dist/types/src/stories/EchoGraph.stories.d.ts.map +1 -1
  30. package/dist/types/src/testing/index.d.ts +2 -0
  31. package/dist/types/src/testing/index.d.ts.map +1 -0
  32. package/dist/types/src/testing/setup-graph-builder.d.ts +31 -0
  33. package/dist/types/src/testing/setup-graph-builder.d.ts.map +1 -0
  34. package/dist/types/src/util.d.ts +40 -0
  35. package/dist/types/src/util.d.ts.map +1 -0
  36. package/dist/types/tsconfig.tsbuildinfo +1 -1
  37. package/package.json +42 -38
  38. package/src/atoms.ts +25 -0
  39. package/src/graph-builder.test.ts +1154 -144
  40. package/src/graph-builder.ts +737 -293
  41. package/src/graph.test.ts +451 -123
  42. package/src/graph.ts +1054 -403
  43. package/src/index.ts +10 -3
  44. package/src/node-matcher.test.ts +301 -0
  45. package/src/node-matcher.ts +314 -0
  46. package/src/node.ts +82 -8
  47. package/src/stories/EchoGraph.stories.tsx +164 -126
  48. package/src/stories/Tree.tsx +1 -1
  49. package/src/testing/index.ts +5 -0
  50. package/src/testing/setup-graph-builder.ts +41 -0
  51. package/src/util.ts +101 -0
  52. package/dist/types/src/experimental/graph-projections.test.d.ts +0 -25
  53. package/dist/types/src/experimental/graph-projections.test.d.ts.map +0 -1
  54. package/dist/types/src/signals-integration.test.d.ts +0 -2
  55. package/dist/types/src/signals-integration.test.d.ts.map +0 -1
  56. package/dist/types/src/testing.d.ts +0 -5
  57. package/dist/types/src/testing.d.ts.map +0 -1
  58. package/src/experimental/graph-projections.test.ts +0 -56
  59. package/src/signals-integration.test.ts +0 -218
  60. package/src/testing.ts +0 -20
@@ -1,853 +1,38 @@
1
- // src/graph.ts
2
- import { Registry, Rx } from "@effect-rx/rx-react";
3
- import { Option, Record, pipe } from "effect";
4
- import { Event, Trigger } from "@dxos/async";
5
- import { todo } from "@dxos/debug";
6
- import { invariant } from "@dxos/invariant";
7
- import { log } from "@dxos/log";
8
- import { isNonNullable } from "@dxos/util";
9
- function _define_property(obj, key, value) {
10
- if (key in obj) {
11
- Object.defineProperty(obj, key, {
12
- value,
13
- enumerable: true,
14
- configurable: true,
15
- writable: true
16
- });
17
- } else {
18
- obj[key] = value;
19
- }
20
- return obj;
21
- }
22
- var __dxlog_file = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph.ts";
23
- var graphSymbol = Symbol("graph");
24
- var getGraph = (node) => {
25
- const graph = node[graphSymbol];
26
- invariant(graph, "Node is not associated with a graph.", {
27
- F: __dxlog_file,
28
- L: 25,
29
- S: void 0,
30
- A: [
31
- "graph",
32
- "'Node is not associated with a graph.'"
33
- ]
34
- });
35
- return graph;
36
- };
37
- var ROOT_ID = "root";
38
- var ROOT_TYPE = "dxos.org/type/GraphRoot";
39
- var ACTION_TYPE = "dxos.org/type/GraphAction";
40
- var ACTION_GROUP_TYPE = "dxos.org/type/GraphActionGroup";
41
- var Graph = class {
42
- toJSON(id = ROOT_ID) {
43
- return this._registry.get(this._json(id));
44
- }
45
- json(id = ROOT_ID) {
46
- return this._json(id);
47
- }
48
- node(id) {
49
- return this._node(id);
50
- }
51
- nodeOrThrow(id) {
52
- return this._nodeOrThrow(id);
53
- }
54
- connections(id, relation = "outbound") {
55
- return this._connections(`${id}$${relation}`);
56
- }
57
- actions(id) {
58
- return this._actions(id);
59
- }
60
- edges(id) {
61
- return this._edges(id);
62
- }
63
- get root() {
64
- return this.getNodeOrThrow(ROOT_ID);
65
- }
66
- getNode(id) {
67
- return this._registry.get(this.node(id));
68
- }
69
- getNodeOrThrow(id) {
70
- return this._registry.get(this.nodeOrThrow(id));
71
- }
72
- getConnections(id, relation = "outbound") {
73
- return this._registry.get(this.connections(id, relation));
74
- }
75
- getActions(id) {
76
- return this._registry.get(this.actions(id));
77
- }
78
- getEdges(id) {
79
- return this._registry.get(this.edges(id));
80
- }
81
- async initialize(id) {
82
- const initialized = Record.get(this._initialized, id).pipe(Option.getOrElse(() => false));
83
- log("initialize", {
84
- id,
85
- initialized
86
- }, {
87
- F: __dxlog_file,
88
- L: 384,
89
- S: this,
90
- C: (f, a) => f(...a)
91
- });
92
- if (!initialized) {
93
- await this._onInitialize?.(id);
94
- Record.set(this._initialized, id, true);
95
- }
96
- }
97
- expand(id, relation = "outbound") {
98
- const key = `${id}$${relation}`;
99
- const expanded = Record.get(this._expanded, key).pipe(Option.getOrElse(() => false));
100
- log("expand", {
101
- key,
102
- expanded
103
- }, {
104
- F: __dxlog_file,
105
- L: 394,
106
- S: this,
107
- C: (f, a) => f(...a)
108
- });
109
- if (!expanded) {
110
- this._onExpand?.(id, relation);
111
- Record.set(this._expanded, key, true);
112
- }
113
- }
114
- addNodes(nodes) {
115
- Rx.batch(() => {
116
- nodes.map((node) => this.addNode(node));
117
- });
118
- }
119
- addNode({ nodes, edges, ...nodeArg }) {
120
- const { id, type, data = null, properties = {} } = nodeArg;
121
- const nodeRx = this._node(id);
122
- const node = this._registry.get(nodeRx);
123
- Option.match(node, {
124
- onSome: (node2) => {
125
- const typeChanged = node2.type !== type;
126
- const dataChanged = node2.data !== data;
127
- const propertiesChanged = Object.keys(properties).some((key) => node2.properties[key] !== properties[key]);
128
- log("existing node", {
129
- id,
130
- typeChanged,
131
- dataChanged,
132
- propertiesChanged
133
- }, {
134
- F: __dxlog_file,
135
- L: 416,
136
- S: this,
137
- C: (f, a) => f(...a)
138
- });
139
- if (typeChanged || dataChanged || propertiesChanged) {
140
- log("updating node", {
141
- id,
142
- type,
143
- data,
144
- properties
145
- }, {
146
- F: __dxlog_file,
147
- L: 418,
148
- S: this,
149
- C: (f, a) => f(...a)
150
- });
151
- const newNode = Option.some({
152
- ...node2,
153
- type,
154
- data,
155
- properties: {
156
- ...node2.properties,
157
- ...properties
158
- }
159
- });
160
- this._registry.set(nodeRx, newNode);
161
- this.onNodeChanged.emit({
162
- id,
163
- node: newNode
164
- });
165
- }
166
- },
167
- onNone: () => {
168
- log("new node", {
169
- id,
170
- type,
171
- data,
172
- properties
173
- }, {
174
- F: __dxlog_file,
175
- L: 425,
176
- S: this,
177
- C: (f, a) => f(...a)
178
- });
179
- const newNode = this._constructNode({
180
- id,
181
- type,
182
- data,
183
- properties
184
- });
185
- this._registry.set(nodeRx, newNode);
186
- this.onNodeChanged.emit({
187
- id,
188
- node: newNode
189
- });
190
- }
191
- });
192
- if (nodes) {
193
- this.addNodes(nodes);
194
- const _edges = nodes.map((node2) => ({
195
- source: id,
196
- target: node2.id
197
- }));
198
- this.addEdges(_edges);
199
- }
200
- if (edges) {
201
- todo();
202
- }
203
- }
204
- removeNodes(ids, edges = false) {
205
- Rx.batch(() => {
206
- ids.map((id) => this.removeNode(id, edges));
207
- });
208
- }
209
- removeNode(id, edges = false) {
210
- const nodeRx = this._node(id);
211
- this._registry.set(nodeRx, Option.none());
212
- this.onNodeChanged.emit({
213
- id,
214
- node: Option.none()
215
- });
216
- if (edges) {
217
- const { inbound, outbound } = this._registry.get(this._edges(id));
218
- const edges2 = [
219
- ...inbound.map((source) => ({
220
- source,
221
- target: id
222
- })),
223
- ...outbound.map((target) => ({
224
- source: id,
225
- target
226
- }))
227
- ];
228
- this.removeEdges(edges2);
229
- }
230
- this._onRemoveNode?.(id);
231
- }
232
- addEdges(edges) {
233
- Rx.batch(() => {
234
- edges.map((edge) => this.addEdge(edge));
235
- });
236
- }
237
- addEdge(edgeArg) {
238
- const sourceRx = this._edges(edgeArg.source);
239
- const source = this._registry.get(sourceRx);
240
- if (!source.outbound.includes(edgeArg.target)) {
241
- log("add outbound edge", {
242
- source: edgeArg.source,
243
- target: edgeArg.target
244
- }, {
245
- F: __dxlog_file,
246
- L: 480,
247
- S: this,
248
- C: (f, a) => f(...a)
249
- });
250
- this._registry.set(sourceRx, {
251
- inbound: source.inbound,
252
- outbound: [
253
- ...source.outbound,
254
- edgeArg.target
255
- ]
256
- });
257
- }
258
- const targetRx = this._edges(edgeArg.target);
259
- const target = this._registry.get(targetRx);
260
- if (!target.inbound.includes(edgeArg.source)) {
261
- log("add inbound edge", {
262
- source: edgeArg.source,
263
- target: edgeArg.target
264
- }, {
265
- F: __dxlog_file,
266
- L: 487,
267
- S: this,
268
- C: (f, a) => f(...a)
269
- });
270
- this._registry.set(targetRx, {
271
- inbound: [
272
- ...target.inbound,
273
- edgeArg.source
274
- ],
275
- outbound: target.outbound
276
- });
277
- }
278
- }
279
- removeEdges(edges, removeOrphans = false) {
280
- Rx.batch(() => {
281
- edges.map((edge) => this.removeEdge(edge, removeOrphans));
282
- });
283
- }
284
- removeEdge(edgeArg, removeOrphans = false) {
285
- const sourceRx = this._edges(edgeArg.source);
286
- const source = this._registry.get(sourceRx);
287
- if (source.outbound.includes(edgeArg.target)) {
288
- this._registry.set(sourceRx, {
289
- inbound: source.inbound,
290
- outbound: source.outbound.filter((id) => id !== edgeArg.target)
291
- });
292
- }
293
- const targetRx = this._edges(edgeArg.target);
294
- const target = this._registry.get(targetRx);
295
- if (target.inbound.includes(edgeArg.source)) {
296
- this._registry.set(targetRx, {
297
- inbound: target.inbound.filter((id) => id !== edgeArg.source),
298
- outbound: target.outbound
299
- });
300
- }
301
- if (removeOrphans) {
302
- const source2 = this._registry.get(sourceRx);
303
- const target2 = this._registry.get(targetRx);
304
- if (source2.outbound.length === 0 && source2.inbound.length === 0 && edgeArg.source !== ROOT_ID) {
305
- this.removeNodes([
306
- edgeArg.source
307
- ]);
308
- }
309
- if (target2.outbound.length === 0 && target2.inbound.length === 0 && edgeArg.target !== ROOT_ID) {
310
- this.removeNodes([
311
- edgeArg.target
312
- ]);
313
- }
314
- }
315
- }
316
- sortEdges(id, relation, order) {
317
- const edgesRx = this._edges(id);
318
- const edges = this._registry.get(edgesRx);
319
- const unsorted = edges[relation].filter((id2) => !order.includes(id2)) ?? [];
320
- const sorted = order.filter((id2) => edges[relation].includes(id2)) ?? [];
321
- edges[relation].splice(0, edges[relation].length, ...[
322
- ...sorted,
323
- ...unsorted
324
- ]);
325
- this._registry.set(edgesRx, edges);
326
- }
327
- traverse({ visitor, source = ROOT_ID, relation = "outbound" }, path = []) {
328
- if (path.includes(source)) {
329
- return;
330
- }
331
- const node = this.getNodeOrThrow(source);
332
- const shouldContinue = visitor(node, [
333
- ...path,
334
- source
335
- ]);
336
- if (shouldContinue === false) {
337
- return;
338
- }
339
- Object.values(this.getConnections(source, relation)).forEach((child) => this.traverse({
340
- source: child.id,
341
- relation,
342
- visitor
343
- }, [
344
- ...path,
345
- source
346
- ]));
347
- }
348
- getPath({ source = "root", target }) {
349
- return pipe(this.getNode(source), Option.flatMap((node) => {
350
- let found = Option.none();
351
- this.traverse({
352
- source: node.id,
353
- visitor: (node2, path) => {
354
- if (Option.isSome(found)) {
355
- return false;
356
- }
357
- if (node2.id === target) {
358
- found = Option.some(path);
359
- }
360
- }
361
- });
362
- return found;
363
- }));
364
- }
365
- async waitForPath(params, { timeout = 5e3, interval = 500 } = {}) {
366
- const path = this.getPath(params);
367
- if (Option.isSome(path)) {
368
- return path.value;
369
- }
370
- const trigger = new Trigger();
371
- const i = setInterval(() => {
372
- const path2 = this.getPath(params);
373
- if (Option.isSome(path2)) {
374
- trigger.wake(path2.value);
375
- }
376
- }, interval);
377
- return trigger.wait({
378
- timeout
379
- }).finally(() => clearInterval(i));
380
- }
381
- /** @internal */
382
- _constructNode(node) {
383
- return Option.some({
384
- [graphSymbol]: this,
385
- data: null,
386
- properties: {},
387
- ...node
388
- });
389
- }
390
- constructor({ registry, nodes, edges, onInitialize, onExpand, onRemoveNode } = {}) {
391
- _define_property(this, "onNodeChanged", new Event());
392
- _define_property(this, "_onExpand", void 0);
393
- _define_property(this, "_onInitialize", void 0);
394
- _define_property(this, "_onRemoveNode", void 0);
395
- _define_property(this, "_registry", void 0);
396
- _define_property(this, "_expanded", Record.empty());
397
- _define_property(this, "_initialized", Record.empty());
398
- _define_property(this, "_initialEdges", Record.empty());
399
- _define_property(this, "_initialNodes", Record.fromEntries([
400
- [
401
- ROOT_ID,
402
- this._constructNode({
403
- id: ROOT_ID,
404
- type: ROOT_TYPE,
405
- data: null,
406
- properties: {}
407
- })
408
- ]
409
- ]));
410
- _define_property(this, "_node", Rx.family((id) => {
411
- const initial = Option.flatten(Record.get(this._initialNodes, id));
412
- return Rx.make(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:node:${id}`));
413
- }));
414
- _define_property(this, "_nodeOrThrow", Rx.family((id) => {
415
- return Rx.make((get) => {
416
- const node = get(this._node(id));
417
- invariant(Option.isSome(node), `Node not available: ${id}`, {
418
- F: __dxlog_file,
419
- L: 252,
420
- S: this,
421
- A: [
422
- "Option.isSome(node)",
423
- "`Node not available: ${id}`"
424
- ]
425
- });
426
- return node.value;
427
- });
428
- }));
429
- _define_property(this, "_edges", Rx.family((id) => {
430
- const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({
431
- inbound: [],
432
- outbound: []
433
- })));
434
- return Rx.make(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:edges:${id}`));
435
- }));
436
- _define_property(this, "_connections", Rx.family((key) => {
437
- return Rx.make((get) => {
438
- const [id, relation] = key.split("$");
439
- const edges2 = get(this._edges(id));
440
- return edges2[relation].map((id2) => get(this._node(id2))).filter(Option.isSome).map((o) => o.value);
441
- }).pipe(Rx.withLabel(`graph:connections:${key}`));
442
- }));
443
- _define_property(this, "_actions", Rx.family((id) => {
444
- return Rx.make((get) => {
445
- return get(this._connections(`${id}$outbound`)).filter((node) => node.type === ACTION_TYPE || node.type === ACTION_GROUP_TYPE);
446
- }).pipe(Rx.withLabel(`graph:actions:${id}`));
447
- }));
448
- _define_property(this, "_json", Rx.family((id) => {
449
- return Rx.make((get) => {
450
- const toJSON = (node, seen = []) => {
451
- const nodes2 = get(this.connections(node.id));
452
- const obj = {
453
- id: node.id.length > 32 ? `${node.id.slice(0, 32)}...` : node.id,
454
- type: node.type
455
- };
456
- if (node.properties.label) {
457
- obj.label = node.properties.label;
458
- }
459
- if (nodes2.length) {
460
- obj.nodes = nodes2.map((n) => {
461
- const nextSeen = [
462
- ...seen,
463
- node.id
464
- ];
465
- return nextSeen.includes(n.id) ? void 0 : toJSON(n, nextSeen);
466
- }).filter(isNonNullable);
467
- }
468
- return obj;
469
- };
470
- const root = get(this.nodeOrThrow(id));
471
- return toJSON(root);
472
- }).pipe(Rx.withLabel(`graph:json:${id}`));
473
- }));
474
- this._registry = registry ?? Registry.make();
475
- this._onInitialize = onInitialize;
476
- this._onExpand = onExpand;
477
- this._onRemoveNode = onRemoveNode;
478
- if (nodes) {
479
- nodes.forEach((node) => {
480
- Record.set(this._initialNodes, node.id, this._constructNode(node));
481
- });
482
- }
483
- if (edges) {
484
- Object.entries(edges).forEach(([source, edges2]) => {
485
- Record.set(this._initialEdges, source, edges2);
486
- });
487
- }
488
- }
489
- };
1
+ import {
2
+ __export,
3
+ getParentId,
4
+ getSegmentId,
5
+ graph_builder_exports,
6
+ graph_exports,
7
+ node_exports,
8
+ node_matcher_exports,
9
+ qualifyId
10
+ } from "./chunk-3T75MQOS.mjs";
490
11
 
491
- // src/graph-builder.ts
492
- import { Registry as Registry2, Rx as Rx2 } from "@effect-rx/rx-react";
493
- import { effect } from "@preact/signals-core";
494
- import { Array, Option as Option2, Record as Record2, pipe as pipe2 } from "effect";
495
- import { log as log2 } from "@dxos/log";
496
- import { byPosition, getDebugName, isNode, isNonNullable as isNonNullable2 } from "@dxos/util";
497
-
498
- // src/node.ts
499
- var isGraphNode = (data) => data && typeof data === "object" && "id" in data && "properties" in data && data.properties ? typeof data.properties === "object" && "data" in data : false;
500
- var isAction = (data) => isGraphNode(data) ? typeof data.data === "function" && data.type === ACTION_TYPE : false;
501
- var actionGroupSymbol = Symbol("ActionGroup");
502
- var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol && data.type === ACTION_GROUP_TYPE : false;
503
- var isActionLike = (data) => isAction(data) || isActionGroup(data);
504
-
505
- // src/graph-builder.ts
506
- function _define_property2(obj, key, value) {
507
- if (key in obj) {
508
- Object.defineProperty(obj, key, {
509
- value,
510
- enumerable: true,
511
- configurable: true,
512
- writable: true
513
- });
514
- } else {
515
- obj[key] = value;
516
- }
517
- return obj;
518
- }
519
- var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph-builder.ts";
520
- var createExtension = (extension) => {
521
- const { id, position = "static", relation = "outbound", resolver: _resolver, connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
522
- const getId = (key) => `${id}/${key}`;
523
- const resolver = _resolver && Rx2.family((id2) => _resolver(id2).pipe(Rx2.withLabel(`graph-builder:_resolver:${id2}`)));
524
- const connector = _connector && Rx2.family((node) => _connector(node).pipe(Rx2.withLabel(`graph-builder:_connector:${id}`)));
525
- const actionGroups = _actionGroups && Rx2.family((node) => _actionGroups(node).pipe(Rx2.withLabel(`graph-builder:_actionGroups:${id}`)));
526
- const actions = _actions && Rx2.family((node) => _actions(node).pipe(Rx2.withLabel(`graph-builder:_actions:${id}`)));
527
- return [
528
- resolver ? {
529
- id: getId("resolver"),
530
- position,
531
- resolver
532
- } : void 0,
533
- connector ? {
534
- id: getId("connector"),
535
- position,
536
- relation,
537
- connector: Rx2.family((node) => Rx2.make((get) => {
538
- try {
539
- return get(connector(node));
540
- } catch {
541
- log2.warn("Error in connector", {
542
- id: getId("connector"),
543
- node
544
- }, {
545
- F: __dxlog_file2,
546
- L: 109,
547
- S: void 0,
548
- C: (f, a) => f(...a)
549
- });
550
- return [];
551
- }
552
- }).pipe(Rx2.withLabel(`graph-builder:connector:${id}`)))
553
- } : void 0,
554
- actionGroups ? {
555
- id: getId("actionGroups"),
556
- position,
557
- relation: "outbound",
558
- connector: Rx2.family((node) => Rx2.make((get) => {
559
- try {
560
- return get(actionGroups(node)).map((arg) => ({
561
- ...arg,
562
- data: actionGroupSymbol,
563
- type: ACTION_GROUP_TYPE
564
- }));
565
- } catch {
566
- log2.warn("Error in actionGroups", {
567
- id: getId("actionGroups"),
568
- node
569
- }, {
570
- F: __dxlog_file2,
571
- L: 130,
572
- S: void 0,
573
- C: (f, a) => f(...a)
574
- });
575
- return [];
576
- }
577
- }).pipe(Rx2.withLabel(`graph-builder:connector:actionGroups:${id}`)))
578
- } : void 0,
579
- actions ? {
580
- id: getId("actions"),
581
- position,
582
- relation: "outbound",
583
- connector: Rx2.family((node) => Rx2.make((get) => {
584
- try {
585
- return get(actions(node)).map((arg) => ({
586
- ...arg,
587
- type: ACTION_TYPE
588
- }));
589
- } catch {
590
- log2.warn("Error in actions", {
591
- id: getId("actions"),
592
- node
593
- }, {
594
- F: __dxlog_file2,
595
- L: 147,
596
- S: void 0,
597
- C: (f, a) => f(...a)
598
- });
599
- return [];
600
- }
601
- }).pipe(Rx2.withLabel(`graph-builder:connector:actions:${id}`)))
602
- } : void 0
603
- ].filter(isNonNullable2);
604
- };
605
- var flattenExtensions = (extension, acc = []) => {
606
- if (Array.isArray(extension)) {
607
- return [
608
- ...acc,
609
- ...extension.flatMap((ext) => flattenExtensions(ext, acc))
610
- ];
611
- } else {
612
- return [
613
- ...acc,
614
- extension
615
- ];
616
- }
617
- };
618
- var GraphBuilder = class _GraphBuilder {
619
- static from(pickle, registry) {
620
- if (!pickle) {
621
- return new _GraphBuilder({
622
- registry
623
- });
624
- }
625
- const { nodes, edges } = JSON.parse(pickle);
626
- return new _GraphBuilder({
627
- nodes,
628
- edges,
629
- registry
630
- });
631
- }
632
- get graph() {
633
- return this._graph;
634
- }
635
- get extensions() {
636
- return this._extensions;
637
- }
638
- addExtension(extensions) {
639
- flattenExtensions(extensions).forEach((extension) => {
640
- const extensions2 = this._registry.get(this._extensions);
641
- this._registry.set(this._extensions, Record2.set(extensions2, extension.id, extension));
642
- });
643
- return this;
644
- }
645
- removeExtension(id) {
646
- const extensions = this._registry.get(this._extensions);
647
- this._registry.set(this._extensions, Record2.remove(extensions, id));
648
- return this;
649
- }
650
- async explore({ registry = Registry2.make(), source = ROOT_ID, relation = "outbound", visitor }, path = []) {
651
- if (path.includes(source)) {
652
- return;
653
- }
654
- if (!isNode()) {
655
- const { yieldOrContinue } = await import("main-thread-scheduling");
656
- await yieldOrContinue("idle");
657
- }
658
- const node = registry.get(this._graph.nodeOrThrow(source));
659
- const shouldContinue = await visitor(node, [
660
- ...path,
661
- node.id
662
- ]);
663
- if (shouldContinue === false) {
664
- return;
665
- }
666
- const nodes = Object.values(this._registry.get(this._extensions)).filter((extension) => relation === (extension.relation ?? "outbound")).map((extension) => extension.connector).filter(isNonNullable2).flatMap((connector) => registry.get(connector(this._graph.node(source))));
667
- await Promise.all(nodes.map((nodeArg) => {
668
- registry.set(this._graph._node(nodeArg.id), this._graph._constructNode(nodeArg));
669
- return this.explore({
670
- registry,
671
- source: nodeArg.id,
672
- relation,
673
- visitor
674
- }, [
675
- ...path,
676
- node.id
677
- ]);
678
- }));
679
- if (registry !== this._registry) {
680
- registry.reset();
681
- registry.dispose();
682
- }
683
- }
684
- destroy() {
685
- this._subscriptions.forEach((unsubscribe) => unsubscribe());
686
- this._subscriptions.clear();
687
- }
688
- _onExpand(id, relation) {
689
- log2("onExpand", {
690
- id,
691
- relation,
692
- registry: getDebugName(this._registry)
693
- }, {
694
- F: __dxlog_file2,
695
- L: 324,
696
- S: this,
697
- C: (f, a) => f(...a)
698
- });
699
- const connectors = this._connectors(`${id}+${relation}`);
700
- let previous = [];
701
- const cancel = this._registry.subscribe(connectors, (nodes) => {
702
- const ids = nodes.map((n) => n.id);
703
- const removed = previous.filter((id2) => !ids.includes(id2));
704
- previous = ids;
705
- log2("update", {
706
- id,
707
- relation,
708
- ids,
709
- removed
710
- }, {
711
- F: __dxlog_file2,
712
- L: 335,
713
- S: this,
714
- C: (f, a) => f(...a)
715
- });
716
- const update = () => {
717
- Rx2.batch(() => {
718
- this._graph.removeEdges(removed.map((target) => ({
719
- source: id,
720
- target
721
- })), true);
722
- this._graph.addNodes(nodes);
723
- this._graph.addEdges(nodes.map((node) => relation === "outbound" ? {
724
- source: id,
725
- target: node.id
726
- } : {
727
- source: node.id,
728
- target: id
729
- }));
730
- this._graph.sortEdges(id, relation, nodes.map(({ id: id2 }) => id2));
731
- });
732
- };
733
- if (typeof requestAnimationFrame === "function") {
734
- requestAnimationFrame(update);
735
- } else {
736
- update();
737
- }
738
- }, {
739
- immediate: true
740
- });
741
- this._subscriptions.set(id, cancel);
742
- }
743
- // TODO(wittjosiah): If the same node is added by a connector, the resolver should probably cancel itself?
744
- async _onInitialize(id) {
745
- log2("onInitialize", {
746
- id
747
- }, {
748
- F: __dxlog_file2,
749
- L: 372,
750
- S: this,
751
- C: (f, a) => f(...a)
752
- });
753
- const resolver = this._resolvers(id);
754
- const cancel = this._registry.subscribe(resolver, (node) => {
755
- const trigger = this._initialized[id];
756
- Option2.match(node, {
757
- onSome: (node2) => {
758
- this._graph.addNodes([
759
- node2
760
- ]);
761
- trigger?.wake();
762
- },
763
- onNone: () => {
764
- trigger?.wake();
765
- this._graph.removeNodes([
766
- id
767
- ]);
768
- }
769
- });
770
- }, {
771
- immediate: true
772
- });
773
- this._subscriptions.set(id, cancel);
774
- }
775
- _onRemoveNode(id) {
776
- this._subscriptions.get(id)?.();
777
- this._subscriptions.delete(id);
778
- }
779
- constructor({ registry, ...params } = {}) {
780
- _define_property2(this, "_subscriptions", /* @__PURE__ */ new Map());
781
- _define_property2(this, "_extensions", Rx2.make(Record2.empty()).pipe(Rx2.keepAlive, Rx2.withLabel("graph-builder:extensions")));
782
- _define_property2(this, "_initialized", {});
783
- _define_property2(this, "_registry", void 0);
784
- _define_property2(this, "_graph", void 0);
785
- _define_property2(this, "_resolvers", Rx2.family((id) => {
786
- return Rx2.make((get) => {
787
- 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);
788
- });
789
- }));
790
- _define_property2(this, "_connectors", Rx2.family((key) => {
791
- return Rx2.make((get) => {
792
- const [id, relation] = key.split("+");
793
- const node = this._graph.node(id);
794
- return pipe2(
795
- get(this._extensions),
796
- Record2.values,
797
- // TODO(wittjosiah): Sort on write rather than read.
798
- Array.sortBy(byPosition),
799
- Array.filter(({ relation: _relation = "outbound" }) => _relation === relation),
800
- Array.map(({ connector }) => connector?.(node)),
801
- Array.filter(isNonNullable2),
802
- Array.flatMap((result) => get(result))
803
- );
804
- }).pipe(Rx2.withLabel(`graph-builder:connectors:${key}`));
805
- }));
806
- this._registry = registry ?? Registry2.make();
807
- this._graph = new Graph({
808
- ...params,
809
- registry: this._registry,
810
- onExpand: (id, relation) => this._onExpand(id, relation),
811
- onInitialize: (id) => this._onInitialize(id),
812
- onRemoveNode: (id) => this._onRemoveNode(id)
813
- });
814
- }
815
- };
816
- var rxFromSignal = (cb) => {
817
- return Rx2.make((get) => {
818
- const dispose = effect(() => {
819
- get.setSelf(cb());
820
- });
821
- get.addFinalizer(() => dispose());
822
- return cb();
823
- });
824
- };
825
- var observableFamily = Rx2.family((observable) => {
826
- return Rx2.make((get) => {
12
+ // src/atoms.ts
13
+ var atoms_exports = {};
14
+ __export(atoms_exports, {
15
+ fromObservable: () => fromObservable
16
+ });
17
+ import { Atom } from "@effect-atom/atom-react";
18
+ var observableFamily = Atom.family((observable) => {
19
+ return Atom.make((get) => {
827
20
  const subscription = observable.subscribe((value) => get.setSelf(value));
828
21
  get.addFinalizer(() => subscription.unsubscribe());
829
22
  return observable.get();
830
23
  });
831
24
  });
832
- var rxFromObservable = (observable) => {
25
+ var fromObservable = (observable) => {
833
26
  return observableFamily(observable);
834
27
  };
835
28
  export {
836
- ACTION_GROUP_TYPE,
837
- ACTION_TYPE,
838
- Graph,
839
- GraphBuilder,
840
- ROOT_ID,
841
- ROOT_TYPE,
842
- actionGroupSymbol,
843
- createExtension,
844
- flattenExtensions,
845
- getGraph,
846
- isAction,
847
- isActionGroup,
848
- isActionLike,
849
- isGraphNode,
850
- rxFromObservable,
851
- rxFromSignal
29
+ atoms_exports as CreateAtom,
30
+ graph_exports as Graph,
31
+ graph_builder_exports as GraphBuilder,
32
+ node_exports as Node,
33
+ node_matcher_exports as NodeMatcher,
34
+ getParentId,
35
+ getSegmentId,
36
+ qualifyId
852
37
  };
853
38
  //# sourceMappingURL=index.mjs.map