@dxos/app-graph 0.8.4-main.67995b8 → 0.8.4-main.72ec0f3
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 +247 -189
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +247 -189
- 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/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 +33 -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 +1 -1
- package/src/signals-integration.test.ts +29 -28
- package/src/stories/EchoGraph.stories.tsx +42 -33
- package/src/stories/Tree.tsx +1 -1
- package/src/testing.ts +4 -4
|
@@ -2,39 +2,39 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import { Option, pipe } from 'effect';
|
|
5
|
+
import { Atom, type Registry, RegistryContext, useAtomValue } from '@effect-atom/atom-react';
|
|
6
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
7
|
+
import * as Function from 'effect/Function';
|
|
8
|
+
import * as Option from 'effect/Option';
|
|
10
9
|
import React, { type PropsWithChildren, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
11
10
|
|
|
12
11
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
Expando,
|
|
13
|
+
Filter,
|
|
14
|
+
type Live,
|
|
15
15
|
Query,
|
|
16
16
|
type QueryResult,
|
|
17
17
|
type Space,
|
|
18
18
|
SpaceState,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Filter,
|
|
19
|
+
isSpace,
|
|
20
|
+
live,
|
|
22
21
|
} from '@dxos/client/echo';
|
|
23
22
|
import { Obj, Type } from '@dxos/echo';
|
|
24
23
|
import { faker } from '@dxos/random';
|
|
25
24
|
import { type Client, useClient } from '@dxos/react-client';
|
|
26
25
|
import { withClientProvider } from '@dxos/react-client/testing';
|
|
27
|
-
import {
|
|
26
|
+
import { Icon, IconButton, Input, Select } from '@dxos/react-ui';
|
|
27
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
28
28
|
import { Path, Tree } from '@dxos/react-ui-list';
|
|
29
29
|
import { getSize, mx } from '@dxos/react-ui-theme';
|
|
30
|
-
import { withTheme } from '@dxos/storybook-utils';
|
|
31
30
|
import { byPosition, isNonNullable, safeParseInt } from '@dxos/util';
|
|
32
31
|
|
|
33
|
-
import { JsonTree } from './Tree';
|
|
34
32
|
import { type ExpandableGraph, ROOT_ID } from '../graph';
|
|
35
|
-
import { GraphBuilder,
|
|
33
|
+
import { GraphBuilder, atomFromObservable, createExtension } from '../graph-builder';
|
|
36
34
|
import { type Node } from '../node';
|
|
37
|
-
import {
|
|
35
|
+
import { atomFromQuery } from '../testing';
|
|
36
|
+
|
|
37
|
+
import { JsonTree } from './Tree';
|
|
38
38
|
|
|
39
39
|
const DEFAULT_PERIOD = 500;
|
|
40
40
|
|
|
@@ -60,18 +60,20 @@ const createGraph = (client: Client, registry: Registry.Registry): ExpandableGra
|
|
|
60
60
|
const spaceBuilderExtension = createExtension({
|
|
61
61
|
id: 'space',
|
|
62
62
|
connector: (node) =>
|
|
63
|
-
|
|
64
|
-
pipe(
|
|
63
|
+
Atom.make((get) =>
|
|
64
|
+
Function.pipe(
|
|
65
65
|
get(node),
|
|
66
66
|
Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
|
|
67
67
|
Option.map(() => {
|
|
68
|
-
const spaces = get(
|
|
68
|
+
const spaces = get(atomFromObservable(client.spaces)) ?? [];
|
|
69
69
|
return spaces
|
|
70
|
-
.filter((space) => get(
|
|
70
|
+
.filter((space) => get(atomFromObservable(space.state)) === SpaceState.SPACE_READY)
|
|
71
71
|
.map((space) => ({
|
|
72
72
|
id: space.id,
|
|
73
73
|
type: 'dxos.org/type/Space',
|
|
74
|
-
properties: {
|
|
74
|
+
properties: {
|
|
75
|
+
label: get(atomFromObservable(space.properties.name)),
|
|
76
|
+
},
|
|
75
77
|
data: space,
|
|
76
78
|
}));
|
|
77
79
|
}),
|
|
@@ -84,15 +86,15 @@ const createGraph = (client: Client, registry: Registry.Registry): ExpandableGra
|
|
|
84
86
|
id: 'object',
|
|
85
87
|
connector: (node) => {
|
|
86
88
|
let query: QueryResult<Live<Expando>> | undefined;
|
|
87
|
-
return
|
|
88
|
-
pipe(
|
|
89
|
+
return Atom.make((get) =>
|
|
90
|
+
Function.pipe(
|
|
89
91
|
get(node),
|
|
90
92
|
Option.flatMap((node) => (isSpace(node.data) ? Option.some(node.data) : Option.none())),
|
|
91
93
|
Option.map((space) => {
|
|
92
94
|
if (!query) {
|
|
93
95
|
query = space.db.query(Query.type(Expando, { type: 'test' }));
|
|
94
96
|
}
|
|
95
|
-
const objects = get(
|
|
97
|
+
const objects = get(atomFromQuery(query));
|
|
96
98
|
return objects.map((object) => ({
|
|
97
99
|
id: object.id,
|
|
98
100
|
type: 'dxos.org/type/test',
|
|
@@ -159,7 +161,12 @@ const runAction = async (client: Client, action: Action) => {
|
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
case Action.ADD_OBJECT:
|
|
162
|
-
getRandomSpace(client)?.db.add(
|
|
164
|
+
getRandomSpace(client)?.db.add(
|
|
165
|
+
Obj.make(Type.Expando, {
|
|
166
|
+
type: 'test',
|
|
167
|
+
name: faker.commerce.productName(),
|
|
168
|
+
}),
|
|
169
|
+
);
|
|
163
170
|
break;
|
|
164
171
|
|
|
165
172
|
case Action.REMOVE_OBJECT: {
|
|
@@ -214,7 +221,7 @@ const Controls = ({ children }: PropsWithChildren) => {
|
|
|
214
221
|
<Input.TextInput
|
|
215
222
|
autoComplete='off'
|
|
216
223
|
size={5}
|
|
217
|
-
classNames='
|
|
224
|
+
classNames='is-[100px] text-right pie-[22px]'
|
|
218
225
|
placeholder='Interval'
|
|
219
226
|
value={actionInterval}
|
|
220
227
|
onChange={({ target: { value } }) => setActionInterval(value)}
|
|
@@ -246,28 +253,30 @@ const Controls = ({ children }: PropsWithChildren) => {
|
|
|
246
253
|
);
|
|
247
254
|
};
|
|
248
255
|
|
|
249
|
-
const meta
|
|
256
|
+
const meta = {
|
|
250
257
|
title: 'sdk/app-graph/EchoGraph',
|
|
251
258
|
decorators: [
|
|
259
|
+
withTheme,
|
|
252
260
|
withClientProvider({
|
|
253
261
|
createIdentity: true,
|
|
254
|
-
|
|
262
|
+
onCreateIdentity: async ({ client }) => {
|
|
255
263
|
await client.spaces.create();
|
|
256
264
|
await client.spaces.create();
|
|
257
265
|
},
|
|
258
266
|
}),
|
|
259
|
-
withTheme,
|
|
260
267
|
],
|
|
261
|
-
};
|
|
268
|
+
} satisfies Meta;
|
|
262
269
|
|
|
263
270
|
export default meta;
|
|
264
271
|
|
|
265
|
-
|
|
272
|
+
type Story = StoryObj<typeof meta>;
|
|
273
|
+
|
|
274
|
+
export const JsonView: Story = {
|
|
266
275
|
render: () => {
|
|
267
276
|
const client = useClient();
|
|
268
277
|
const registry = useContext(RegistryContext);
|
|
269
278
|
const graph = useMemo(() => createGraph(client, registry), [client, registry]);
|
|
270
|
-
const data =
|
|
279
|
+
const data = useAtomValue(graph.json());
|
|
271
280
|
|
|
272
281
|
return (
|
|
273
282
|
<>
|
|
@@ -278,7 +287,7 @@ export const JsonView = {
|
|
|
278
287
|
},
|
|
279
288
|
};
|
|
280
289
|
|
|
281
|
-
export const TreeView = {
|
|
290
|
+
export const TreeView: Story = {
|
|
282
291
|
render: () => {
|
|
283
292
|
const client = useClient();
|
|
284
293
|
const registry = useContext(RegistryContext);
|
|
@@ -287,7 +296,7 @@ export const TreeView = {
|
|
|
287
296
|
|
|
288
297
|
const useItems = useCallback(
|
|
289
298
|
(node?: Node, options?: { disposition?: string; sort?: boolean }) => {
|
|
290
|
-
const connections =
|
|
299
|
+
const connections = useAtomValue(graph.connections(node?.id ?? ROOT_ID));
|
|
291
300
|
return options?.sort ? connections.toSorted((a, b) => byPosition(a.properties, b.properties)) : connections;
|
|
292
301
|
},
|
|
293
302
|
[graph],
|
package/src/stories/Tree.tsx
CHANGED
|
@@ -72,7 +72,7 @@ const Scalar: FC<{ value: any }> = ({ value }) => {
|
|
|
72
72
|
|
|
73
73
|
const Box: FC<HTMLAttributes<HTMLDivElement>> = ({ children, className, ...props }) => {
|
|
74
74
|
return (
|
|
75
|
-
<div className={mx('flex
|
|
75
|
+
<div className={mx('flex pli-2 border border-l-0 font-mono truncate', className)} {...props}>
|
|
76
76
|
{children}
|
|
77
77
|
</div>
|
|
78
78
|
);
|
package/src/testing.ts
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Atom } from '@effect-atom/atom-react';
|
|
6
6
|
|
|
7
|
+
import { type AnyEchoObject } from '@dxos/echo/internal';
|
|
7
8
|
import { type QueryResult } from '@dxos/echo-db';
|
|
8
|
-
import { type AnyEchoObject } from '@dxos/echo-schema';
|
|
9
9
|
|
|
10
|
-
export const
|
|
11
|
-
return
|
|
10
|
+
export const atomFromQuery = <T extends AnyEchoObject>(query: QueryResult<T>): Atom.Atom<T[]> => {
|
|
11
|
+
return Atom.make((get) => {
|
|
12
12
|
const unsubscribe = query.subscribe((result) => {
|
|
13
13
|
get.setSelf(result.objects);
|
|
14
14
|
});
|