@grafema/util 0.3.0-beta

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 (324) hide show
  1. package/LICENSE +190 -0
  2. package/dist/api/GraphAPI.d.ts +87 -0
  3. package/dist/api/GraphAPI.d.ts.map +1 -0
  4. package/dist/api/GraphAPI.js +212 -0
  5. package/dist/api/GraphAPI.js.map +1 -0
  6. package/dist/api/GuaranteeAPI.d.ts +147 -0
  7. package/dist/api/GuaranteeAPI.d.ts.map +1 -0
  8. package/dist/api/GuaranteeAPI.js +290 -0
  9. package/dist/api/GuaranteeAPI.js.map +1 -0
  10. package/dist/config/ConfigLoader.d.ts +214 -0
  11. package/dist/config/ConfigLoader.d.ts.map +1 -0
  12. package/dist/config/ConfigLoader.js +441 -0
  13. package/dist/config/ConfigLoader.js.map +1 -0
  14. package/dist/config/index.d.ts +6 -0
  15. package/dist/config/index.d.ts.map +1 -0
  16. package/dist/config/index.js +5 -0
  17. package/dist/config/index.js.map +1 -0
  18. package/dist/core/CoverageAnalyzer.d.ts +65 -0
  19. package/dist/core/CoverageAnalyzer.d.ts.map +1 -0
  20. package/dist/core/CoverageAnalyzer.js +199 -0
  21. package/dist/core/CoverageAnalyzer.js.map +1 -0
  22. package/dist/core/FileExplainer.d.ts +101 -0
  23. package/dist/core/FileExplainer.d.ts.map +1 -0
  24. package/dist/core/FileExplainer.js +140 -0
  25. package/dist/core/FileExplainer.js.map +1 -0
  26. package/dist/core/FileOverview.d.ts +124 -0
  27. package/dist/core/FileOverview.d.ts.map +1 -0
  28. package/dist/core/FileOverview.js +279 -0
  29. package/dist/core/FileOverview.js.map +1 -0
  30. package/dist/core/GrafemaUri.d.ts +66 -0
  31. package/dist/core/GrafemaUri.d.ts.map +1 -0
  32. package/dist/core/GrafemaUri.js +191 -0
  33. package/dist/core/GrafemaUri.js.map +1 -0
  34. package/dist/core/GraphBackend.d.ts +158 -0
  35. package/dist/core/GraphBackend.d.ts.map +1 -0
  36. package/dist/core/GraphBackend.js +85 -0
  37. package/dist/core/GraphBackend.js.map +1 -0
  38. package/dist/core/GraphFreshnessChecker.d.ts +33 -0
  39. package/dist/core/GraphFreshnessChecker.d.ts.map +1 -0
  40. package/dist/core/GraphFreshnessChecker.js +104 -0
  41. package/dist/core/GraphFreshnessChecker.js.map +1 -0
  42. package/dist/core/GuaranteeManager.d.ts +254 -0
  43. package/dist/core/GuaranteeManager.d.ts.map +1 -0
  44. package/dist/core/GuaranteeManager.js +447 -0
  45. package/dist/core/GuaranteeManager.js.map +1 -0
  46. package/dist/core/HashUtils.d.ts +24 -0
  47. package/dist/core/HashUtils.d.ts.map +1 -0
  48. package/dist/core/HashUtils.js +46 -0
  49. package/dist/core/HashUtils.js.map +1 -0
  50. package/dist/core/IncrementalReanalyzer.d.ts +33 -0
  51. package/dist/core/IncrementalReanalyzer.d.ts.map +1 -0
  52. package/dist/core/IncrementalReanalyzer.js +67 -0
  53. package/dist/core/IncrementalReanalyzer.js.map +1 -0
  54. package/dist/core/ResourceRegistry.d.ts +17 -0
  55. package/dist/core/ResourceRegistry.d.ts.map +1 -0
  56. package/dist/core/ResourceRegistry.js +32 -0
  57. package/dist/core/ResourceRegistry.js.map +1 -0
  58. package/dist/core/SemanticId.d.ts +159 -0
  59. package/dist/core/SemanticId.d.ts.map +1 -0
  60. package/dist/core/SemanticId.js +291 -0
  61. package/dist/core/SemanticId.js.map +1 -0
  62. package/dist/core/VersionManager.d.ts +166 -0
  63. package/dist/core/VersionManager.d.ts.map +1 -0
  64. package/dist/core/VersionManager.js +239 -0
  65. package/dist/core/VersionManager.js.map +1 -0
  66. package/dist/core/brandNodeInternal.d.ts +14 -0
  67. package/dist/core/brandNodeInternal.d.ts.map +1 -0
  68. package/dist/core/brandNodeInternal.js +4 -0
  69. package/dist/core/brandNodeInternal.js.map +1 -0
  70. package/dist/core/nodes/GuaranteeNode.d.ts +76 -0
  71. package/dist/core/nodes/GuaranteeNode.d.ts.map +1 -0
  72. package/dist/core/nodes/GuaranteeNode.js +118 -0
  73. package/dist/core/nodes/GuaranteeNode.js.map +1 -0
  74. package/dist/core/nodes/IssueNode.d.ts +73 -0
  75. package/dist/core/nodes/IssueNode.d.ts.map +1 -0
  76. package/dist/core/nodes/IssueNode.js +130 -0
  77. package/dist/core/nodes/IssueNode.js.map +1 -0
  78. package/dist/core/nodes/NodeKind.d.ts +104 -0
  79. package/dist/core/nodes/NodeKind.d.ts.map +1 -0
  80. package/dist/core/nodes/NodeKind.js +166 -0
  81. package/dist/core/nodes/NodeKind.js.map +1 -0
  82. package/dist/diagnostics/DiagnosticCollector.d.ts +103 -0
  83. package/dist/diagnostics/DiagnosticCollector.d.ts.map +1 -0
  84. package/dist/diagnostics/DiagnosticCollector.js +133 -0
  85. package/dist/diagnostics/DiagnosticCollector.js.map +1 -0
  86. package/dist/diagnostics/DiagnosticReporter.d.ts +122 -0
  87. package/dist/diagnostics/DiagnosticReporter.d.ts.map +1 -0
  88. package/dist/diagnostics/DiagnosticReporter.js +300 -0
  89. package/dist/diagnostics/DiagnosticReporter.js.map +1 -0
  90. package/dist/diagnostics/DiagnosticWriter.d.ts +31 -0
  91. package/dist/diagnostics/DiagnosticWriter.d.ts.map +1 -0
  92. package/dist/diagnostics/DiagnosticWriter.js +44 -0
  93. package/dist/diagnostics/DiagnosticWriter.js.map +1 -0
  94. package/dist/diagnostics/categories.d.ts +57 -0
  95. package/dist/diagnostics/categories.d.ts.map +1 -0
  96. package/dist/diagnostics/categories.js +71 -0
  97. package/dist/diagnostics/categories.js.map +1 -0
  98. package/dist/diagnostics/index.d.ts +17 -0
  99. package/dist/diagnostics/index.d.ts.map +1 -0
  100. package/dist/diagnostics/index.js +15 -0
  101. package/dist/diagnostics/index.js.map +1 -0
  102. package/dist/errors/GrafemaError.d.ts +200 -0
  103. package/dist/errors/GrafemaError.d.ts.map +1 -0
  104. package/dist/errors/GrafemaError.js +209 -0
  105. package/dist/errors/GrafemaError.js.map +1 -0
  106. package/dist/index.d.ts +75 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/index.js +76 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/instructions/index.d.ts +8 -0
  111. package/dist/instructions/index.d.ts.map +1 -0
  112. package/dist/instructions/index.js +20 -0
  113. package/dist/instructions/index.js.map +1 -0
  114. package/dist/instructions/onboarding.md +133 -0
  115. package/dist/knowledge/KnowledgeBase.d.ts +113 -0
  116. package/dist/knowledge/KnowledgeBase.d.ts.map +1 -0
  117. package/dist/knowledge/KnowledgeBase.js +420 -0
  118. package/dist/knowledge/KnowledgeBase.js.map +1 -0
  119. package/dist/knowledge/SemanticAddressResolver.d.ts +59 -0
  120. package/dist/knowledge/SemanticAddressResolver.d.ts.map +1 -0
  121. package/dist/knowledge/SemanticAddressResolver.js +160 -0
  122. package/dist/knowledge/SemanticAddressResolver.js.map +1 -0
  123. package/dist/knowledge/git-ingest.d.ts +58 -0
  124. package/dist/knowledge/git-ingest.d.ts.map +1 -0
  125. package/dist/knowledge/git-ingest.js +301 -0
  126. package/dist/knowledge/git-ingest.js.map +1 -0
  127. package/dist/knowledge/git-queries.d.ts +86 -0
  128. package/dist/knowledge/git-queries.d.ts.map +1 -0
  129. package/dist/knowledge/git-queries.js +177 -0
  130. package/dist/knowledge/git-queries.js.map +1 -0
  131. package/dist/knowledge/index.d.ts +14 -0
  132. package/dist/knowledge/index.d.ts.map +1 -0
  133. package/dist/knowledge/index.js +10 -0
  134. package/dist/knowledge/index.js.map +1 -0
  135. package/dist/knowledge/parser.d.ts +39 -0
  136. package/dist/knowledge/parser.d.ts.map +1 -0
  137. package/dist/knowledge/parser.js +292 -0
  138. package/dist/knowledge/parser.js.map +1 -0
  139. package/dist/knowledge/types.d.ts +133 -0
  140. package/dist/knowledge/types.d.ts.map +1 -0
  141. package/dist/knowledge/types.js +8 -0
  142. package/dist/knowledge/types.js.map +1 -0
  143. package/dist/logging/Logger.d.ts +98 -0
  144. package/dist/logging/Logger.d.ts.map +1 -0
  145. package/dist/logging/Logger.js +274 -0
  146. package/dist/logging/Logger.js.map +1 -0
  147. package/dist/notation/archetypes.d.ts +36 -0
  148. package/dist/notation/archetypes.d.ts.map +1 -0
  149. package/dist/notation/archetypes.js +173 -0
  150. package/dist/notation/archetypes.js.map +1 -0
  151. package/dist/notation/fold.d.ts +25 -0
  152. package/dist/notation/fold.d.ts.map +1 -0
  153. package/dist/notation/fold.js +598 -0
  154. package/dist/notation/fold.js.map +1 -0
  155. package/dist/notation/index.d.ts +18 -0
  156. package/dist/notation/index.d.ts.map +1 -0
  157. package/dist/notation/index.js +16 -0
  158. package/dist/notation/index.js.map +1 -0
  159. package/dist/notation/lodExtractor.d.ts +32 -0
  160. package/dist/notation/lodExtractor.d.ts.map +1 -0
  161. package/dist/notation/lodExtractor.js +149 -0
  162. package/dist/notation/lodExtractor.js.map +1 -0
  163. package/dist/notation/nameShortener.d.ts +22 -0
  164. package/dist/notation/nameShortener.d.ts.map +1 -0
  165. package/dist/notation/nameShortener.js +24 -0
  166. package/dist/notation/nameShortener.js.map +1 -0
  167. package/dist/notation/perspectives.d.ts +11 -0
  168. package/dist/notation/perspectives.d.ts.map +1 -0
  169. package/dist/notation/perspectives.js +16 -0
  170. package/dist/notation/perspectives.js.map +1 -0
  171. package/dist/notation/renderer.d.ts +31 -0
  172. package/dist/notation/renderer.d.ts.map +1 -0
  173. package/dist/notation/renderer.js +315 -0
  174. package/dist/notation/renderer.js.map +1 -0
  175. package/dist/notation/traceRenderer.d.ts +39 -0
  176. package/dist/notation/traceRenderer.d.ts.map +1 -0
  177. package/dist/notation/traceRenderer.js +358 -0
  178. package/dist/notation/traceRenderer.js.map +1 -0
  179. package/dist/notation/types.d.ts +66 -0
  180. package/dist/notation/types.d.ts.map +1 -0
  181. package/dist/notation/types.js +10 -0
  182. package/dist/notation/types.js.map +1 -0
  183. package/dist/queries/NodeContext.d.ts +81 -0
  184. package/dist/queries/NodeContext.d.ts.map +1 -0
  185. package/dist/queries/NodeContext.js +196 -0
  186. package/dist/queries/NodeContext.js.map +1 -0
  187. package/dist/queries/findCallsInFunction.d.ts +62 -0
  188. package/dist/queries/findCallsInFunction.d.ts.map +1 -0
  189. package/dist/queries/findCallsInFunction.js +169 -0
  190. package/dist/queries/findCallsInFunction.js.map +1 -0
  191. package/dist/queries/findContainingFunction.d.ts +57 -0
  192. package/dist/queries/findContainingFunction.d.ts.map +1 -0
  193. package/dist/queries/findContainingFunction.js +91 -0
  194. package/dist/queries/findContainingFunction.js.map +1 -0
  195. package/dist/queries/index.d.ts +18 -0
  196. package/dist/queries/index.d.ts.map +1 -0
  197. package/dist/queries/index.js +14 -0
  198. package/dist/queries/index.js.map +1 -0
  199. package/dist/queries/traceDataflow.d.ts +65 -0
  200. package/dist/queries/traceDataflow.d.ts.map +1 -0
  201. package/dist/queries/traceDataflow.js +754 -0
  202. package/dist/queries/traceDataflow.js.map +1 -0
  203. package/dist/queries/traceValues.d.ts +70 -0
  204. package/dist/queries/traceValues.d.ts.map +1 -0
  205. package/dist/queries/traceValues.js +373 -0
  206. package/dist/queries/traceValues.js.map +1 -0
  207. package/dist/queries/types.d.ts +166 -0
  208. package/dist/queries/types.d.ts.map +1 -0
  209. package/dist/queries/types.js +10 -0
  210. package/dist/queries/types.js.map +1 -0
  211. package/dist/schema/GraphSchemaExtractor.d.ts +53 -0
  212. package/dist/schema/GraphSchemaExtractor.d.ts.map +1 -0
  213. package/dist/schema/GraphSchemaExtractor.js +125 -0
  214. package/dist/schema/GraphSchemaExtractor.js.map +1 -0
  215. package/dist/schema/InterfaceSchemaExtractor.d.ts +73 -0
  216. package/dist/schema/InterfaceSchemaExtractor.d.ts.map +1 -0
  217. package/dist/schema/InterfaceSchemaExtractor.js +113 -0
  218. package/dist/schema/InterfaceSchemaExtractor.js.map +1 -0
  219. package/dist/schema/index.d.ts +5 -0
  220. package/dist/schema/index.d.ts.map +1 -0
  221. package/dist/schema/index.js +3 -0
  222. package/dist/schema/index.js.map +1 -0
  223. package/dist/storage/backends/RFDBServerBackend.d.ts +356 -0
  224. package/dist/storage/backends/RFDBServerBackend.d.ts.map +1 -0
  225. package/dist/storage/backends/RFDBServerBackend.js +748 -0
  226. package/dist/storage/backends/RFDBServerBackend.js.map +1 -0
  227. package/dist/storage/backends/typeValidation.d.ts +47 -0
  228. package/dist/storage/backends/typeValidation.d.ts.map +1 -0
  229. package/dist/storage/backends/typeValidation.js +141 -0
  230. package/dist/storage/backends/typeValidation.js.map +1 -0
  231. package/dist/utils/findRfdbBinary.d.ts +67 -0
  232. package/dist/utils/findRfdbBinary.d.ts.map +1 -0
  233. package/dist/utils/findRfdbBinary.js +261 -0
  234. package/dist/utils/findRfdbBinary.js.map +1 -0
  235. package/dist/utils/lazyDownload.d.ts +43 -0
  236. package/dist/utils/lazyDownload.d.ts.map +1 -0
  237. package/dist/utils/lazyDownload.js +175 -0
  238. package/dist/utils/lazyDownload.js.map +1 -0
  239. package/dist/utils/moduleResolution.d.ts +134 -0
  240. package/dist/utils/moduleResolution.d.ts.map +1 -0
  241. package/dist/utils/moduleResolution.js +189 -0
  242. package/dist/utils/moduleResolution.js.map +1 -0
  243. package/dist/utils/resolveNodeFile.d.ts +13 -0
  244. package/dist/utils/resolveNodeFile.d.ts.map +1 -0
  245. package/dist/utils/resolveNodeFile.js +18 -0
  246. package/dist/utils/resolveNodeFile.js.map +1 -0
  247. package/dist/utils/startRfdbServer.d.ts +63 -0
  248. package/dist/utils/startRfdbServer.d.ts.map +1 -0
  249. package/dist/utils/startRfdbServer.js +142 -0
  250. package/dist/utils/startRfdbServer.js.map +1 -0
  251. package/dist/validation/PathValidator.d.ts +80 -0
  252. package/dist/validation/PathValidator.d.ts.map +1 -0
  253. package/dist/validation/PathValidator.js +252 -0
  254. package/dist/validation/PathValidator.js.map +1 -0
  255. package/dist/version.d.ts +11 -0
  256. package/dist/version.d.ts.map +1 -0
  257. package/dist/version.js +26 -0
  258. package/dist/version.js.map +1 -0
  259. package/package.json +50 -0
  260. package/src/api/GraphAPI.ts +307 -0
  261. package/src/api/GuaranteeAPI.ts +402 -0
  262. package/src/config/ConfigLoader.ts +653 -0
  263. package/src/config/index.ts +13 -0
  264. package/src/core/CoverageAnalyzer.ts +243 -0
  265. package/src/core/FileExplainer.ts +179 -0
  266. package/src/core/FileOverview.ts +397 -0
  267. package/src/core/GrafemaUri.ts +216 -0
  268. package/src/core/GraphBackend.ts +266 -0
  269. package/src/core/GraphFreshnessChecker.ts +145 -0
  270. package/src/core/GuaranteeManager.ts +684 -0
  271. package/src/core/HashUtils.ts +48 -0
  272. package/src/core/IncrementalReanalyzer.ts +106 -0
  273. package/src/core/ResourceRegistry.ts +39 -0
  274. package/src/core/SemanticId.ts +423 -0
  275. package/src/core/VersionManager.ts +405 -0
  276. package/src/core/brandNodeInternal.ts +16 -0
  277. package/src/core/nodes/GuaranteeNode.ts +162 -0
  278. package/src/core/nodes/IssueNode.ts +177 -0
  279. package/src/core/nodes/NodeKind.ts +192 -0
  280. package/src/diagnostics/DiagnosticCollector.ts +170 -0
  281. package/src/diagnostics/DiagnosticReporter.ts +395 -0
  282. package/src/diagnostics/DiagnosticWriter.ts +50 -0
  283. package/src/diagnostics/categories.ts +104 -0
  284. package/src/diagnostics/index.ts +30 -0
  285. package/src/errors/GrafemaError.ts +297 -0
  286. package/src/index.ts +261 -0
  287. package/src/instructions/index.ts +21 -0
  288. package/src/instructions/onboarding.md +133 -0
  289. package/src/knowledge/KnowledgeBase.ts +486 -0
  290. package/src/knowledge/SemanticAddressResolver.ts +191 -0
  291. package/src/knowledge/git-ingest.ts +402 -0
  292. package/src/knowledge/git-queries.ts +269 -0
  293. package/src/knowledge/index.ts +29 -0
  294. package/src/knowledge/parser.ts +294 -0
  295. package/src/knowledge/types.ts +146 -0
  296. package/src/logging/Logger.ts +303 -0
  297. package/src/notation/archetypes.ts +189 -0
  298. package/src/notation/fold.ts +696 -0
  299. package/src/notation/index.ts +27 -0
  300. package/src/notation/lodExtractor.ts +177 -0
  301. package/src/notation/nameShortener.ts +24 -0
  302. package/src/notation/perspectives.ts +18 -0
  303. package/src/notation/renderer.ts +394 -0
  304. package/src/notation/traceRenderer.ts +458 -0
  305. package/src/notation/types.ts +79 -0
  306. package/src/queries/NodeContext.ts +280 -0
  307. package/src/queries/findCallsInFunction.ts +249 -0
  308. package/src/queries/findContainingFunction.ts +124 -0
  309. package/src/queries/index.ts +44 -0
  310. package/src/queries/traceDataflow.ts +838 -0
  311. package/src/queries/traceValues.ts +531 -0
  312. package/src/queries/types.ts +191 -0
  313. package/src/schema/GraphSchemaExtractor.ts +177 -0
  314. package/src/schema/InterfaceSchemaExtractor.ts +173 -0
  315. package/src/schema/index.ts +5 -0
  316. package/src/storage/backends/RFDBServerBackend.ts +895 -0
  317. package/src/storage/backends/typeValidation.ts +154 -0
  318. package/src/utils/findRfdbBinary.ts +288 -0
  319. package/src/utils/lazyDownload.ts +206 -0
  320. package/src/utils/moduleResolution.ts +271 -0
  321. package/src/utils/resolveNodeFile.ts +18 -0
  322. package/src/utils/startRfdbServer.ts +197 -0
  323. package/src/validation/PathValidator.ts +334 -0
  324. package/src/version.ts +28 -0
