@xenolithengine/graph-core 0.7.0-beta.0
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/LICENSE +21 -0
- package/README.md +55 -0
- package/dist/command-bus.d.ts +56 -0
- package/dist/command-bus.d.ts.map +1 -0
- package/dist/command-bus.js +180 -0
- package/dist/command-bus.js.map +1 -0
- package/dist/commands-comment.d.ts +52 -0
- package/dist/commands-comment.d.ts.map +1 -0
- package/dist/commands-comment.js +92 -0
- package/dist/commands-comment.js.map +1 -0
- package/dist/commands-mut.d.ts +58 -0
- package/dist/commands-mut.d.ts.map +1 -0
- package/dist/commands-mut.js +119 -0
- package/dist/commands-mut.js.map +1 -0
- package/dist/commands.d.ts +36 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +72 -0
- package/dist/commands.js.map +1 -0
- package/dist/comment-spatial.d.ts +20 -0
- package/dist/comment-spatial.d.ts.map +1 -0
- package/dist/comment-spatial.js +21 -0
- package/dist/comment-spatial.js.map +1 -0
- package/dist/event-emitter.d.ts +15 -0
- package/dist/event-emitter.d.ts.map +1 -0
- package/dist/event-emitter.js +55 -0
- package/dist/event-emitter.js.map +1 -0
- package/dist/fuzzy.d.ts +17 -0
- package/dist/fuzzy.d.ts.map +1 -0
- package/dist/fuzzy.js +55 -0
- package/dist/fuzzy.js.map +1 -0
- package/dist/graph.d.ts +108 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +141 -0
- package/dist/graph.js.map +1 -0
- package/dist/ids.d.ts +28 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +31 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/macro.d.ts +120 -0
- package/dist/macro.d.ts.map +1 -0
- package/dist/macro.js +226 -0
- package/dist/macro.js.map +1 -0
- package/dist/node-registry.d.ts +101 -0
- package/dist/node-registry.d.ts.map +1 -0
- package/dist/node-registry.js +96 -0
- package/dist/node-registry.js.map +1 -0
- package/dist/reroute.d.ts +21 -0
- package/dist/reroute.d.ts.map +1 -0
- package/dist/reroute.js +40 -0
- package/dist/reroute.js.map +1 -0
- package/dist/selection.d.ts +17 -0
- package/dist/selection.d.ts.map +1 -0
- package/dist/selection.js +56 -0
- package/dist/selection.js.map +1 -0
- package/dist/template-def.d.ts +113 -0
- package/dist/template-def.d.ts.map +1 -0
- package/dist/template-def.js +0 -0
- package/dist/template-def.js.map +1 -0
- package/dist/template-flatten.d.ts +38 -0
- package/dist/template-flatten.d.ts.map +1 -0
- package/dist/template-flatten.js +157 -0
- package/dist/template-flatten.js.map +1 -0
- package/dist/traversal.d.ts +27 -0
- package/dist/traversal.d.ts.map +1 -0
- package/dist/traversal.js +119 -0
- package/dist/traversal.js.map +1 -0
- package/dist/types-registry.d.ts +41 -0
- package/dist/types-registry.d.ts.map +1 -0
- package/dist/types-registry.js +60 -0
- package/dist/types-registry.js.map +1 -0
- package/dist/widget.d.ts +141 -0
- package/dist/widget.d.ts.map +1 -0
- package/dist/widget.js +112 -0
- package/dist/widget.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { TEMPLATE_INPUT_TYPE, TEMPLATE_OUTPUT_TYPE, isTemplateBoundary, isTemplateInstance, } from './template-def.js';
|
|
2
|
+
/** Flatten `instance` against the definitions reachable through `resolveDef`. Returns null if a
|
|
3
|
+
* definition is missing or a recursion cycle is detected (a definition transitively containing an
|
|
4
|
+
* instance of itself). Pure — never mutates the instance, definitions, or document. */
|
|
5
|
+
export function flattenTemplateInstance(instance, resolveDef, mint) {
|
|
6
|
+
return flatten(instance, resolveDef, mint, []);
|
|
7
|
+
}
|
|
8
|
+
function flatten(instance, resolveDef, mint, path) {
|
|
9
|
+
const defId = instance.state['definitionId'];
|
|
10
|
+
if (defId === undefined)
|
|
11
|
+
return null;
|
|
12
|
+
if (path.includes(defId))
|
|
13
|
+
return null; // cycle: this definition is already being flattened above us
|
|
14
|
+
const def = resolveDef(defId);
|
|
15
|
+
if (!def)
|
|
16
|
+
return null;
|
|
17
|
+
const childPath = [...path, defId];
|
|
18
|
+
const boundaryToInstPin = invertPinBoundary(instance);
|
|
19
|
+
const nodes = [];
|
|
20
|
+
const edges = [];
|
|
21
|
+
const inputs = {};
|
|
22
|
+
const outputs = {};
|
|
23
|
+
// Resolve each definition member: a primitive gets a fresh-id clone; a nested instance is flattened
|
|
24
|
+
// recursively and remembered so edges touching its pins redirect to its internal pins.
|
|
25
|
+
const primitive = new Map();
|
|
26
|
+
const nested = new Map();
|
|
27
|
+
for (const m of def.nodes) {
|
|
28
|
+
if (isTemplateBoundary(m))
|
|
29
|
+
continue;
|
|
30
|
+
if (isTemplateInstance(m)) {
|
|
31
|
+
const child = flatten(m, resolveDef, mint, childPath);
|
|
32
|
+
if (!child)
|
|
33
|
+
return null;
|
|
34
|
+
nodes.push(...child.nodes);
|
|
35
|
+
edges.push(...child.edges);
|
|
36
|
+
nested.set(String(m.id), child);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const id = mint.node();
|
|
40
|
+
const pinRemap = new Map();
|
|
41
|
+
const pins = m.pins.map((p) => { const np = mint.pin(); pinRemap.set(String(p.id), np); return { ...p, id: np }; });
|
|
42
|
+
primitive.set(String(m.id), { id, pinRemap });
|
|
43
|
+
nodes.push({
|
|
44
|
+
...m, id, position: { ...m.position }, state: { ...m.state }, pins,
|
|
45
|
+
...(m.size ? { size: { ...m.size } } : {}),
|
|
46
|
+
...(m.widgets ? { widgets: m.widgets.map((w) => ({ ...w })) } : {}),
|
|
47
|
+
...(m.meta ? { meta: { ...m.meta } } : {}),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// Resolve an OUT endpoint (the producing pin) to its concrete internal pin(s) — normally one.
|
|
51
|
+
const resolveOut = (node, pin) => {
|
|
52
|
+
const prim = primitive.get(String(node));
|
|
53
|
+
if (prim)
|
|
54
|
+
return [{ node: prim.id, pin: prim.pinRemap.get(String(pin)) }];
|
|
55
|
+
const child = nested.get(String(node));
|
|
56
|
+
if (child) {
|
|
57
|
+
const o = child.boundary.outputs[String(pin)];
|
|
58
|
+
return o ? [o] : [];
|
|
59
|
+
}
|
|
60
|
+
return [];
|
|
61
|
+
};
|
|
62
|
+
// Resolve an IN endpoint (the consuming pin) to its concrete internal pin(s) — a nested input may
|
|
63
|
+
// fan out to several internal pins.
|
|
64
|
+
const resolveIn = (node, pin) => {
|
|
65
|
+
const prim = primitive.get(String(node));
|
|
66
|
+
if (prim)
|
|
67
|
+
return [{ node: prim.id, pin: prim.pinRemap.get(String(pin)) }];
|
|
68
|
+
const child = nested.get(String(node));
|
|
69
|
+
if (child)
|
|
70
|
+
return child.boundary.inputs[String(pin)] ?? [];
|
|
71
|
+
return [];
|
|
72
|
+
};
|
|
73
|
+
for (const e of def.edges) {
|
|
74
|
+
const srcInput = isType(def, e.from.node, TEMPLATE_INPUT_TYPE);
|
|
75
|
+
const dstOutput = isType(def, e.to.node, TEMPLATE_OUTPUT_TYPE);
|
|
76
|
+
if (srcInput && dstOutput)
|
|
77
|
+
continue; // degenerate passthrough (input wired straight to output)
|
|
78
|
+
if (srcInput) {
|
|
79
|
+
const instPin = boundaryToInstPin.get(String(e.from.node));
|
|
80
|
+
if (instPin === undefined)
|
|
81
|
+
continue;
|
|
82
|
+
(inputs[instPin] ??= []).push(...resolveIn(e.to.node, e.to.pin));
|
|
83
|
+
}
|
|
84
|
+
else if (dstOutput) {
|
|
85
|
+
const instPin = boundaryToInstPin.get(String(e.to.node));
|
|
86
|
+
if (instPin === undefined)
|
|
87
|
+
continue;
|
|
88
|
+
const producer = resolveOut(e.from.node, e.from.pin)[0];
|
|
89
|
+
if (producer)
|
|
90
|
+
outputs[instPin] = producer;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
const srcs = resolveOut(e.from.node, e.from.pin);
|
|
94
|
+
const dsts = resolveIn(e.to.node, e.to.pin);
|
|
95
|
+
for (const s of srcs)
|
|
96
|
+
for (const d of dsts)
|
|
97
|
+
edges.push({ id: mint.edge(), from: s, to: d });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return { nodes, edges, boundary: { inputs, outputs } };
|
|
101
|
+
}
|
|
102
|
+
/** Snapshot-level helper: replace every `$templateInstance` in (`nodes`, `edges`) with its flattened
|
|
103
|
+
* primitive sub-graph and rewire the external edges that touched the instance's interface pins to
|
|
104
|
+
* the boundary-mapped internal pins. Mirrors `flattenMacroProxies` for templates. Pure — inputs are
|
|
105
|
+
* not mutated. An instance whose definition is missing or recursive is left in place. */
|
|
106
|
+
export function flattenAllTemplateInstances(nodes, edges, resolveDef, mint) {
|
|
107
|
+
const instanceFlat = new Map();
|
|
108
|
+
const outNodes = [];
|
|
109
|
+
for (const n of nodes) {
|
|
110
|
+
if (!isTemplateInstance(n)) {
|
|
111
|
+
outNodes.push(n);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const flat = flattenTemplateInstance(n, resolveDef, mint);
|
|
115
|
+
if (!flat) {
|
|
116
|
+
outNodes.push(n);
|
|
117
|
+
continue;
|
|
118
|
+
} // unresolved / recursive — leave as data so the host sees it
|
|
119
|
+
instanceFlat.set(String(n.id), flat);
|
|
120
|
+
outNodes.push(...flat.nodes);
|
|
121
|
+
}
|
|
122
|
+
const outEdges = [];
|
|
123
|
+
for (const e of edges) {
|
|
124
|
+
const srcFlat = instanceFlat.get(String(e.from.node));
|
|
125
|
+
const dstFlat = instanceFlat.get(String(e.to.node));
|
|
126
|
+
if (!srcFlat && !dstFlat) {
|
|
127
|
+
outEdges.push(e);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
const sources = srcFlat
|
|
131
|
+
? (srcFlat.boundary.outputs[String(e.from.pin)] ? [srcFlat.boundary.outputs[String(e.from.pin)]] : [])
|
|
132
|
+
: [{ node: e.from.node, pin: e.from.pin }];
|
|
133
|
+
const targets = dstFlat
|
|
134
|
+
? (dstFlat.boundary.inputs[String(e.to.pin)] ?? [])
|
|
135
|
+
: [{ node: e.to.node, pin: e.to.pin }];
|
|
136
|
+
for (const s of sources)
|
|
137
|
+
for (const t of targets)
|
|
138
|
+
outEdges.push({ id: mint.edge(), from: s, to: t });
|
|
139
|
+
}
|
|
140
|
+
// Internal definition edges already live in flat.edges (carried via outNodes' spread above isn't right —
|
|
141
|
+
// edges live separately). Concat them explicitly.
|
|
142
|
+
for (const flat of instanceFlat.values())
|
|
143
|
+
outEdges.push(...flat.edges);
|
|
144
|
+
return { nodes: outNodes, edges: outEdges };
|
|
145
|
+
}
|
|
146
|
+
function invertPinBoundary(instance) {
|
|
147
|
+
const pinBoundary = (instance.state['pinBoundary'] ?? {});
|
|
148
|
+
const out = new Map();
|
|
149
|
+
for (const [pinId, boundaryId] of Object.entries(pinBoundary))
|
|
150
|
+
out.set(boundaryId, pinId);
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
function isType(def, nodeId, type) {
|
|
154
|
+
const n = def.nodes.find((x) => String(x.id) === String(nodeId));
|
|
155
|
+
return n?.type === type;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=template-flatten.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-flatten.js","sourceRoot":"","sources":["../src/template-flatten.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Graph, Node, Edge } from './graph.js';
|
|
2
|
+
import type { NodeId } from './ids.js';
|
|
3
|
+
/** Nodes with an edge INTO `id` (its upstream dependencies). De-duplicated. */
|
|
4
|
+
export declare function incomers(graph: Graph, id: NodeId): Node[];
|
|
5
|
+
/** Nodes with an edge OUT of `id` (its downstream consumers). De-duplicated. */
|
|
6
|
+
export declare function outgoers(graph: Graph, id: NodeId): Node[];
|
|
7
|
+
/** Edges touching `id`. `direction` filters to incoming (`in`) or outgoing (`out`); omit for both. */
|
|
8
|
+
export declare function connectedEdges(graph: Graph, id: NodeId, direction?: 'in' | 'out'): Edge[];
|
|
9
|
+
/** Nodes with no incoming edges (sources). */
|
|
10
|
+
export declare function roots(graph: Graph): Node[];
|
|
11
|
+
/** Nodes with no outgoing edges (sinks). */
|
|
12
|
+
export declare function leaves(graph: Graph): Node[];
|
|
13
|
+
/** The set of node ids reachable from `start` by following outgoing edges (the active downstream
|
|
14
|
+
* chain), including `start` itself. Cycle-safe. A host runtime uses this to decide which nodes are
|
|
15
|
+
* actually "live": when an edge is cut or a node deleted, everything past the break drops out of
|
|
16
|
+
* the set, so downstream nodes can stop playing / stop showing as running. */
|
|
17
|
+
export declare function reachableFrom(graph: Graph, start: NodeId): Set<NodeId>;
|
|
18
|
+
/** Kahn topological sort. `order` lists node ids so every edge goes earlier→later; `cyclic` holds
|
|
19
|
+
* the ids that couldn't be ordered because they sit in (or downstream of) a cycle. */
|
|
20
|
+
export declare function topoOrder(graph: Graph): {
|
|
21
|
+
order: NodeId[];
|
|
22
|
+
cyclic: NodeId[];
|
|
23
|
+
};
|
|
24
|
+
/** Would adding an edge `from → to` introduce a cycle? True if `from === to`, or a path already
|
|
25
|
+
* leads from `to` back to `from`. Handy for an `isValidConnection` rule that forbids cycles. */
|
|
26
|
+
export declare function wouldCreateCycle(graph: Graph, from: NodeId, to: NodeId): boolean;
|
|
27
|
+
//# sourceMappingURL=traversal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traversal.d.ts","sourceRoot":"","sources":["../src/traversal.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEtC,+EAA+E;AAC/E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,EAAE,CAEzD;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,EAAE,CAEzD;AAgBD,sGAAsG;AACtG,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,IAAI,EAAE,CASzF;AAED,8CAA8C;AAC9C,wBAAgB,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,CAE1C;AAED,4CAA4C;AAC5C,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,CAE3C;AAED;;;+EAG+E;AAC/E,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAWtE;AAED;uFACuF;AACvF,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAuB7E;AAED;iGACiG;AACjG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAYhF"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/** Nodes with an edge INTO `id` (its upstream dependencies). De-duplicated. */
|
|
2
|
+
export function incomers(graph, id) {
|
|
3
|
+
return neighbours(graph, id, 'in');
|
|
4
|
+
}
|
|
5
|
+
/** Nodes with an edge OUT of `id` (its downstream consumers). De-duplicated. */
|
|
6
|
+
export function outgoers(graph, id) {
|
|
7
|
+
return neighbours(graph, id, 'out');
|
|
8
|
+
}
|
|
9
|
+
function neighbours(graph, id, dir) {
|
|
10
|
+
const seen = new Set();
|
|
11
|
+
const out = [];
|
|
12
|
+
for (const e of graph.edges()) {
|
|
13
|
+
const hit = dir === 'in' ? e.to.node === id : e.from.node === id;
|
|
14
|
+
if (!hit)
|
|
15
|
+
continue;
|
|
16
|
+
const otherId = dir === 'in' ? e.from.node : e.to.node;
|
|
17
|
+
if (seen.has(otherId))
|
|
18
|
+
continue;
|
|
19
|
+
const n = graph.getNode(otherId);
|
|
20
|
+
if (n) {
|
|
21
|
+
seen.add(otherId);
|
|
22
|
+
out.push(n);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
/** Edges touching `id`. `direction` filters to incoming (`in`) or outgoing (`out`); omit for both. */
|
|
28
|
+
export function connectedEdges(graph, id, direction) {
|
|
29
|
+
const out = [];
|
|
30
|
+
for (const e of graph.edges()) {
|
|
31
|
+
const isIn = e.to.node === id, isOut = e.from.node === id;
|
|
32
|
+
if ((direction === 'in' && isIn) || (direction === 'out' && isOut) || (!direction && (isIn || isOut))) {
|
|
33
|
+
out.push(e);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
/** Nodes with no incoming edges (sources). */
|
|
39
|
+
export function roots(graph) {
|
|
40
|
+
return [...graph.nodes()].filter((n) => connectedEdges(graph, n.id, 'in').length === 0);
|
|
41
|
+
}
|
|
42
|
+
/** Nodes with no outgoing edges (sinks). */
|
|
43
|
+
export function leaves(graph) {
|
|
44
|
+
return [...graph.nodes()].filter((n) => connectedEdges(graph, n.id, 'out').length === 0);
|
|
45
|
+
}
|
|
46
|
+
/** The set of node ids reachable from `start` by following outgoing edges (the active downstream
|
|
47
|
+
* chain), including `start` itself. Cycle-safe. A host runtime uses this to decide which nodes are
|
|
48
|
+
* actually "live": when an edge is cut or a node deleted, everything past the break drops out of
|
|
49
|
+
* the set, so downstream nodes can stop playing / stop showing as running. */
|
|
50
|
+
export function reachableFrom(graph, start) {
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
if (!graph.hasNode(start))
|
|
53
|
+
return seen;
|
|
54
|
+
const stack = [start];
|
|
55
|
+
while (stack.length > 0) {
|
|
56
|
+
const id = stack.pop();
|
|
57
|
+
if (seen.has(id))
|
|
58
|
+
continue;
|
|
59
|
+
seen.add(id);
|
|
60
|
+
for (const n of outgoers(graph, id))
|
|
61
|
+
if (!seen.has(n.id))
|
|
62
|
+
stack.push(n.id);
|
|
63
|
+
}
|
|
64
|
+
return seen;
|
|
65
|
+
}
|
|
66
|
+
/** Kahn topological sort. `order` lists node ids so every edge goes earlier→later; `cyclic` holds
|
|
67
|
+
* the ids that couldn't be ordered because they sit in (or downstream of) a cycle. */
|
|
68
|
+
export function topoOrder(graph) {
|
|
69
|
+
const indegree = new Map();
|
|
70
|
+
const outAdj = new Map();
|
|
71
|
+
for (const n of graph.nodes()) {
|
|
72
|
+
indegree.set(n.id, 0);
|
|
73
|
+
outAdj.set(n.id, []);
|
|
74
|
+
}
|
|
75
|
+
for (const e of graph.edges()) {
|
|
76
|
+
if (!indegree.has(e.from.node) || !indegree.has(e.to.node))
|
|
77
|
+
continue;
|
|
78
|
+
indegree.set(e.to.node, (indegree.get(e.to.node) ?? 0) + 1);
|
|
79
|
+
outAdj.get(e.from.node).push(e.to.node);
|
|
80
|
+
}
|
|
81
|
+
const queue = [];
|
|
82
|
+
for (const [id, deg] of indegree)
|
|
83
|
+
if (deg === 0)
|
|
84
|
+
queue.push(id);
|
|
85
|
+
const order = [];
|
|
86
|
+
while (queue.length) {
|
|
87
|
+
const id = queue.shift();
|
|
88
|
+
order.push(id);
|
|
89
|
+
for (const next of outAdj.get(id)) {
|
|
90
|
+
const d = (indegree.get(next) ?? 0) - 1;
|
|
91
|
+
indegree.set(next, d);
|
|
92
|
+
if (d === 0)
|
|
93
|
+
queue.push(next);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const cyclic = [...indegree].filter(([, d]) => d > 0).map(([id]) => id);
|
|
97
|
+
return { order, cyclic };
|
|
98
|
+
}
|
|
99
|
+
/** Would adding an edge `from → to` introduce a cycle? True if `from === to`, or a path already
|
|
100
|
+
* leads from `to` back to `from`. Handy for an `isValidConnection` rule that forbids cycles. */
|
|
101
|
+
export function wouldCreateCycle(graph, from, to) {
|
|
102
|
+
if (from === to)
|
|
103
|
+
return true;
|
|
104
|
+
const stack = [to];
|
|
105
|
+
const seen = new Set();
|
|
106
|
+
while (stack.length) {
|
|
107
|
+
const id = stack.pop();
|
|
108
|
+
if (id === from)
|
|
109
|
+
return true;
|
|
110
|
+
if (seen.has(id))
|
|
111
|
+
continue;
|
|
112
|
+
seen.add(id);
|
|
113
|
+
for (const e of graph.edges())
|
|
114
|
+
if (e.from.node === id)
|
|
115
|
+
stack.push(e.to.node);
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=traversal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traversal.js","sourceRoot":"","sources":["../src/traversal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** A custom pin data-type the host declares: its colour, optional shape, and extra compatibility.
|
|
2
|
+
* Consumed by both connection validation (`canConnect`) and the renderer (pin fill/stroke). */
|
|
3
|
+
export interface TypeDescriptor {
|
|
4
|
+
id: string;
|
|
5
|
+
color: string;
|
|
6
|
+
shape?: 'circle' | 'diamond' | 'arrow';
|
|
7
|
+
/** Types this one may also connect to, beyond an exact id match. Honoured symmetrically. */
|
|
8
|
+
compatibleWith?: string[];
|
|
9
|
+
}
|
|
10
|
+
/** A directional conversion `from → to`. Applied to values flowing across an edge when the OUT
|
|
11
|
+
* pin's type differs from the IN pin's type. Pure — the same input should always yield the same
|
|
12
|
+
* output. Throwing is allowed (signals an invalid value at runtime) — the editor doesn't catch. */
|
|
13
|
+
export type ConversionFn = (value: unknown) => unknown;
|
|
14
|
+
/** Registry of {@link TypeDescriptor}s. Pure, zero-dep — the editor owns one instance and hands it
|
|
15
|
+
* to `canConnect` and the renderer so custom typed pins get correct colours and connection rules. */
|
|
16
|
+
export declare class TypeRegistry {
|
|
17
|
+
#private;
|
|
18
|
+
get size(): number;
|
|
19
|
+
register(desc: TypeDescriptor): void;
|
|
20
|
+
unregister(id: string): boolean;
|
|
21
|
+
clear(): void;
|
|
22
|
+
has(id: string): boolean;
|
|
23
|
+
get(id: string): TypeDescriptor | undefined;
|
|
24
|
+
all(): TypeDescriptor[];
|
|
25
|
+
/** Register a value-coercion function applied when an OUT pin of type `from` connects to an IN
|
|
26
|
+
* pin of type `to`. Directional — call again with swapped args for the reverse direction.
|
|
27
|
+
* Replaces any prior fn for the same pair. */
|
|
28
|
+
registerConversion(from: string, to: string, fn: ConversionFn): void;
|
|
29
|
+
unregisterConversion(from: string, to: string): boolean;
|
|
30
|
+
hasConversion(from: string, to: string): boolean;
|
|
31
|
+
getConversion(from: string, to: string): ConversionFn | undefined;
|
|
32
|
+
/** Apply the conversion `from → to` to `value`. Identity when `from === to`. Throws when no
|
|
33
|
+
* conversion is registered (use `hasConversion` first if you need to choose at runtime). */
|
|
34
|
+
convert(value: unknown, from: string, to: string): unknown;
|
|
35
|
+
/** Are two pin types connectable by type? True on exact match, or if either descriptor lists the
|
|
36
|
+
* other in `compatibleWith` (symmetric), or if EITHER direction has a registered conversion.
|
|
37
|
+
* Returning true for either-direction conversion keeps `canConnect` orientation-agnostic — the
|
|
38
|
+
* actual cast is applied per-direction at value-flow time using `convert(from, to)`. */
|
|
39
|
+
compatible(a: string, b: string): boolean;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=types-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-registry.d.ts","sourceRoot":"","sources":["../src/types-registry.ts"],"names":[],"mappings":"AAAA;gGACgG;AAChG,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAA;IACtC,4FAA4F;IAC5F,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;CAC1B;AAED;;oGAEoG;AACpG,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAA;AAEtD;sGACsG;AACtG,qBAAa,YAAY;;IAOvB,IAAI,IAAI,IAAI,MAAM,CAAkC;IAEpD,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IACpC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAC/B,KAAK,IAAI,IAAI;IAMb,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IACxB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAC3C,GAAG,IAAI,cAAc,EAAE;IAIvB;;mDAE+C;IAC/C,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,GAAG,IAAI;IAGpE,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO;IAGvD,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO;IAGhD,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAGjE;iGAC6F;IAC7F,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO;IAO1D;;;6FAGyF;IACzF,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;CAM1C"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Registry of {@link TypeDescriptor}s. Pure, zero-dep — the editor owns one instance and hands it
|
|
2
|
+
* to `canConnect` and the renderer so custom typed pins get correct colours and connection rules. */
|
|
3
|
+
export class TypeRegistry {
|
|
4
|
+
#descriptors = new Map();
|
|
5
|
+
// Conversions are keyed `${from}→${to}` to make lookup O(1) and direction explicit. Symmetry
|
|
6
|
+
// (`from→to` does NOT imply `to→from`) matters: a `number→text` cast is well-defined; the
|
|
7
|
+
// reverse needs its own parse with its own failure mode.
|
|
8
|
+
#conversions = new Map();
|
|
9
|
+
get size() { return this.#descriptors.size; }
|
|
10
|
+
register(desc) { this.#descriptors.set(desc.id, desc); }
|
|
11
|
+
unregister(id) { return this.#descriptors.delete(id); }
|
|
12
|
+
clear() {
|
|
13
|
+
this.#descriptors.clear();
|
|
14
|
+
// Conversions are tied to the type pairs they bridge — clearing types clears conversions too,
|
|
15
|
+
// otherwise stale entries would silently lift `compatible()` for types that no longer exist.
|
|
16
|
+
this.#conversions.clear();
|
|
17
|
+
}
|
|
18
|
+
has(id) { return this.#descriptors.has(id); }
|
|
19
|
+
get(id) { return this.#descriptors.get(id); }
|
|
20
|
+
all() { return [...this.#descriptors.values()]; }
|
|
21
|
+
// ---- conversions (G2 — type-driven value coercion across an edge) ----------------------------
|
|
22
|
+
/** Register a value-coercion function applied when an OUT pin of type `from` connects to an IN
|
|
23
|
+
* pin of type `to`. Directional — call again with swapped args for the reverse direction.
|
|
24
|
+
* Replaces any prior fn for the same pair. */
|
|
25
|
+
registerConversion(from, to, fn) {
|
|
26
|
+
this.#conversions.set(`${from}${to}`, fn);
|
|
27
|
+
}
|
|
28
|
+
unregisterConversion(from, to) {
|
|
29
|
+
return this.#conversions.delete(`${from}${to}`);
|
|
30
|
+
}
|
|
31
|
+
hasConversion(from, to) {
|
|
32
|
+
return this.#conversions.has(`${from}${to}`);
|
|
33
|
+
}
|
|
34
|
+
getConversion(from, to) {
|
|
35
|
+
return this.#conversions.get(`${from}${to}`);
|
|
36
|
+
}
|
|
37
|
+
/** Apply the conversion `from → to` to `value`. Identity when `from === to`. Throws when no
|
|
38
|
+
* conversion is registered (use `hasConversion` first if you need to choose at runtime). */
|
|
39
|
+
convert(value, from, to) {
|
|
40
|
+
if (from === to)
|
|
41
|
+
return value;
|
|
42
|
+
const fn = this.#conversions.get(`${from}${to}`);
|
|
43
|
+
if (!fn)
|
|
44
|
+
throw new Error(`TypeRegistry: no conversion registered for ${from} → ${to}`);
|
|
45
|
+
return fn(value);
|
|
46
|
+
}
|
|
47
|
+
/** Are two pin types connectable by type? True on exact match, or if either descriptor lists the
|
|
48
|
+
* other in `compatibleWith` (symmetric), or if EITHER direction has a registered conversion.
|
|
49
|
+
* Returning true for either-direction conversion keeps `canConnect` orientation-agnostic — the
|
|
50
|
+
* actual cast is applied per-direction at value-flow time using `convert(from, to)`. */
|
|
51
|
+
compatible(a, b) {
|
|
52
|
+
if (a === b)
|
|
53
|
+
return true;
|
|
54
|
+
if ((this.#descriptors.get(a)?.compatibleWith?.includes(b) ?? false) ||
|
|
55
|
+
(this.#descriptors.get(b)?.compatibleWith?.includes(a) ?? false))
|
|
56
|
+
return true;
|
|
57
|
+
return this.hasConversion(a, b) || this.hasConversion(b, a);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=types-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-registry.js","sourceRoot":"","sources":["../src/types-registry.ts"],"names":[],"mappings":"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"}
|
package/dist/widget.d.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { Node } from './graph.js';
|
|
2
|
+
/** Declarative in-node UI control. Widgets are pure DATA — rendering and interaction live in the
|
|
3
|
+
* render/editor layers. A widget's value is stored in `node.state[key]` (single source of truth),
|
|
4
|
+
* so it serialises with the node and mutates through the command bus (undoable). `button` carries
|
|
5
|
+
* an action name instead of a value; `custom` defers to a host-registered renderer. */
|
|
6
|
+
export type WidgetType = 'number' | 'slider' | 'combo' | 'text' | 'toggle' | 'button' | 'color' | 'custom';
|
|
7
|
+
export type ComboOption = string | {
|
|
8
|
+
label: string;
|
|
9
|
+
value: string | number;
|
|
10
|
+
};
|
|
11
|
+
/** Per-widget visual override. Any field set here wins over the theme's widget tokens for THIS
|
|
12
|
+
* widget only — so every widget instance is fully customisable without touching the theme. */
|
|
13
|
+
export interface WidgetStyle {
|
|
14
|
+
bg?: string;
|
|
15
|
+
bgHover?: string;
|
|
16
|
+
bgFocused?: string;
|
|
17
|
+
track?: string;
|
|
18
|
+
fill?: string;
|
|
19
|
+
fillAlpha?: number;
|
|
20
|
+
text?: string;
|
|
21
|
+
label?: string;
|
|
22
|
+
placeholder?: string;
|
|
23
|
+
border?: string;
|
|
24
|
+
borderFocused?: string;
|
|
25
|
+
selection?: string;
|
|
26
|
+
knob?: string;
|
|
27
|
+
radius?: number;
|
|
28
|
+
paddingX?: number;
|
|
29
|
+
paddingY?: number;
|
|
30
|
+
borderWidth?: number;
|
|
31
|
+
toggleWidth?: number;
|
|
32
|
+
toggleHeight?: number;
|
|
33
|
+
}
|
|
34
|
+
interface WidgetBase {
|
|
35
|
+
id: string;
|
|
36
|
+
label: string;
|
|
37
|
+
/** Key into `node.state` holding the value. Absent for `button`. Also doubles as the implicit
|
|
38
|
+
* pin-binding key (see `pinKey`) — most schemas don't need to set `pinKey` manually if the
|
|
39
|
+
* widget's `key` matches a data IN-pin's `label` / `id`. */
|
|
40
|
+
key?: string;
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
hint?: string;
|
|
43
|
+
/** Per-widget visual override, merged over the theme's widget tokens. */
|
|
44
|
+
style?: WidgetStyle;
|
|
45
|
+
/** Override the implicit `key`-based pin match. Matched against a data IN-pin's `label` (schema
|
|
46
|
+
* authors can't predict auto-minted pin ids), then by pin `id` (loaded graphs serialize ids).
|
|
47
|
+
* Almost never needed — leave unset and use the same `key` on widget and pin. */
|
|
48
|
+
pinKey?: string;
|
|
49
|
+
/** Render-time visibility against the bound pin:
|
|
50
|
+
* - `'whenDisconnected'` (default for input controls — number/slider/text/combo/toggle/color):
|
|
51
|
+
* UE-Blueprint default-value behaviour. Widget visible only while the pin has no edge;
|
|
52
|
+
* connecting hides it (the pin's wire becomes the value source).
|
|
53
|
+
* - `'always'`: display/preview behaviour. Widget always visible regardless of pin state;
|
|
54
|
+
* when the pin has a wire, the widget reads the runtime's LIVE value and renders read-only.
|
|
55
|
+
* Default for `custom` widgets — most custom controls are visualisations. */
|
|
56
|
+
visibility?: 'whenDisconnected' | 'always';
|
|
57
|
+
/** Opt-in: include this widget in the editor's properties sidebar when one is open for the
|
|
58
|
+
* containing node (G4 — Baklava `displayInSidebar` parity). The SAME widget renders both
|
|
59
|
+
* inline on the node and in the sidebar — no separate component to author. Default: omit
|
|
60
|
+
* (widget appears only inline). */
|
|
61
|
+
showInSidebar?: boolean;
|
|
62
|
+
/** Declarative conditional rendering keyed off OTHER widgets' values in the same node (n8n
|
|
63
|
+
* `displayOptions.show` parity). `show(state)` is evaluated against `node.state` after every
|
|
64
|
+
* `setWidgetValue` — return `false` to hide the widget (renderer skips layout, sidebar skips
|
|
65
|
+
* the row). Fails OPEN if the callback throws (a schema bug must not blank the node). */
|
|
66
|
+
displayOptions?: {
|
|
67
|
+
show?: (state: Readonly<Record<string, unknown>>) => boolean;
|
|
68
|
+
};
|
|
69
|
+
/** Render this widget as a body-band row even if there's no matching pin. Use for node-level
|
|
70
|
+
* config fields that aren't connectable from outside (HTTP body, secret tokens, schema editor)
|
|
71
|
+
* — they get a full-width row under the pin band. Without this, non-custom orphan widgets are
|
|
72
|
+
* silently dropped. Always combines with `displayOptions.show`: hidden widgets disappear
|
|
73
|
+
* entirely, no leftover pin row. */
|
|
74
|
+
freeFloating?: boolean;
|
|
75
|
+
}
|
|
76
|
+
export type WidgetSpec = (WidgetBase & {
|
|
77
|
+
type: 'number';
|
|
78
|
+
key: string;
|
|
79
|
+
min?: number;
|
|
80
|
+
max?: number;
|
|
81
|
+
step?: number;
|
|
82
|
+
precision?: number;
|
|
83
|
+
unit?: string;
|
|
84
|
+
}) | (WidgetBase & {
|
|
85
|
+
type: 'slider';
|
|
86
|
+
key: string;
|
|
87
|
+
min: number;
|
|
88
|
+
max: number;
|
|
89
|
+
step?: number;
|
|
90
|
+
}) | (WidgetBase & {
|
|
91
|
+
type: 'combo';
|
|
92
|
+
key: string;
|
|
93
|
+
values: ComboOption[];
|
|
94
|
+
}) | (WidgetBase & {
|
|
95
|
+
type: 'text';
|
|
96
|
+
key: string;
|
|
97
|
+
multiline?: boolean;
|
|
98
|
+
placeholder?: string;
|
|
99
|
+
maxLength?: number;
|
|
100
|
+
}) | (WidgetBase & {
|
|
101
|
+
type: 'toggle';
|
|
102
|
+
key: string;
|
|
103
|
+
onLabel?: string;
|
|
104
|
+
offLabel?: string;
|
|
105
|
+
}) | (WidgetBase & {
|
|
106
|
+
type: 'button';
|
|
107
|
+
action: string;
|
|
108
|
+
}) | (WidgetBase & {
|
|
109
|
+
type: 'color';
|
|
110
|
+
key: string;
|
|
111
|
+
}) | (WidgetBase & {
|
|
112
|
+
type: 'custom';
|
|
113
|
+
renderer: string;
|
|
114
|
+
key: string;
|
|
115
|
+
height?: number;
|
|
116
|
+
});
|
|
117
|
+
export interface ComboOptionResolved {
|
|
118
|
+
label: string;
|
|
119
|
+
value: string | number;
|
|
120
|
+
}
|
|
121
|
+
export declare function comboOptions(spec: Extract<WidgetSpec, {
|
|
122
|
+
type: 'combo';
|
|
123
|
+
}>): ComboOptionResolved[];
|
|
124
|
+
export declare function defaultWidgetValue(spec: WidgetSpec): unknown;
|
|
125
|
+
export declare function clampWidgetValue(spec: WidgetSpec, raw: unknown): unknown;
|
|
126
|
+
/** Current value of a widget on a node: the clamped `node.state[key]`, or its default. */
|
|
127
|
+
export declare function widgetValue(node: Node, spec: WidgetSpec): unknown;
|
|
128
|
+
/** Effective widget visibility policy. ALL widget types default to `'whenDisconnected'` — they're
|
|
129
|
+
* input controls that the user sets a value for, and connecting a wire makes the widget's value
|
|
130
|
+
* redundant. Display/preview widgets (e.g. an Output node's value readout) opt into `'always'`
|
|
131
|
+
* explicitly. `button` widgets aren't pin-bound — they live in the actions row. */
|
|
132
|
+
export declare function widgetVisibility(spec: WidgetSpec): 'whenDisconnected' | 'always';
|
|
133
|
+
/** Resolve `displayOptions.show(state)` against a node — true (visible) unless the callback exists
|
|
134
|
+
* and explicitly returns false. Defensive: a throwing callback fails OPEN so a schema bug doesn't
|
|
135
|
+
* blank the node entirely. */
|
|
136
|
+
export declare function widgetIsVisible(spec: WidgetSpec, node: Node): boolean;
|
|
137
|
+
/** The lookup key used to bind a widget to its pin: explicit `pinKey`, else the widget's `key`.
|
|
138
|
+
* Returns undefined for widgets that don't bind to a pin (`button` — actions, not values). */
|
|
139
|
+
export declare function widgetBindKey(spec: WidgetSpec): string | undefined;
|
|
140
|
+
export {};
|
|
141
|
+
//# sourceMappingURL=widget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"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"}
|