@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.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -0
  3. package/dist/command-bus.d.ts +56 -0
  4. package/dist/command-bus.d.ts.map +1 -0
  5. package/dist/command-bus.js +180 -0
  6. package/dist/command-bus.js.map +1 -0
  7. package/dist/commands-comment.d.ts +52 -0
  8. package/dist/commands-comment.d.ts.map +1 -0
  9. package/dist/commands-comment.js +92 -0
  10. package/dist/commands-comment.js.map +1 -0
  11. package/dist/commands-mut.d.ts +58 -0
  12. package/dist/commands-mut.d.ts.map +1 -0
  13. package/dist/commands-mut.js +119 -0
  14. package/dist/commands-mut.js.map +1 -0
  15. package/dist/commands.d.ts +36 -0
  16. package/dist/commands.d.ts.map +1 -0
  17. package/dist/commands.js +72 -0
  18. package/dist/commands.js.map +1 -0
  19. package/dist/comment-spatial.d.ts +20 -0
  20. package/dist/comment-spatial.d.ts.map +1 -0
  21. package/dist/comment-spatial.js +21 -0
  22. package/dist/comment-spatial.js.map +1 -0
  23. package/dist/event-emitter.d.ts +15 -0
  24. package/dist/event-emitter.d.ts.map +1 -0
  25. package/dist/event-emitter.js +55 -0
  26. package/dist/event-emitter.js.map +1 -0
  27. package/dist/fuzzy.d.ts +17 -0
  28. package/dist/fuzzy.d.ts.map +1 -0
  29. package/dist/fuzzy.js +55 -0
  30. package/dist/fuzzy.js.map +1 -0
  31. package/dist/graph.d.ts +108 -0
  32. package/dist/graph.d.ts.map +1 -0
  33. package/dist/graph.js +141 -0
  34. package/dist/graph.js.map +1 -0
  35. package/dist/ids.d.ts +28 -0
  36. package/dist/ids.d.ts.map +1 -0
  37. package/dist/ids.js +31 -0
  38. package/dist/ids.js.map +1 -0
  39. package/dist/index.d.ts +35 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +20 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/macro.d.ts +120 -0
  44. package/dist/macro.d.ts.map +1 -0
  45. package/dist/macro.js +226 -0
  46. package/dist/macro.js.map +1 -0
  47. package/dist/node-registry.d.ts +101 -0
  48. package/dist/node-registry.d.ts.map +1 -0
  49. package/dist/node-registry.js +96 -0
  50. package/dist/node-registry.js.map +1 -0
  51. package/dist/reroute.d.ts +21 -0
  52. package/dist/reroute.d.ts.map +1 -0
  53. package/dist/reroute.js +40 -0
  54. package/dist/reroute.js.map +1 -0
  55. package/dist/selection.d.ts +17 -0
  56. package/dist/selection.d.ts.map +1 -0
  57. package/dist/selection.js +56 -0
  58. package/dist/selection.js.map +1 -0
  59. package/dist/template-def.d.ts +113 -0
  60. package/dist/template-def.d.ts.map +1 -0
  61. package/dist/template-def.js +0 -0
  62. package/dist/template-def.js.map +1 -0
  63. package/dist/template-flatten.d.ts +38 -0
  64. package/dist/template-flatten.d.ts.map +1 -0
  65. package/dist/template-flatten.js +157 -0
  66. package/dist/template-flatten.js.map +1 -0
  67. package/dist/traversal.d.ts +27 -0
  68. package/dist/traversal.d.ts.map +1 -0
  69. package/dist/traversal.js +119 -0
  70. package/dist/traversal.js.map +1 -0
  71. package/dist/types-registry.d.ts +41 -0
  72. package/dist/types-registry.d.ts.map +1 -0
  73. package/dist/types-registry.js +60 -0
  74. package/dist/types-registry.js.map +1 -0
  75. package/dist/widget.d.ts +141 -0
  76. package/dist/widget.d.ts.map +1 -0
  77. package/dist/widget.js +112 -0
  78. package/dist/widget.js.map +1 -0
  79. package/package.json +55 -0
