@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,154 @@
1
+ /**
2
+ * Type Validation Utilities
3
+ *
4
+ * Levenshtein distance and typo detection for node/edge types.
5
+ * Extracted from ReginaFlowBackend for use in multiple contexts.
6
+ */
7
+
8
+ // Known node types - source of truth for validation
9
+ // Initial set of types, dynamically expanded as new valid types are encountered
10
+ const KNOWN_NODE_TYPES = new Set<string>([
11
+ // Base types
12
+ 'FUNCTION', 'CLASS', 'METHOD', 'VARIABLE', 'PARAMETER', 'CONSTANT', 'LITERAL',
13
+ 'MODULE', 'IMPORT', 'EXPORT', 'CALL', 'PROJECT', 'SERVICE', 'FILE', 'SCOPE',
14
+ 'EXTERNAL', 'EXTERNAL_MODULE', 'SIDE_EFFECT',
15
+ // Namespaced types - HTTP/Express
16
+ 'http:route', 'http:request',
17
+ 'express:router', 'express:middleware', 'express:mount',
18
+ // Namespaced types - Socket.IO
19
+ 'socketio:emit', 'socketio:on', 'socketio:namespace', 'socketio:room',
20
+ // Namespaced types - Database
21
+ 'db:query', 'db:connection', 'db:table',
22
+ // Namespaced types - File System
23
+ 'fs:read', 'fs:write', 'fs:operation',
24
+ // Namespaced types - Network/IO
25
+ 'net:request', 'net:stdio',
26
+ // Namespaced types - Events
27
+ 'event:listener', 'event:emit',
28
+ // Service layer types (legacy, to be refactored)
29
+ 'SERVICE_CLASS', 'SERVICE_INSTANCE', 'SERVICE_REGISTRATION', 'SERVICE_USAGE',
30
+ // Guarantees/Invariants
31
+ 'GUARANTEE',
32
+ ]);
33
+
34
+ // Store initial types for reset
35
+ const INITIAL_NODE_TYPES = [...KNOWN_NODE_TYPES];
36
+
37
+ // Known edge types - source of truth for validation
38
+ const KNOWN_EDGE_TYPES = new Set<string>([
39
+ // Base edge types
40
+ 'UNKNOWN', 'CONTAINS', 'DEPENDS_ON', 'CALLS', 'EXTENDS', 'IMPLEMENTS',
41
+ 'USES', 'DEFINES', 'IMPORTS', 'EXPORTS', 'ROUTES_TO', 'HAS_SCOPE',
42
+ 'CAPTURES', 'MODIFIES', 'DECLARES', 'WRITES_TO', 'INSTANCE_OF',
43
+ 'HAS_CALLBACK', 'IMPORTS_FROM', 'HANDLED_BY', 'MAKES_REQUEST',
44
+ 'PASSES_ARGUMENT', 'ASSIGNED_FROM', 'MOUNTS', 'EXPOSES',
45
+ 'INTERACTS_WITH', 'CALLS_API', 'LISTENS_TO', 'JOINS_ROOM', 'EMITS_EVENT',
46
+ 'RETURNS', 'RECEIVES_ARGUMENT', 'READS_FROM', 'THROWS', 'REGISTERS_VIEW',
47
+ 'GOVERNS', 'VIOLATES', 'HAS_PARAMETER', 'DERIVES_FROM',
48
+ 'RESOLVES_TO', // Promise resolve() data flow
49
+ 'YIELDS', // Generator yield data flow (REG-270)
50
+ 'DELEGATES_TO', // Generator yield* delegation (REG-270)
51
+ ]);
52
+
53
+ // Store initial edge types for reset
54
+ const INITIAL_EDGE_TYPES = [...KNOWN_EDGE_TYPES];
55
+
56
+ export interface TypoCheckResult {
57
+ isTooSimilar: boolean;
58
+ similarTo: string | null;
59
+ }
60
+
61
+ /**
62
+ * Levenshtein distance for typo detection
63
+ */
64
+ export function levenshtein(a: string, b: string): number {
65
+ if (a.length === 0) return b.length;
66
+ if (b.length === 0) return a.length;
67
+ const matrix: number[][] = [];
68
+ for (let i = 0; i <= b.length; i++) matrix[i] = [i];
69
+ for (let j = 0; j <= a.length; j++) matrix[0][j] = j;
70
+ for (let i = 1; i <= b.length; i++) {
71
+ for (let j = 1; j <= a.length; j++) {
72
+ matrix[i][j] = b[i - 1] === a[j - 1]
73
+ ? matrix[i - 1][j - 1]
74
+ : Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
75
+ }
76
+ }
77
+ return matrix[b.length][a.length];
78
+ }
79
+
80
+ /**
81
+ * Check if a type is too similar to any existing known type (possible typo)
82
+ */
83
+ export function checkTypoAgainstKnownTypes(newType: string): TypoCheckResult {
84
+ const newTypeLower = newType.toLowerCase();
85
+ for (const known of KNOWN_NODE_TYPES) {
86
+ const dist = levenshtein(newTypeLower, known.toLowerCase());
87
+ if (dist > 0 && dist <= 2) {
88
+ return { isTooSimilar: true, similarTo: known };
89
+ }
90
+ }
91
+ return { isTooSimilar: false, similarTo: null };
92
+ }
93
+
94
+ /**
95
+ * Reset KNOWN_NODE_TYPES to initial state (for testing)
96
+ */
97
+ export function resetKnownNodeTypes(): void {
98
+ KNOWN_NODE_TYPES.clear();
99
+ for (const t of INITIAL_NODE_TYPES) {
100
+ KNOWN_NODE_TYPES.add(t);
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Get current known node types (for testing/debugging)
106
+ */
107
+ export function getKnownNodeTypes(): Set<string> {
108
+ return new Set(KNOWN_NODE_TYPES);
109
+ }
110
+
111
+ /**
112
+ * Check if an edge type is too similar to any existing known edge type (possible typo)
113
+ */
114
+ export function checkTypoAgainstKnownEdgeTypes(newType: string): TypoCheckResult {
115
+ const newTypeLower = newType.toLowerCase();
116
+ for (const known of KNOWN_EDGE_TYPES) {
117
+ const dist = levenshtein(newTypeLower, known.toLowerCase());
118
+ if (dist > 0 && dist <= 2) {
119
+ return { isTooSimilar: true, similarTo: known };
120
+ }
121
+ }
122
+ return { isTooSimilar: false, similarTo: null };
123
+ }
124
+
125
+ /**
126
+ * Reset KNOWN_EDGE_TYPES to initial state (for testing)
127
+ */
128
+ export function resetKnownEdgeTypes(): void {
129
+ KNOWN_EDGE_TYPES.clear();
130
+ for (const t of INITIAL_EDGE_TYPES) {
131
+ KNOWN_EDGE_TYPES.add(t);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Get current known edge types (for testing/debugging)
137
+ */
138
+ export function getKnownEdgeTypes(): Set<string> {
139
+ return new Set(KNOWN_EDGE_TYPES);
140
+ }
141
+
142
+ /**
143
+ * Add a new node type to the known types set
144
+ */
145
+ export function addKnownNodeType(nodeType: string): void {
146
+ KNOWN_NODE_TYPES.add(nodeType);
147
+ }
148
+
149
+ /**
150
+ * Add a new edge type to the known types set
151
+ */
152
+ export function addKnownEdgeType(edgeType: string): void {
153
+ KNOWN_EDGE_TYPES.add(edgeType);
154
+ }
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Unified binary lookup for Grafema native binaries.
3
+ *
4
+ * Used by CLI, MCP server, and the unified grafema package.
5
+ * Finds rfdb-server, grafema-orchestrator, or any binary by name.
6
+ *
7
+ * Search order:
8
+ * 1. Explicit path (from config or flag)
9
+ * 2. Environment variable (GRAFEMA_RFDB_SERVER / GRAFEMA_ORCHESTRATOR)
10
+ * 3. Platform package (@grafema/grafema-{os}-{arch})
11
+ * 4. Monorepo target/release (development)
12
+ * 5. Monorepo target/debug (development)
13
+ * 6. System PATH lookup
14
+ * 7. ~/.grafema/bin/ (lazy-downloaded analyzers)
15
+ * 8. ~/.local/bin/ (user-installed)
16
+ */
17
+
18
+ import { existsSync } from 'fs';
19
+ import { join, delimiter, dirname, resolve } from 'path';
20
+ import { createRequire } from 'module';
21
+ import { fileURLToPath } from 'url';
22
+
23
+ const __filename = fileURLToPath(import.meta.url);
24
+ const __dirname = dirname(__filename);
25
+
26
+ export type BinaryName = 'rfdb-server' | 'grafema-orchestrator';
27
+
28
+ export interface FindBinaryOptions {
29
+ /** Explicit path to binary (highest priority) */
30
+ explicitPath?: string;
31
+ /** Base directory for monorepo search (defaults to auto-detect) */
32
+ monorepoRoot?: string;
33
+ }
34
+
35
+ interface BinaryConfig {
36
+ envVar: string;
37
+ monorepoPackage: string;
38
+ }
39
+
40
+ const BINARY_CONFIG: Record<BinaryName, BinaryConfig> = {
41
+ 'rfdb-server': {
42
+ envVar: 'GRAFEMA_RFDB_SERVER',
43
+ monorepoPackage: 'rfdb-server',
44
+ },
45
+ 'grafema-orchestrator': {
46
+ envVar: 'GRAFEMA_ORCHESTRATOR',
47
+ monorepoPackage: 'grafema-orchestrator',
48
+ },
49
+ };
50
+
51
+ /**
52
+ * Get platform directory name for prebuilt binaries.
53
+ * E.g., "darwin-arm64", "linux-x64"
54
+ */
55
+ export function getPlatformDir(): string {
56
+ const platform = process.platform;
57
+ const arch = process.arch;
58
+
59
+ if (platform === 'darwin') {
60
+ return arch === 'arm64' ? 'darwin-arm64' : 'darwin-x64';
61
+ } else if (platform === 'linux') {
62
+ return arch === 'arm64' ? 'linux-arm64' : 'linux-x64';
63
+ }
64
+ return `${platform}-${arch}`;
65
+ }
66
+
67
+ /**
68
+ * Get platform package name for the current OS/arch.
69
+ * E.g., "@grafema/grafema-darwin-arm64"
70
+ */
71
+ export function getPlatformPackageName(): string {
72
+ const platform = process.platform === 'darwin' ? 'darwin' : 'linux';
73
+ const arch = process.arch === 'arm64' ? 'arm64' : 'x64';
74
+ return `@grafema/grafema-${platform}-${arch}`;
75
+ }
76
+
77
+ /**
78
+ * Try to load the platform package and get a binary path from it.
79
+ */
80
+ function tryPlatformPackage(binaryName: BinaryName): string | null {
81
+ try {
82
+ const require = createRequire(import.meta.url);
83
+ const pkgName = getPlatformPackageName();
84
+ const pkg = require(pkgName);
85
+
86
+ if (binaryName === 'rfdb-server' && pkg.rfdbServerPath) {
87
+ const p = pkg.rfdbServerPath;
88
+ if (existsSync(p)) return p;
89
+ }
90
+ if (binaryName === 'grafema-orchestrator' && pkg.orchestratorPath) {
91
+ const p = pkg.orchestratorPath;
92
+ if (existsSync(p)) return p;
93
+ }
94
+
95
+ // Fallback: try binDir + binaryName
96
+ if (pkg.binDir) {
97
+ const p = join(pkg.binDir, binaryName);
98
+ if (existsSync(p)) return p;
99
+ }
100
+ } catch {
101
+ // Platform package not installed
102
+ }
103
+ return null;
104
+ }
105
+
106
+ /**
107
+ * Find monorepo root by looking for characteristic files.
108
+ */
109
+ function findMonorepoRoot(startDir?: string): string | null {
110
+ // Walk up from provided dir or this file's location
111
+ let dir = startDir || join(__dirname, '..', '..', '..', '..');
112
+ for (let i = 0; i < 8; i++) {
113
+ const hasPackagesDir = existsSync(join(dir, 'packages', 'util'));
114
+ const hasPnpmWorkspace = existsSync(join(dir, 'pnpm-workspace.yaml'));
115
+ if (hasPackagesDir && hasPnpmWorkspace) {
116
+ return dir;
117
+ }
118
+ const parent = dirname(dir);
119
+ if (parent === dir) break;
120
+ dir = parent;
121
+ }
122
+
123
+ // Try GRAFEMA_ROOT env var
124
+ const envRoot = process.env.GRAFEMA_ROOT;
125
+ if (envRoot && existsSync(join(envRoot, 'packages', 'util'))) {
126
+ return envRoot;
127
+ }
128
+
129
+ return null;
130
+ }
131
+
132
+ /**
133
+ * Find a Grafema native binary.
134
+ *
135
+ * @param binaryName - Which binary to find
136
+ * @param options - Search options
137
+ * @returns Absolute path to the binary, or null if not found
138
+ */
139
+ export function findBinary(binaryName: BinaryName, options: FindBinaryOptions = {}): string | null {
140
+ const config = BINARY_CONFIG[binaryName];
141
+
142
+ // 1. Explicit path (from config or flag) — no fallback
143
+ if (options.explicitPath) {
144
+ const resolved = resolve(options.explicitPath);
145
+ return existsSync(resolved) ? resolved : null;
146
+ }
147
+
148
+ // 2. Environment variable
149
+ const envPath = process.env[config.envVar];
150
+ if (envPath && existsSync(envPath)) {
151
+ return envPath;
152
+ }
153
+
154
+ // 3. Platform package (@grafema/grafema-{os}-{arch})
155
+ const platformPath = tryPlatformPackage(binaryName);
156
+ if (platformPath) return platformPath;
157
+
158
+ // 4-5. Monorepo development builds
159
+ const monorepoRoot = findMonorepoRoot(options.monorepoRoot);
160
+ if (monorepoRoot) {
161
+ for (const profile of ['release', 'debug']) {
162
+ const p = join(monorepoRoot, 'packages', config.monorepoPackage, 'target', profile, binaryName);
163
+ if (existsSync(p)) return p;
164
+ }
165
+ }
166
+
167
+ // 6. System PATH lookup
168
+ const pathDirs = (process.env.PATH || '').split(delimiter);
169
+ for (const dir of pathDirs) {
170
+ if (!dir) continue;
171
+ const p = join(dir, binaryName);
172
+ if (existsSync(p)) return p;
173
+ }
174
+
175
+ // 7. ~/.grafema/bin/ (lazy-downloaded analyzers)
176
+ const home = process.env.HOME || process.env.USERPROFILE || '';
177
+ if (home) {
178
+ const p = join(home, '.grafema', 'bin', binaryName);
179
+ if (existsSync(p)) return p;
180
+ }
181
+
182
+ // 8. ~/.local/bin/ (user-installed)
183
+ if (home) {
184
+ const p = join(home, '.local', 'bin', binaryName);
185
+ if (existsSync(p)) return p;
186
+ }
187
+
188
+ // Legacy: @grafema/rfdb npm package (old prebuilt location)
189
+ if (binaryName === 'rfdb-server') {
190
+ try {
191
+ const require = createRequire(import.meta.url);
192
+ const rfdbPkg = require.resolve('@grafema/rfdb');
193
+ const rfdbDir = dirname(rfdbPkg);
194
+ const platformDir = getPlatformDir();
195
+ const npmBinary = join(rfdbDir, 'prebuilt', platformDir, 'rfdb-server');
196
+ if (existsSync(npmBinary)) {
197
+ return npmBinary;
198
+ }
199
+ } catch {
200
+ // @grafema/rfdb not installed
201
+ }
202
+ }
203
+
204
+ return null;
205
+ }
206
+
207
+ /**
208
+ * Find rfdb-server binary.
209
+ *
210
+ * @param options - Search options
211
+ * @returns Path to binary or null if not found
212
+ */
213
+ export function findRfdbBinary(options: FindBinaryOptions = {}): string | null {
214
+ return findBinary('rfdb-server', options);
215
+ }
216
+
217
+ /**
218
+ * Find grafema-orchestrator binary.
219
+ *
220
+ * @param options - Search options
221
+ * @returns Path to binary or null if not found
222
+ */
223
+ export function findOrchestratorBinary(options: FindBinaryOptions = {}): string | null {
224
+ return findBinary('grafema-orchestrator', options);
225
+ }
226
+
227
+ /**
228
+ * Find an analyzer binary by name (e.g. "grafema-analyzer", "haskell-resolve").
229
+ *
230
+ * Simpler search than findBinary() — no env var or platform package lookup.
231
+ * Search order: ~/.grafema/bin/, ~/.local/bin/, ~/.cabal/bin/, system PATH.
232
+ */
233
+ export function findAnalyzerBinary(binaryName: string): string | null {
234
+ const home = process.env.HOME || process.env.USERPROFILE || '';
235
+
236
+ // ~/.grafema/bin/ (lazy-downloaded)
237
+ if (home) {
238
+ const p = join(home, '.grafema', 'bin', binaryName);
239
+ if (existsSync(p)) return p;
240
+ }
241
+
242
+ // ~/.local/bin/
243
+ if (home) {
244
+ const p = join(home, '.local', 'bin', binaryName);
245
+ if (existsSync(p)) return p;
246
+ }
247
+
248
+ // ~/.cabal/bin/ (Haskell builds)
249
+ if (home) {
250
+ const p = join(home, '.cabal', 'bin', binaryName);
251
+ if (existsSync(p)) return p;
252
+ }
253
+
254
+ // System PATH
255
+ const pathDirs = (process.env.PATH || '').split(delimiter);
256
+ for (const dir of pathDirs) {
257
+ if (!dir) continue;
258
+ const p = join(dir, binaryName);
259
+ if (existsSync(p)) return p;
260
+ }
261
+
262
+ return null;
263
+ }
264
+
265
+ /**
266
+ * Get human-readable error message when binary not found.
267
+ */
268
+ export function getBinaryNotFoundMessage(binaryName?: BinaryName): string {
269
+ const name = binaryName || 'rfdb-server';
270
+ const config = BINARY_CONFIG[name];
271
+ const platformDir = getPlatformDir();
272
+
273
+ return `${name} binary not found for ${platformDir}
274
+
275
+ Options:
276
+ 1. Install the grafema package (includes all binaries):
277
+ npm install grafema
278
+
279
+ 2. Set environment variable:
280
+ export ${config.envVar}=/path/to/${name}
281
+
282
+ 3. Build from source:
283
+ cd packages/${config.monorepoPackage} && cargo build --release
284
+
285
+ 4. Install to system PATH or ~/.local/bin:
286
+ cp target/release/${name} ~/.local/bin/
287
+ `;
288
+ }
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Lazy binary downloader for Grafema.
3
+ *
4
+ * Downloads Haskell analyzer binaries from GitHub Releases on first use.
5
+ * Binaries are cached in ~/.grafema/bin/ and reused across projects.
6
+ *
7
+ * Asset naming convention: {binary-name}-{platform}
8
+ * Example: grafema-analyzer-darwin-arm64
9
+ */
10
+
11
+ import { existsSync, mkdirSync, chmodSync, renameSync, unlinkSync, createWriteStream } from 'fs';
12
+ import { join } from 'path';
13
+ import { get as httpsGet } from 'https';
14
+ import type { IncomingMessage } from 'http';
15
+ import { getPlatformDir } from './findRfdbBinary.js';
16
+
17
+ const GITHUB_REPO = 'Disentinel/grafema';
18
+
19
+ /** All analyzer binaries that can be lazy-downloaded. */
20
+ const DOWNLOADABLE_BINARIES = [
21
+ 'grafema-analyzer',
22
+ 'grafema-resolve',
23
+ 'haskell-analyzer',
24
+ 'haskell-resolve',
25
+ 'grafema-rust-analyzer',
26
+ 'grafema-rust-resolve',
27
+ 'grafema-java-analyzer',
28
+ 'java-resolve',
29
+ 'java-parser',
30
+ 'grafema-kotlin-analyzer',
31
+ 'kotlin-resolve',
32
+ 'kotlin-parser',
33
+ 'jvm-cross-resolve',
34
+ 'grafema-python-analyzer',
35
+ 'python-resolve',
36
+ 'grafema-go-analyzer',
37
+ 'go-resolve',
38
+ 'go-parser',
39
+ 'grafema-cpp-analyzer',
40
+ 'cpp-resolve',
41
+ ];
42
+
43
+ /**
44
+ * Get the directory where lazy-downloaded binaries are stored.
45
+ */
46
+ export function getGrafemaBinDir(): string {
47
+ const home = process.env.HOME || process.env.USERPROFILE || '';
48
+ return join(home, '.grafema', 'bin');
49
+ }
50
+
51
+ /**
52
+ * Check if a binary name is eligible for lazy download.
53
+ */
54
+ export function isDownloadable(binaryName: string): boolean {
55
+ return DOWNLOADABLE_BINARIES.includes(binaryName);
56
+ }
57
+
58
+ /**
59
+ * Find a binary in ~/.grafema/bin/.
60
+ */
61
+ export function findInGrafemaBin(binaryName: string): string | null {
62
+ const binDir = getGrafemaBinDir();
63
+ const p = join(binDir, binaryName);
64
+ return existsSync(p) ? p : null;
65
+ }
66
+
67
+ /**
68
+ * Simple HTTPS GET that follows redirects (GitHub uses 302 → S3).
69
+ */
70
+ function httpsGetFollowRedirects(url: string): Promise<IncomingMessage> {
71
+ return new Promise((resolve, reject) => {
72
+ const req = httpsGet(url, { headers: { 'User-Agent': 'grafema-cli' } }, (res) => {
73
+ if (res.statusCode === 301 || res.statusCode === 302) {
74
+ const location = res.headers.location;
75
+ if (!location) return reject(new Error('Redirect without location'));
76
+ httpsGetFollowRedirects(location).then(resolve, reject);
77
+ return;
78
+ }
79
+ resolve(res);
80
+ });
81
+ req.on('error', reject);
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Find the latest binaries-v* release tag from GitHub API.
87
+ */
88
+ async function findLatestReleaseTag(): Promise<string> {
89
+ const url = `https://api.github.com/repos/${GITHUB_REPO}/releases?per_page=30`;
90
+ const res = await httpsGetFollowRedirects(url);
91
+
92
+ const chunks: Buffer[] = [];
93
+ for await (const chunk of res) {
94
+ chunks.push(chunk as Buffer);
95
+ }
96
+ const body = Buffer.concat(chunks).toString('utf-8');
97
+
98
+ if (res.statusCode !== 200) {
99
+ throw new Error(`GitHub API returned ${res.statusCode}: ${body.slice(0, 200)}`);
100
+ }
101
+
102
+ const releases = JSON.parse(body) as Array<{ tag_name: string }>;
103
+ const binRelease = releases.find(r => r.tag_name.startsWith('binaries-v'));
104
+ if (!binRelease) {
105
+ throw new Error('No binaries-v* release found on GitHub');
106
+ }
107
+ return binRelease.tag_name;
108
+ }
109
+
110
+ /**
111
+ * Download a single binary from a GitHub Release.
112
+ *
113
+ * @param binaryName - e.g. "grafema-analyzer"
114
+ * @param tag - e.g. "binaries-v0.3.0-beta"
115
+ * @param onProgress - optional callback for download progress
116
+ * @returns Path to the downloaded binary
117
+ */
118
+ export async function downloadBinary(
119
+ binaryName: string,
120
+ tag?: string,
121
+ onProgress?: (msg: string) => void,
122
+ ): Promise<string> {
123
+ const platform = getPlatformDir();
124
+ const assetName = `${binaryName}-${platform}`;
125
+ const binDir = getGrafemaBinDir();
126
+
127
+ // Ensure ~/.grafema/bin/ exists
128
+ if (!existsSync(binDir)) {
129
+ mkdirSync(binDir, { recursive: true });
130
+ }
131
+
132
+ const targetPath = join(binDir, binaryName);
133
+ const tmpPath = `${targetPath}.downloading`;
134
+
135
+ // Resolve tag
136
+ const releaseTag = tag || await findLatestReleaseTag();
137
+ const downloadUrl = `https://github.com/${GITHUB_REPO}/releases/download/${releaseTag}/${assetName}`;
138
+
139
+ const log = onProgress || (() => {});
140
+ log(`Downloading ${binaryName} for ${platform}...`);
141
+
142
+ // Download to temp file
143
+ const res = await httpsGetFollowRedirects(downloadUrl);
144
+
145
+ if (res.statusCode !== 200) {
146
+ throw new Error(
147
+ `Failed to download ${assetName}: HTTP ${res.statusCode}. ` +
148
+ `Check that release ${releaseTag} has asset ${assetName}.`
149
+ );
150
+ }
151
+
152
+ const contentLength = parseInt(res.headers['content-length'] || '0', 10);
153
+ const sizeMB = contentLength > 0 ? `${(contentLength / 1024 / 1024).toFixed(1)}MB` : 'unknown size';
154
+ log(` ${assetName} (${sizeMB})`);
155
+
156
+ await new Promise<void>((resolve, reject) => {
157
+ const file = createWriteStream(tmpPath);
158
+ res.pipe(file);
159
+ file.on('finish', () => { file.close(); resolve(); });
160
+ file.on('error', (err) => { unlinkSync(tmpPath); reject(err); });
161
+ res.on('error', (err) => { unlinkSync(tmpPath); reject(err); });
162
+ });
163
+
164
+ // Atomic rename + make executable
165
+ renameSync(tmpPath, targetPath);
166
+ chmodSync(targetPath, 0o755);
167
+
168
+ log(` Installed to ${targetPath}`);
169
+ return targetPath;
170
+ }
171
+
172
+ /**
173
+ * Ensure a binary exists, downloading it if missing and eligible.
174
+ *
175
+ * This is the main entry point for lazy downloading. Call it before
176
+ * spawning an analyzer binary. Returns the path if found or downloaded,
177
+ * null if the binary can't be obtained.
178
+ *
179
+ * @param binaryName - e.g. "grafema-analyzer"
180
+ * @param existingPath - path from findBinary() (null = not found locally)
181
+ * @param onProgress - optional callback for download progress
182
+ */
183
+ export async function ensureBinary(
184
+ binaryName: string,
185
+ existingPath: string | null,
186
+ onProgress?: (msg: string) => void,
187
+ ): Promise<string | null> {
188
+ // Already found locally
189
+ if (existingPath) return existingPath;
190
+
191
+ // Check ~/.grafema/bin/ first (may have been downloaded previously)
192
+ const cached = findInGrafemaBin(binaryName);
193
+ if (cached) return cached;
194
+
195
+ // Not downloadable (e.g. rfdb-server, grafema-orchestrator — these must be in npm package)
196
+ if (!isDownloadable(binaryName)) return null;
197
+
198
+ // Download
199
+ try {
200
+ return await downloadBinary(binaryName, undefined, onProgress);
201
+ } catch (err) {
202
+ const msg = err instanceof Error ? err.message : String(err);
203
+ (onProgress || console.error)(`Failed to download ${binaryName}: ${msg}`);
204
+ return null;
205
+ }
206
+ }