@@ -0,0 +1,177 @@
1
+ /**
2
+ * GraphSchemaExtractor - Extracts graph node/edge type schemas
3
+ *
4
+ * Usage:
5
+ * const extractor = new GraphSchemaExtractor(backend);
6
+ * const schema = await extractor.extract();
7
+ *
8
+ * When to use:
9
+ * - Export graph schema for contract tracking
10
+ * - Track node/edge type changes via checksum
11
+ * - Generate graph documentation
12
+ */
13
+
14
+ import { createHash } from 'crypto';
15
+ import { NODE_TYPE, NAMESPACED_TYPE, EDGE_TYPE } from '@grafema/types';
16
+ import type { RFDBServerBackend } from '../storage/backends/RFDBServerBackend.js';
17
+
18
+ // ============================================================================
19
+ // Types
20
+ // ============================================================================
21
+
22
+ export interface NodeTypeSchema {
23
+ category: 'base' | 'namespaced';
24
+ namespace?: string;
25
+ count: number;
26
+ }
27
+
28
+ export interface EdgeTypeSchema {
29
+ count: number;
30
+ }
31
+
32
+ export interface GraphSchema {
33
+ $schema: 'grafema-graph-v1';
34
+ extractedAt: string;
35
+ nodeTypes: Record<string, NodeTypeSchema>;
36
+ edgeTypes: Record<string, EdgeTypeSchema>;
37
+ statistics: {
38
+ totalNodes: number;
39
+ totalEdges: number;
40
+ nodeTypeCount: number;
41
+ edgeTypeCount: number;
42
+ };
43
+ checksum: string;
44
+ }
45
+
46
+ // ============================================================================
47
+ // Extractor
48
+ // ============================================================================
49
+
50
+ export interface GraphExtractOptions {
51
+ /** Include all defined types, not just used ones (default: false) */
52
+ includeAll?: boolean;
53
+ }
54
+
55
+ export class GraphSchemaExtractor {
56
+ constructor(private backend: RFDBServerBackend) {}
57
+
58
+ /**
59
+ * Extract graph schema from current database
60
+ *
61
+ * @param options.includeAll - If true, include all defined types even with count=0
62
+ */
63
+ async extract(options?: GraphExtractOptions): Promise<GraphSchema> {
64
+ const includeAll = options?.includeAll ?? false;
65
+ // Get actual counts from graph
66
+ const nodeCounts = await this.backend.countNodesByType();
67
+ const edgeCounts = await this.backend.countEdgesByType();
68
+
69
+ // Build node types from definitions + counts
70
+ const nodeTypes: Record<string, NodeTypeSchema> = {};
71
+
72
+ // Base node types
73
+ for (const [_key, value] of Object.entries(NODE_TYPE)) {
74
+ nodeTypes[value] = {
75
+ category: 'base',
76
+ count: nodeCounts[value] || 0,
77
+ };
78
+ }
79
+
80
+ // Namespaced node types
81
+ for (const [_key, value] of Object.entries(NAMESPACED_TYPE)) {
82
+ const namespace = value.split(':')[0];
83
+ nodeTypes[value] = {
84
+ category: 'namespaced',
85
+ namespace,
86
+ count: nodeCounts[value] || 0,
87
+ };
88
+ }
89
+
90
+ // Add any additional types found in the graph but not in definitions
91
+ for (const [type, count] of Object.entries(nodeCounts)) {
92
+ if (!nodeTypes[type]) {
93
+ const namespace = type.includes(':') ? type.split(':')[0] : undefined;
94
+ nodeTypes[type] = {
95
+ category: namespace ? 'namespaced' : 'base',
96
+ namespace,
97
+ count,
98
+ };
99
+ }
100
+ }
101
+
102
+ // Build edge types from definitions + counts
103
+ const edgeTypes: Record<string, EdgeTypeSchema> = {};
104
+
105
+ for (const [_key, value] of Object.entries(EDGE_TYPE)) {
106
+ edgeTypes[value] = {
107
+ count: edgeCounts[value] || 0,
108
+ };
109
+ }
110
+
111
+ // Add any additional edge types found in the graph
112
+ for (const [type, count] of Object.entries(edgeCounts)) {
113
+ if (!edgeTypes[type]) {
114
+ edgeTypes[type] = { count };
115
+ }
116
+ }
117
+
118
+ // Calculate totals
119
+ const totalNodes = Object.values(nodeCounts).reduce((sum, n) => sum + n, 0);
120
+ const totalEdges = Object.values(edgeCounts).reduce((sum, n) => sum + n, 0);
121
+
122
+ // Filter out types with count=0 unless includeAll is true
123
+ const filteredNodeTypes: Record<string, NodeTypeSchema> = {};
124
+ for (const [type, info] of Object.entries(nodeTypes)) {
125
+ if (includeAll || info.count > 0) {
126
+ filteredNodeTypes[type] = info;
127
+ }
128
+ }
129
+
130
+ const filteredEdgeTypes: Record<string, EdgeTypeSchema> = {};
131
+ for (const [type, info] of Object.entries(edgeTypes)) {
132
+ if (includeAll || info.count > 0) {
133
+ filteredEdgeTypes[type] = info;
134
+ }
135
+ }
136
+
137
+ // Sort for deterministic output
138
+ const sortedNodeTypes = this.sortObject(filteredNodeTypes);
139
+ const sortedEdgeTypes = this.sortObject(filteredEdgeTypes);
140
+
141
+ // Compute checksum from normalized content (based on filtered types)
142
+ const checksumContent = {
143
+ nodeTypes: Object.keys(sortedNodeTypes).sort(),
144
+ edgeTypes: Object.keys(sortedEdgeTypes).sort(),
145
+ };
146
+
147
+ const checksum = createHash('sha256')
148
+ .update(JSON.stringify(checksumContent))
149
+ .digest('hex');
150
+
151
+ return {
152
+ $schema: 'grafema-graph-v1',
153
+ extractedAt: new Date().toISOString(),
154
+ nodeTypes: sortedNodeTypes,
155
+ edgeTypes: sortedEdgeTypes,
156
+ statistics: {
157
+ totalNodes,
158
+ totalEdges,
159
+ nodeTypeCount: Object.keys(sortedNodeTypes).length,
160
+ edgeTypeCount: Object.keys(sortedEdgeTypes).length,
161
+ },
162
+ checksum: `sha256:${checksum}`,
163
+ };
164
+ }
165
+
166
+ /**
167
+ * Sort object keys alphabetically for deterministic output
168
+ */
169
+ private sortObject<T>(obj: Record<string, T>): Record<string, T> {
170
+ const sorted: Record<string, T> = {};
171
+ const keys = Object.keys(obj).sort();
172
+ for (const key of keys) {
173
+ sorted[key] = obj[key];
174
+ }
175
+ return sorted;
176
+ }
177
+ }
@@ -0,0 +1,173 @@
1
+ /**
2
+ * InterfaceSchemaExtractor - Extracts interface schemas from graph
3
+ *
4
+ * Usage:
5
+ * const extractor = new InterfaceSchemaExtractor(backend);
6
+ * const schema = await extractor.extract('ConfigSchema');
7
+ *
8
+ * When to use:
9
+ * - Export interface contracts for documentation
10
+ * - Track interface changes via checksum
11
+ * - Generate API documentation from graph
12
+ */
13
+
14
+ import { createHash } from 'crypto';
15
+ import type { RFDBServerBackend } from '../storage/backends/RFDBServerBackend.js';
16
+
17
+ // ============================================================================
18
+ // Types
19
+ // ============================================================================
20
+
21
+ export interface PropertySchema {
22
+ type: string;
23
+ required: boolean;
24
+ readonly: boolean;
25
+ }
26
+
27
+ export interface InterfaceSchema {
28
+ $schema: 'grafema-interface-v1';
29
+ name: string;
30
+ source: {
31
+ file: string;
32
+ line: number;
33
+ column: number;
34
+ };
35
+ typeParameters?: string[];
36
+ properties: Record<string, PropertySchema>;
37
+ extends: string[];
38
+ checksum: string;
39
+ }
40
+
41
+ export interface ExtractOptions {
42
+ /** Specific file path if multiple interfaces have same name */
43
+ file?: string;
44
+ }
45
+
46
+ export interface InterfaceNodeRecord {
47
+ id: string;
48
+ type: 'INTERFACE';
49
+ name: string;
50
+ file: string;
51
+ line: number;
52
+ column: number;
53
+ extends: string[];
54
+ properties: Array<{
55
+ name: string;
56
+ type?: string;
57
+ optional?: boolean;
58
+ readonly?: boolean;
59
+ }>;
60
+ typeParameters?: string[];
61
+ }
62
+
63
+ // ============================================================================
64
+ // Extractor
65
+ // ============================================================================
66
+
67
+ export class InterfaceSchemaExtractor {
68
+ constructor(private backend: RFDBServerBackend) {}
69
+
70
+ /**
71
+ * Extract schema for interface by name
72
+ *
73
+ * @param interfaceName - Name of the interface (e.g., 'ConfigSchema')
74
+ * @param options - Optional filters
75
+ * @returns InterfaceSchema or null if not found
76
+ * @throws Error if multiple interfaces match and no file specified
77
+ */
78
+ async extract(interfaceName: string, options?: ExtractOptions): Promise<InterfaceSchema | null> {
79
+ const interfaces = await this.findInterfaces(interfaceName);
80
+
81
+ if (interfaces.length === 0) {
82
+ return null;
83
+ }
84
+
85
+ // Filter by file if specified
86
+ let match: InterfaceNodeRecord;
87
+ if (options?.file) {
88
+ const fileFilter = options.file;
89
+ const filtered = interfaces.filter(i => i.file === fileFilter || i.file.endsWith(fileFilter));
90
+ if (filtered.length === 0) {
91
+ return null;
92
+ }
93
+ match = filtered[0];
94
+ } else if (interfaces.length > 1) {
95
+ const locations = interfaces.map(i => ` - ${i.file}:${i.line}`).join('\n');
96
+ throw new Error(
97
+ `Multiple interfaces named "${interfaceName}" found:\n${locations}\n` +
98
+ `Use --file option to specify which one.`
99
+ );
100
+ } else {
101
+ match = interfaces[0];
102
+ }
103
+
104
+ return this.buildSchema(match);
105
+ }
106
+
107
+ /**
108
+ * Find all interfaces with given name
109
+ */
110
+ async findInterfaces(name: string): Promise<InterfaceNodeRecord[]> {
111
+ const result: InterfaceNodeRecord[] = [];
112
+
113
+ for await (const node of this.backend.queryNodes({ nodeType: 'INTERFACE' })) {
114
+ if (node.name === name) {
115
+ result.push(node as unknown as InterfaceNodeRecord);
116
+ }
117
+ }
118
+
119
+ return result;
120
+ }
121
+
122
+ /**
123
+ * Build InterfaceSchema from node record
124
+ */
125
+ private buildSchema(node: InterfaceNodeRecord): InterfaceSchema {
126
+ // Sort properties alphabetically for deterministic output
127
+ const sortedProperties = [...(node.properties || [])].sort((a, b) =>
128
+ a.name.localeCompare(b.name)
129
+ );
130
+
131
+ const properties: Record<string, PropertySchema> = {};
132
+ for (const prop of sortedProperties) {
133
+ properties[prop.name] = {
134
+ type: prop.type || 'unknown',
135
+ required: !prop.optional,
136
+ readonly: prop.readonly || false
137
+ };
138
+ }
139
+
140
+ // Compute checksum from normalized content
141
+ const checksumContent = {
142
+ name: node.name,
143
+ properties: sortedProperties.map(p => ({
144
+ name: p.name,
145
+ type: p.type,
146
+ optional: p.optional,
147
+ readonly: p.readonly
148
+ })),
149
+ extends: [...(node.extends || [])].sort(),
150
+ typeParameters: node.typeParameters
151
+ };
152
+
153
+ const checksum = createHash('sha256')
154
+ .update(JSON.stringify(checksumContent))
155
+ .digest('hex');
156
+
157
+ return {
158
+ $schema: 'grafema-interface-v1',
159
+ name: node.name,
160
+ source: {
161
+ file: node.file,
162
+ line: node.line,
163
+ column: node.column
164
+ },
165
+ ...(node.typeParameters && node.typeParameters.length > 0 && {
166
+ typeParameters: node.typeParameters
167
+ }),
168
+ properties,
169
+ extends: node.extends || [],
170
+ checksum: `sha256:${checksum}`
171
+ };
172
+ }
173
+ }
@@ -0,0 +1,5 @@
1
+ export { InterfaceSchemaExtractor } from './InterfaceSchemaExtractor.js';
2
+ export type { InterfaceSchema, PropertySchema, ExtractOptions } from './InterfaceSchemaExtractor.js';
3
+
4
+ export { GraphSchemaExtractor } from './GraphSchemaExtractor.js';
5
+ export type { GraphSchema, NodeTypeSchema, EdgeTypeSchema, GraphExtractOptions } from './GraphSchemaExtractor.js';