@danielfgray/pg-sourcerer 0.1.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 (145) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +104 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/config.d.ts +133 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +47 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/errors.d.ts +129 -0
  10. package/dist/errors.d.ts.map +1 -0
  11. package/dist/errors.js +41 -0
  12. package/dist/errors.js.map +1 -0
  13. package/dist/generate.d.ts +75 -0
  14. package/dist/generate.d.ts.map +1 -0
  15. package/dist/generate.js +183 -0
  16. package/dist/generate.js.map +1 -0
  17. package/dist/index.d.ts +35 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +62 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/init.d.ts +4 -0
  22. package/dist/init.d.ts.map +1 -0
  23. package/dist/init.js +229 -0
  24. package/dist/init.js.map +1 -0
  25. package/dist/ir/index.d.ts +7 -0
  26. package/dist/ir/index.d.ts.map +1 -0
  27. package/dist/ir/index.js +7 -0
  28. package/dist/ir/index.js.map +1 -0
  29. package/dist/ir/relation-graph.d.ts +113 -0
  30. package/dist/ir/relation-graph.d.ts.map +1 -0
  31. package/dist/ir/relation-graph.js +232 -0
  32. package/dist/ir/relation-graph.js.map +1 -0
  33. package/dist/ir/semantic-ir.d.ts +448 -0
  34. package/dist/ir/semantic-ir.d.ts.map +1 -0
  35. package/dist/ir/semantic-ir.js +138 -0
  36. package/dist/ir/semantic-ir.js.map +1 -0
  37. package/dist/ir/smart-tags.d.ts +24 -0
  38. package/dist/ir/smart-tags.d.ts.map +1 -0
  39. package/dist/ir/smart-tags.js +30 -0
  40. package/dist/ir/smart-tags.js.map +1 -0
  41. package/dist/lib/conjure.d.ts +431 -0
  42. package/dist/lib/conjure.d.ts.map +1 -0
  43. package/dist/lib/conjure.js +697 -0
  44. package/dist/lib/conjure.js.map +1 -0
  45. package/dist/lib/field-utils.d.ts +61 -0
  46. package/dist/lib/field-utils.d.ts.map +1 -0
  47. package/dist/lib/field-utils.js +132 -0
  48. package/dist/lib/field-utils.js.map +1 -0
  49. package/dist/lib/hex.d.ts +117 -0
  50. package/dist/lib/hex.d.ts.map +1 -0
  51. package/dist/lib/hex.js +185 -0
  52. package/dist/lib/hex.js.map +1 -0
  53. package/dist/plugins/arktype.d.ts +11 -0
  54. package/dist/plugins/arktype.d.ts.map +1 -0
  55. package/dist/plugins/arktype.js +207 -0
  56. package/dist/plugins/arktype.js.map +1 -0
  57. package/dist/plugins/effect-model.d.ts +10 -0
  58. package/dist/plugins/effect-model.d.ts.map +1 -0
  59. package/dist/plugins/effect-model.js +261 -0
  60. package/dist/plugins/effect-model.js.map +1 -0
  61. package/dist/plugins/kysely-queries.d.ts +7 -0
  62. package/dist/plugins/kysely-queries.d.ts.map +1 -0
  63. package/dist/plugins/kysely-queries.js +380 -0
  64. package/dist/plugins/kysely-queries.js.map +1 -0
  65. package/dist/plugins/sql-queries.d.ts +6 -0
  66. package/dist/plugins/sql-queries.d.ts.map +1 -0
  67. package/dist/plugins/sql-queries.js +249 -0
  68. package/dist/plugins/sql-queries.js.map +1 -0
  69. package/dist/plugins/types.d.ts +18 -0
  70. package/dist/plugins/types.d.ts.map +1 -0
  71. package/dist/plugins/types.js +263 -0
  72. package/dist/plugins/types.js.map +1 -0
  73. package/dist/plugins/zod.d.ts +11 -0
  74. package/dist/plugins/zod.d.ts.map +1 -0
  75. package/dist/plugins/zod.js +180 -0
  76. package/dist/plugins/zod.js.map +1 -0
  77. package/dist/services/artifact-store.d.ts +55 -0
  78. package/dist/services/artifact-store.d.ts.map +1 -0
  79. package/dist/services/artifact-store.js +51 -0
  80. package/dist/services/artifact-store.js.map +1 -0
  81. package/dist/services/config-loader.d.ts +45 -0
  82. package/dist/services/config-loader.d.ts.map +1 -0
  83. package/dist/services/config-loader.js +113 -0
  84. package/dist/services/config-loader.js.map +1 -0
  85. package/dist/services/emissions.d.ts +89 -0
  86. package/dist/services/emissions.d.ts.map +1 -0
  87. package/dist/services/emissions.js +194 -0
  88. package/dist/services/emissions.js.map +1 -0
  89. package/dist/services/file-builder.d.ts +81 -0
  90. package/dist/services/file-builder.d.ts.map +1 -0
  91. package/dist/services/file-builder.js +112 -0
  92. package/dist/services/file-builder.js.map +1 -0
  93. package/dist/services/file-writer.d.ts +57 -0
  94. package/dist/services/file-writer.d.ts.map +1 -0
  95. package/dist/services/file-writer.js +76 -0
  96. package/dist/services/file-writer.js.map +1 -0
  97. package/dist/services/inflection.d.ts +227 -0
  98. package/dist/services/inflection.d.ts.map +1 -0
  99. package/dist/services/inflection.js +350 -0
  100. package/dist/services/inflection.js.map +1 -0
  101. package/dist/services/introspection.d.ts +46 -0
  102. package/dist/services/introspection.d.ts.map +1 -0
  103. package/dist/services/introspection.js +99 -0
  104. package/dist/services/introspection.js.map +1 -0
  105. package/dist/services/ir-builder.d.ts +46 -0
  106. package/dist/services/ir-builder.d.ts.map +1 -0
  107. package/dist/services/ir-builder.js +923 -0
  108. package/dist/services/ir-builder.js.map +1 -0
  109. package/dist/services/ir.d.ts +28 -0
  110. package/dist/services/ir.d.ts.map +1 -0
  111. package/dist/services/ir.js +25 -0
  112. package/dist/services/ir.js.map +1 -0
  113. package/dist/services/pg-types.d.ts +197 -0
  114. package/dist/services/pg-types.d.ts.map +1 -0
  115. package/dist/services/pg-types.js +274 -0
  116. package/dist/services/pg-types.js.map +1 -0
  117. package/dist/services/plugin-meta.d.ts +33 -0
  118. package/dist/services/plugin-meta.d.ts.map +1 -0
  119. package/dist/services/plugin-meta.js +24 -0
  120. package/dist/services/plugin-meta.js.map +1 -0
  121. package/dist/services/plugin-runner.d.ts +52 -0
  122. package/dist/services/plugin-runner.d.ts.map +1 -0
  123. package/dist/services/plugin-runner.js +182 -0
  124. package/dist/services/plugin-runner.js.map +1 -0
  125. package/dist/services/plugin.d.ts +286 -0
  126. package/dist/services/plugin.d.ts.map +1 -0
  127. package/dist/services/plugin.js +132 -0
  128. package/dist/services/plugin.js.map +1 -0
  129. package/dist/services/smart-tags-parser.d.ts +37 -0
  130. package/dist/services/smart-tags-parser.d.ts.map +1 -0
  131. package/dist/services/smart-tags-parser.js +79 -0
  132. package/dist/services/smart-tags-parser.js.map +1 -0
  133. package/dist/services/symbols.d.ts +85 -0
  134. package/dist/services/symbols.d.ts.map +1 -0
  135. package/dist/services/symbols.js +128 -0
  136. package/dist/services/symbols.js.map +1 -0
  137. package/dist/services/type-hints.d.ts +62 -0
  138. package/dist/services/type-hints.d.ts.map +1 -0
  139. package/dist/services/type-hints.js +117 -0
  140. package/dist/services/type-hints.js.map +1 -0
  141. package/dist/testing.d.ts +77 -0
  142. package/dist/testing.d.ts.map +1 -0
  143. package/dist/testing.js +84 -0
  144. package/dist/testing.js.map +1 -0
  145. package/package.json +74 -0
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Relation Graph Utilities
3
+ *
4
+ * Utilities for navigating entity relationships in the IR using Effect's Graph module.
5
+ * Useful for query builders, documentation generators, ERD tools, etc.
6
+ */
7
+ import { Graph, Option } from "effect";
8
+ import type { Relation, ReverseRelation, SemanticIR, TableEntity } from "./semantic-ir.js";
9
+ /**
10
+ * Edge data stored in the relation graph.
11
+ * Represents a foreign key constraint between two entities.
12
+ */
13
+ export interface RelationEdge {
14
+ readonly constraintName: string;
15
+ readonly columns: readonly {
16
+ readonly local: string;
17
+ readonly foreign: string;
18
+ }[];
19
+ /** Entity that owns the FK column (the "child" in the relationship) */
20
+ readonly fkHolder: string;
21
+ }
22
+ /**
23
+ * The relation graph type - a directed graph where:
24
+ * - Nodes are entity names (strings)
25
+ * - Edges point from FK holder → referenced entity
26
+ * - Edge data contains constraint info
27
+ */
28
+ export type RelationGraph = Graph.DirectedGraph<string, RelationEdge>;
29
+ /**
30
+ * An entity that can be directly joined from another entity.
31
+ */
32
+ export interface JoinableEntity {
33
+ readonly entity: TableEntity;
34
+ readonly direction: "belongsTo" | "hasMany";
35
+ readonly relation: Relation | ReverseRelation;
36
+ /** Human-readable description: "orders via user_id → users.id" */
37
+ readonly description: string;
38
+ }
39
+ /**
40
+ * A single step in a join path between two entities.
41
+ */
42
+ export interface JoinStep {
43
+ readonly from: string;
44
+ readonly to: string;
45
+ readonly direction: "belongsTo" | "hasMany";
46
+ readonly constraintName: string;
47
+ readonly columns: readonly {
48
+ readonly local: string;
49
+ readonly foreign: string;
50
+ }[];
51
+ }
52
+ /**
53
+ * Result of path finding - either a path or information about why none exists.
54
+ */
55
+ export type JoinPathResult = {
56
+ readonly _tag: "Found";
57
+ readonly path: readonly JoinStep[];
58
+ } | {
59
+ readonly _tag: "NotFound";
60
+ readonly from: string;
61
+ readonly to: string;
62
+ } | {
63
+ readonly _tag: "SameEntity";
64
+ readonly entity: string;
65
+ } | {
66
+ readonly _tag: "EntityNotFound";
67
+ readonly entity: string;
68
+ };
69
+ /**
70
+ * Build a directed graph from the IR's entity relations.
71
+ *
72
+ * Edges point from FK holder → referenced entity (i.e., orders → users
73
+ * when orders.user_id references users.id).
74
+ *
75
+ * Use with Graph.bfs/dfs and direction: 'outgoing' for belongsTo traversal,
76
+ * direction: 'incoming' for hasMany traversal.
77
+ */
78
+ export declare function buildRelationGraph(ir: SemanticIR): RelationGraph;
79
+ /**
80
+ * Get the node index for an entity name in the graph.
81
+ */
82
+ export declare function getEntityIndex(graph: RelationGraph, entityName: string): Option.Option<Graph.NodeIndex>;
83
+ /**
84
+ * Get all entities directly joinable from this entity (via FK in either direction).
85
+ *
86
+ * Returns both:
87
+ * - belongsTo: entities this one references (we have the FK)
88
+ * - hasMany: entities that reference this one (they have the FK)
89
+ */
90
+ export declare function getJoinableEntities(ir: SemanticIR, entityName: string): readonly JoinableEntity[];
91
+ /**
92
+ * Find the shortest path between two entities using BFS.
93
+ *
94
+ * Returns a JoinPathResult indicating:
95
+ * - Found: path exists with the steps to take
96
+ * - NotFound: no path exists between the entities
97
+ * - SameEntity: from and to are the same entity
98
+ * - EntityNotFound: one of the entity names doesn't exist in the IR
99
+ *
100
+ * The algorithm explores both directions (belongsTo and hasMany) to find
101
+ * any valid path through the relation graph.
102
+ */
103
+ export declare function findJoinPath(ir: SemanticIR, from: string, to: string): JoinPathResult;
104
+ /**
105
+ * Export the relation graph as a Mermaid diagram.
106
+ * Useful for documentation and debugging.
107
+ */
108
+ export declare function toMermaid(graph: RelationGraph): string;
109
+ /**
110
+ * Export the relation graph as a Mermaid diagram directly from IR.
111
+ */
112
+ export declare function irToMermaid(ir: SemanticIR): string;
113
+ //# sourceMappingURL=relation-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-graph.d.ts","sourceRoot":"","sources":["../../src/ir/relation-graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAS,KAAK,EAAE,MAAM,EAAQ,MAAM,QAAQ,CAAA;AAEnD,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAO1F;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACjF,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;AAErE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAA;IAC3C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,eAAe,CAAA;IAC7C,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAA;IAC3C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAClF;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAA;CAAE,GAC9D;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACzE;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAMhE;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,UAAU,GAAG,aAAa,CA+BhE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAEhC;AAuBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CA6CjG;AAeD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,cAAc,CAmFrF;AA4CD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAMtD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,UAAU,GAAG,MAAM,CAElD"}
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Relation Graph Utilities
3
+ *
4
+ * Utilities for navigating entity relationships in the IR using Effect's Graph module.
5
+ * Useful for query builders, documentation generators, ERD tools, etc.
6
+ */
7
+ import { Array, Graph, Option, pipe } from "effect";
8
+ import { getAllRelations, isTableEntity } from "./semantic-ir.js";
9
+ // ============================================================================
10
+ // Graph Construction
11
+ // ============================================================================
12
+ /**
13
+ * Build a directed graph from the IR's entity relations.
14
+ *
15
+ * Edges point from FK holder → referenced entity (i.e., orders → users
16
+ * when orders.user_id references users.id).
17
+ *
18
+ * Use with Graph.bfs/dfs and direction: 'outgoing' for belongsTo traversal,
19
+ * direction: 'incoming' for hasMany traversal.
20
+ */
21
+ export function buildRelationGraph(ir) {
22
+ const tableEntities = pipe(Array.fromIterable(ir.entities.values()), Array.filter(isTableEntity));
23
+ return Graph.directed((mutable) => {
24
+ // Build entity name → node index mapping
25
+ const nodeIndices = new Map(tableEntities.map((entity) => [entity.name, Graph.addNode(mutable, entity.name)]));
26
+ // Add edges for all belongsTo relations
27
+ for (const entity of tableEntities) {
28
+ const fromIdx = nodeIndices.get(entity.name);
29
+ if (fromIdx === undefined)
30
+ continue;
31
+ for (const rel of entity.relations) {
32
+ if (rel.kind !== "belongsTo")
33
+ continue;
34
+ const toIdx = nodeIndices.get(rel.targetEntity);
35
+ if (toIdx === undefined)
36
+ continue; // Skip broken refs
37
+ Graph.addEdge(mutable, fromIdx, toIdx, {
38
+ constraintName: rel.constraintName,
39
+ columns: rel.columns,
40
+ fkHolder: entity.name,
41
+ });
42
+ }
43
+ }
44
+ });
45
+ }
46
+ /**
47
+ * Get the node index for an entity name in the graph.
48
+ */
49
+ export function getEntityIndex(graph, entityName) {
50
+ return Graph.findNode(graph, (name) => name === entityName);
51
+ }
52
+ // ============================================================================
53
+ // Joinable Entities
54
+ // ============================================================================
55
+ /**
56
+ * Format a relation as a human-readable description.
57
+ * Example: "orders via user_id → users.id"
58
+ */
59
+ function formatRelationDescription(fromEntity, toEntity, columns, direction) {
60
+ const columnPairs = columns.map((c) => `${c.local} → ${c.foreign}`).join(", ");
61
+ return direction === "belongsTo"
62
+ ? `${fromEntity} via ${columnPairs}`
63
+ : `${toEntity} via ${columnPairs}`;
64
+ }
65
+ /**
66
+ * Get all entities directly joinable from this entity (via FK in either direction).
67
+ *
68
+ * Returns both:
69
+ * - belongsTo: entities this one references (we have the FK)
70
+ * - hasMany: entities that reference this one (they have the FK)
71
+ */
72
+ export function getJoinableEntities(ir, entityName) {
73
+ const allRels = getAllRelations(ir, entityName);
74
+ if (!allRels)
75
+ return [];
76
+ const belongsToResults = pipe(allRels.belongsTo, Array.filterMap((rel) => {
77
+ const target = ir.entities.get(rel.targetEntity);
78
+ if (!target || !isTableEntity(target))
79
+ return Option.none();
80
+ return Option.some({
81
+ entity: target,
82
+ direction: "belongsTo",
83
+ relation: rel,
84
+ description: formatRelationDescription(entityName, rel.targetEntity, rel.columns, "belongsTo"),
85
+ });
86
+ }));
87
+ const hasManyResults = pipe(allRels.hasMany, Array.filterMap((rel) => {
88
+ const source = ir.entities.get(rel.sourceEntity);
89
+ if (!source || !isTableEntity(source))
90
+ return Option.none();
91
+ return Option.some({
92
+ entity: source,
93
+ direction: "hasMany",
94
+ relation: rel,
95
+ description: formatRelationDescription(rel.sourceEntity, entityName, rel.columns, "hasMany"),
96
+ });
97
+ }));
98
+ return [...belongsToResults, ...hasManyResults];
99
+ }
100
+ /**
101
+ * Find the shortest path between two entities using BFS.
102
+ *
103
+ * Returns a JoinPathResult indicating:
104
+ * - Found: path exists with the steps to take
105
+ * - NotFound: no path exists between the entities
106
+ * - SameEntity: from and to are the same entity
107
+ * - EntityNotFound: one of the entity names doesn't exist in the IR
108
+ *
109
+ * The algorithm explores both directions (belongsTo and hasMany) to find
110
+ * any valid path through the relation graph.
111
+ */
112
+ export function findJoinPath(ir, from, to) {
113
+ // Same entity check
114
+ if (from === to) {
115
+ return { _tag: "SameEntity", entity: from };
116
+ }
117
+ // Validate entities exist
118
+ const fromEntity = ir.entities.get(from);
119
+ const toEntity = ir.entities.get(to);
120
+ if (!fromEntity || !isTableEntity(fromEntity)) {
121
+ return { _tag: "EntityNotFound", entity: from };
122
+ }
123
+ if (!toEntity || !isTableEntity(toEntity)) {
124
+ return { _tag: "EntityNotFound", entity: to };
125
+ }
126
+ // Build graph and get node indices
127
+ const graph = buildRelationGraph(ir);
128
+ const fromIdxOpt = getEntityIndex(graph, from);
129
+ const toIdxOpt = getEntityIndex(graph, to);
130
+ if (Option.isNone(fromIdxOpt) || Option.isNone(toIdxOpt)) {
131
+ return { _tag: "NotFound", from, to };
132
+ }
133
+ const fromIdx = fromIdxOpt.value;
134
+ const toIdx = toIdxOpt.value;
135
+ // BFS with parent tracking for path reconstruction
136
+ // We need to explore both edge directions (outgoing = belongsTo, incoming = hasMany)
137
+ const visited = new Set();
138
+ const parents = new Map();
139
+ const queue = [{ nodeIdx: fromIdx }];
140
+ visited.add(fromIdx);
141
+ while (queue.length > 0) {
142
+ const { nodeIdx: currentIdx } = queue.shift();
143
+ if (currentIdx === toIdx) {
144
+ // Found! Reconstruct path
145
+ return { _tag: "Found", path: reconstructPath(graph, parents, fromIdx, toIdx) };
146
+ }
147
+ // Explore outgoing edges (belongsTo direction)
148
+ const outgoingEdges = graph.adjacency.get(currentIdx) ?? [];
149
+ for (const edgeIdx of outgoingEdges) {
150
+ const edge = graph.edges.get(edgeIdx);
151
+ if (!edge)
152
+ continue;
153
+ const neighborIdx = edge.target;
154
+ if (!visited.has(neighborIdx)) {
155
+ visited.add(neighborIdx);
156
+ parents.set(neighborIdx, {
157
+ parentIdx: currentIdx,
158
+ edgeIdx,
159
+ direction: "belongsTo",
160
+ });
161
+ queue.push({ nodeIdx: neighborIdx });
162
+ }
163
+ }
164
+ // Explore incoming edges (hasMany direction)
165
+ const incomingEdges = graph.reverseAdjacency.get(currentIdx) ?? [];
166
+ for (const edgeIdx of incomingEdges) {
167
+ const edge = graph.edges.get(edgeIdx);
168
+ if (!edge)
169
+ continue;
170
+ const neighborIdx = edge.source;
171
+ if (!visited.has(neighborIdx)) {
172
+ visited.add(neighborIdx);
173
+ parents.set(neighborIdx, {
174
+ parentIdx: currentIdx,
175
+ edgeIdx,
176
+ direction: "hasMany",
177
+ });
178
+ queue.push({ nodeIdx: neighborIdx });
179
+ }
180
+ }
181
+ }
182
+ return { _tag: "NotFound", from, to };
183
+ }
184
+ /**
185
+ * Reconstruct the path from BFS parent pointers.
186
+ */
187
+ function reconstructPath(graph, parents, fromIdx, toIdx) {
188
+ const steps = [];
189
+ let currentIdx = toIdx;
190
+ while (currentIdx !== fromIdx) {
191
+ const parent = parents.get(currentIdx);
192
+ if (!parent)
193
+ break; // Should never happen if BFS worked correctly
194
+ const edge = graph.edges.get(parent.edgeIdx);
195
+ if (!edge)
196
+ break;
197
+ const fromName = graph.nodes.get(parent.parentIdx);
198
+ const toName = graph.nodes.get(currentIdx);
199
+ if (fromName && toName) {
200
+ steps.unshift({
201
+ from: fromName,
202
+ to: toName,
203
+ direction: parent.direction,
204
+ constraintName: edge.data.constraintName,
205
+ columns: edge.data.columns,
206
+ });
207
+ }
208
+ currentIdx = parent.parentIdx;
209
+ }
210
+ return steps;
211
+ }
212
+ // ============================================================================
213
+ // Visualization Helpers
214
+ // ============================================================================
215
+ /**
216
+ * Export the relation graph as a Mermaid diagram.
217
+ * Useful for documentation and debugging.
218
+ */
219
+ export function toMermaid(graph) {
220
+ return Graph.toMermaid(graph, {
221
+ direction: "LR",
222
+ nodeLabel: (name) => name,
223
+ edgeLabel: (edge) => edge.constraintName,
224
+ });
225
+ }
226
+ /**
227
+ * Export the relation graph as a Mermaid diagram directly from IR.
228
+ */
229
+ export function irToMermaid(ir) {
230
+ return toMermaid(buildRelationGraph(ir));
231
+ }
232
+ //# sourceMappingURL=relation-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-graph.js","sourceRoot":"","sources":["../../src/ir/relation-graph.ts"],"names":[],"mappings":"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"}