@nesso-how/formats 0.1.0-alpha.33 → 0.1.0-alpha.34
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.d.ts +24 -11
- package/dist/index.js +32 -29
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,25 +1,38 @@
|
|
|
1
1
|
import type { Node, Edge } from '@xyflow/react';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
2
|
+
import type { GraphDisplaySettings } from '@nesso-how/types';
|
|
3
|
+
/** Current on-disk graph file schema version. Bump only when the envelope shape changes. */
|
|
4
|
+
export declare const GRAPH_FORMAT_VERSION: 1;
|
|
5
|
+
export interface NessoGraphFile<D extends Record<string, unknown> = Record<string, unknown>> {
|
|
6
|
+
/** File format version — always {@link GRAPH_FORMAT_VERSION} for the current schema. */
|
|
7
|
+
version: typeof GRAPH_FORMAT_VERSION;
|
|
8
|
+
/**
|
|
9
|
+
* Vocabulary this graph was built with: its id (e.g. `@nesso-how/vocab-learning`)
|
|
10
|
+
* and normative version. Opaque to formats, which only round-trips the reference.
|
|
11
|
+
*/
|
|
12
|
+
vocabulary?: {
|
|
13
|
+
id: string;
|
|
14
|
+
version: string;
|
|
15
|
+
};
|
|
4
16
|
/** Internal graph id (desktop sync); omitted in manual exports. */
|
|
5
17
|
id?: string;
|
|
6
18
|
/** Last save time (Unix ms); desktop sync metadata. */
|
|
7
19
|
updatedAt?: number;
|
|
8
20
|
name: string;
|
|
9
|
-
nodes: Node<
|
|
21
|
+
nodes: Node<D>[];
|
|
10
22
|
edges: Edge[];
|
|
11
23
|
display?: Partial<GraphDisplaySettings>;
|
|
12
24
|
}
|
|
13
|
-
|
|
25
|
+
/** Graph payload for {@link serializeGraph} — format version is injected by the serializer. */
|
|
26
|
+
export type NessoGraphFileInput<D extends Record<string, unknown> = Record<string, unknown>> = Omit<NessoGraphFile<D>, 'version'>;
|
|
27
|
+
/** Serialize a graph to JSON with keys in a stable, human-readable order. */
|
|
28
|
+
export declare function serializeGraph<D extends Record<string, unknown>>(file: NessoGraphFileInput<D>): string;
|
|
14
29
|
/**
|
|
15
30
|
* Parse and structurally validate a graph file. Files are user-editable (and
|
|
16
31
|
* importable from anywhere), so each element is checked before it can reach
|
|
17
32
|
* the store: a node without a valid id/position crashes the canvas and would
|
|
18
|
-
* then be re-persisted.
|
|
19
|
-
*
|
|
33
|
+
* then be re-persisted. Vocabulary-specific normalization (e.g. private params)
|
|
34
|
+
* is the caller's responsibility.
|
|
20
35
|
*/
|
|
21
|
-
export declare function deserializeGraph(json: string): NessoGraphFile
|
|
22
|
-
/**
|
|
23
|
-
export declare function
|
|
24
|
-
/** Reset review fields on import so shared files never restore someone else's scheduling. */
|
|
25
|
-
export declare function nodesFromGraphShareImport(nodes: Node<ConceptNodeData>[]): Node<ConceptNodeData>[];
|
|
36
|
+
export declare function deserializeGraph<D extends Record<string, unknown> = Record<string, unknown>>(json: string): NessoGraphFile<D>;
|
|
37
|
+
/** Overwrite private node params with vocabulary defaults (e.g. for share export/import). */
|
|
38
|
+
export declare function stripPrivateNodeParams<D extends Record<string, unknown>>(nodes: Node<D>[], privateDefaults: Partial<D>): Node<D>[];
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
/** Current on-disk graph file schema version. Bump only when the envelope shape changes. */
|
|
2
|
+
export const GRAPH_FORMAT_VERSION = 1;
|
|
3
|
+
/** Serialize a graph to JSON with keys in a stable, human-readable order. */
|
|
2
4
|
export function serializeGraph(file) {
|
|
3
|
-
|
|
5
|
+
const { vocabulary, id, updatedAt, name, nodes, edges, display } = file;
|
|
6
|
+
return JSON.stringify({
|
|
7
|
+
version: GRAPH_FORMAT_VERSION,
|
|
8
|
+
...(vocabulary !== undefined && { vocabulary }),
|
|
9
|
+
...(id !== undefined && { id }),
|
|
10
|
+
...(updatedAt !== undefined && { updatedAt }),
|
|
11
|
+
name,
|
|
12
|
+
nodes,
|
|
13
|
+
edges,
|
|
14
|
+
...(display !== undefined && { display }),
|
|
15
|
+
}, null, 2);
|
|
4
16
|
}
|
|
5
17
|
function asRecord(value) {
|
|
6
18
|
return typeof value === 'object' && value !== null ? value : null;
|
|
@@ -9,8 +21,8 @@ function asRecord(value) {
|
|
|
9
21
|
* Parse and structurally validate a graph file. Files are user-editable (and
|
|
10
22
|
* importable from anywhere), so each element is checked before it can reach
|
|
11
23
|
* the store: a node without a valid id/position crashes the canvas and would
|
|
12
|
-
* then be re-persisted.
|
|
13
|
-
*
|
|
24
|
+
* then be re-persisted. Vocabulary-specific normalization (e.g. private params)
|
|
25
|
+
* is the caller's responsibility.
|
|
14
26
|
*/
|
|
15
27
|
export function deserializeGraph(json) {
|
|
16
28
|
const data = JSON.parse(json);
|
|
@@ -18,7 +30,9 @@ export function deserializeGraph(json) {
|
|
|
18
30
|
if (!root || !Array.isArray(root.nodes) || !Array.isArray(root.edges)) {
|
|
19
31
|
throw new Error('Invalid Nesso graph file: missing nodes or edges array');
|
|
20
32
|
}
|
|
21
|
-
|
|
33
|
+
if (typeof root.version === 'number' && root.version !== GRAPH_FORMAT_VERSION) {
|
|
34
|
+
throw new Error(`Unsupported Nesso graph file version: ${root.version}`);
|
|
35
|
+
}
|
|
22
36
|
const nodes = root.nodes.map((value, i) => {
|
|
23
37
|
const node = asRecord(value);
|
|
24
38
|
const pos = node ? asRecord(node.position) : null;
|
|
@@ -32,11 +46,7 @@ export function deserializeGraph(json) {
|
|
|
32
46
|
!Number.isFinite(pos.y)) {
|
|
33
47
|
throw new Error(`Invalid Nesso graph file: node ${i} is missing a valid id or position`);
|
|
34
48
|
}
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
...node,
|
|
38
|
-
data: { ...review, ...d, text: typeof d.text === 'string' ? d.text : '' },
|
|
39
|
-
};
|
|
49
|
+
return node;
|
|
40
50
|
});
|
|
41
51
|
const edges = root.edges.map((value, i) => {
|
|
42
52
|
const edge = asRecord(value);
|
|
@@ -48,24 +58,17 @@ export function deserializeGraph(json) {
|
|
|
48
58
|
}
|
|
49
59
|
return edge;
|
|
50
60
|
});
|
|
51
|
-
return {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const { text, elaboration } = node.data ?? { text: '' };
|
|
58
|
-
return {
|
|
59
|
-
...node,
|
|
60
|
-
data: {
|
|
61
|
-
text: text ?? '',
|
|
62
|
-
...(elaboration ? { elaboration } : {}),
|
|
63
|
-
...review,
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
});
|
|
61
|
+
return {
|
|
62
|
+
...root,
|
|
63
|
+
version: GRAPH_FORMAT_VERSION,
|
|
64
|
+
nodes,
|
|
65
|
+
edges,
|
|
66
|
+
};
|
|
67
67
|
}
|
|
68
|
-
/**
|
|
69
|
-
export function
|
|
70
|
-
return
|
|
68
|
+
/** Overwrite private node params with vocabulary defaults (e.g. for share export/import). */
|
|
69
|
+
export function stripPrivateNodeParams(nodes, privateDefaults) {
|
|
70
|
+
return nodes.map((node) => ({
|
|
71
|
+
...node,
|
|
72
|
+
data: { ...node.data, ...privateDefaults },
|
|
73
|
+
}));
|
|
71
74
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nesso-how/formats",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.34",
|
|
4
4
|
"description": "Nesso graph serialization formats — JSON serialize/deserialize",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@nesso-how/types": "0.1.0-alpha.
|
|
25
|
+
"@nesso-how/types": "0.1.0-alpha.34"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@xyflow/react": "^12.6.4"
|