@linklabjs/core 0.1.0 → 0.1.2

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 (206) hide show
  1. package/dist/api/DomainNode.d.ts +154 -0
  2. package/dist/api/DomainNode.d.ts.map +1 -0
  3. package/dist/api/DomainNode.js +1157 -0
  4. package/dist/api/DomainNode.js.map +1 -0
  5. package/dist/api/Graph.d.ts +117 -0
  6. package/dist/api/Graph.d.ts.map +1 -0
  7. package/dist/api/Graph.js +212 -0
  8. package/dist/api/Graph.js.map +1 -0
  9. package/dist/api/PathBuilder.d.ts +76 -0
  10. package/dist/api/PathBuilder.d.ts.map +1 -0
  11. package/dist/api/PathBuilder.js +182 -0
  12. package/dist/api/PathBuilder.js.map +1 -0
  13. package/dist/api/index.d.ts +8 -0
  14. package/dist/api/index.d.ts.map +1 -0
  15. package/dist/api/index.js +7 -0
  16. package/dist/api/index.js.map +1 -0
  17. package/dist/api/loadGraph.d.ts +57 -0
  18. package/dist/api/loadGraph.d.ts.map +1 -0
  19. package/dist/api/loadGraph.js +153 -0
  20. package/dist/api/loadGraph.js.map +1 -0
  21. package/dist/api/test-api.d.ts +9 -0
  22. package/dist/api/test-api.d.ts.map +1 -0
  23. package/dist/api/test-api.js +133 -0
  24. package/dist/api/test-api.js.map +1 -0
  25. package/dist/api/test-domain.d.ts +13 -0
  26. package/dist/api/test-domain.d.ts.map +1 -0
  27. package/dist/api/test-domain.js +105 -0
  28. package/dist/api/test-domain.js.map +1 -0
  29. package/dist/api/types.d.ts +69 -0
  30. package/dist/api/types.d.ts.map +1 -0
  31. package/dist/api/types.js +22 -0
  32. package/dist/api/types.js.map +1 -0
  33. package/dist/config/synonyms.json +25 -0
  34. package/dist/core/EventBus.d.ts +56 -0
  35. package/dist/core/EventBus.d.ts.map +1 -0
  36. package/dist/core/EventBus.js +147 -0
  37. package/dist/core/EventBus.js.map +1 -0
  38. package/dist/core/GraphEvents.d.ts +118 -0
  39. package/dist/core/GraphEvents.d.ts.map +1 -0
  40. package/dist/core/GraphEvents.js +23 -0
  41. package/dist/core/GraphEvents.js.map +1 -0
  42. package/dist/core/PathFinder.d.ts +43 -0
  43. package/dist/core/PathFinder.d.ts.map +1 -0
  44. package/dist/core/PathFinder.js +264 -0
  45. package/dist/core/PathFinder.js.map +1 -0
  46. package/dist/formatters/BaseFormatter.d.ts +15 -0
  47. package/dist/formatters/BaseFormatter.d.ts.map +1 -0
  48. package/dist/formatters/BaseFormatter.js +9 -0
  49. package/dist/formatters/BaseFormatter.js.map +1 -0
  50. package/dist/graph/GraphAssembler.d.ts +14 -0
  51. package/dist/graph/GraphAssembler.d.ts.map +1 -0
  52. package/dist/graph/GraphAssembler.js +44 -0
  53. package/dist/graph/GraphAssembler.js.map +1 -0
  54. package/dist/graph/GraphCompiler.d.ts +37 -0
  55. package/dist/graph/GraphCompiler.d.ts.map +1 -0
  56. package/dist/graph/GraphCompiler.js +355 -0
  57. package/dist/graph/GraphCompiler.js.map +1 -0
  58. package/dist/graph/GraphExtractor.d.ts +21 -0
  59. package/dist/graph/GraphExtractor.d.ts.map +1 -0
  60. package/dist/graph/GraphExtractor.js +145 -0
  61. package/dist/graph/GraphExtractor.js.map +1 -0
  62. package/dist/graph/GraphOptimizer.d.ts +104 -0
  63. package/dist/graph/GraphOptimizer.d.ts.map +1 -0
  64. package/dist/graph/GraphOptimizer.js +306 -0
  65. package/dist/graph/GraphOptimizer.js.map +1 -0
  66. package/dist/graph/GraphTrainer.d.ts +52 -0
  67. package/dist/graph/GraphTrainer.d.ts.map +1 -0
  68. package/dist/graph/GraphTrainer.js +188 -0
  69. package/dist/graph/GraphTrainer.js.map +1 -0
  70. package/dist/http/LinkBuilder.d.ts +82 -0
  71. package/dist/http/LinkBuilder.d.ts.map +1 -0
  72. package/dist/http/LinkBuilder.js +190 -0
  73. package/dist/http/LinkBuilder.js.map +1 -0
  74. package/dist/http/TrailRequest.d.ts +39 -0
  75. package/dist/http/TrailRequest.d.ts.map +1 -0
  76. package/dist/http/TrailRequest.js +22 -0
  77. package/dist/http/TrailRequest.js.map +1 -0
  78. package/dist/http/example-netflix.d.ts +6 -0
  79. package/dist/http/example-netflix.d.ts.map +1 -0
  80. package/dist/http/example-netflix.js +52 -0
  81. package/dist/http/example-netflix.js.map +1 -0
  82. package/dist/http/index.d.ts +32 -0
  83. package/dist/http/index.d.ts.map +1 -0
  84. package/dist/http/index.js +27 -0
  85. package/dist/http/index.js.map +1 -0
  86. package/dist/http/plugin.d.ts +110 -0
  87. package/dist/http/plugin.d.ts.map +1 -0
  88. package/dist/http/plugin.js +217 -0
  89. package/dist/http/plugin.js.map +1 -0
  90. package/dist/index.d.ts +55 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +71 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/instrumentation/TelemetryShim.d.ts +114 -0
  95. package/dist/instrumentation/TelemetryShim.d.ts.map +1 -0
  96. package/dist/instrumentation/TelemetryShim.js +107 -0
  97. package/dist/instrumentation/TelemetryShim.js.map +1 -0
  98. package/dist/navigation/NavigationEngine.d.ts +69 -0
  99. package/dist/navigation/NavigationEngine.d.ts.map +1 -0
  100. package/dist/navigation/NavigationEngine.js +361 -0
  101. package/dist/navigation/NavigationEngine.js.map +1 -0
  102. package/dist/navigation/Resolver.d.ts +35 -0
  103. package/dist/navigation/Resolver.d.ts.map +1 -0
  104. package/dist/navigation/Resolver.js +113 -0
  105. package/dist/navigation/Resolver.js.map +1 -0
  106. package/dist/navigation/Scheduler.d.ts +36 -0
  107. package/dist/navigation/Scheduler.d.ts.map +1 -0
  108. package/dist/navigation/Scheduler.js +107 -0
  109. package/dist/navigation/Scheduler.js.map +1 -0
  110. package/dist/navigation/Trail.d.ts +129 -0
  111. package/dist/navigation/Trail.d.ts.map +1 -0
  112. package/dist/navigation/Trail.js +202 -0
  113. package/dist/navigation/Trail.js.map +1 -0
  114. package/dist/navigation/TrailParser.d.ts +96 -0
  115. package/dist/navigation/TrailParser.d.ts.map +1 -0
  116. package/dist/navigation/TrailParser.js +180 -0
  117. package/dist/navigation/TrailParser.js.map +1 -0
  118. package/dist/navigation/index.d.ts +10 -0
  119. package/dist/navigation/index.d.ts.map +1 -0
  120. package/dist/navigation/index.js +9 -0
  121. package/dist/navigation/index.js.map +1 -0
  122. package/dist/providers/MockProvider.d.ts +29 -0
  123. package/dist/providers/MockProvider.d.ts.map +1 -0
  124. package/dist/providers/MockProvider.js +55 -0
  125. package/dist/providers/MockProvider.js.map +1 -0
  126. package/dist/providers/PostgresProvider.d.ts +46 -0
  127. package/dist/providers/PostgresProvider.d.ts.map +1 -0
  128. package/dist/providers/PostgresProvider.js +152 -0
  129. package/dist/providers/PostgresProvider.js.map +1 -0
  130. package/dist/runtime/CompiledGraphEngine.d.ts +74 -0
  131. package/dist/runtime/CompiledGraphEngine.d.ts.map +1 -0
  132. package/dist/runtime/CompiledGraphEngine.js +211 -0
  133. package/dist/runtime/CompiledGraphEngine.js.map +1 -0
  134. package/dist/runtime/DataLoader.d.ts +90 -0
  135. package/dist/runtime/DataLoader.d.ts.map +1 -0
  136. package/dist/runtime/DataLoader.js +178 -0
  137. package/dist/runtime/DataLoader.js.map +1 -0
  138. package/dist/runtime/Engine.d.ts +36 -0
  139. package/dist/runtime/Engine.d.ts.map +1 -0
  140. package/dist/runtime/Engine.js +128 -0
  141. package/dist/runtime/Engine.js.map +1 -0
  142. package/dist/runtime/QueryEngine.d.ts +80 -0
  143. package/dist/runtime/QueryEngine.d.ts.map +1 -0
  144. package/dist/runtime/QueryEngine.js +188 -0
  145. package/dist/runtime/QueryEngine.js.map +1 -0
  146. package/dist/scenarios/test-metro-paris/config.json +6 -0
  147. package/dist/scenarios/test-metro-paris/graph.json +16325 -0
  148. package/dist/scenarios/test-metro-paris/queries.d.ts +22 -0
  149. package/dist/scenarios/test-metro-paris/queries.d.ts.map +1 -0
  150. package/dist/scenarios/test-metro-paris/queries.js +128 -0
  151. package/dist/scenarios/test-metro-paris/queries.js.map +1 -0
  152. package/dist/scenarios/test-metro-paris/stack.json +1 -0
  153. package/dist/scenarios/test-musicians/config.json +10 -0
  154. package/dist/scenarios/test-musicians/graph.json +20 -0
  155. package/dist/scenarios/test-musicians/stack.json +1 -0
  156. package/dist/scenarios/test-netflix/actions.d.ts +14 -0
  157. package/dist/scenarios/test-netflix/actions.d.ts.map +1 -0
  158. package/dist/scenarios/test-netflix/actions.js +86 -0
  159. package/dist/scenarios/test-netflix/actions.js.map +1 -0
  160. package/dist/scenarios/test-netflix/config.json +6 -0
  161. package/dist/scenarios/test-netflix/data/categories.json +1 -0
  162. package/dist/scenarios/test-netflix/data/companies.json +1 -0
  163. package/dist/scenarios/test-netflix/data/credits.json +19797 -0
  164. package/dist/scenarios/test-netflix/data/departments.json +18 -0
  165. package/dist/scenarios/test-netflix/data/jobs.json +142 -0
  166. package/dist/scenarios/test-netflix/data/movies.json +3497 -0
  167. package/dist/scenarios/test-netflix/data/people.json +1 -0
  168. package/dist/scenarios/test-netflix/data/synonyms.json +7 -0
  169. package/dist/scenarios/test-netflix/data/users.json +70 -0
  170. package/dist/scenarios/test-netflix/graph.json +1017 -0
  171. package/dist/scenarios/test-netflix/queries.d.ts +29 -0
  172. package/dist/scenarios/test-netflix/queries.d.ts.map +1 -0
  173. package/dist/scenarios/test-netflix/queries.js +134 -0
  174. package/dist/scenarios/test-netflix/queries.js.map +1 -0
  175. package/dist/scenarios/test-netflix/stack.json +14 -0
  176. package/dist/schema/GraphBuilder.d.ts +9 -0
  177. package/dist/schema/GraphBuilder.d.ts.map +1 -0
  178. package/dist/schema/GraphBuilder.js +90 -0
  179. package/dist/schema/GraphBuilder.js.map +1 -0
  180. package/dist/schema/JsonSchemaExtractor.d.ts +21 -0
  181. package/dist/schema/JsonSchemaExtractor.d.ts.map +1 -0
  182. package/dist/schema/JsonSchemaExtractor.js +88 -0
  183. package/dist/schema/JsonSchemaExtractor.js.map +1 -0
  184. package/dist/schema/SchemaAnalyzer.d.ts +41 -0
  185. package/dist/schema/SchemaAnalyzer.d.ts.map +1 -0
  186. package/dist/schema/SchemaAnalyzer.js +144 -0
  187. package/dist/schema/SchemaAnalyzer.js.map +1 -0
  188. package/dist/schema/SchemaExtractor.d.ts +10 -0
  189. package/dist/schema/SchemaExtractor.d.ts.map +1 -0
  190. package/dist/schema/SchemaExtractor.js +90 -0
  191. package/dist/schema/SchemaExtractor.js.map +1 -0
  192. package/dist/schema/SynonymResolver.d.ts +55 -0
  193. package/dist/schema/SynonymResolver.d.ts.map +1 -0
  194. package/dist/schema/SynonymResolver.js +121 -0
  195. package/dist/schema/SynonymResolver.js.map +1 -0
  196. package/dist/scripts/dictionary.json +796 -0
  197. package/dist/scripts/graph.json +664 -0
  198. package/dist/scripts/regenerate.d.ts +23 -0
  199. package/dist/scripts/regenerate.d.ts.map +1 -0
  200. package/dist/scripts/regenerate.js +206 -0
  201. package/dist/scripts/regenerate.js.map +1 -0
  202. package/dist/types/index.d.ts +394 -0
  203. package/dist/types/index.d.ts.map +1 -0
  204. package/dist/types/index.js +21 -0
  205. package/dist/types/index.js.map +1 -0
  206. package/package.json +1 -1
