@dxos/app-graph 0.8.4-main.f9ba587 → 0.8.4-main.fffef41
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 +249 -191
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +249 -191
- 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 +29 -18
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +25 -21
- package/dist/types/src/graph.d.ts.map +1 -1
- package/dist/types/src/node.d.ts +1 -1
- package/dist/types/src/node.d.ts.map +1 -1
- package/dist/types/src/stories/EchoGraph.stories.d.ts +8 -10
- package/dist/types/src/stories/EchoGraph.stories.d.ts.map +1 -1
- package/dist/types/src/testing.d.ts +3 -3
- package/dist/types/src/testing.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -34
- package/src/graph-builder.test.ts +90 -32
- package/src/graph-builder.ts +109 -60
- package/src/graph.test.ts +4 -4
- package/src/graph.ts +130 -89
- package/src/node.ts +5 -3
- package/src/signals-integration.test.ts +29 -28
- package/src/stories/EchoGraph.stories.tsx +49 -39
- package/src/stories/Tree.tsx +1 -1
- package/src/testing.ts +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/app-graph",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.fffef41",
|
|
4
4
|
"description": "Constructs knowledge graphs for the purpose of building applications on top of",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"type": "module",
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
|
+
"source": "./src/index.ts",
|
|
13
14
|
"types": "./dist/types/src/index.d.ts",
|
|
14
15
|
"browser": "./dist/lib/browser/index.mjs",
|
|
15
16
|
"node": "./dist/lib/node-esm/index.mjs"
|
|
@@ -24,46 +25,43 @@
|
|
|
24
25
|
"src"
|
|
25
26
|
],
|
|
26
27
|
"dependencies": {
|
|
27
|
-
"@preact/signals-core": "^1.
|
|
28
|
+
"@preact/signals-core": "^1.12.1",
|
|
28
29
|
"main-thread-scheduling": "^14.1.1",
|
|
29
|
-
"@dxos/async": "0.8.4-main.
|
|
30
|
-
"@dxos/debug": "0.8.4-main.
|
|
31
|
-
"@dxos/echo": "0.8.4-main.
|
|
32
|
-
"@dxos/echo-
|
|
33
|
-
"@dxos/
|
|
34
|
-
"@dxos/
|
|
35
|
-
"@dxos/
|
|
36
|
-
"@dxos/
|
|
37
|
-
"@dxos/util": "0.8.4-main.f9ba587"
|
|
30
|
+
"@dxos/async": "0.8.4-main.fffef41",
|
|
31
|
+
"@dxos/debug": "0.8.4-main.fffef41",
|
|
32
|
+
"@dxos/echo": "0.8.4-main.fffef41",
|
|
33
|
+
"@dxos/echo-signals": "0.8.4-main.fffef41",
|
|
34
|
+
"@dxos/invariant": "0.8.4-main.fffef41",
|
|
35
|
+
"@dxos/log": "0.8.4-main.fffef41",
|
|
36
|
+
"@dxos/util": "0.8.4-main.fffef41",
|
|
37
|
+
"@dxos/live-object": "0.8.4-main.fffef41"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@effect-
|
|
41
|
-
"@effect/platform": "0.
|
|
42
|
-
"@
|
|
43
|
-
"@types/react": "~
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"react": "~
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"@dxos/
|
|
50
|
-
"@dxos/
|
|
51
|
-
"@dxos/react-
|
|
52
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
53
|
-
"@dxos/react-ui-
|
|
54
|
-
"@dxos/react-ui-
|
|
55
|
-
"@dxos/
|
|
56
|
-
"@dxos/storybook-utils": "0.8.4-main.f9ba587"
|
|
40
|
+
"@effect-atom/atom-react": "^0.3.4",
|
|
41
|
+
"@effect/platform": "0.92.1",
|
|
42
|
+
"@types/react": "~19.2.2",
|
|
43
|
+
"@types/react-dom": "~19.2.2",
|
|
44
|
+
"effect": "3.18.3",
|
|
45
|
+
"react": "~19.2.0",
|
|
46
|
+
"react-dom": "~19.2.0",
|
|
47
|
+
"vite": "7.1.9",
|
|
48
|
+
"@dxos/echo-db": "0.8.4-main.fffef41",
|
|
49
|
+
"@dxos/random": "0.8.4-main.fffef41",
|
|
50
|
+
"@dxos/react-client": "0.8.4-main.fffef41",
|
|
51
|
+
"@dxos/react-ui": "0.8.4-main.fffef41",
|
|
52
|
+
"@dxos/react-ui-list": "0.8.4-main.fffef41",
|
|
53
|
+
"@dxos/react-ui-tabs": "0.8.4-main.fffef41",
|
|
54
|
+
"@dxos/react-ui-theme": "0.8.4-main.fffef41",
|
|
55
|
+
"@dxos/storybook-utils": "0.8.4-main.fffef41"
|
|
57
56
|
},
|
|
58
57
|
"peerDependencies": {
|
|
59
|
-
"@effect-
|
|
58
|
+
"@effect-atom/atom-react": "^0.3.4",
|
|
60
59
|
"@effect/platform": "^0.80.12",
|
|
61
|
-
"@phosphor-icons/react": "^2.1.5",
|
|
62
60
|
"effect": "3.14.21",
|
|
63
|
-
"react": "
|
|
64
|
-
"react-dom": "
|
|
65
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
66
|
-
"@dxos/react-ui-theme": "0.8.4-main.
|
|
61
|
+
"react": "^19.0.0",
|
|
62
|
+
"react-dom": "^19.0.0",
|
|
63
|
+
"@dxos/react-ui": "0.8.4-main.fffef41",
|
|
64
|
+
"@dxos/react-ui-theme": "0.8.4-main.fffef41"
|
|
67
65
|
},
|
|
68
66
|
"publishConfig": {
|
|
69
67
|
"access": "public"
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
5
|
+
import { Atom, Registry } from '@effect-atom/atom-react';
|
|
6
|
+
import * as Function from 'effect/Function';
|
|
7
|
+
import * as Option from 'effect/Option';
|
|
7
8
|
import { describe, expect, onTestFinished, test } from 'vitest';
|
|
8
9
|
|
|
9
|
-
import {
|
|
10
|
+
import { Trigger, sleep } from '@dxos/async';
|
|
10
11
|
|
|
11
12
|
import { ROOT_ID } from './graph';
|
|
12
|
-
import {
|
|
13
|
+
import { GraphBuilder, createExtension } from './graph-builder';
|
|
13
14
|
import { type Node } from './node';
|
|
14
15
|
|
|
15
16
|
const exampleId = (id: number) => `dx:test:${id}`;
|
|
@@ -17,6 +18,63 @@ const EXAMPLE_ID = exampleId(1);
|
|
|
17
18
|
const EXAMPLE_TYPE = 'dxos.org/type/example';
|
|
18
19
|
|
|
19
20
|
describe('GraphBuilder', () => {
|
|
21
|
+
describe('resolver', () => {
|
|
22
|
+
test('works', async () => {
|
|
23
|
+
const registry = Registry.make();
|
|
24
|
+
const builder = new GraphBuilder({ registry });
|
|
25
|
+
const graph = builder.graph;
|
|
26
|
+
|
|
27
|
+
{
|
|
28
|
+
const node = graph.getNode(EXAMPLE_ID).pipe(Option.getOrNull);
|
|
29
|
+
expect(node).to.be.null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
builder.addExtension(
|
|
33
|
+
createExtension({
|
|
34
|
+
id: 'resolver',
|
|
35
|
+
resolver: () => {
|
|
36
|
+
console.log('resolver');
|
|
37
|
+
return Atom.make({ id: EXAMPLE_ID, type: EXAMPLE_TYPE, data: 1 });
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
41
|
+
await graph.initialize(EXAMPLE_ID);
|
|
42
|
+
|
|
43
|
+
{
|
|
44
|
+
const node = graph.getNode(EXAMPLE_ID).pipe(Option.getOrNull);
|
|
45
|
+
expect(node?.id).to.equal(EXAMPLE_ID);
|
|
46
|
+
expect(node?.type).to.equal(EXAMPLE_TYPE);
|
|
47
|
+
expect(node?.data).to.equal(1);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('updates', async () => {
|
|
52
|
+
const registry = Registry.make();
|
|
53
|
+
const builder = new GraphBuilder({ registry });
|
|
54
|
+
const name = Atom.make('default');
|
|
55
|
+
builder.addExtension(
|
|
56
|
+
createExtension({
|
|
57
|
+
id: 'resolver',
|
|
58
|
+
resolver: () => Atom.make((get) => ({ id: EXAMPLE_ID, type: EXAMPLE_TYPE, data: get(name) })),
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
61
|
+
const graph = builder.graph;
|
|
62
|
+
await graph.initialize(EXAMPLE_ID);
|
|
63
|
+
|
|
64
|
+
{
|
|
65
|
+
const node = graph.getNode(EXAMPLE_ID).pipe(Option.getOrNull);
|
|
66
|
+
expect(node?.data).to.equal('default');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
registry.set(name, 'updated');
|
|
70
|
+
|
|
71
|
+
{
|
|
72
|
+
const node = graph.getNode(EXAMPLE_ID).pipe(Option.getOrNull);
|
|
73
|
+
expect(node?.data).to.equal('updated');
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
20
78
|
describe('connector', () => {
|
|
21
79
|
test('works', () => {
|
|
22
80
|
const registry = Registry.make();
|
|
@@ -24,14 +82,14 @@ describe('GraphBuilder', () => {
|
|
|
24
82
|
builder.addExtension(
|
|
25
83
|
createExtension({
|
|
26
84
|
id: 'outbound-connector',
|
|
27
|
-
connector: () =>
|
|
85
|
+
connector: () => Atom.make([{ id: 'child', type: EXAMPLE_TYPE, data: 2 }]),
|
|
28
86
|
}),
|
|
29
87
|
);
|
|
30
88
|
builder.addExtension(
|
|
31
89
|
createExtension({
|
|
32
90
|
id: 'inbound-connector',
|
|
33
91
|
relation: 'inbound',
|
|
34
|
-
connector: () =>
|
|
92
|
+
connector: () => Atom.make([{ id: 'parent', type: EXAMPLE_TYPE, data: 0 }]),
|
|
35
93
|
}),
|
|
36
94
|
);
|
|
37
95
|
|
|
@@ -53,11 +111,11 @@ describe('GraphBuilder', () => {
|
|
|
53
111
|
test('updates', () => {
|
|
54
112
|
const registry = Registry.make();
|
|
55
113
|
const builder = new GraphBuilder({ registry });
|
|
56
|
-
const state =
|
|
114
|
+
const state = Atom.make(0);
|
|
57
115
|
builder.addExtension(
|
|
58
116
|
createExtension({
|
|
59
117
|
id: 'connector',
|
|
60
|
-
connector: () =>
|
|
118
|
+
connector: () => Atom.make((get) => [{ id: EXAMPLE_ID, type: EXAMPLE_TYPE, data: get(state) }]),
|
|
61
119
|
}),
|
|
62
120
|
);
|
|
63
121
|
const graph = builder.graph;
|
|
@@ -78,11 +136,11 @@ describe('GraphBuilder', () => {
|
|
|
78
136
|
test('subscribes to updates', () => {
|
|
79
137
|
const registry = Registry.make();
|
|
80
138
|
const builder = new GraphBuilder({ registry });
|
|
81
|
-
const state =
|
|
139
|
+
const state = Atom.make(0);
|
|
82
140
|
builder.addExtension(
|
|
83
141
|
createExtension({
|
|
84
142
|
id: 'connector',
|
|
85
|
-
connector: () =>
|
|
143
|
+
connector: () => Atom.make((get) => [{ id: EXAMPLE_ID, type: EXAMPLE_TYPE, data: get(state) }]),
|
|
86
144
|
}),
|
|
87
145
|
);
|
|
88
146
|
const graph = builder.graph;
|
|
@@ -109,7 +167,7 @@ describe('GraphBuilder', () => {
|
|
|
109
167
|
builder.addExtension(
|
|
110
168
|
createExtension({
|
|
111
169
|
id: 'connector',
|
|
112
|
-
connector: () =>
|
|
170
|
+
connector: () => Atom.make([{ id: EXAMPLE_ID, type: EXAMPLE_TYPE }]),
|
|
113
171
|
}),
|
|
114
172
|
);
|
|
115
173
|
const graph = builder.graph;
|
|
@@ -132,7 +190,7 @@ describe('GraphBuilder', () => {
|
|
|
132
190
|
builder.addExtension(
|
|
133
191
|
createExtension({
|
|
134
192
|
id: 'connector-2',
|
|
135
|
-
connector: () =>
|
|
193
|
+
connector: () => Atom.make([{ id: exampleId(2), type: EXAMPLE_TYPE }]),
|
|
136
194
|
}),
|
|
137
195
|
);
|
|
138
196
|
expect(nodes).has.length(2);
|
|
@@ -142,14 +200,14 @@ describe('GraphBuilder', () => {
|
|
|
142
200
|
test('removes', () => {
|
|
143
201
|
const registry = Registry.make();
|
|
144
202
|
const builder = new GraphBuilder({ registry });
|
|
145
|
-
const nodes =
|
|
203
|
+
const nodes = Atom.make([
|
|
146
204
|
{ id: exampleId(1), type: EXAMPLE_TYPE },
|
|
147
205
|
{ id: exampleId(2), type: EXAMPLE_TYPE },
|
|
148
206
|
]);
|
|
149
207
|
builder.addExtension(
|
|
150
208
|
createExtension({
|
|
151
209
|
id: 'connector',
|
|
152
|
-
connector: () =>
|
|
210
|
+
connector: () => Atom.make((get) => get(nodes)),
|
|
153
211
|
}),
|
|
154
212
|
);
|
|
155
213
|
const graph = builder.graph;
|
|
@@ -174,14 +232,14 @@ describe('GraphBuilder', () => {
|
|
|
174
232
|
test('nodes are updated when removed', () => {
|
|
175
233
|
const registry = Registry.make();
|
|
176
234
|
const builder = new GraphBuilder({ registry });
|
|
177
|
-
const name =
|
|
235
|
+
const name = Atom.make('removed');
|
|
178
236
|
|
|
179
237
|
builder.addExtension([
|
|
180
238
|
createExtension({
|
|
181
239
|
id: 'root',
|
|
182
240
|
connector: (node) =>
|
|
183
|
-
|
|
184
|
-
pipe(
|
|
241
|
+
Atom.make((get) =>
|
|
242
|
+
Function.pipe(
|
|
185
243
|
get(node),
|
|
186
244
|
Option.flatMap((node) => (node.id === 'root' ? Option.some(get(name)) : Option.none())),
|
|
187
245
|
Option.filter((name) => name !== 'removed'),
|
|
@@ -222,7 +280,7 @@ describe('GraphBuilder', () => {
|
|
|
222
280
|
test('sort edges', async () => {
|
|
223
281
|
const registry = Registry.make();
|
|
224
282
|
const builder = new GraphBuilder({ registry });
|
|
225
|
-
const nodes =
|
|
283
|
+
const nodes = Atom.make([
|
|
226
284
|
{ id: exampleId(1), type: EXAMPLE_TYPE, data: 1 },
|
|
227
285
|
{ id: exampleId(2), type: EXAMPLE_TYPE, data: 2 },
|
|
228
286
|
{ id: exampleId(3), type: EXAMPLE_TYPE, data: 3 },
|
|
@@ -230,7 +288,7 @@ describe('GraphBuilder', () => {
|
|
|
230
288
|
builder.addExtension(
|
|
231
289
|
createExtension({
|
|
232
290
|
id: 'connector',
|
|
233
|
-
connector: () =>
|
|
291
|
+
connector: () => Atom.make((get) => get(nodes)),
|
|
234
292
|
}),
|
|
235
293
|
);
|
|
236
294
|
const graph = builder.graph;
|
|
@@ -265,15 +323,15 @@ describe('GraphBuilder', () => {
|
|
|
265
323
|
test('updates are constrained', () => {
|
|
266
324
|
const registry = Registry.make();
|
|
267
325
|
const builder = new GraphBuilder({ registry });
|
|
268
|
-
const name =
|
|
269
|
-
const sub =
|
|
326
|
+
const name = Atom.make('default');
|
|
327
|
+
const sub = Atom.make('default');
|
|
270
328
|
|
|
271
329
|
builder.addExtension([
|
|
272
330
|
createExtension({
|
|
273
331
|
id: 'root',
|
|
274
332
|
connector: (node) =>
|
|
275
|
-
|
|
276
|
-
pipe(
|
|
333
|
+
Atom.make((get) =>
|
|
334
|
+
Function.pipe(
|
|
277
335
|
get(node),
|
|
278
336
|
Option.flatMap((node) => (node.id === 'root' ? Option.some(get(name)) : Option.none())),
|
|
279
337
|
Option.filter((name) => name !== 'removed'),
|
|
@@ -285,8 +343,8 @@ describe('GraphBuilder', () => {
|
|
|
285
343
|
createExtension({
|
|
286
344
|
id: 'connector1',
|
|
287
345
|
connector: (node) =>
|
|
288
|
-
|
|
289
|
-
pipe(
|
|
346
|
+
Atom.make((get) =>
|
|
347
|
+
Function.pipe(
|
|
290
348
|
get(node),
|
|
291
349
|
Option.flatMap((node) => (node.id === EXAMPLE_ID ? Option.some(get(sub)) : Option.none())),
|
|
292
350
|
Option.map((sub) => [{ id: exampleId(2), type: EXAMPLE_TYPE, data: sub }]),
|
|
@@ -297,8 +355,8 @@ describe('GraphBuilder', () => {
|
|
|
297
355
|
createExtension({
|
|
298
356
|
id: 'connector2',
|
|
299
357
|
connector: (node) =>
|
|
300
|
-
|
|
301
|
-
pipe(
|
|
358
|
+
Atom.make((get) =>
|
|
359
|
+
Function.pipe(
|
|
302
360
|
get(node),
|
|
303
361
|
Option.flatMap((node) => (node.id === EXAMPLE_ID ? Option.some(node.data) : Option.none())),
|
|
304
362
|
Option.map((data) => [{ id: exampleId(3), type: EXAMPLE_TYPE, data }]),
|
|
@@ -353,7 +411,7 @@ describe('GraphBuilder', () => {
|
|
|
353
411
|
expect(dependentCount).to.equal(2);
|
|
354
412
|
|
|
355
413
|
// Independent count should update if its state changes even if the parent is removed.
|
|
356
|
-
|
|
414
|
+
Atom.batch(() => {
|
|
357
415
|
registry.set(name, 'removed');
|
|
358
416
|
registry.set(sub, 'batch');
|
|
359
417
|
});
|
|
@@ -381,8 +439,8 @@ describe('GraphBuilder', () => {
|
|
|
381
439
|
createExtension({
|
|
382
440
|
id: 'connector',
|
|
383
441
|
connector: (node) => {
|
|
384
|
-
return
|
|
385
|
-
pipe(
|
|
442
|
+
return Atom.make((get) =>
|
|
443
|
+
Function.pipe(
|
|
386
444
|
get(node),
|
|
387
445
|
Option.map((node) => (node.data ? node.data + 1 : 1)),
|
|
388
446
|
Option.filter((data) => data <= 5),
|
|
@@ -417,8 +475,8 @@ describe('GraphBuilder', () => {
|
|
|
417
475
|
createExtension({
|
|
418
476
|
id: 'connector',
|
|
419
477
|
connector: (node) =>
|
|
420
|
-
|
|
421
|
-
pipe(
|
|
478
|
+
Atom.make((get) =>
|
|
479
|
+
Function.pipe(
|
|
422
480
|
get(node),
|
|
423
481
|
Option.map((node) => (node.data ? node.data + 1 : 1)),
|
|
424
482
|
Option.filter((data) => data <= 5),
|