@linklabjs/core 0.1.0 → 0.1.1

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,211 @@
1
+ /**
2
+ * CompiledGraphEngine - Production engine using precompiled graph
3
+ *
4
+ * - O(1) route lookup
5
+ * - Automatic fallback
6
+ * - Live metrics
7
+ * - Hot reload support
8
+ */
9
+ export class CompiledGraphEngine {
10
+ compiled;
11
+ provider;
12
+ liveMetrics;
13
+ routeCache;
14
+ constructor(compiled, provider) {
15
+ this.compiled = compiled;
16
+ this.provider = provider;
17
+ this.liveMetrics = new Map();
18
+ this.routeCache = this.buildRouteCache(compiled);
19
+ console.log('🚀 Compiled Graph Engine initialized');
20
+ console.log(` Routes loaded: ${compiled.routes.length}`);
21
+ console.log(` Nodes: ${compiled.nodes.length}`);
22
+ }
23
+ /**
24
+ * Build fast lookup cache
25
+ */
26
+ buildRouteCache(compiled) {
27
+ const cache = new Map();
28
+ for (const route of compiled.routes) {
29
+ const key = `${route.from}→${route.to}`;
30
+ cache.set(key, route);
31
+ }
32
+ return cache;
33
+ }
34
+ /**
35
+ * Execute query from -> to
36
+ */
37
+ async query(from, to, data = {}) {
38
+ const key = `${from}→${to}`;
39
+ // O(1) lookup!
40
+ const route = this.routeCache.get(key);
41
+ if (!route) {
42
+ throw new Error(`No compiled route from ${from} to ${to}`);
43
+ }
44
+ // Try primary path
45
+ try {
46
+ const start = performance.now();
47
+ const result = await this.executePath(route.primary.path, data);
48
+ const duration = performance.now() - start;
49
+ // Update metrics
50
+ this.updateMetrics(route.primary.path, duration, true);
51
+ return result;
52
+ }
53
+ catch (err) {
54
+ console.warn(`⚠️ Primary path failed: ${err.message}`);
55
+ // Try fallbacks
56
+ return await this.fallback(route, data);
57
+ }
58
+ }
59
+ /**
60
+ * Execute path with JOINs
61
+ */
62
+ async executePath(path, data) {
63
+ // Build SQL with JOINs
64
+ let sql = `SELECT * FROM ${path[0]}`;
65
+ const params = [];
66
+ // Add JOINs
67
+ for (let i = 1; i < path.length; i++) {
68
+ const from = path[i - 1];
69
+ const to = path[i];
70
+ // Find edge in compiled graph
71
+ const edge = this.findEdge(from, to);
72
+ if (edge) {
73
+ sql += ` JOIN ${to} ON ${from}.${edge.via} = ${to}.id`;
74
+ }
75
+ }
76
+ // Add WHERE if ID provided
77
+ if (data.id) {
78
+ sql += ` WHERE ${path[0]}.id = $${params.length + 1}`;
79
+ params.push(data.id);
80
+ }
81
+ // Execute
82
+ return await this.provider.query(sql, params);
83
+ }
84
+ /**
85
+ * Find edge between nodes
86
+ */
87
+ findEdge(from, to) {
88
+ // Simplified - would look in compiled graph edges
89
+ return { via: 'id' };
90
+ }
91
+ /**
92
+ * Fallback to alternative paths
93
+ */
94
+ async fallback(route, data) {
95
+ for (const [index, fallback] of route.fallbacks.entries()) {
96
+ try {
97
+ console.log(` Trying fallback ${index + 1}/${route.fallbacks.length}...`);
98
+ const start = performance.now();
99
+ const result = await this.executePath(fallback.path, data);
100
+ const duration = performance.now() - start;
101
+ // Success!
102
+ console.log(` ✅ Fallback worked: ${fallback.path.join('→')}`);
103
+ this.updateMetrics(fallback.path, duration, true);
104
+ // Maybe promote this fallback?
105
+ this.considerPromotion(route, index);
106
+ return result;
107
+ }
108
+ catch (err) {
109
+ console.warn(` ✗ Fallback ${index + 1} failed: ${err.message}`);
110
+ this.updateMetrics(fallback.path, 0, false);
111
+ continue;
112
+ }
113
+ }
114
+ throw new Error('All paths failed');
115
+ }
116
+ /**
117
+ * Update live metrics
118
+ */
119
+ updateMetrics(path, duration, success) {
120
+ const key = path.join('→');
121
+ if (!this.liveMetrics.has(key)) {
122
+ this.liveMetrics.set(key, {
123
+ path,
124
+ executions: 0,
125
+ successes: 0,
126
+ failures: 0,
127
+ totalTime: 0,
128
+ avgTime: 0
129
+ });
130
+ }
131
+ const metric = this.liveMetrics.get(key);
132
+ metric.executions++;
133
+ if (success) {
134
+ metric.successes++;
135
+ metric.totalTime += duration;
136
+ metric.avgTime = metric.totalTime / metric.successes;
137
+ }
138
+ else {
139
+ metric.failures++;
140
+ }
141
+ }
142
+ /**
143
+ * Consider promoting a fallback to primary
144
+ */
145
+ considerPromotion(route, fallbackIndex) {
146
+ const fallback = route.fallbacks[fallbackIndex];
147
+ const fallbackKey = fallback.path.join('→');
148
+ const primaryKey = route.primary.path.join('→');
149
+ const fallbackMetric = this.liveMetrics.get(fallbackKey);
150
+ const primaryMetric = this.liveMetrics.get(primaryKey);
151
+ if (!fallbackMetric || !primaryMetric)
152
+ return;
153
+ // Promote if fallback is faster AND more reliable
154
+ const fallbackBetter = fallbackMetric.avgTime < primaryMetric.avgTime && fallbackMetric.successes > 5; // Min sample size
155
+ if (fallbackBetter) {
156
+ console.log(`🔄 Promoting fallback to primary: ${fallbackKey}`);
157
+ // Swap
158
+ const temp = route.primary;
159
+ route.primary = fallback;
160
+ route.fallbacks[fallbackIndex] = temp;
161
+ // Update cache
162
+ const key = `${route.from}→${route.to}`;
163
+ this.routeCache.set(key, route);
164
+ }
165
+ }
166
+ /**
167
+ * Get live statistics
168
+ */
169
+ getStats() {
170
+ const metrics = Array.from(this.liveMetrics.values());
171
+ if (metrics.length === 0) {
172
+ return {
173
+ totalExecutions: 0,
174
+ totalSuccesses: 0,
175
+ successRate: '0%',
176
+ avgTime: '0ms',
177
+ uniquePaths: 0
178
+ };
179
+ }
180
+ const totalExecutions = metrics.reduce((sum, m) => sum + m.executions, 0);
181
+ const totalSuccesses = metrics.reduce((sum, m) => sum + m.successes, 0);
182
+ const avgTime = metrics.reduce((sum, m) => sum + m.avgTime * m.successes, 0) / totalSuccesses;
183
+ const fastest = metrics.reduce((min, m) => (m.avgTime < min.avgTime ? m : min));
184
+ const slowest = metrics.reduce((max, m) => (m.avgTime > max.avgTime ? m : max));
185
+ return {
186
+ totalExecutions,
187
+ totalSuccesses,
188
+ successRate: ((totalSuccesses / totalExecutions) * 100).toFixed(1) + '%',
189
+ avgTime: avgTime.toFixed(2) + 'ms',
190
+ uniquePaths: metrics.length,
191
+ fastest,
192
+ slowest
193
+ };
194
+ }
195
+ /**
196
+ * Export metrics for recompilation
197
+ */
198
+ exportMetrics() {
199
+ return new Map(this.liveMetrics);
200
+ }
201
+ /**
202
+ * Hot reload compiled graph
203
+ */
204
+ reload(compiled) {
205
+ console.log('🔄 Hot reloading compiled graph...');
206
+ this.compiled = compiled;
207
+ this.routeCache = this.buildRouteCache(compiled);
208
+ console.log(`✅ Reloaded: ${compiled.routes.length} routes`);
209
+ }
210
+ }
211
+ //# sourceMappingURL=CompiledGraphEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CompiledGraphEngine.js","sourceRoot":"","sources":["../../src/runtime/CompiledGraphEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * DataLoader — Fetch les données pour un Trail résolu
3
+ *
4
+ * Fait le pont entre :
5
+ * Trail (sémantique — où on est, d'où on vient)
6
+ * QueryEngine (technique — comment fetcher les données)
7
+ * Provider (physique — SQL ou JSON en mémoire)
8
+ *
9
+ * Principe :
10
+ * Pour chaque frame RESOLVED dans le Trail, DataLoader
11
+ * construit la requête optimale depuis le graphe compilé
12
+ * et remplit frame.data avec les résultats.
13
+ *
14
+ * Deux modes de fetch :
15
+ * SQL — via Provider (PostgreSQL, MySQL...)
16
+ * JSON — via dataset en mémoire (mock, tests, Netflix JSON)
17
+ *
18
+ * Usage :
19
+ * ```typescript
20
+ * const loader = new DataLoader(compiledGraph, { dataset })
21
+ * await loader.load(trail)
22
+ * // trail.current.data contient maintenant les données
23
+ * ```
24
+ */
25
+ import type { CompiledGraph, Frame } from '../types/index.js';
26
+ import type { Trail } from '../navigation/Trail.js';
27
+ export interface DataLoaderOptions {
28
+ /**
29
+ * Dataset JSON en mémoire — pour les providers mock ou Netflix JSON.
30
+ * Clé = nom de l'entité, valeur = tableau de rows.
31
+ */
32
+ dataset?: Record<string, any[]>;
33
+ /**
34
+ * Provider SQL — pour PostgreSQL, MySQL, etc.
35
+ * Si fourni, prend la priorité sur dataset.
36
+ */
37
+ provider?: {
38
+ query<T = any>(sql: string, params?: any[]): Promise<T[]>;
39
+ };
40
+ /**
41
+ * Transforme les filtres d'une frame en paramètres SQL.
42
+ * Par défaut : { field: 'id', value: 1 } → WHERE entity.id = 1
43
+ */
44
+ buildFilters?: (frame: Frame) => Record<string, any>;
45
+ }
46
+ export declare class DataLoader {
47
+ private queryEngine;
48
+ private options;
49
+ constructor(compiledGraph: CompiledGraph, options?: DataLoaderOptions);
50
+ /**
51
+ * Charge les données pour la frame courante du Trail.
52
+ *
53
+ * Stratégie :
54
+ * 1. Si la frame courante est UNRESOLVED → rien à fetcher
55
+ * 2. Si depth === 1 → fetch direct de l'entité (avec id si présent)
56
+ * 3. Si depth > 1 → traverse depuis le dernier ancêtre résolu
57
+ *
58
+ * Mutate trail.current.data avec les résultats.
59
+ */
60
+ load(trail: Trail): Promise<void>;
61
+ /**
62
+ * Charge les données pour toutes les frames RESOLVED du Trail.
63
+ * Utile pour les réponses enrichies (chaque frame a ses données).
64
+ */
65
+ loadAll(trail: Trail): Promise<void>;
66
+ /**
67
+ * Trouve le premier ancêtre résolu avec un id dans le Trail.
68
+ * C'est le point de départ de la traversée.
69
+ */
70
+ private findAnchor;
71
+ /**
72
+ * Construit les filtres depuis le Trail.
73
+ * Combine les filtres de resolvedBy + l'id de l'ancêtre.
74
+ */
75
+ private buildFilters;
76
+ /**
77
+ * Résout la clé primaire d'une entité depuis le graphe compilé.
78
+ * Fallback : {entity}_id (convention dvdrental, PostgreSQL standard).
79
+ */
80
+ private pkOf;
81
+ /**
82
+ * Fetch direct — une seule entité, sans traversée.
83
+ */
84
+ private fetchDirect;
85
+ /**
86
+ * Fetch via route compilée — traverse from → to.
87
+ */
88
+ private fetchViaRoute;
89
+ }
90
+ //# sourceMappingURL=DataLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataLoader.d.ts","sourceRoot":"","sources":["../../src/runtime/DataLoader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAO,mBAAmB,CAAA;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAuB,wBAAwB,CAAA;AAKpE,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IAE/B;;;OAGG;IACH,QAAQ,CAAC,EAAE;QACT,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAA;KAC1D,CAAA;IAED;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACrD;AAID,qBAAa,UAAU;IACrB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,OAAO,CAAuB;gBAE1B,aAAa,EAAE,aAAa,EAAE,OAAO,GAAE,iBAAsB;IAKzE;;;;;;;;;OASG;IACG,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBvC;;;OAGG;IACG,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1C;;;OAGG;IACH,OAAO,CAAC,UAAU;IAWlB;;;OAGG;IACH,OAAO,CAAC,YAAY;IA0BpB;;;OAGG;IACH,OAAO,CAAC,IAAI;IAMZ;;OAEG;YACW,WAAW;IAoCzB;;OAEG;YACW,aAAa;CA4B5B"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * DataLoader — Fetch les données pour un Trail résolu
3
+ *
4
+ * Fait le pont entre :
5
+ * Trail (sémantique — où on est, d'où on vient)
6
+ * QueryEngine (technique — comment fetcher les données)
7
+ * Provider (physique — SQL ou JSON en mémoire)
8
+ *
9
+ * Principe :
10
+ * Pour chaque frame RESOLVED dans le Trail, DataLoader
11
+ * construit la requête optimale depuis le graphe compilé
12
+ * et remplit frame.data avec les résultats.
13
+ *
14
+ * Deux modes de fetch :
15
+ * SQL — via Provider (PostgreSQL, MySQL...)
16
+ * JSON — via dataset en mémoire (mock, tests, Netflix JSON)
17
+ *
18
+ * Usage :
19
+ * ```typescript
20
+ * const loader = new DataLoader(compiledGraph, { dataset })
21
+ * await loader.load(trail)
22
+ * // trail.current.data contient maintenant les données
23
+ * ```
24
+ */
25
+ import { QueryEngine } from './QueryEngine.js';
26
+ // ── DataLoader ────────────────────────────────────────────────
27
+ export class DataLoader {
28
+ queryEngine;
29
+ options;
30
+ constructor(compiledGraph, options = {}) {
31
+ this.queryEngine = new QueryEngine(compiledGraph);
32
+ this.options = options;
33
+ }
34
+ /**
35
+ * Charge les données pour la frame courante du Trail.
36
+ *
37
+ * Stratégie :
38
+ * 1. Si la frame courante est UNRESOLVED → rien à fetcher
39
+ * 2. Si depth === 1 → fetch direct de l'entité (avec id si présent)
40
+ * 3. Si depth > 1 → traverse depuis le dernier ancêtre résolu
41
+ *
42
+ * Mutate trail.current.data avec les résultats.
43
+ */
44
+ async load(trail) {
45
+ const current = trail.current;
46
+ if (!current)
47
+ return;
48
+ if (current.state === 'UNRESOLVED')
49
+ return;
50
+ // Trouver l'ancêtre — point d'entrée de la traversée
51
+ const anchor = this.findAnchor(trail);
52
+ let data;
53
+ if (!anchor || anchor.entity === current.entity) {
54
+ const filters = current.id !== undefined ? { id: current.id } : {};
55
+ data = await this.fetchDirect(current.entity, filters);
56
+ }
57
+ else {
58
+ const filters = anchor.id !== undefined ? { id: anchor.id } : {};
59
+ data = await this.fetchViaRoute(anchor.entity, current.entity, filters);
60
+ }
61
+ ;
62
+ current.data = data;
63
+ }
64
+ /**
65
+ * Charge les données pour toutes les frames RESOLVED du Trail.
66
+ * Utile pour les réponses enrichies (chaque frame a ses données).
67
+ */
68
+ async loadAll(trail) {
69
+ for (let i = 0; i < trail.depth; i++) {
70
+ const frame = trail.at(i);
71
+ if (!frame || frame.state !== 'RESOLVED')
72
+ continue;
73
+ const subTrail = trail.slice(i + 1);
74
+ await this.load(subTrail);
75
+ }
76
+ }
77
+ // ── Privé ──────────────────────────────────────────────────
78
+ /**
79
+ * Trouve le premier ancêtre résolu avec un id dans le Trail.
80
+ * C'est le point de départ de la traversée.
81
+ */
82
+ findAnchor(trail) {
83
+ // Remonter le Trail depuis l'avant-dernière frame
84
+ for (let i = trail.depth - 2; i >= 0; i--) {
85
+ const frame = trail.at(i);
86
+ if (frame?.state === 'RESOLVED' && frame.id !== undefined) {
87
+ return frame;
88
+ }
89
+ }
90
+ return undefined;
91
+ }
92
+ /**
93
+ * Construit les filtres depuis le Trail.
94
+ * Combine les filtres de resolvedBy + l'id de l'ancêtre.
95
+ */
96
+ buildFilters(trail) {
97
+ const current = trail.current;
98
+ const filters = {};
99
+ // Filtre sur l'id de la frame courante si présent
100
+ if (current.id !== undefined) {
101
+ filters['id'] = current.id;
102
+ }
103
+ // Filtres portés par resolvedBy (conditions sémantiques)
104
+ if (current.resolvedBy?.filters) {
105
+ for (const f of current.resolvedBy.filters) {
106
+ if (f.operator === 'equals') {
107
+ filters[f.field] = f.value;
108
+ }
109
+ }
110
+ }
111
+ // Override par buildFilters custom si fourni
112
+ if (this.options.buildFilters) {
113
+ return { ...filters, ...this.options.buildFilters(current) };
114
+ }
115
+ return filters;
116
+ }
117
+ /**
118
+ * Résout la clé primaire d'une entité depuis le graphe compilé.
119
+ * Fallback : {entity}_id (convention dvdrental, PostgreSQL standard).
120
+ */
121
+ pkOf(entity) {
122
+ const node = this.queryEngine.compiledGraph.nodes.find((n) => n.id === entity);
123
+ const pk = node?.primaryKey;
124
+ return Array.isArray(pk) ? pk[0] : (pk ?? `${entity}_id`);
125
+ }
126
+ /**
127
+ * Fetch direct — une seule entité, sans traversée.
128
+ */
129
+ async fetchDirect(entity, filters) {
130
+ if (this.options.provider) {
131
+ // SQL via provider — résoudre la PK réelle au lieu de supposer 'id'
132
+ const conditions = Object.entries(filters)
133
+ .map(([k, v], i) => {
134
+ const col = k === 'id' ? this.pkOf(entity) : k;
135
+ return `${entity}.${col} = $${i + 1}`;
136
+ })
137
+ .join(' AND ');
138
+ const sql = conditions
139
+ ? `SELECT * FROM ${entity} WHERE ${conditions}`
140
+ : `SELECT * FROM ${entity}`;
141
+ const params = Object.values(filters);
142
+ return this.options.provider.query(sql, params);
143
+ }
144
+ if (this.options.dataset) {
145
+ // JSON en mémoire — chercher sur la PK réelle ou 'id'
146
+ const pk = this.pkOf(entity);
147
+ const rows = this.options.dataset[entity] ?? [];
148
+ return rows.filter(row => Object.entries(filters).every(([k, v]) => {
149
+ const col = k === 'id' ? pk : k;
150
+ return row[col] === v;
151
+ }));
152
+ }
153
+ return [];
154
+ }
155
+ /**
156
+ * Fetch via route compilée — traverse from → to.
157
+ */
158
+ async fetchViaRoute(from, to, filters) {
159
+ // Vérifier que la route existe
160
+ let route;
161
+ try {
162
+ route = this.queryEngine.getRoute(from, to);
163
+ }
164
+ catch {
165
+ return this.fetchDirect(to, filters);
166
+ }
167
+ if (this.options.provider) {
168
+ const sql = this.queryEngine.generateSQL({ from, to, filters });
169
+ return this.options.provider.query(sql);
170
+ }
171
+ if (this.options.dataset) {
172
+ const result = this.queryEngine.executeInMemory({ from, to, filters }, this.options.dataset);
173
+ return result;
174
+ }
175
+ return [];
176
+ }
177
+ }
178
+ //# sourceMappingURL=DataLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataLoader.js","sourceRoot":"","sources":["../../src/runtime/DataLoader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Engine - Core runtime engine with LRU cache
3
+ *
4
+ * Bus exposés :
5
+ * engine.events — cache.hit, cache.miss
6
+ * engine.errors — (extensible)
7
+ */
8
+ import type { Provider, EngineConfig, CacheStats } from '../types/index.js';
9
+ import { EventBus, ErrorBus } from '../core/EventBus.js';
10
+ import type { CacheHitPayload, CacheMissPayload, GraphErrors } from '../core/GraphEvents.js';
11
+ interface EngineEventMap {
12
+ 'cache.hit': CacheHitPayload;
13
+ 'cache.miss': CacheMissPayload;
14
+ }
15
+ export declare class Engine {
16
+ private provider;
17
+ maxSize: number;
18
+ private cache;
19
+ private hits;
20
+ private misses;
21
+ readonly events: EventBus<EngineEventMap>;
22
+ readonly errors: ErrorBus<GraphErrors>;
23
+ constructor(provider: Provider, config?: EngineConfig);
24
+ get<T = any>(key: string, fetcher: () => Promise<T>): Promise<T>;
25
+ set<T = any>(key: string, value: T): void;
26
+ private evictIfNeeded;
27
+ clearCache(): void;
28
+ getStats(): CacheStats;
29
+ private getCurrentSize;
30
+ private estimateSize;
31
+ private formatSize;
32
+ query<T = any>(sql: string, params?: any[]): Promise<T[]>;
33
+ close(): Promise<void>;
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=Engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../../src/runtime/Engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAW5F,UAAU,cAAc;IACtB,WAAW,EAAG,eAAe,CAAA;IAC7B,YAAY,EAAE,gBAAgB,CAAA;CAC/B;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAU;IACnB,OAAO,EAAI,MAAM,CAAA;IACxB,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,IAAI,CAAY;IACxB,OAAO,CAAC,MAAM,CAAU;IAGxB,SAAgB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAA;IAChD,SAAgB,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;gBAEjC,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAE,YAAiB;IAUnD,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA8BtE,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAiBzC,OAAO,CAAC,aAAa;IAmBrB,UAAU,IAAI,IAAI;IAOlB,QAAQ,IAAI,UAAU;IAmBtB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,UAAU;IAMZ,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,GAAG,EAAO,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAI7D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Engine - Core runtime engine with LRU cache
3
+ *
4
+ * Bus exposés :
5
+ * engine.events — cache.hit, cache.miss
6
+ * engine.errors — (extensible)
7
+ */
8
+ import { EventBus, ErrorBus } from '../core/EventBus.js';
9
+ export class Engine {
10
+ provider;
11
+ maxSize;
12
+ cache;
13
+ hits;
14
+ misses;
15
+ // ── Bus ──────────────────────────────────────────────────────
16
+ events;
17
+ errors;
18
+ constructor(provider, config = {}) {
19
+ this.provider = provider;
20
+ this.maxSize = config.cache?.maxSize ?? 10 * 1024 * 1024;
21
+ this.cache = new Map();
22
+ this.hits = 0;
23
+ this.misses = 0;
24
+ this.events = new EventBus();
25
+ this.errors = new ErrorBus();
26
+ }
27
+ async get(key, fetcher) {
28
+ const cached = this.cache.get(key);
29
+ if (cached) {
30
+ this.hits++;
31
+ cached.accessCount++;
32
+ cached.lastAccess = Date.now();
33
+ // ── Event : cache.hit ──────────────────────────────────
34
+ this.events.emit('cache.hit', {
35
+ key,
36
+ accessCount: cached.accessCount,
37
+ });
38
+ return cached.value;
39
+ }
40
+ this.misses++;
41
+ // ── Event : cache.miss ─────────────────────────────────
42
+ this.events.emit('cache.miss', {
43
+ key,
44
+ requestedAt: Date.now(),
45
+ });
46
+ const value = await fetcher();
47
+ this.set(key, value);
48
+ return value;
49
+ }
50
+ set(key, value) {
51
+ const size = this.estimateSize(value);
52
+ this.evictIfNeeded(size);
53
+ this.cache.set(key, {
54
+ key,
55
+ value,
56
+ size,
57
+ accessCount: 1,
58
+ lastAccess: Date.now(),
59
+ });
60
+ const formatted = this.formatSize(size);
61
+ const maxFormatted = this.formatSize(this.maxSize);
62
+ console.log(`💾 RAM CACHED: ${key} (${formatted}/${maxFormatted})`);
63
+ }
64
+ evictIfNeeded(neededSize) {
65
+ const currentSize = this.getCurrentSize();
66
+ if (currentSize + neededSize <= this.maxSize)
67
+ return;
68
+ const entries = Array.from(this.cache.values()).sort((a, b) => {
69
+ const scoreA = a.accessCount * 1000 + a.lastAccess;
70
+ const scoreB = b.accessCount * 1000 + b.lastAccess;
71
+ return scoreA - scoreB;
72
+ });
73
+ let freedSize = 0;
74
+ for (const entry of entries) {
75
+ if (currentSize - freedSize + neededSize <= this.maxSize)
76
+ break;
77
+ this.cache.delete(entry.key);
78
+ freedSize += entry.size;
79
+ console.log(`🗑️ RAM EVICTED: ${entry.key}`);
80
+ }
81
+ }
82
+ clearCache() {
83
+ this.cache.clear();
84
+ this.hits = 0;
85
+ this.misses = 0;
86
+ console.log('💾 RAM CLEARED');
87
+ }
88
+ getStats() {
89
+ const size = this.getCurrentSize();
90
+ const totalAccesses = this.hits + this.misses;
91
+ const hitRate = totalAccesses > 0
92
+ ? ((this.hits / totalAccesses) * 100).toFixed(1) + '%'
93
+ : '0%';
94
+ return {
95
+ entries: this.cache.size,
96
+ size,
97
+ sizeFormatted: this.formatSize(size),
98
+ maxSize: this.maxSize,
99
+ usage: ((size / this.maxSize) * 100).toFixed(1) + '%',
100
+ hits: this.hits,
101
+ misses: this.misses,
102
+ hitRate,
103
+ };
104
+ }
105
+ getCurrentSize() {
106
+ let total = 0;
107
+ for (const entry of this.cache.values())
108
+ total += entry.size;
109
+ return total;
110
+ }
111
+ estimateSize(obj) {
112
+ return JSON.stringify(obj).length;
113
+ }
114
+ formatSize(bytes) {
115
+ if (bytes < 1024)
116
+ return `${bytes} B`;
117
+ if (bytes < 1024 * 1024)
118
+ return `${(bytes / 1024).toFixed(1)} KB`;
119
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
120
+ }
121
+ async query(sql, params = []) {
122
+ return this.provider.query(sql, params);
123
+ }
124
+ async close() {
125
+ await this.provider.close();
126
+ }
127
+ }
128
+ //# sourceMappingURL=Engine.js.map