@@ -0,0 +1,355 @@
1
+ /**
2
+ * GraphCompiler — v2.0.0
3
+ *
4
+ * Changements vs v1 :
5
+ * - Routes sémantiques (semantic_view) compilées et incluses
6
+ * - compiled-graph contient physical + semantic routes
7
+ * - version bump : '2.0.0'
8
+ *
9
+ * v2.1 :
10
+ * - Support expose config (ADR-0010)
11
+ * - node.exposed compilé depuis CompilerConfig.expose
12
+ */
13
+ import { PathFinder } from '../core/PathFinder.js';
14
+ export class GraphCompiler {
15
+ config;
16
+ constructor(config = {}) {
17
+ this.config = {
18
+ weightThreshold: config.weightThreshold ?? 1000,
19
+ minUsage: config.minUsage ?? 0,
20
+ keepFallbacks: config.keepFallbacks ?? true,
21
+ maxFallbacks: config.maxFallbacks ?? 2,
22
+ expose: config.expose ?? 'none'
23
+ };
24
+ }
25
+ compile(graph, metrics) {
26
+ console.log('🔧 Compiling optimized graph (v2 — physical + semantic)...\n');
27
+ const compiled = {
28
+ version: '2.0.0',
29
+ compiledAt: new Date().toISOString(),
30
+ config: this.config,
31
+ nodes: this.compileNodes(graph.nodes, this.config.expose),
32
+ routes: [],
33
+ stats: { totalPairs: 0, routesCompiled: 0, routesFiltered: 0, compressionRatio: '0%' }
34
+ };
35
+ // ── Nœuds réels (depuis les edges) ───────────────────────────────────────
36
+ const realNodes = new Set();
37
+ graph.edges.forEach(e => {
38
+ realNodes.add(e.from);
39
+ realNodes.add(e.to);
40
+ });
41
+ const nodeIds = Array.from(realNodes);
42
+ // ── 1. Routes physiques ───────────────────────────────────────────────────
43
+ const fkEdges = graph.edges.filter((e) => e.metadata?.type !== 'semantic_view' &&
44
+ e.metadata?.type !== 'virtual' &&
45
+ e.metadata?.type !== 'SEMANTIC');
46
+ const existingPairs = new Set(fkEdges.map((e) => `${e.from}→${e.to}`));
47
+ const inverseEdges = fkEdges
48
+ .filter((e) => !existingPairs.has(`${e.to}→${e.from}`))
49
+ .map((e) => ({
50
+ ...e,
51
+ from: e.to,
52
+ to: e.from,
53
+ name: `${e.name}_inv`,
54
+ metadata: { ...e.metadata, type: 'physical_reverse' }
55
+ }));
56
+ const physicalGraph = { ...graph, edges: [...fkEdges, ...inverseEdges] };
57
+ let kept = 0, filtered = 0;
58
+ const pairs = this.getAllPairs(nodeIds);
59
+ for (const { from, to } of pairs) {
60
+ const route = this.compilePath(from, to, physicalGraph, metrics);
61
+ if (route) {
62
+ compiled.routes.push(route);
63
+ kept++;
64
+ }
65
+ else {
66
+ filtered++;
67
+ }
68
+ }
69
+ // ── 2. Routes sémantiques ─────────────────────────────────────────────────
70
+ const semanticEdges = graph.edges.filter((e) => e.metadata?.type === 'semantic_view' && e.metadata?.condition != null);
71
+ let semanticKept = 0;
72
+ for (const edge of semanticEdges) {
73
+ const route = this.compileSemanticRoute(edge, graph);
74
+ if (route) {
75
+ compiled.routes.push(route);
76
+ semanticKept++;
77
+ }
78
+ }
79
+ // ── 2b. Routes virtuelles ─────────────────────────────────────────────────
80
+ const virtualEdges = graph.edges.filter((e) => e.metadata?.type === 'virtual');
81
+ let virtualKept = 0;
82
+ for (const edge of virtualEdges) {
83
+ const { from, to, via, name, weight } = edge;
84
+ if (!nodeIds.includes(from) || !nodeIds.includes(to))
85
+ continue;
86
+ const viaTable = via && nodeIds.includes(via) ? via : null;
87
+ const path = viaTable ? [from, viaTable, to] : [from, to];
88
+ const edges = viaTable
89
+ ? [
90
+ { fromCol: 'id', toCol: 'id' },
91
+ { fromCol: 'id', toCol: 'id' }
92
+ ]
93
+ : [{ fromCol: 'id', toCol: 'id' }];
94
+ compiled.routes.push({
95
+ from,
96
+ to,
97
+ semantic: false,
98
+ composed: false,
99
+ label: name ?? `virtual_${from}_${to}`,
100
+ virtual: true,
101
+ primary: {
102
+ path,
103
+ edges,
104
+ weight: weight ?? 1,
105
+ joins: path.length - 1,
106
+ avgTime: weight ?? 1
107
+ },
108
+ fallbacks: [],
109
+ alternativesDiscarded: 0
110
+ });
111
+ virtualKept++;
112
+ }
113
+ // ── 3. Routes composées ───────────────────────────────────────────────────
114
+ const compiledSemRoutes = compiled.routes.filter((r) => r.semantic);
115
+ let composedKept = 0;
116
+ const semByFrom = new Map();
117
+ for (const r of compiledSemRoutes) {
118
+ if (!semByFrom.has(r.from))
119
+ semByFrom.set(r.from, []);
120
+ semByFrom.get(r.from).push(r);
121
+ }
122
+ for (const [entityId, outRoutes] of semByFrom) {
123
+ const inRoutes = compiledSemRoutes.filter((r) => r.to === entityId);
124
+ if (!inRoutes.length)
125
+ continue;
126
+ for (const rOut of outRoutes) {
127
+ const pivot = rOut.to;
128
+ const matchingIn = inRoutes.filter((r) => r.from === pivot);
129
+ for (const rIn of matchingIn) {
130
+ if (rOut.label === rIn.label)
131
+ continue;
132
+ const composedLabel = `${rOut.label}→${rIn.label}`;
133
+ const composedWeight = rOut.primary.weight + rIn.primary.weight;
134
+ const composedPath = [...rOut.primary.path, ...rIn.primary.path.slice(1)];
135
+ const composedEdges = [...rOut.primary.edges, ...rIn.primary.edges];
136
+ const metricKey = `composed:${entityId}→${entityId}:${composedLabel}`;
137
+ const metric = metrics.get(metricKey);
138
+ if (metrics.size > 0) {
139
+ if (!metric)
140
+ continue;
141
+ const w = metric.avgTime ?? composedWeight;
142
+ if (!metric.used || w > this.config.weightThreshold)
143
+ continue;
144
+ }
145
+ compiled.routes.push({
146
+ from: entityId,
147
+ to: entityId,
148
+ semantic: true,
149
+ composed: true,
150
+ label: composedLabel,
151
+ primary: {
152
+ path: composedPath,
153
+ edges: composedEdges,
154
+ weight: composedWeight,
155
+ joins: composedPath.length - 1,
156
+ avgTime: composedWeight
157
+ },
158
+ fallbacks: [],
159
+ alternativesDiscarded: 0
160
+ });
161
+ composedKept++;
162
+ }
163
+ }
164
+ }
165
+ compiled.stats = {
166
+ totalPairs: pairs.length,
167
+ routesCompiled: kept + semanticKept + virtualKept + composedKept,
168
+ routesFiltered: filtered,
169
+ compressionRatio: '—'
170
+ };
171
+ console.log('\n✅ Compilation complete:');
172
+ console.log(` Physical routes: ${kept}`);
173
+ console.log(` Semantic routes: ${semanticKept}`);
174
+ console.log(` Composed routes: ${composedKept}`);
175
+ console.log(` Filtered: ${filtered}`);
176
+ return compiled;
177
+ }
178
+ // ── Compile exposed flag sur chaque node ────────────────────────────────────
179
+ compileNodes(nodes, expose) {
180
+ return nodes.map(node => {
181
+ let exposed;
182
+ if (expose === 'all') {
183
+ exposed = true;
184
+ }
185
+ else if (expose === 'none') {
186
+ exposed = false;
187
+ }
188
+ else if ('include' in expose) {
189
+ exposed = expose.include.includes(node.id);
190
+ }
191
+ else {
192
+ exposed = !expose.exclude.includes(node.id);
193
+ }
194
+ return { ...node, exposed };
195
+ });
196
+ }
197
+ // ── Route sémantique ─────────────────────────────────────────────────────────
198
+ compileSemanticRoute(edge, graph) {
199
+ const { from, to, via, metadata } = edge;
200
+ const condition = metadata.condition ?? {};
201
+ const label = edge.name ?? metadata.label ?? 'view';
202
+ const e1Raw = graph.edges.find((e) => ((e.from === from && e.to === via) || (e.from === via && e.to === from)) &&
203
+ (e.metadata?.type === 'physical' || e.metadata?.type === 'physical_reverse'));
204
+ const e2Raw = graph.edges.find((e) => ((e.from === via && e.to === to) || (e.from === to && e.to === via)) &&
205
+ (e.metadata?.type === 'physical' || e.metadata?.type === 'physical_reverse'));
206
+ if (!e1Raw || !e2Raw)
207
+ return null;
208
+ const e1IsReversed = e1Raw.from === via;
209
+ const e1 = {
210
+ fromCol: e1IsReversed ? 'id' : (e1Raw.via ?? 'id'),
211
+ toCol: e1IsReversed ? (e1Raw.via ?? 'id') : 'id',
212
+ condition,
213
+ label
214
+ };
215
+ const e2IsReversed = e2Raw.from === to;
216
+ const e2 = {
217
+ fromCol: e2IsReversed ? 'id' : (e2Raw.via ?? 'id'),
218
+ toCol: e2IsReversed ? (e2Raw.via ?? 'id') : 'id'
219
+ };
220
+ return {
221
+ from,
222
+ to,
223
+ semantic: true,
224
+ label,
225
+ primary: {
226
+ path: [from, via, to],
227
+ edges: [e1, e2],
228
+ weight: edge.weight ?? 0.8,
229
+ joins: 2,
230
+ avgTime: edge.weight ?? 0.8
231
+ },
232
+ fallbacks: [],
233
+ alternativesDiscarded: 0
234
+ };
235
+ }
236
+ // ── Routes physiques ──────────────────────────────────────────────────────────
237
+ getAllPairs(nodeIds) {
238
+ const pairs = [];
239
+ for (const from of nodeIds)
240
+ for (const to of nodeIds)
241
+ if (from !== to)
242
+ pairs.push({ from, to });
243
+ return pairs;
244
+ }
245
+ compilePath(from, to, graph, metrics) {
246
+ const finder = new PathFinder(graph);
247
+ const allPaths = finder.findAllPaths(from, to, 5);
248
+ if (!allPaths.length)
249
+ return null;
250
+ const pathsWithMetrics = allPaths.map(path => {
251
+ const key = path.join('→');
252
+ const metric = metrics.get(key);
253
+ let w = 0;
254
+ for (let i = 0; i < path.length - 1; i++) {
255
+ const ee = graph.edges.filter(e => (e.from === path[i] && e.to === path[i + 1]) ||
256
+ (e.from === path[i + 1] && e.to === path[i]));
257
+ const ws = ee.map(e => Number(e.weight)).filter(x => !isNaN(x));
258
+ w += ws.length ? Math.min(...ws) : 1;
259
+ }
260
+ const finalWeight = metric && !isNaN(metric.avgTime) ? metric.avgTime : w;
261
+ return {
262
+ path,
263
+ key,
264
+ weight: finalWeight,
265
+ failed: metric?.failed === true,
266
+ used: metric ? metric.used : true
267
+ };
268
+ });
269
+ const valid = pathsWithMetrics
270
+ .filter(p => !p.failed && p.used !== false)
271
+ .filter(p => !isNaN(p.weight) && p.weight <= this.config.weightThreshold)
272
+ .sort((a, b) => a.weight - b.weight);
273
+ if (!valid.length)
274
+ return null;
275
+ const unique = [];
276
+ const seen = new Set();
277
+ for (const p of valid) {
278
+ if (!seen.has(p.key)) {
279
+ unique.push(p);
280
+ seen.add(p.key);
281
+ }
282
+ }
283
+ const best = unique[0];
284
+ const fallbacks = this.config.keepFallbacks ? unique.slice(1, this.config.maxFallbacks + 1) : [];
285
+ const primaryEdges = this.resolveEdges(best.path, graph);
286
+ if (!primaryEdges)
287
+ return null;
288
+ return {
289
+ from,
290
+ to,
291
+ primary: {
292
+ path: best.path,
293
+ edges: primaryEdges,
294
+ weight: best.weight,
295
+ joins: best.path.length - 1,
296
+ avgTime: best.weight
297
+ },
298
+ fallbacks: fallbacks
299
+ .map(fb => {
300
+ const ee = this.resolveEdges(fb.path, graph);
301
+ if (!ee)
302
+ return null;
303
+ return {
304
+ path: fb.path,
305
+ edges: ee,
306
+ weight: fb.weight,
307
+ joins: fb.path.length - 1,
308
+ avgTime: fb.weight
309
+ };
310
+ })
311
+ .filter((fb) => fb !== null),
312
+ alternativesDiscarded: unique.length - 1 - fallbacks.length
313
+ };
314
+ }
315
+ resolveEdges(path, graph) {
316
+ const result = [];
317
+ const nodeNames = new Set(graph.nodes.map((n) => n.id));
318
+ for (let i = 0; i < path.length - 1; i++) {
319
+ const from = path[i], to = path[i + 1];
320
+ const edgeDirect = graph.edges.find((e) => e.from === from && e.to === to);
321
+ const edgeReverse = graph.edges.find((e) => e.from === to && e.to === from);
322
+ const edge = edgeDirect ?? edgeReverse;
323
+ const isReversed = !edgeDirect && !!edgeReverse;
324
+ if (!edge) {
325
+ result.push({ fromCol: 'id', toCol: `${from.toLowerCase()}Id` });
326
+ continue;
327
+ }
328
+ if (edge.metadata?.type === 'semantic_view' && nodeNames.has(edge.via))
329
+ return null;
330
+ const flipCols = edge.metadata?.type === 'physical_reverse' || isReversed;
331
+ result.push({
332
+ fromCol: flipCols ? 'id' : edge.via || 'id',
333
+ toCol: flipCols ? edge.via || 'id' : 'id'
334
+ });
335
+ }
336
+ return result;
337
+ }
338
+ static getStats(compiled) {
339
+ const routes = compiled.routes;
340
+ const semantic = routes.filter(r => r.semantic && !r.composed).length;
341
+ const composed = routes.filter(r => r.composed).length;
342
+ const physical = routes.length - semantic - composed;
343
+ if (!routes.length)
344
+ return { totalRoutes: 0, fallbackRatio: '0%', semantic: 0, physical: 0, composed: 0 };
345
+ const withFallbacks = routes.filter(r => r.fallbacks.length > 0).length;
346
+ return {
347
+ totalRoutes: routes.length,
348
+ physical,
349
+ semantic,
350
+ composed,
351
+ fallbackRatio: ((withFallbacks / routes.length) * 100).toFixed(1) + '%'
352
+ };
353
+ }
354
+ }
355
+ //# sourceMappingURL=GraphCompiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphCompiler.js","sourceRoot":"","sources":["../../src/graph/GraphCompiler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { Graph, Provider, ActionRegistry } from '../types/index.js';
2
+ export declare class GraphExtractor {
3
+ private provider;
4
+ private actionRegistry?;
5
+ constructor(provider: Provider, actionRegistry?: ActionRegistry);
6
+ /**
7
+ * Extrait le graphe complet : Tables + Actions + Relations
8
+ */
9
+ extract(): Promise<Graph>;
10
+ private getTables;
11
+ private getColumns;
12
+ private getRowCount;
13
+ private getForeignKeys;
14
+ /**
15
+ * Calcul du poids initial (Physique de la donnée)
16
+ * On utilise le logarithme de la taille pour ne pas pénaliser trop lourdement
17
+ * les grosses tables, mais garder une notion de "frais de déplacement".
18
+ */
19
+ private calculateInitialWeight;
20
+ }
21
+ //# sourceMappingURL=GraphExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphExtractor.d.ts","sourceRoot":"","sources":["../../src/graph/GraphExtractor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EAGL,QAAQ,EAER,cAAc,EACf,MAAM,mBAAmB,CAAA;AAe1B,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,cAAc,CAAC,CAAgB;gBAE3B,QAAQ,EAAE,QAAQ,EAAE,cAAc,CAAC,EAAE,cAAc;IAK/D;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC;YAmDjB,SAAS;YAgCT,UAAU;YA0BV,WAAW;YAUX,cAAc;IAwB5B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;CAO/B"}
@@ -0,0 +1,145 @@
1
+ import fs from 'fs';
2
+ export class GraphExtractor {
3
+ provider;
4
+ actionRegistry;
5
+ constructor(provider, actionRegistry) {
6
+ this.provider = provider;
7
+ this.actionRegistry = actionRegistry;
8
+ }
9
+ /**
10
+ * Extrait le graphe complet : Tables + Actions + Relations
11
+ */
12
+ async extract() {
13
+ console.log('📊 LinkLab : Extraction du graphe sémantique...');
14
+ // 1. Extraction des tables et leurs métadonnées
15
+ const tables = await this.getTables();
16
+ console.log(` Found ${tables.length} tables`);
17
+ // 2. Extraction des clés étrangères (Relations natives)
18
+ const foreignKeys = await this.getForeignKeys();
19
+ console.log(` Found ${foreignKeys.length} foreign keys`);
20
+ // 3. Construction des Nœuds (Tables)
21
+ const nodes = tables.map(t => ({
22
+ id: t.name,
23
+ type: 'table',
24
+ columns: t.columns,
25
+ rowCount: t.rowCount,
26
+ description: t.description || ''
27
+ }));
28
+ // 4. Injection des Nœuds (Actions) - Si présentes dans le registre
29
+ if (this.actionRegistry) {
30
+ const actions = this.actionRegistry.getAll();
31
+ actions.forEach(action => {
32
+ nodes.push({
33
+ id: action.id,
34
+ type: 'action',
35
+ description: action.description || 'Action système',
36
+ params: action.requiredParams
37
+ });
38
+ });
39
+ }
40
+ // 5. Construction des Edges (Liaisons)
41
+ const edges = foreignKeys.map(fk => ({
42
+ name: `rel_${fk.fromTable}_${fk.toTable}`,
43
+ from: fk.fromTable,
44
+ to: fk.toTable,
45
+ via: fk.column,
46
+ type: 'foreign_key',
47
+ weight: this.calculateInitialWeight(fk, tables)
48
+ }));
49
+ const graph = { nodes, edges };
50
+ console.log('✅ Graphe LinkLab extrait avec succès');
51
+ fs.writeFileSync('./graph.json', JSON.stringify(graph, null, 2));
52
+ return graph;
53
+ }
54
+ async getTables() {
55
+ // On récupère aussi la description de la table (COMMENT ON TABLE)
56
+ const query = `
57
+ SELECT
58
+ t.table_name as name,
59
+ obj_description(pgc.oid, 'pg_class') as description
60
+ FROM information_schema.tables t
61
+ JOIN pg_class pgc ON t.table_name = pgc.relname
62
+ JOIN pg_namespace pgn ON pgc.relnamespace = pgn.oid
63
+ WHERE t.table_schema = 'public'
64
+ AND t.table_type = 'BASE TABLE'
65
+ AND pgn.nspname = 'public'
66
+ `;
67
+ const result = await this.provider.query(query);
68
+ const tables = [];
69
+ for (const table of result) {
70
+ const columns = await this.getColumns(table.name);
71
+ const rowCount = await this.getRowCount(table.name);
72
+ tables.push({
73
+ name: table.name,
74
+ columns,
75
+ rowCount,
76
+ description: table.description
77
+ });
78
+ }
79
+ return tables;
80
+ }
81
+ async getColumns(tableName) {
82
+ // Récupère les colonnes ET leurs descriptions (COMMENT ON COLUMN)
83
+ const query = `
84
+ SELECT
85
+ cols.column_name,
86
+ cols.data_type,
87
+ (SELECT pg_catalog.col_description(c.oid, cols.ordinal_position::int)
88
+ FROM pg_catalog.pg_class c
89
+ WHERE c.relname = cols.table_name) as description
90
+ FROM information_schema.columns cols
91
+ WHERE table_name = $1
92
+ `;
93
+ const result = await this.provider.query(query, [tableName]);
94
+ return result.map(c => ({
95
+ name: c.column_name,
96
+ type: c.data_type,
97
+ description: c.description || ''
98
+ }));
99
+ }
100
+ async getRowCount(tableName) {
101
+ try {
102
+ const query = `SELECT reltuples::bigint as count FROM pg_class WHERE relname = $1`;
103
+ const result = await this.provider.query(query, [tableName]);
104
+ return parseInt(result[0]?.count || '0', 10);
105
+ }
106
+ catch {
107
+ return 0;
108
+ }
109
+ }
110
+ async getForeignKeys() {
111
+ const query = `
112
+ SELECT
113
+ tc.table_name as from_table,
114
+ kcu.column_name as column,
115
+ ccu.table_name as to_table,
116
+ -- Vérifie si la colonne est unique ou PK pour la cardinalité
117
+ (SELECT COUNT(*)
118
+ FROM information_schema.table_constraints i_tc
119
+ JOIN information_schema.key_column_usage i_kcu
120
+ ON i_tc.constraint_name = i_kcu.constraint_name
121
+ WHERE i_tc.table_name = tc.table_name
122
+ AND i_kcu.column_name = kcu.column_name
123
+ AND (i_tc.constraint_type = 'PRIMARY KEY' OR i_tc.constraint_type = 'UNIQUE')
124
+ ) > 0 as is_unique
125
+ FROM information_schema.table_constraints tc
126
+ JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name
127
+ JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name
128
+ WHERE tc.constraint_type = 'FOREIGN KEY'
129
+ `;
130
+ return await this.provider.query(query);
131
+ }
132
+ /**
133
+ * Calcul du poids initial (Physique de la donnée)
134
+ * On utilise le logarithme de la taille pour ne pas pénaliser trop lourdement
135
+ * les grosses tables, mais garder une notion de "frais de déplacement".
136
+ */
137
+ calculateInitialWeight(fk, tables) {
138
+ const targetTable = tables.find(t => t.name === fk.toTable);
139
+ if (!targetTable || targetTable.rowCount <= 0)
140
+ return 1;
141
+ // Formule : 1 + log10(n) -> 100 lignes = poids 3, 1M lignes = poids 7.
142
+ return 1 + Math.log10(targetTable.rowCount);
143
+ }
144
+ }
145
+ //# sourceMappingURL=GraphExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphExtractor.js","sourceRoot":"","sources":["../../src/graph/GraphExtractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * GraphOptimizer — Analyse et rapport sur la qualité du graphe
3
+ *
4
+ * PRINCIPE : signaler, jamais détruire silencieusement.
5
+ *
6
+ * Chaque étape produit un rapport (warnings, suggestions).
7
+ * Le dev décide ensuite de ce qu'il fait.
8
+ *
9
+ * Seules deux opérations sont automatiques et non destructives :
10
+ * - Suppression des nœuds orphelins (aucune arête — objectivement inutiles)
11
+ * - Suppression des nœuds dead-end stricts (aucune arête entrante ET sortante)
12
+ *
13
+ * Les cycles sont DÉTECTÉS et CLASSIFIÉS, jamais supprimés :
14
+ * - SELF_LOOP : arête A → A (ex: Station-chatelet → Station-chatelet TRANSFER)
15
+ * - BIDIRECTIONAL : A → B et B → A (ex: CREATED + CREDITED — intentionnel)
16
+ * - STRUCTURAL_CYCLE : A → B → C → A (même type de relation — potentiellement problématique)
17
+ */
18
+ import type { Graph } from '../types/index.js';
19
+ export type CycleType = 'SELF_LOOP' | 'BIDIRECTIONAL' | 'STRUCTURAL_CYCLE';
20
+ export type WarningSeverity = 'INFO' | 'WARNING';
21
+ export interface CycleWarning {
22
+ type: CycleType;
23
+ severity: WarningSeverity;
24
+ edges: string[];
25
+ nodes: string[];
26
+ note: string;
27
+ }
28
+ export interface DuplicatePathWarning {
29
+ from: string;
30
+ to: string;
31
+ paths: string[][];
32
+ note: string;
33
+ }
34
+ export interface GraphOptimizationReport {
35
+ graph: Graph;
36
+ summary: {
37
+ nodes: {
38
+ before: number;
39
+ after: number;
40
+ removed: number;
41
+ };
42
+ edges: {
43
+ before: number;
44
+ after: number;
45
+ removed: number;
46
+ };
47
+ };
48
+ cycles: CycleWarning[];
49
+ duplicatePaths: DuplicatePathWarning[];
50
+ removedOrphans: string[];
51
+ removedDeadEnds: string[];
52
+ isClean: boolean;
53
+ }
54
+ export interface GraphOptimizerConfig {
55
+ /**
56
+ * Types de relations bidirectionnelles considérés comme intentionnels (INFO, pas WARNING).
57
+ * Ex: ['DIRECT', 'TRANSFER', 'physical_reverse', 'INFLUENCE']
58
+ * Par défaut : ['physical_reverse'] — les inverses FK sont toujours intentionnels.
59
+ */
60
+ intentionalBidirectional?: string[];
61
+ /**
62
+ * Types de self-loops considérés comme intentionnels (INFO, pas WARNING).
63
+ * Ex: ['TRANSFER'] — les correspondances métro sont des self-loops normaux.
64
+ * Par défaut : [] — tout self-loop est signalé.
65
+ */
66
+ intentionalSelfLoops?: string[];
67
+ }
68
+ export declare class GraphOptimizer {
69
+ private graph;
70
+ private config;
71
+ constructor(graph: Graph, config?: GraphOptimizerConfig);
72
+ /**
73
+ * Pipeline complet — retourne un rapport, ne modifie pas le graphe original.
74
+ * Seuls orphelins et dead-ends stricts sont supprimés (safe).
75
+ */
76
+ optimize(): GraphOptimizationReport;
77
+ /**
78
+ * Détecte et classifie les cycles — ne supprime rien.
79
+ */
80
+ private detectCycles;
81
+ /**
82
+ * Détecte les cycles structurels A → B → ... → A
83
+ * en ne suivant que les arêtes du même type.
84
+ */
85
+ private detectStructuralCycles;
86
+ /**
87
+ * Supprime les nœuds sans aucune arête (entrante ou sortante).
88
+ * Inoffensif — un nœud isolé ne contribue à aucune traversée.
89
+ */
90
+ private removeOrphans;
91
+ /**
92
+ * Supprime les nœuds sans arête entrante ET sans arête sortante
93
+ * après suppression des orphelins.
94
+ * Différent de removeOrphans — cible les nœuds stricts.
95
+ */
96
+ private removeStrictDeadEnds;
97
+ /**
98
+ * Détecte les paires de nœuds avec plusieurs chemins possibles.
99
+ * Informatif — les chemins multiples sont souvent intentionnels (fallbacks).
100
+ */
101
+ private detectDuplicatePaths;
102
+ private printReport;
103
+ }
104
+ //# sourceMappingURL=GraphOptimizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphOptimizer.d.ts","sourceRoot":"","sources":["../../src/graph/GraphOptimizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAwB,MAAM,mBAAmB,CAAA;AAKpE,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,eAAe,GAAG,kBAAkB,CAAA;AAC1E,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,CAAA;AAEhD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAA;IACf,QAAQ,EAAE,eAAe,CAAA;IACzB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,EAAE,EAAE,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,KAAK,CAAA;IACZ,OAAO,EAAE;QACP,KAAK,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;QACzD,KAAK,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;KAC1D,CAAA;IACD,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,cAAc,EAAE,oBAAoB,EAAE,CAAA;IACtC,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;CACjB;AAID,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAA;IAEnC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAA;CAChC;AAOD,qBAAa,cAAc;IAIb,OAAO,CAAC,KAAK;IAFzB,OAAO,CAAC,MAAM,CAAgC;gBAE1B,KAAK,EAAE,KAAK,EAAE,MAAM,GAAE,oBAAyB;IAOnE;;;OAGG;IACH,QAAQ,IAAI,uBAAuB;IA4DnC;;OAEG;IACH,OAAO,CAAC,YAAY;IA8DpB;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAmE9B;;;OAGG;IACH,OAAO,CAAC,aAAa;IAoBrB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAsB5B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA6B5B,OAAO,CAAC,WAAW;CA+BpB"}