@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,29 @@
1
+ /**
2
+ * queries.ts — Requêtes scénario Netflix
3
+ *
4
+ * Démontre la navigation dans un graphe généré automatiquement par le pipeline.
5
+ * Le graphe contient 7 nœuds et 66 arêtes dont 56 vues sémantiques issues de
6
+ * credits.jobId → jobs (actor, director, writer, screenplay...).
7
+ *
8
+ * Usage :
9
+ * tsx cli/run-scenario.ts scenarios/test-netflix --query directors-of-movie
10
+ * tsx cli/run-scenario.ts scenarios/test-netflix --query all
11
+ *
12
+ * Graphe disponible :
13
+ * Nœuds : movies, people, credits, jobs, departments, categories, users
14
+ * Arêtes physiques : credits→movies, credits→people, credits→jobs, jobs→departments
15
+ * Arêtes sémantiques : movies↔people via [actor | director | writer | screenplay ...]
16
+ * Arêtes virtuelles : movies↔categories (array inline)
17
+ */
18
+ import type { PathQuery } from '../../types/index.js';
19
+ export interface NamedQuery {
20
+ name: string;
21
+ description: string;
22
+ query: PathQuery;
23
+ }
24
+ export declare const netflixQueries: NamedQuery[];
25
+ /**
26
+ * Requête par défaut (utilisée sans --query)
27
+ */
28
+ export declare const defaultQuery: NamedQuery;
29
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../src/scenarios/test-netflix/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAErD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,SAAS,CAAA;CACjB;AAED,eAAO,MAAM,cAAc,EAAE,UAAU,EA+HtC,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,YAA6D,CAAA"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * queries.ts — Requêtes scénario Netflix
3
+ *
4
+ * Démontre la navigation dans un graphe généré automatiquement par le pipeline.
5
+ * Le graphe contient 7 nœuds et 66 arêtes dont 56 vues sémantiques issues de
6
+ * credits.jobId → jobs (actor, director, writer, screenplay...).
7
+ *
8
+ * Usage :
9
+ * tsx cli/run-scenario.ts scenarios/test-netflix --query directors-of-movie
10
+ * tsx cli/run-scenario.ts scenarios/test-netflix --query all
11
+ *
12
+ * Graphe disponible :
13
+ * Nœuds : movies, people, credits, jobs, departments, categories, users
14
+ * Arêtes physiques : credits→movies, credits→people, credits→jobs, jobs→departments
15
+ * Arêtes sémantiques : movies↔people via [actor | director | writer | screenplay ...]
16
+ * Arêtes virtuelles : movies↔categories (array inline)
17
+ */
18
+ export const netflixQueries = [
19
+ // ============================================================
20
+ // NAVIGATION SÉMANTIQUE — Vues générées depuis credits.jobId
21
+ // ============================================================
22
+ {
23
+ name: 'directors-of-movie',
24
+ description: 'movies → people via vue sémantique "director"',
25
+ query: {
26
+ from: 'movies',
27
+ to: 'people',
28
+ via: ['director'],
29
+ maxPaths: 3
30
+ }
31
+ },
32
+ {
33
+ name: 'actors-of-movie',
34
+ description: 'movies → people via vue sémantique "actor"',
35
+ query: {
36
+ from: 'movies',
37
+ to: 'people',
38
+ via: ['actor'],
39
+ maxPaths: 3
40
+ }
41
+ },
42
+ {
43
+ name: 'movies-of-director',
44
+ description: 'people → movies via vue sémantique "director_in"',
45
+ query: {
46
+ from: 'people',
47
+ to: 'movies',
48
+ via: ['director_in'],
49
+ maxPaths: 3
50
+ }
51
+ },
52
+ {
53
+ name: 'movies-of-actor',
54
+ description: 'people → movies via vue sémantique "actor_in"',
55
+ query: {
56
+ from: 'people',
57
+ to: 'movies',
58
+ via: ['actor_in'],
59
+ maxPaths: 3
60
+ }
61
+ },
62
+ // ============================================================
63
+ // NAVIGATION PHYSIQUE — Relations FK déclarées
64
+ // ============================================================
65
+ {
66
+ name: 'credits-to-jobs',
67
+ description: 'credits → jobs (FK physique credits.jobId → jobs.id)',
68
+ query: {
69
+ from: 'credits',
70
+ to: 'jobs',
71
+ maxPaths: 2
72
+ }
73
+ },
74
+ {
75
+ name: 'jobs-to-departments',
76
+ description: 'jobs → departments (FK physique jobs.departmentId → departments.id)',
77
+ query: {
78
+ from: 'jobs',
79
+ to: 'departments',
80
+ maxPaths: 2
81
+ }
82
+ },
83
+ // ============================================================
84
+ // NAVIGATION VIRTUELLE — Array inline movies.categories
85
+ // ============================================================
86
+ {
87
+ name: 'movies-to-categories',
88
+ description: 'movies → categories (relation virtuelle depuis array inline)',
89
+ query: {
90
+ from: 'movies',
91
+ to: 'categories',
92
+ maxPaths: 2
93
+ }
94
+ },
95
+ // ============================================================
96
+ // CHEMINS LONGS — Traversées multi-sauts
97
+ // ============================================================
98
+ {
99
+ name: 'movies-to-departments',
100
+ description: 'movies → departments (2 sauts : movies→credits→jobs→departments)',
101
+ query: {
102
+ from: 'movies',
103
+ to: 'departments',
104
+ maxPaths: 2
105
+ }
106
+ },
107
+ {
108
+ name: 'people-to-departments',
109
+ description: 'people → departments (via credits → jobs → departments)',
110
+ query: {
111
+ from: 'people',
112
+ to: 'departments',
113
+ maxPaths: 3
114
+ }
115
+ },
116
+ // ============================================================
117
+ // CHEMIN MINIMAL — minHops
118
+ // ============================================================
119
+ {
120
+ name: 'people-to-movies-minhops',
121
+ description: 'people → movies chemin le plus court (minHops)',
122
+ query: {
123
+ from: 'people',
124
+ to: 'movies',
125
+ minHops: 1,
126
+ maxPaths: 5
127
+ }
128
+ }
129
+ ];
130
+ /**
131
+ * Requête par défaut (utilisée sans --query)
132
+ */
133
+ export const defaultQuery = netflixQueries.find(q => q.name === 'directors-of-movie');
134
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../../src/scenarios/test-netflix/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAUH,MAAM,CAAC,MAAM,cAAc,GAAiB;IAE1C,+DAA+D;IAC/D,6DAA6D;IAC7D,+DAA+D;IAE/D;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,+CAA+C;QAC5D,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,QAAQ;YACZ,GAAG,EAAE,CAAC,UAAU,CAAC;YACjB,QAAQ,EAAE,CAAC;SACZ;KACF;IAED;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,4CAA4C;QACzD,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,QAAQ;YACZ,GAAG,EAAE,CAAC,OAAO,CAAC;YACd,QAAQ,EAAE,CAAC;SACZ;KACF;IAED;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,kDAAkD;QAC/D,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,QAAQ;YACZ,GAAG,EAAE,CAAC,aAAa,CAAC;YACpB,QAAQ,EAAE,CAAC;SACZ;KACF;IAED;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,+CAA+C;QAC5D,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,QAAQ;YACZ,GAAG,EAAE,CAAC,UAAU,CAAC;YACjB,QAAQ,EAAE,CAAC;SACZ;KACF;IAED,+DAA+D;IAC/D,+CAA+C;IAC/C,+DAA+D;IAE/D;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,sDAAsD;QACnE,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,MAAM;YACV,QAAQ,EAAE,CAAC;SACZ;KACF;IAED;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,qEAAqE;QAClF,KAAK,EAAE;YACL,IAAI,EAAE,MAAM;YACZ,EAAE,EAAE,aAAa;YACjB,QAAQ,EAAE,CAAC;SACZ;KACF;IAED,+DAA+D;IAC/D,wDAAwD;IACxD,+DAA+D;IAE/D;QACE,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,8DAA8D;QAC3E,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,YAAY;YAChB,QAAQ,EAAE,CAAC;SACZ;KACF;IAED,+DAA+D;IAC/D,yCAAyC;IACzC,+DAA+D;IAE/D;QACE,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,kEAAkE;QAC/E,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,aAAa;YACjB,QAAQ,EAAE,CAAC;SACZ;KACF;IAED;QACE,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,yDAAyD;QACtE,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,aAAa;YACjB,QAAQ,EAAE,CAAC;SACZ;KACF;IAED,+DAA+D;IAC/D,2BAA2B;IAC3B,+DAA+D;IAE/D;QACE,IAAI,EAAE,0BAA0B;QAChC,WAAW,EAAE,gDAAgD;QAC7D,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,QAAQ;YACZ,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,CAAC;SACZ;KACF;CAEF,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,oBAAoB,CAAE,CAAA"}
@@ -0,0 +1,14 @@
1
+ [
2
+ {
3
+ "entity": "Directors",
4
+ "id": 2,
5
+ "state": "RESOLVED",
6
+ "purpose": "explore"
7
+ },
8
+ {
9
+ "entity": "Movies",
10
+ "id": null,
11
+ "state": "UNRESOLVED",
12
+ "purpose": "list"
13
+ }
14
+ ]
@@ -0,0 +1,9 @@
1
+ import type { AnalyzedSchema, Dictionary } from '../types/index.js';
2
+ export declare class GraphBuilder {
3
+ /**
4
+ * Construit le dictionnaire final à partir du schéma analysé
5
+ */
6
+ build(analyzed: AnalyzedSchema, dataPath: string): Dictionary;
7
+ private injectVirtualViews;
8
+ }
9
+ //# sourceMappingURL=GraphBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphBuilder.d.ts","sourceRoot":"","sources":["../../src/schema/GraphBuilder.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAY,MAAM,mBAAmB,CAAA;AAE7E,qBAAa,YAAY;IACvB;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU;IA6C7D,OAAO,CAAC,kBAAkB;CAoD3B"}
@@ -0,0 +1,90 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ export class GraphBuilder {
4
+ /**
5
+ * Construit le dictionnaire final à partir du schéma analysé
6
+ */
7
+ build(analyzed, dataPath) {
8
+ const dictionary = {
9
+ tables: [],
10
+ relations: []
11
+ };
12
+ // 1. Déclarer les tables
13
+ for (const ent of analyzed.entities) {
14
+ dictionary.tables.push({
15
+ name: ent.name,
16
+ columns: ent.properties.map(p => p.name),
17
+ rowCount: ent.rowCount
18
+ });
19
+ // 2. Transformer les PK/FK physiques en relations de base
20
+ for (const prop of ent.properties) {
21
+ if (prop.isFK && prop.references) {
22
+ dictionary.relations.push({
23
+ from: ent.name,
24
+ to: prop.references.table,
25
+ via: prop.name,
26
+ type: 'physical',
27
+ weight: analyzed.weights[`${ent.name}.${prop.name}`] || 1,
28
+ label: `FK_${prop.name}`
29
+ });
30
+ // Relation inverse (One-to-Many implicite)
31
+ dictionary.relations.push({
32
+ from: prop.references.table,
33
+ to: ent.name,
34
+ via: prop.name,
35
+ type: 'physical_reverse',
36
+ weight: (analyzed.weights[`${ent.name}.${prop.name}`] || 1) * 1.1, // Légèrement plus lourd de remonter
37
+ label: `LIST_OF_${ent.name.toUpperCase()}`
38
+ });
39
+ }
40
+ }
41
+ }
42
+ // 3. Génération des Vues Sémantiques (L'intelligence métier)
43
+ this.injectVirtualViews(analyzed, dictionary, dataPath);
44
+ return dictionary;
45
+ }
46
+ injectVirtualViews(analyzed, dict, dataPath) {
47
+ // On cherche le conseil de pivot que l'Analyzer a posé
48
+ const pivotAdvices = analyzed.advices.filter(a => a.action === 'SUGGEST_VIRTUAL_VIEWS');
49
+ for (const advice of pivotAdvices) {
50
+ const pivotTable = advice.target; // ex: 'credits'
51
+ // On cherche quelle table sert de "Type" pour segmenter (ex: jobs)
52
+ const entity = analyzed.entities.find(e => e.name === pivotTable);
53
+ const typeFK = entity?.properties.find(p => /type|job|category|role/i.test(p.references?.table || ''));
54
+ if (typeFK && typeFK.references) {
55
+ const typeTableName = typeFK.references.table;
56
+ const typeDataPath = path.join(dataPath, `${typeTableName}.json`);
57
+ if (fs.existsSync(typeDataPath)) {
58
+ const types = JSON.parse(fs.readFileSync(typeDataPath, 'utf-8'));
59
+ types.forEach((typeObj) => {
60
+ const roleName = typeObj.name.toLowerCase();
61
+ // Ignorer les rôles sans nom significatif
62
+ if (!roleName || /^unknow|^unknown|^n\/a/i.test(roleName))
63
+ return;
64
+ // On crée l'arête sémantique : movies -> people (via credits filtré)
65
+ dict.relations.push({
66
+ from: 'movies',
67
+ to: 'people',
68
+ via: pivotTable,
69
+ type: 'semantic_view',
70
+ label: roleName,
71
+ condition: { [typeFK.name]: typeObj.id },
72
+ weight: 0.8 // Très léger car c'est une intention directe de l'utilisateur
73
+ });
74
+ // Et l'inverse : people -> movies (via credits filtré)
75
+ dict.relations.push({
76
+ from: 'people',
77
+ to: 'movies',
78
+ via: pivotTable,
79
+ type: 'semantic_view',
80
+ label: `${roleName}_in`,
81
+ condition: { [typeFK.name]: typeObj.id },
82
+ weight: 0.8
83
+ });
84
+ });
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ //# sourceMappingURL=GraphBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphBuilder.js","sourceRoot":"","sources":["../../src/schema/GraphBuilder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * JsonSchemaExtractor — Extraction de schéma depuis des fichiers JSON
3
+ *
4
+ * Inférence automatique :
5
+ * - Types de colonnes depuis le premier enregistrement
6
+ * - FK par convention de nommage (*Id → table cible) via SynonymResolver
7
+ * - Détection des arrays inline (ex: movies.categories)
8
+ *
9
+ * Synonymes :
10
+ * Délégués à SynonymResolver — config/synonyms.json + <dataPath>/synonyms.json
11
+ */
12
+ import type { TechnicalSchema } from '../types/index.js';
13
+ export declare class JsonSchemaExtractor {
14
+ private dataPath;
15
+ private resolver;
16
+ constructor(dataPath: string, configPath?: string);
17
+ extract(): Promise<TechnicalSchema>;
18
+ private inferProperties;
19
+ private resolveForeignKeys;
20
+ }
21
+ //# sourceMappingURL=JsonSchemaExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonSchemaExtractor.d.ts","sourceRoot":"","sources":["../../src/schema/JsonSchemaExtractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,eAAe,EAA4B,MAAM,mBAAmB,CAAA;AAGlF,qBAAa,mBAAmB;IAK5B,OAAO,CAAC,QAAQ;IAHlB,OAAO,CAAC,QAAQ,CAAiB;gBAGvB,QAAQ,EAAE,MAAM,EACxB,UAAU,GAAE,MAA2C;IAMnD,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC;IA0CzC,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,kBAAkB;CAqB3B"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * JsonSchemaExtractor — Extraction de schéma depuis des fichiers JSON
3
+ *
4
+ * Inférence automatique :
5
+ * - Types de colonnes depuis le premier enregistrement
6
+ * - FK par convention de nommage (*Id → table cible) via SynonymResolver
7
+ * - Détection des arrays inline (ex: movies.categories)
8
+ *
9
+ * Synonymes :
10
+ * Délégués à SynonymResolver — config/synonyms.json + <dataPath>/synonyms.json
11
+ */
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { SynonymResolver } from './SynonymResolver.js';
15
+ export class JsonSchemaExtractor {
16
+ dataPath;
17
+ resolver;
18
+ constructor(dataPath, configPath = path.join(process.cwd(), 'config')) {
19
+ this.dataPath = dataPath;
20
+ // Passe le dataPath comme projectPath — synonyms.json projet y est optionnel
21
+ this.resolver = new SynonymResolver(configPath, dataPath);
22
+ }
23
+ async extract() {
24
+ console.log(`📂 JsonSchemaExtractor — scanning : ${this.dataPath}`);
25
+ const files = fs.readdirSync(this.dataPath)
26
+ .filter(f => f.endsWith('.json') && f !== 'synonyms.json');
27
+ const entities = [];
28
+ // Passe 1 — inférer entités et propriétés
29
+ for (const file of files) {
30
+ const tableName = path.basename(file, '.json');
31
+ const content = JSON.parse(fs.readFileSync(path.join(this.dataPath, file), 'utf-8'));
32
+ if (!Array.isArray(content) || content.length === 0) {
33
+ console.log(` ⏭️ ${file} — vide ou non-liste, ignoré`);
34
+ continue;
35
+ }
36
+ const properties = this.inferProperties(content[0]);
37
+ const arrayCols = properties.filter(p => p.type === 'array').map(p => p.name);
38
+ entities.push({ name: tableName, properties, rowCount: content.length });
39
+ console.log(` ✅ ${tableName} (${content.length} entrées` +
40
+ (arrayCols.length ? `, arrays: ${arrayCols.join(', ')}` : '') + ')');
41
+ }
42
+ // Passe 2 — résoudre les FK via SynonymResolver
43
+ this.resolveForeignKeys(entities);
44
+ return {
45
+ source: {
46
+ type: 'json_files',
47
+ name: path.basename(this.dataPath),
48
+ generatedAt: new Date().toISOString()
49
+ },
50
+ entities
51
+ };
52
+ }
53
+ inferProperties(sample) {
54
+ return Object.entries(sample).map(([key, value]) => ({
55
+ name: key,
56
+ type: Array.isArray(value) ? 'array'
57
+ : value === null ? 'null'
58
+ : typeof value === 'object' ? 'object'
59
+ : typeof value,
60
+ isPK: key === 'id',
61
+ isFK: false,
62
+ isIndexed: true,
63
+ nullable: value === null
64
+ }));
65
+ }
66
+ resolveForeignKeys(entities) {
67
+ const tableNames = entities.map(e => e.name);
68
+ for (const entity of entities) {
69
+ for (const prop of entity.properties) {
70
+ if (prop.isPK)
71
+ continue;
72
+ if (!prop.name.endsWith('Id') && !prop.name.endsWith('_id'))
73
+ continue;
74
+ const target = this.resolver.resolveColumn(prop.name, tableNames);
75
+ if (target) {
76
+ prop.isFK = true;
77
+ prop.references = { table: target, column: 'id' };
78
+ console.log(` 🔗 ${entity.name}.${prop.name} → ${target}.id`);
79
+ }
80
+ else {
81
+ const prefix = this.resolver.extractPrefix(prop.name);
82
+ console.log(` ❓ ${entity.name}.${prop.name} — "${prefix}" introuvable`);
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ //# sourceMappingURL=JsonSchemaExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonSchemaExtractor.js","sourceRoot":"","sources":["../../src/schema/JsonSchemaExtractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * SchemaAnalyzer — Analyse sémantique d'un schéma technique
3
+ *
4
+ * Produit :
5
+ * - Poids par colonne (basés sur volumétrie et indexation)
6
+ * - Advices de performance (FK non indexées)
7
+ * - Détection de pivots sémantiques (tables de liaison)
8
+ * - Détection de FK implicites via SynonymResolver
9
+ * (colonnes *_id sans FK déclarée qui correspondent à une table existante)
10
+ *
11
+ * Compatible PostgreSQL et JSON — même logique quelque soit la source.
12
+ */
13
+ import type { TechnicalSchema, AnalyzedSchema } from '../types/index.js';
14
+ export declare class SchemaAnalyzer {
15
+ private advices;
16
+ private weights;
17
+ private resolver;
18
+ constructor(configPath?: string, projectPath?: string);
19
+ analyze(schema: TechnicalSchema): AnalyzedSchema;
20
+ private analyzeEntity;
21
+ /**
22
+ * Détecte les tables de liaison (credits, film_category...)
23
+ * Pattern : table avec 2+ FK dont une vers une table de "types"
24
+ */
25
+ private detectSemanticPivots;
26
+ /**
27
+ * Détecte les colonnes *_id sans FK déclarée qui correspondent
28
+ * à une table existante via SynonymResolver.
29
+ *
30
+ * Utile pour :
31
+ * - PostgreSQL : FK non déclarées (store.store_id non contrainte)
32
+ * - JSON : colonnes oubliées dans la passe 2 de JsonSchemaExtractor
33
+ */
34
+ private detectImplicitFKs;
35
+ /**
36
+ * Collecte les FK implicites comme relations exploitables par GraphBuilder.
37
+ */
38
+ private collectImplicitRelations;
39
+ saveAnalysis(analyzed: AnalyzedSchema, outputPath: string): void;
40
+ }
41
+ //# sourceMappingURL=SchemaAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaAnalyzer.d.ts","sourceRoot":"","sources":["../../src/schema/SchemaAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,eAAe,EAA8B,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAGpG,qBAAa,cAAc;IAEzB,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,QAAQ,CAAiB;gBAG/B,UAAU,GAAE,MAAkC,EAC9C,WAAW,CAAC,EAAE,MAAM;IAKtB,OAAO,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc;IAqBhD,OAAO,CAAC,aAAa;IA4BrB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAuB5B;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IAwBzB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA6BhC,YAAY,CAAC,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;CAIjE"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * SchemaAnalyzer — Analyse sémantique d'un schéma technique
3
+ *
4
+ * Produit :
5
+ * - Poids par colonne (basés sur volumétrie et indexation)
6
+ * - Advices de performance (FK non indexées)
7
+ * - Détection de pivots sémantiques (tables de liaison)
8
+ * - Détection de FK implicites via SynonymResolver
9
+ * (colonnes *_id sans FK déclarée qui correspondent à une table existante)
10
+ *
11
+ * Compatible PostgreSQL et JSON — même logique quelque soit la source.
12
+ */
13
+ import fs from 'fs';
14
+ import { SynonymResolver } from './SynonymResolver.js';
15
+ export class SchemaAnalyzer {
16
+ advices = [];
17
+ weights = {};
18
+ resolver;
19
+ constructor(configPath = process.cwd() + '/config', projectPath) {
20
+ this.resolver = new SynonymResolver(configPath, projectPath);
21
+ }
22
+ analyze(schema) {
23
+ this.advices = [];
24
+ this.weights = {};
25
+ for (const entity of schema.entities) {
26
+ this.analyzeEntity(entity);
27
+ }
28
+ this.detectSemanticPivots(schema);
29
+ this.detectImplicitFKs(schema);
30
+ return {
31
+ ...schema,
32
+ advices: this.advices,
33
+ weights: this.weights,
34
+ implicitRelations: this.collectImplicitRelations(schema)
35
+ };
36
+ }
37
+ // ─── Analyse par entité ────────────────────────────────────────────────────
38
+ analyzeEntity(entity) {
39
+ for (const prop of entity.properties) {
40
+ const key = `${entity.name}.${prop.name}`;
41
+ let weight = 1;
42
+ // FK non indexée — coût de traversée élevé
43
+ if (prop.isFK && !prop.isIndexed) {
44
+ weight = 10;
45
+ this.advices.push({
46
+ type: 'PERFORMANCE',
47
+ level: 'WARNING',
48
+ target: key,
49
+ message: `FK '${prop.name}' non indexée dans '${entity.name}'.`,
50
+ action: `CREATE INDEX idx_${entity.name}_${prop.name} ON ${entity.name}(${prop.name});`
51
+ });
52
+ }
53
+ // Volumétrie — tables larges coûtent plus cher à traverser
54
+ if (entity.rowCount > 1000) {
55
+ weight += parseFloat(Math.log10(entity.rowCount / 100).toFixed(2));
56
+ }
57
+ this.weights[key] = weight;
58
+ }
59
+ }
60
+ // ─── Pivots sémantiques ────────────────────────────────────────────────────
61
+ /**
62
+ * Détecte les tables de liaison (credits, film_category...)
63
+ * Pattern : table avec 2+ FK dont une vers une table de "types"
64
+ */
65
+ detectSemanticPivots(schema) {
66
+ for (const entity of schema.entities) {
67
+ const fks = entity.properties.filter(p => p.isFK);
68
+ if (fks.length < 2)
69
+ continue;
70
+ const typeFK = fks.find(fk => /type|job|category|dept|role|department/i.test(fk.references?.table ?? ''));
71
+ if (typeFK) {
72
+ this.advices.push({
73
+ type: 'STRUCTURE',
74
+ level: 'INFO',
75
+ target: entity.name,
76
+ message: `Pivot sémantique — segmentation possible par '${typeFK.references.table}'.`,
77
+ action: 'SUGGEST_VIRTUAL_VIEWS'
78
+ });
79
+ }
80
+ }
81
+ }
82
+ // ─── FK implicites ─────────────────────────────────────────────────────────
83
+ /**
84
+ * Détecte les colonnes *_id sans FK déclarée qui correspondent
85
+ * à une table existante via SynonymResolver.
86
+ *
87
+ * Utile pour :
88
+ * - PostgreSQL : FK non déclarées (store.store_id non contrainte)
89
+ * - JSON : colonnes oubliées dans la passe 2 de JsonSchemaExtractor
90
+ */
91
+ detectImplicitFKs(schema) {
92
+ const tableNames = schema.entities.map(e => e.name);
93
+ for (const entity of schema.entities) {
94
+ for (const prop of entity.properties) {
95
+ // Ignorer PK et FK déjà déclarées
96
+ if (prop.isPK || prop.isFK)
97
+ continue;
98
+ if (!prop.name.endsWith('_id') && !prop.name.endsWith('Id'))
99
+ continue;
100
+ const target = this.resolver.resolveColumn(prop.name, tableNames);
101
+ if (!target)
102
+ continue;
103
+ // FK implicite trouvée
104
+ this.advices.push({
105
+ type: 'STRUCTURE',
106
+ level: 'INFO',
107
+ target: `${entity.name}.${prop.name}`,
108
+ message: `FK implicite détectée : '${entity.name}.${prop.name}' → '${target}'.`,
109
+ action: 'ADD_IMPLICIT_FK'
110
+ });
111
+ }
112
+ }
113
+ }
114
+ /**
115
+ * Collecte les FK implicites comme relations exploitables par GraphBuilder.
116
+ */
117
+ collectImplicitRelations(schema) {
118
+ const tableNames = schema.entities.map(e => e.name);
119
+ const result = [];
120
+ for (const entity of schema.entities) {
121
+ for (const prop of entity.properties) {
122
+ if (prop.isPK || prop.isFK)
123
+ continue;
124
+ if (!prop.name.endsWith('_id') && !prop.name.endsWith('Id'))
125
+ continue;
126
+ const target = this.resolver.resolveColumn(prop.name, tableNames);
127
+ if (target) {
128
+ result.push({
129
+ fromTable: entity.name,
130
+ column: prop.name,
131
+ guessedTable: target
132
+ });
133
+ }
134
+ }
135
+ }
136
+ return result;
137
+ }
138
+ // ─── Persistence ───────────────────────────────────────────────────────────
139
+ saveAnalysis(analyzed, outputPath) {
140
+ fs.writeFileSync(outputPath, JSON.stringify(analyzed, null, 2));
141
+ console.log(`💾 Analyse sauvegardée : ${outputPath}`);
142
+ }
143
+ }
144
+ //# sourceMappingURL=SchemaAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaAnalyzer.js","sourceRoot":"","sources":["../../src/schema/SchemaAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAA;AAEnB,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEtD,MAAM,OAAO,cAAc;IAEjB,OAAO,GAAqB,EAAE,CAAA;IAC9B,OAAO,GAA2B,EAAE,CAAA;IACpC,QAAQ,CAAiB;IAEjC,YACE,aAAqB,OAAO,CAAC,GAAG,EAAE,GAAG,SAAS,EAC9C,WAAoB;QAEpB,IAAI,CAAC,QAAQ,GAAG,IAAI,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;IAC9D,CAAC;IAED,OAAO,CAAC,MAAuB;QAC7B,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QACjB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QAEjB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;QAC5B,CAAC;QAED,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAA;QACjC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAA;QAE9B,OAAO;YACL,GAAG,MAAM;YACT,OAAO,EAAY,IAAI,CAAC,OAAO;YAC/B,OAAO,EAAY,IAAI,CAAC,OAAO;YAC/B,iBAAiB,EAAE,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC;SACzD,CAAA;IACH,CAAC;IAED,8EAA8E;IAEtE,aAAa,CAAC,MAAkB;QACtC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAA;YACzC,IAAI,MAAM,GAAG,CAAC,CAAA;YAEd,2CAA2C;YAC3C,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACjC,MAAM,GAAG,EAAE,CAAA;gBACX,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;oBAChB,IAAI,EAAK,aAAa;oBACtB,KAAK,EAAI,SAAS;oBAClB,MAAM,EAAG,GAAG;oBACZ,OAAO,EAAE,OAAO,IAAI,CAAC,IAAI,uBAAuB,MAAM,CAAC,IAAI,IAAI;oBAC/D,MAAM,EAAG,oBAAoB,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,OAAO,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI;iBACzF,CAAC,CAAA;YACJ,CAAC;YAED,2DAA2D;YAC3D,IAAI,MAAM,CAAC,QAAQ,GAAG,IAAI,EAAE,CAAC;gBAC3B,MAAM,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;YACpE,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAA;QAC5B,CAAC;IACH,CAAC;IAED,8EAA8E;IAE9E;;;OAGG;IACK,oBAAoB,CAAC,MAAuB;QAClD,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;YACjD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAQ;YAE5B,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAC3B,yCAAyC,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,CAC3E,CAAA;YAED,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;oBAChB,IAAI,EAAK,WAAW;oBACpB,KAAK,EAAI,MAAM;oBACf,MAAM,EAAG,MAAM,CAAC,IAAI;oBACpB,OAAO,EAAE,iDAAiD,MAAM,CAAC,UAAW,CAAC,KAAK,IAAI;oBACtF,MAAM,EAAG,uBAAuB;iBACjC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,8EAA8E;IAE9E;;;;;;;OAOG;IACK,iBAAiB,CAAC,MAAuB;QAC/C,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QAEnD,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBACrC,kCAAkC;gBAClC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI;oBAAE,SAAQ;gBACpC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAAE,SAAQ;gBAErE,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;gBACjE,IAAI,CAAC,MAAM;oBAAE,SAAQ;gBAErB,uBAAuB;gBACvB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;oBAChB,IAAI,EAAK,WAAW;oBACpB,KAAK,EAAI,MAAM;oBACf,MAAM,EAAG,GAAG,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE;oBACtC,OAAO,EAAE,4BAA4B,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,QAAQ,MAAM,IAAI;oBAC/E,MAAM,EAAG,iBAAiB;iBAC3B,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,wBAAwB,CAAC,MAAuB;QAKtD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QACnD,MAAM,MAAM,GAAuE,EAAE,CAAA;QAErF,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBACrC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI;oBAAE,SAAQ;gBACpC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAAE,SAAQ;gBAErE,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;gBACjE,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,CAAC,IAAI,CAAC;wBACV,SAAS,EAAK,MAAM,CAAC,IAAI;wBACzB,MAAM,EAAQ,IAAI,CAAC,IAAI;wBACvB,YAAY,EAAE,MAAM;qBACrB,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;IAED,8EAA8E;IAE9E,YAAY,CAAC,QAAwB,EAAE,UAAkB;QACvD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QAC/D,OAAO,CAAC,GAAG,CAAC,4BAA4B,UAAU,EAAE,CAAC,CAAA;IACvD,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ import type { Provider, TechnicalSchema } from '../types/index.js';
2
+ export declare class SchemaExtractor {
3
+ private provider;
4
+ constructor(provider: Provider);
5
+ extract(databaseName: string): Promise<TechnicalSchema>;
6
+ private getTables;
7
+ private getProperties;
8
+ private getRowCount;
9
+ }
10
+ //# sourceMappingURL=SchemaExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaExtractor.d.ts","sourceRoot":"","sources":["../../src/schema/SchemaExtractor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAA4B,MAAM,mBAAmB,CAAA;AAE5F,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,QAAQ;IAEhC,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;YA8B/C,SAAS;YAST,aAAa;YAiDb,WAAW;CAO1B"}