@@ -0,0 +1,119 @@
1
+ export class MoveNode {
2
+ nodeId;
3
+ type = 'MoveNode';
4
+ #target;
5
+ constructor(nodeId, target) {
6
+ this.nodeId = nodeId;
7
+ this.#target = { x: target.x, y: target.y };
8
+ }
9
+ apply(ctx) {
10
+ const node = ctx.graph.getNode(this.nodeId);
11
+ if (!node)
12
+ throw new Error(`MoveNode: node not found: ${this.nodeId}`);
13
+ const old = { x: node.position.x, y: node.position.y };
14
+ ctx.graph._patchNode(this.nodeId, { position: { x: this.#target.x, y: this.#target.y } });
15
+ return old;
16
+ }
17
+ undo(ctx, old) {
18
+ ctx.graph._patchNode(this.nodeId, { position: old });
19
+ }
20
+ }
21
+ export class ResizeNode {
22
+ nodeId;
23
+ type = 'ResizeNode';
24
+ #target;
25
+ constructor(nodeId, target) {
26
+ this.nodeId = nodeId;
27
+ this.#target = { x: target.x, y: target.y };
28
+ }
29
+ apply(ctx) {
30
+ const node = ctx.graph.getNode(this.nodeId);
31
+ if (!node)
32
+ throw new Error(`ResizeNode: node not found: ${this.nodeId}`);
33
+ const old = node.size ? { x: node.size.x, y: node.size.y } : undefined;
34
+ ctx.graph._patchNode(this.nodeId, { size: { x: this.#target.x, y: this.#target.y } });
35
+ return old;
36
+ }
37
+ undo(ctx, old) {
38
+ ctx.graph._patchNode(this.nodeId, { size: old });
39
+ }
40
+ }
41
+ export class SetNodeState {
42
+ nodeId;
43
+ partial;
44
+ type = 'SetNodeState';
45
+ constructor(nodeId, partial) {
46
+ this.nodeId = nodeId;
47
+ this.partial = partial;
48
+ }
49
+ apply(ctx) {
50
+ const node = ctx.graph.getNode(this.nodeId);
51
+ if (!node)
52
+ throw new Error(`SetNodeState: node not found: ${this.nodeId}`);
53
+ const old = { ...node.state };
54
+ ctx.graph._patchNode(this.nodeId, { state: { ...node.state, ...this.partial } });
55
+ return old;
56
+ }
57
+ undo(ctx, old) {
58
+ ctx.graph._patchNode(this.nodeId, { state: old });
59
+ }
60
+ }
61
+ /** Replace a node's pin list wholesale (variadic pins: Sequence/MakeArray "+", Branch true/false).
62
+ * Edges incident to a pin that no longer exists are pruned and restored on undo. */
63
+ export class SetNodePins {
64
+ nodeId;
65
+ type = 'SetNodePins';
66
+ #pins;
67
+ constructor(nodeId, pins) {
68
+ this.nodeId = nodeId;
69
+ this.#pins = pins.map((p) => ({ ...p }));
70
+ }
71
+ apply(ctx) {
72
+ const node = ctx.graph.getNode(this.nodeId);
73
+ if (!node)
74
+ throw new Error(`SetNodePins: node not found: ${this.nodeId}`);
75
+ const oldPins = node.pins.map((p) => ({ ...p }));
76
+ const survivors = new Set(this.#pins.map((p) => p.id));
77
+ const pruned = [];
78
+ for (const edge of ctx.graph.edges()) {
79
+ const touchesDropped = (edge.from.node === this.nodeId && !survivors.has(edge.from.pin)) ||
80
+ (edge.to.node === this.nodeId && !survivors.has(edge.to.pin));
81
+ if (touchesDropped)
82
+ pruned.push(edge);
83
+ }
84
+ for (const edge of pruned)
85
+ ctx.graph._removeEdge(edge.id);
86
+ ctx.graph._setNodePins(this.nodeId, this.#pins.map((p) => ({ ...p })));
87
+ return { pins: oldPins, prunedEdges: pruned };
88
+ }
89
+ undo(ctx, applied) {
90
+ ctx.graph._setNodePins(this.nodeId, applied.pins.map((p) => ({ ...p })));
91
+ for (const edge of applied.prunedEdges)
92
+ ctx.graph._addEdge(edge);
93
+ }
94
+ }
95
+ /** Replace a node's widget list wholesale. Used by runtime plugins to synthesise widgets in
96
+ * response to schema changes (e.g. `@xenolithengine/graph-plugin-runtime`'s Schema-node flow that derives a
97
+ * Struct's editable fields from a wired Schema). Per-widget `state[key]` values survive removal,
98
+ * so re-adding a widget under the same key picks up the previously typed value. */
99
+ export class SetNodeWidgets {
100
+ nodeId;
101
+ type = 'SetNodeWidgets';
102
+ #widgets;
103
+ constructor(nodeId, widgets) {
104
+ this.nodeId = nodeId;
105
+ this.#widgets = widgets ? widgets.map((w) => ({ ...w })) : undefined;
106
+ }
107
+ apply(ctx) {
108
+ const node = ctx.graph.getNode(this.nodeId);
109
+ if (!node)
110
+ throw new Error(`SetNodeWidgets: node not found: ${this.nodeId}`);
111
+ const old = node.widgets ? node.widgets.map((w) => ({ ...w })) : undefined;
112
+ ctx.graph._setNodeWidgets(this.nodeId, this.#widgets ? this.#widgets.map((w) => ({ ...w })) : undefined);
113
+ return { widgets: old };
114
+ }
115
+ undo(ctx, applied) {
116
+ ctx.graph._setNodeWidgets(this.nodeId, applied.widgets ? applied.widgets.map((w) => ({ ...w })) : undefined);
117
+ }
118
+ }
119
+ //# sourceMappingURL=commands-mut.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands-mut.js","sourceRoot":"","sources":["../src/commands-mut.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { Command, CommandContext } from './command-bus.js';
2
+ import type { Edge, Node } from './graph.js';
3
+ import type { EdgeId, NodeId } from './ids.js';
4
+ export declare class AddNode implements Command<void> {
5
+ readonly node: Node;
6
+ readonly type = "AddNode";
7
+ constructor(node: Node);
8
+ apply(ctx: CommandContext): void;
9
+ undo(ctx: CommandContext): void;
10
+ }
11
+ export interface RemoveNodeUndo {
12
+ node: Node;
13
+ cascadedEdges: Edge[];
14
+ }
15
+ export declare class RemoveNode implements Command<RemoveNodeUndo> {
16
+ readonly nodeId: NodeId;
17
+ readonly type = "RemoveNode";
18
+ constructor(nodeId: NodeId);
19
+ apply(ctx: CommandContext): RemoveNodeUndo;
20
+ undo(ctx: CommandContext, applied: RemoveNodeUndo): void;
21
+ }
22
+ export declare class ConnectPins implements Command<void> {
23
+ readonly edge: Edge;
24
+ readonly type = "ConnectPins";
25
+ constructor(edge: Edge);
26
+ apply(ctx: CommandContext): void;
27
+ undo(ctx: CommandContext): void;
28
+ }
29
+ export declare class DisconnectEdge implements Command<Edge> {
30
+ readonly edgeId: EdgeId;
31
+ readonly type = "DisconnectEdge";
32
+ constructor(edgeId: EdgeId);
33
+ apply(ctx: CommandContext): Edge;
34
+ undo(ctx: CommandContext, applied: Edge): void;
35
+ }
36
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC/D,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAE9C,qBAAa,OAAQ,YAAW,OAAO,CAAC,IAAI,CAAC;IAE/B,QAAQ,CAAC,IAAI,EAAE,IAAI;IAD/B,QAAQ,CAAC,IAAI,aAAY;gBACJ,IAAI,EAAE,IAAI;IAE/B,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;IAIhC,IAAI,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;CAGhC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,IAAI,CAAA;IACV,aAAa,EAAE,IAAI,EAAE,CAAA;CACtB;AAED,qBAAa,UAAW,YAAW,OAAO,CAAC,cAAc,CAAC;IAE5C,QAAQ,CAAC,MAAM,EAAE,MAAM;IADnC,QAAQ,CAAC,IAAI,gBAAe;gBACP,MAAM,EAAE,MAAM;IAEnC,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,cAAc;IAiB1C,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;CAIzD;AAED,qBAAa,WAAY,YAAW,OAAO,CAAC,IAAI,CAAC;IAEnC,QAAQ,CAAC,IAAI,EAAE,IAAI;IAD/B,QAAQ,CAAC,IAAI,iBAAgB;gBACR,IAAI,EAAE,IAAI;IAE/B,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;IAIhC,IAAI,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;CAGhC;AAED,qBAAa,cAAe,YAAW,OAAO,CAAC,IAAI,CAAC;IAEtC,QAAQ,CAAC,MAAM,EAAE,MAAM;IADnC,QAAQ,CAAC,IAAI,oBAAmB;gBACX,MAAM,EAAE,MAAM;IAEnC,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;IAMhC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,GAAG,IAAI;CAG/C"}
@@ -0,0 +1,72 @@
1
+ export class AddNode {
2
+ node;
3
+ type = 'AddNode';
4
+ constructor(node) {
5
+ this.node = node;
6
+ }
7
+ apply(ctx) {
8
+ ctx.graph._addNode(this.node);
9
+ }
10
+ undo(ctx) {
11
+ ctx.graph._removeNode(this.node.id);
12
+ }
13
+ }
14
+ export class RemoveNode {
15
+ nodeId;
16
+ type = 'RemoveNode';
17
+ constructor(nodeId) {
18
+ this.nodeId = nodeId;
19
+ }
20
+ apply(ctx) {
21
+ const cascaded = [];
22
+ for (const edge of ctx.graph.edges()) {
23
+ if (edge.from.node === this.nodeId || edge.to.node === this.nodeId) {
24
+ cascaded.push(edge);
25
+ }
26
+ }
27
+ for (const edge of cascaded)
28
+ ctx.graph._removeEdge(edge.id);
29
+ const node = ctx.graph._removeNode(this.nodeId);
30
+ if (!node) {
31
+ for (const edge of cascaded)
32
+ ctx.graph._addEdge(edge);
33
+ throw new Error(`RemoveNode: node not found: ${this.nodeId}`);
34
+ }
35
+ return { node, cascadedEdges: cascaded };
36
+ }
37
+ undo(ctx, applied) {
38
+ ctx.graph._addNode(applied.node);
39
+ for (const edge of applied.cascadedEdges)
40
+ ctx.graph._addEdge(edge);
41
+ }
42
+ }
43
+ export class ConnectPins {
44
+ edge;
45
+ type = 'ConnectPins';
46
+ constructor(edge) {
47
+ this.edge = edge;
48
+ }
49
+ apply(ctx) {
50
+ ctx.graph._addEdge(this.edge);
51
+ }
52
+ undo(ctx) {
53
+ ctx.graph._removeEdge(this.edge.id);
54
+ }
55
+ }
56
+ export class DisconnectEdge {
57
+ edgeId;
58
+ type = 'DisconnectEdge';
59
+ constructor(edgeId) {
60
+ this.edgeId = edgeId;
61
+ }
62
+ apply(ctx) {
63
+ const removed = ctx.graph._removeEdge(this.edgeId);
64
+ if (!removed)
65
+ throw new Error(`DisconnectEdge: edge not found: ${this.edgeId}`);
66
+ return removed;
67
+ }
68
+ undo(ctx, applied) {
69
+ ctx.graph._addEdge(applied);
70
+ }
71
+ }
72
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { Vec2 } from './graph.js';
2
+ import type { NodeId } from './ids.js';
3
+ /** Minimal node shape needed for containment (avoids importing the full Node). */
4
+ export interface PlacedNode {
5
+ id: NodeId;
6
+ position: Vec2;
7
+ size?: Vec2;
8
+ }
9
+ export interface CommentRect {
10
+ position: Vec2;
11
+ size: Vec2;
12
+ }
13
+ /**
14
+ * Ids of nodes spatially inside a comment frame — membership is by geometry, not an explicit list
15
+ * (like React Flow groups). A node counts as inside when its CENTRE falls within the frame rect, so
16
+ * dragging the frame captures exactly the nodes visually sitting on it. A node with no size is
17
+ * treated as a point at its position.
18
+ */
19
+ export declare function nodesInsideComment(comment: CommentRect, nodes: Iterable<PlacedNode>): NodeId[];
20
+ //# sourceMappingURL=comment-spatial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment-spatial.d.ts","sourceRoot":"","sources":["../src/comment-spatial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEtC,kFAAkF;AAClF,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,IAAI,CAAA;IACd,IAAI,CAAC,EAAE,IAAI,CAAA;CACZ;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,IAAI,CAAA;IACd,IAAI,EAAE,IAAI,CAAA;CACX;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,MAAM,EAAE,CAY9F"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Ids of nodes spatially inside a comment frame — membership is by geometry, not an explicit list
3
+ * (like React Flow groups). A node counts as inside when its CENTRE falls within the frame rect, so
4
+ * dragging the frame captures exactly the nodes visually sitting on it. A node with no size is
5
+ * treated as a point at its position.
6
+ */
7
+ export function nodesInsideComment(comment, nodes) {
8
+ const x0 = comment.position.x;
9
+ const y0 = comment.position.y;
10
+ const x1 = x0 + comment.size.x;
11
+ const y1 = y0 + comment.size.y;
12
+ const inside = [];
13
+ for (const n of nodes) {
14
+ const cx = n.position.x + (n.size ? n.size.x / 2 : 0);
15
+ const cy = n.position.y + (n.size ? n.size.y / 2 : 0);
16
+ if (cx >= x0 && cx <= x1 && cy >= y0 && cy <= y1)
17
+ inside.push(n.id);
18
+ }
19
+ return inside;
20
+ }
21
+ //# sourceMappingURL=comment-spatial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment-spatial.js","sourceRoot":"","sources":["../src/comment-spatial.ts"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAoB,EAAE,KAA2B;IAClF,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC7B,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IAC9B,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IAC9B,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACrD,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACrD,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACrE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,15 @@
1
+ export type EventMap = Record<string, unknown>;
2
+ export type Listener<Payload> = (payload: Payload) => void;
3
+ export type Unsubscribe = () => void;
4
+ export type ErrorListener = (error: unknown, eventName: string) => void;
5
+ export declare class EventEmitter<Events extends EventMap> {
6
+ #private;
7
+ on<E extends keyof Events>(event: E, listener: Listener<Events[E]>): Unsubscribe;
8
+ off<E extends keyof Events>(event: E, listener: Listener<Events[E]>): void;
9
+ once<E extends keyof Events>(event: E, listener: Listener<Events[E]>): Unsubscribe;
10
+ emit<E extends keyof Events>(event: E, payload: Events[E]): void;
11
+ onError(listener: ErrorListener): void;
12
+ clear<E extends keyof Events>(event?: E): void;
13
+ listenerCount<E extends keyof Events>(event: E): number;
14
+ }
15
+ //# sourceMappingURL=event-emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-emitter.d.ts","sourceRoot":"","sources":["../src/event-emitter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAE9C,MAAM,MAAM,QAAQ,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;AAE1D,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAA;AAEpC,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;AAEvE,qBAAa,YAAY,CAAC,MAAM,SAAS,QAAQ;;IAI/C,EAAE,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW;IAOhF,GAAG,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAO1E,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW;IAQlF,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI;IAahE,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAItC,KAAK,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI;IAQ9C,aAAa,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM;CAGxD"}
@@ -0,0 +1,55 @@
1
+ export class EventEmitter {
2
+ #listeners = new Map();
3
+ #errorListener = null;
4
+ on(event, listener) {
5
+ const list = (this.#listeners.get(event) ?? []);
6
+ list.push(listener);
7
+ this.#listeners.set(event, list);
8
+ return () => this.off(event, listener);
9
+ }
10
+ off(event, listener) {
11
+ const list = this.#listeners.get(event);
12
+ if (!list)
13
+ return;
14
+ const idx = list.indexOf(listener);
15
+ if (idx !== -1)
16
+ list.splice(idx, 1);
17
+ }
18
+ once(event, listener) {
19
+ const unsubscribe = this.on(event, (payload) => {
20
+ unsubscribe();
21
+ listener(payload);
22
+ });
23
+ return unsubscribe;
24
+ }
25
+ emit(event, payload) {
26
+ const list = this.#listeners.get(event);
27
+ if (!list || list.length === 0)
28
+ return;
29
+ const snapshot = list.slice();
30
+ for (const listener of snapshot) {
31
+ try {
32
+ ;
33
+ listener(payload);
34
+ }
35
+ catch (err) {
36
+ this.#errorListener?.(err, event);
37
+ }
38
+ }
39
+ }
40
+ onError(listener) {
41
+ this.#errorListener = listener;
42
+ }
43
+ clear(event) {
44
+ if (event === undefined) {
45
+ this.#listeners.clear();
46
+ }
47
+ else {
48
+ this.#listeners.delete(event);
49
+ }
50
+ }
51
+ listenerCount(event) {
52
+ return this.#listeners.get(event)?.length ?? 0;
53
+ }
54
+ }
55
+ //# sourceMappingURL=event-emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-emitter.js","sourceRoot":"","sources":["../src/event-emitter.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,YAAY;IACd,UAAU,GAAG,IAAI,GAAG,EAAuD,CAAA;IACpF,cAAc,GAAyB,IAAI,CAAA;IAE3C,EAAE,CAAyB,KAAQ,EAAE,QAA6B;QAChE,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAA+B,CAAA;QAC7E,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACnB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,IAA6C,CAAC,CAAA;QACzE,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;IACxC,CAAC;IAED,GAAG,CAAyB,KAAQ,EAAE,QAA6B;QACjE,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACvC,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAA0C,CAAC,CAAA;QACpE,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACrC,CAAC;IAED,IAAI,CAAyB,KAAQ,EAAE,QAA6B;QAClE,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE;YAC7C,WAAW,EAAE,CAAA;YACb,QAAQ,CAAC,OAAO,CAAC,CAAA;QACnB,CAAC,CAAC,CAAA;QACF,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,IAAI,CAAyB,KAAQ,EAAE,OAAkB;QACvD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACvC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAM;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;QAC7B,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC;gBACH,CAAC;gBAAC,QAAgC,CAAC,OAAO,CAAC,CAAA;YAC7C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,KAAe,CAAC,CAAA;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,QAAuB;QAC7B,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAA;IAChC,CAAC;IAED,KAAK,CAAyB,KAAS;QACrC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;QACzB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;IAED,aAAa,CAAyB,KAAQ;QAC5C,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC,CAAA;IAChD,CAAC;CACF"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Tiny zero-dependency fuzzy matcher for the insert palette. Subsequence match with a score that
3
+ * rewards contiguous runs, matches at word boundaries (camelCase / separators), and an early
4
+ * first match. Returns the matched character indices so the UI can highlight them.
5
+ *
6
+ * Lives in `@xenolithengine/graph-core` (zero-dep invariant) so the node registry's search stays headless —
7
+ * hence hand-rolled rather than a package.
8
+ */
9
+ export interface FuzzyMatch {
10
+ matched: boolean;
11
+ /** Higher is better. 0 for an empty query or a non-match. */
12
+ score: number;
13
+ /** Indices into `target` of the matched characters, in order. For highlighting. */
14
+ indices: number[];
15
+ }
16
+ export declare function fuzzyMatch(query: string, target: string): FuzzyMatch;
17
+ //# sourceMappingURL=fuzzy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy.d.ts","sourceRoot":"","sources":["../src/fuzzy.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb,mFAAmF;IACnF,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAiBD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CA2BpE"}
package/dist/fuzzy.js ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Tiny zero-dependency fuzzy matcher for the insert palette. Subsequence match with a score that
3
+ * rewards contiguous runs, matches at word boundaries (camelCase / separators), and an early
4
+ * first match. Returns the matched character indices so the UI can highlight them.
5
+ *
6
+ * Lives in `@xenolithengine/graph-core` (zero-dep invariant) so the node registry's search stays headless —
7
+ * hence hand-rolled rather than a package.
8
+ */
9
+ const SCORE_FIRST_CHAR = 8; // bonus when the first query char lands at target[0]
10
+ const SCORE_CONSECUTIVE = 6; // bonus per char that immediately follows the previous match
11
+ const SCORE_WORD_START = 5; // bonus when a match lands at a word boundary
12
+ const SCORE_BASE = 1; // every matched char scores at least this
13
+ function isWordStart(target, i) {
14
+ if (i === 0)
15
+ return true;
16
+ const prev = target[i - 1];
17
+ const cur = target[i];
18
+ if (prev === ' ' || prev === '_' || prev === '-' || prev === '/' || prev === '.')
19
+ return true;
20
+ // camelCase boundary: lower→Upper
21
+ if (prev >= 'a' && prev <= 'z' && cur >= 'A' && cur <= 'Z')
22
+ return true;
23
+ return false;
24
+ }
25
+ export function fuzzyMatch(query, target) {
26
+ if (query.length === 0)
27
+ return { matched: true, score: 0, indices: [] };
28
+ const q = query.toLowerCase();
29
+ const t = target.toLowerCase();
30
+ const indices = [];
31
+ let score = 0;
32
+ let qi = 0;
33
+ let prevMatch = -2; // so the first match is never "consecutive"
34
+ for (let ti = 0; ti < t.length && qi < q.length; ti++) {
35
+ if (t[ti] !== q[qi])
36
+ continue;
37
+ indices.push(ti);
38
+ let charScore = SCORE_BASE;
39
+ if (ti === prevMatch + 1)
40
+ charScore += SCORE_CONSECUTIVE;
41
+ if (isWordStart(target, ti))
42
+ charScore += SCORE_WORD_START;
43
+ if (qi === 0 && ti === 0)
44
+ charScore += SCORE_FIRST_CHAR;
45
+ // Earlier matches are slightly better — small decay by position keeps prefix wins ahead.
46
+ charScore += Math.max(0, 4 - ti * 0.1);
47
+ score += charScore;
48
+ prevMatch = ti;
49
+ qi++;
50
+ }
51
+ if (qi < q.length)
52
+ return { matched: false, score: 0, indices: [] };
53
+ return { matched: true, score, indices };
54
+ }
55
+ //# sourceMappingURL=fuzzy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy.js","sourceRoot":"","sources":["../src/fuzzy.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,MAAM,gBAAgB,GAAK,CAAC,CAAA,CAAG,qDAAqD;AACpF,MAAM,iBAAiB,GAAI,CAAC,CAAA,CAAG,6DAA6D;AAC5F,MAAM,gBAAgB,GAAK,CAAC,CAAA,CAAG,8CAA8C;AAC7E,MAAM,UAAU,GAAW,CAAC,CAAA,CAAG,0CAA0C;AAEzE,SAAS,WAAW,CAAC,MAAc,EAAE,CAAS;IAC5C,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACxB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,CAAA;IAC3B,MAAM,GAAG,GAAI,MAAM,CAAC,CAAC,CAAE,CAAA;IACvB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IAC7F,kCAAkC;IAClC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG;QAAE,OAAO,IAAI,CAAA;IACvE,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,MAAc;IACtD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;IAEvE,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;IAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,CAAA;IAE9B,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,EAAE,GAAG,CAAC,CAAA;IACV,IAAI,SAAS,GAAG,CAAC,CAAC,CAAA,CAAC,4CAA4C;IAE/D,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QACtD,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAAE,SAAQ;QAC7B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAChB,IAAI,SAAS,GAAG,UAAU,CAAA;QAC1B,IAAI,EAAE,KAAK,SAAS,GAAG,CAAC;YAAE,SAAS,IAAI,iBAAiB,CAAA;QACxD,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;YAAE,SAAS,IAAI,gBAAgB,CAAA;QAC1D,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC;YAAE,SAAS,IAAI,gBAAgB,CAAA;QACvD,yFAAyF;QACzF,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,CAAA;QACtC,KAAK,IAAI,SAAS,CAAA;QAClB,SAAS,GAAG,EAAE,CAAA;QACd,EAAE,EAAE,CAAA;IACN,CAAC;IAED,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;IACnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;AAC1C,CAAC"}
@@ -0,0 +1,108 @@
1
+ import type { NodeId, EdgeId, PinId, CommentId, TypeId } from './ids.js';
2
+ import type { WidgetSpec } from './widget.js';
3
+ export interface Vec2 {
4
+ x: number;
5
+ y: number;
6
+ }
7
+ export type PinKind = 'exec' | 'data';
8
+ export type PinDirection = 'in' | 'out';
9
+ /** A header glyph marker for a node — a small icon drawn in the node header. `icon` names an entry in
10
+ * the renderer's icon registry (a built-in like 'cpu'/'layers', or a host/plugin-registered name).
11
+ * `side` picks which side of the title it sits on (default 'left'). Positioning is automatic. */
12
+ export interface NodeGlyph {
13
+ icon: string;
14
+ side?: 'left' | 'right';
15
+ }
16
+ export interface Pin {
17
+ id: PinId;
18
+ kind: PinKind;
19
+ direction: PinDirection;
20
+ type: TypeId | string;
21
+ multiple: boolean;
22
+ label?: string;
23
+ default?: unknown;
24
+ }
25
+ export interface Node {
26
+ id: NodeId;
27
+ type: string;
28
+ position: Vec2;
29
+ size?: Vec2;
30
+ state: Record<string, unknown>;
31
+ pins: Pin[];
32
+ /** In-node UI controls. Values live in `state` (keyed by each widget's `key`). */
33
+ widgets?: WidgetSpec[];
34
+ /** Blueprint "pure" node — no exec flow, lazily pulled. The editor doesn't interpret this; it's a
35
+ * hint for a host evaluator (and a render cue: pure nodes carry no exec pins). */
36
+ pure?: boolean;
37
+ /** Arbitrary host/plugin metadata, passed through serialization untouched. The core never reads it. */
38
+ meta?: Record<string, unknown>;
39
+ /** A header glyph icon for this node (auto-positioned in the header by the renderer). */
40
+ glyph?: NodeGlyph;
41
+ /** Schema version this node was instantiated under (defaults to its NodeSchema's `version`, or
42
+ * 1). Serialized to JSON so `loadJSON` can route stale payloads through the schema's
43
+ * `migrate(oldNode, oldVersion)` hook. */
44
+ version?: number;
45
+ }
46
+ export interface Edge {
47
+ id: EdgeId;
48
+ from: {
49
+ node: NodeId;
50
+ pin: PinId;
51
+ };
52
+ to: {
53
+ node: NodeId;
54
+ pin: PinId;
55
+ };
56
+ }
57
+ export interface Comment {
58
+ id: CommentId;
59
+ position: Vec2;
60
+ size: Vec2;
61
+ text: string;
62
+ color?: string;
63
+ }
64
+ export declare class Graph {
65
+ #private;
66
+ get version(): number;
67
+ get nodeCount(): number;
68
+ get edgeCount(): number;
69
+ get commentCount(): number;
70
+ getNode(id: NodeId): Readonly<Node> | undefined;
71
+ hasNode(id: NodeId): boolean;
72
+ nodes(): IterableIterator<Readonly<Node>>;
73
+ getEdge(id: EdgeId): Readonly<Edge> | undefined;
74
+ hasEdge(id: EdgeId): boolean;
75
+ edges(): IterableIterator<Readonly<Edge>>;
76
+ getComment(id: CommentId): Readonly<Comment> | undefined;
77
+ hasComment(id: CommentId): boolean;
78
+ comments(): IterableIterator<Readonly<Comment>>;
79
+ /** @internal */
80
+ _addComment(comment: Comment): void;
81
+ /** @internal */
82
+ _removeComment(id: CommentId): Comment | undefined;
83
+ /** @internal — patch mutable Comment fields in place (identity `id` is immutable). */
84
+ _patchComment(id: CommentId, patch: Partial<Pick<Comment, 'position' | 'size' | 'text' | 'color'>>): Readonly<Comment> | undefined;
85
+ /** @internal — call only from CommandBus-applied commands. */
86
+ _addNode(node: Node): void;
87
+ /** @internal */
88
+ _removeNode(id: NodeId): Node | undefined;
89
+ /** @internal */
90
+ _addEdge(edge: Edge): void;
91
+ /** @internal */
92
+ _removeEdge(id: EdgeId): Edge | undefined;
93
+ /**
94
+ * @internal — patch a subset of mutable Node fields in place.
95
+ * Only `position`, `size`, `state`, and `type` may be patched; identity (`id`) and pin structure
96
+ * (`pins`) are immutable through this method by design. Returns the patched node (same reference)
97
+ * or undefined if the id is unknown.
98
+ */
99
+ _patchNode(id: NodeId, patch: Partial<Pick<Node, 'position' | 'size' | 'state' | 'type'>>): Readonly<Node> | undefined;
100
+ /** @internal — replace a node's pin list wholesale. Pruning edges incident to dropped pins is the
101
+ * caller's job (the SetNodePins command does it so the change is undoable). */
102
+ _setNodePins(id: NodeId, pins: Pin[]): Readonly<Node> | undefined;
103
+ /** @internal — replace a node's widget list wholesale. Per-widget `node.state[key]` values are
104
+ * NOT touched: re-adding a previously-removed widget under the same key restores its value.
105
+ * Use via the `SetNodeWidgets` command so the change is undoable. */
106
+ _setNodeWidgets(id: NodeId, widgets: WidgetSpec[] | undefined): Readonly<Node> | undefined;
107
+ }
108
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}