@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,405 @@
1
+ /**
2
+ * VersionManager - управление версиями нод для incremental analysis
3
+ *
4
+ * КОНЦЕПЦИЯ:
5
+ * - Храним несколько версий кода одновременно (main, __local, branch names)
6
+ * - Используем stable IDs для сравнения версий
7
+ * - Поддерживаем fine-grained merge (только изменённые ноды)
8
+ *
9
+ * ВЕРСИИ:
10
+ * - "main" - committed код из git HEAD
11
+ * - "__local" - uncommitted изменения (working directory)
12
+ * - "branch-name" - другие ветки (будущее)
13
+ */
14
+
15
+ import { createHash } from 'crypto';
16
+
17
+ /**
18
+ * Version constants
19
+ */
20
+ export interface VersionConstants {
21
+ MAIN: 'main';
22
+ LOCAL: '__local';
23
+ }
24
+
25
+ /**
26
+ * Node types for stable ID generation
27
+ */
28
+ export type StableIdNodeType =
29
+ | 'FUNCTION'
30
+ | 'CLASS'
31
+ | 'INTERFACE'
32
+ | 'TYPE_ALIAS'
33
+ | 'VARIABLE_DECLARATION'
34
+ | 'MODULE'
35
+ | 'SERVICE'
36
+ | 'CALL_SITE'
37
+ | 'SCOPE'
38
+ | 'EXPRESSION'
39
+ | 'STATEMENT'
40
+ | 'DATABASE_QUERY'
41
+ | 'HTTP_REQUEST'
42
+ | 'FILESYSTEM'
43
+ | 'NETWORK'
44
+ | 'ENDPOINT';
45
+
46
+ /**
47
+ * Node for stable ID generation
48
+ */
49
+ export interface VersionedNode {
50
+ type: string;
51
+ name?: string;
52
+ file?: string;
53
+ line?: number;
54
+ column?: number;
55
+ // Content fields for external nodes
56
+ query?: string;
57
+ url?: string;
58
+ path?: string;
59
+ endpoint?: string;
60
+ // Additional fields for structural comparison
61
+ params?: unknown[];
62
+ returnType?: string;
63
+ async?: boolean;
64
+ exported?: boolean;
65
+ bodyHash?: string;
66
+ methods?: unknown[];
67
+ properties?: unknown[];
68
+ extends?: string;
69
+ implements?: string[];
70
+ kind?: string;
71
+ value?: unknown;
72
+ contentHash?: string;
73
+ imports?: unknown[];
74
+ exports?: unknown[];
75
+ arguments?: unknown[];
76
+ callee?: string;
77
+ operation?: string;
78
+ collection?: string;
79
+ method?: string;
80
+ handler?: string;
81
+ // Version-aware fields
82
+ id?: string;
83
+ version?: string;
84
+ _stableId?: string;
85
+ _replaces?: string;
86
+ updatedAt?: number;
87
+ }
88
+
89
+ /**
90
+ * REPLACES edge structure
91
+ */
92
+ export interface ReplacesEdge {
93
+ type: 'REPLACES';
94
+ fromId: string;
95
+ toId: string;
96
+ version: string;
97
+ }
98
+
99
+ /**
100
+ * Enrichment options
101
+ */
102
+ export interface EnrichOptions {
103
+ replacesId?: string;
104
+ }
105
+
106
+ /**
107
+ * Modified node info
108
+ */
109
+ export interface ModifiedNodeInfo {
110
+ old: VersionedNode;
111
+ new: VersionedNode;
112
+ stableId: string;
113
+ }
114
+
115
+ /**
116
+ * Changes summary
117
+ */
118
+ export interface ChangesSummary {
119
+ addedCount: number;
120
+ modifiedCount: number;
121
+ unchangedCount: number;
122
+ deletedCount: number;
123
+ totalChanges: number;
124
+ }
125
+
126
+ /**
127
+ * Classification result
128
+ */
129
+ export interface ClassifyChangesResult {
130
+ added: VersionedNode[];
131
+ modified: ModifiedNodeInfo[];
132
+ unchanged: VersionedNode[];
133
+ deleted: VersionedNode[];
134
+ summary: ChangesSummary;
135
+ }
136
+
137
+ /**
138
+ * Type-specific comparison keys
139
+ */
140
+ interface TypeSpecificKeys {
141
+ [nodeType: string]: string[];
142
+ }
143
+
144
+ export class VersionManager {
145
+ readonly versions: VersionConstants;
146
+
147
+ constructor() {
148
+ this.versions = {
149
+ MAIN: 'main',
150
+ LOCAL: '__local'
151
+ };
152
+ }
153
+
154
+ /**
155
+ * Генерировать stable ID для ноды (без версии)
156
+ *
157
+ * Stable ID остаётся одинаковым для одной и той же сущности
158
+ * в разных версиях кода
159
+ */
160
+ generateStableId(node: VersionedNode): string {
161
+ const { type, name, file, line, column } = node;
162
+
163
+ // Для FUNCTION, CLASS - используем type:name:file
164
+ if (['FUNCTION', 'CLASS', 'INTERFACE', 'TYPE_ALIAS'].includes(type)) {
165
+ return `${type}:${name}:${file}`;
166
+ }
167
+
168
+ // Для VARIABLE_DECLARATION - добавляем line для различения локальных переменных
169
+ if (type === 'VARIABLE_DECLARATION') {
170
+ return `${type}:${name}:${file}:${line || 0}`;
171
+ }
172
+
173
+ // Для MODULE - use semantic ID format with name (relative path)
174
+ if (type === 'MODULE') {
175
+ // name stores the relative path for MODULE nodes
176
+ return `${name}->global->MODULE->module`;
177
+ }
178
+
179
+ // Для SERVICE - используем имя или file
180
+ if (type === 'SERVICE') {
181
+ return `SERVICE:${name || file}`;
182
+ }
183
+
184
+ // Для вложенных нод (CALL_SITE, SCOPE, EXPRESSION) - используем file:line:column
185
+ if (['CALL_SITE', 'SCOPE', 'EXPRESSION', 'STATEMENT'].includes(type)) {
186
+ return `${type}:${file}:${line || 0}:${column || 0}`;
187
+ }
188
+
189
+ // Для EXTERNAL нод (DATABASE_QUERY, HTTP_REQUEST) - используем содержимое
190
+ if (['DATABASE_QUERY', 'HTTP_REQUEST', 'FILESYSTEM', 'NETWORK'].includes(type)) {
191
+ // Используем хеш содержимого для уникальности
192
+ const content = node.query || node.url || node.path || node.endpoint || '';
193
+ const hash = createHash('sha256').update(content).digest('hex').substring(0, 16);
194
+ return `${type}:${hash}`;
195
+ }
196
+
197
+ // По умолчанию - используем все доступные поля
198
+ const parts = [type, name, file, line, column].filter(p => p !== undefined && p !== null);
199
+ return parts.join(':');
200
+ }
201
+
202
+ /**
203
+ * Генерировать versioned ID для ноды
204
+ */
205
+ generateVersionedId(node: VersionedNode, version: string): string {
206
+ const stableId = this.generateStableId(node);
207
+ return `${stableId}:${version}`;
208
+ }
209
+
210
+ /**
211
+ * Извлечь stable ID из versioned ID
212
+ */
213
+ extractStableId(versionedId: string): string {
214
+ const lastColonIndex = versionedId.lastIndexOf(':');
215
+ return versionedId.substring(0, lastColonIndex);
216
+ }
217
+
218
+ /**
219
+ * Извлечь версию из versioned ID
220
+ */
221
+ extractVersion(versionedId: string): string {
222
+ const lastColonIndex = versionedId.lastIndexOf(':');
223
+ return versionedId.substring(lastColonIndex + 1);
224
+ }
225
+
226
+ /**
227
+ * Проверить, имеет ли нода структурные изменения
228
+ */
229
+ hasStructuralChanges(oldNode: VersionedNode, newNode: VersionedNode): boolean {
230
+ // Список ключевых полей для сравнения (зависит от типа ноды)
231
+ const keysToCompare = this._getComparisonKeys(oldNode.type);
232
+
233
+ for (const key of keysToCompare) {
234
+ const oldValue = (oldNode as unknown as Record<string, unknown>)[key];
235
+ const newValue = (newNode as unknown as Record<string, unknown>)[key];
236
+
237
+ // Глубокое сравнение для массивов и объектов
238
+ if (JSON.stringify(oldValue) !== JSON.stringify(newValue)) {
239
+ return true;
240
+ }
241
+ }
242
+
243
+ return false;
244
+ }
245
+
246
+ /**
247
+ * Получить ключи для сравнения в зависимости от типа ноды
248
+ */
249
+ private _getComparisonKeys(nodeType: string): string[] {
250
+ const commonKeys = ['name', 'line', 'column'];
251
+
252
+ const typeSpecificKeys: TypeSpecificKeys = {
253
+ FUNCTION: ['params', 'returnType', 'async', 'exported', 'bodyHash'],
254
+ CLASS: ['methods', 'properties', 'extends', 'implements', 'exported'],
255
+ VARIABLE_DECLARATION: ['kind', 'value', 'exported'],
256
+ MODULE: ['contentHash', 'imports', 'exports'],
257
+ CALL_SITE: ['arguments', 'callee'],
258
+ DATABASE_QUERY: ['query', 'operation', 'collection'],
259
+ HTTP_REQUEST: ['method', 'url', 'endpoint'],
260
+ ENDPOINT: ['path', 'method', 'handler']
261
+ };
262
+
263
+ return [...commonKeys, ...(typeSpecificKeys[nodeType] || [])];
264
+ }
265
+
266
+ /**
267
+ * Вычислить хеш тела функции для сравнения
268
+ */
269
+ calculateBodyHash(bodySource: string | null | undefined): string | null {
270
+ if (!bodySource) return null;
271
+
272
+ // Нормализуем код: убираем пробелы и комментарии для сравнения
273
+ const normalized = bodySource
274
+ .replace(/\/\*[\s\S]*?\*\//g, '') // Блочные комментарии
275
+ .replace(/\/\/.*/g, '') // Строчные комментарии
276
+ .replace(/\s+/g, ' ') // Множественные пробелы -> один пробел
277
+ .trim();
278
+
279
+ return createHash('sha256').update(normalized, 'utf-8').digest('hex');
280
+ }
281
+
282
+ /**
283
+ * Создать REPLACES ребро между версиями
284
+ */
285
+ createReplacesEdge(localNodeId: string, mainNodeId: string): ReplacesEdge {
286
+ return {
287
+ type: 'REPLACES',
288
+ fromId: localNodeId,
289
+ toId: mainNodeId,
290
+ version: '__local' // Edge тоже имеет версию
291
+ };
292
+ }
293
+
294
+ /**
295
+ * Дополнить ноду полями для version-aware анализа
296
+ */
297
+ enrichNodeWithVersion(
298
+ node: VersionedNode,
299
+ version: string,
300
+ options: EnrichOptions = {}
301
+ ): VersionedNode {
302
+ const stableId = this.generateStableId(node);
303
+ const versionedId = this.generateVersionedId(node, version);
304
+
305
+ const enriched: VersionedNode = {
306
+ ...node,
307
+ id: versionedId,
308
+ version: version,
309
+ _stableId: stableId
310
+ };
311
+
312
+ // Добавляем _replaces если это замена main версии
313
+ if (options.replacesId) {
314
+ enriched._replaces = options.replacesId;
315
+ }
316
+
317
+ // Добавляем timestamp
318
+ if (!enriched.updatedAt) {
319
+ enriched.updatedAt = Date.now();
320
+ }
321
+
322
+ return enriched;
323
+ }
324
+
325
+ /**
326
+ * Классифицировать изменения между версиями
327
+ */
328
+ classifyChanges(mainNodes: VersionedNode[], localNodes: VersionedNode[]): ClassifyChangesResult {
329
+ // Создаём Map по stable ID
330
+ const mainMap = new Map<string, VersionedNode>();
331
+ for (const node of mainNodes) {
332
+ const stableId = this.generateStableId(node);
333
+ mainMap.set(stableId, node);
334
+ }
335
+
336
+ const localMap = new Map<string, VersionedNode>();
337
+ for (const node of localNodes) {
338
+ const stableId = this.generateStableId(node);
339
+ localMap.set(stableId, node);
340
+ }
341
+
342
+ // Классификация
343
+ const added: VersionedNode[] = [];
344
+ const modified: ModifiedNodeInfo[] = [];
345
+ const unchanged: VersionedNode[] = [];
346
+ const deleted: VersionedNode[] = [];
347
+
348
+ // Проверяем локальные ноды
349
+ for (const [stableId, localNode] of localMap) {
350
+ if (!mainMap.has(stableId)) {
351
+ // Нода добавлена
352
+ added.push(localNode);
353
+ } else {
354
+ const mainNode = mainMap.get(stableId)!;
355
+ if (this.hasStructuralChanges(mainNode, localNode)) {
356
+ // Нода изменена
357
+ modified.push({ old: mainNode, new: localNode, stableId });
358
+ } else {
359
+ // Нода не изменилась
360
+ unchanged.push(localNode);
361
+ }
362
+ }
363
+ }
364
+
365
+ // Проверяем удалённые ноды (есть в main, нет в local)
366
+ for (const [stableId, mainNode] of mainMap) {
367
+ if (!localMap.has(stableId)) {
368
+ deleted.push(mainNode);
369
+ }
370
+ }
371
+
372
+ return {
373
+ added, // Новые ноды
374
+ modified, // Изменённые ноды
375
+ unchanged, // Неизменённые ноды
376
+ deleted, // Удалённые ноды
377
+ summary: {
378
+ addedCount: added.length,
379
+ modifiedCount: modified.length,
380
+ unchangedCount: unchanged.length,
381
+ deletedCount: deleted.length,
382
+ totalChanges: added.length + modified.length + deleted.length
383
+ }
384
+ };
385
+ }
386
+
387
+ /**
388
+ * Проверить, является ли версия локальной (uncommitted)
389
+ */
390
+ isLocalVersion(version: string): boolean {
391
+ return version === this.versions.LOCAL;
392
+ }
393
+
394
+ /**
395
+ * Проверить, является ли версия основной (committed)
396
+ */
397
+ isMainVersion(version: string): boolean {
398
+ return version === this.versions.MAIN;
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Singleton instance
404
+ */
405
+ export const versionManager = new VersionManager();
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Internal branding helper for legitimate uses outside NodeFactory.
3
+ * DO NOT import this in analyzers or plugins - use NodeFactory instead.
4
+ *
5
+ * Legitimate uses:
6
+ * - NodeFactory (centralized node creation)
7
+ * - GraphBuilder._flushNodes() - batches validated nodes from builders
8
+ * - RFDBServerBackend._parseNode() - re-brands nodes from database
9
+ *
10
+ * @internal
11
+ */
12
+ import type { BaseNodeRecord, BrandedNode } from '@grafema/types';
13
+
14
+ export function brandNodeInternal<T extends BaseNodeRecord>(node: T): BrandedNode<T> {
15
+ return node as BrandedNode<T>;
16
+ }
@@ -0,0 +1,162 @@
1
+ /**
2
+ * GuaranteeNode - contract for contract-based guarantee nodes
3
+ *
4
+ * Types: guarantee:queue, guarantee:api, guarantee:permission
5
+ * ID format: guarantee:queue#orders, guarantee:api#rate-limit
6
+ *
7
+ * Unlike Datalog-based GUARANTEE nodes (handled by GuaranteeManager),
8
+ * these nodes use JSON schema validation for contract verification.
9
+ */
10
+
11
+ import type { BaseNodeRecord } from '@grafema/types';
12
+ import { NAMESPACED_TYPE, isGuaranteeType } from './NodeKind.js';
13
+
14
+ // Re-export types from nodes.ts for convenience
15
+ export type GuaranteePriority = 'critical' | 'important' | 'observed' | 'tracked';
16
+ export type GuaranteeStatus = 'discovered' | 'reviewed' | 'active' | 'changing' | 'deprecated';
17
+ export type GuaranteeType = 'guarantee:queue' | 'guarantee:api' | 'guarantee:permission';
18
+
19
+ export interface GuaranteeNodeRecord extends BaseNodeRecord {
20
+ type: GuaranteeType;
21
+ priority: GuaranteePriority;
22
+ status: GuaranteeStatus;
23
+ owner?: string;
24
+ schema?: Record<string, unknown>;
25
+ condition?: string;
26
+ description?: string;
27
+ createdAt?: number;
28
+ updatedAt?: number;
29
+ }
30
+
31
+ export interface GuaranteeNodeOptions {
32
+ priority?: GuaranteePriority;
33
+ status?: GuaranteeStatus;
34
+ owner?: string;
35
+ schema?: Record<string, unknown>;
36
+ condition?: string;
37
+ description?: string;
38
+ }
39
+
40
+ // Valid guarantee namespaces
41
+ const GUARANTEE_NAMESPACES = ['queue', 'api', 'permission'] as const;
42
+ type GuaranteeNamespace = typeof GUARANTEE_NAMESPACES[number];
43
+
44
+ export class GuaranteeNode {
45
+ static readonly TYPE_QUEUE = NAMESPACED_TYPE.GUARANTEE_QUEUE;
46
+ static readonly TYPE_API = NAMESPACED_TYPE.GUARANTEE_API;
47
+ static readonly TYPE_PERMISSION = NAMESPACED_TYPE.GUARANTEE_PERMISSION;
48
+
49
+ static readonly REQUIRED = ['name', 'file', 'priority', 'status'] as const;
50
+ static readonly OPTIONAL = ['owner', 'schema', 'condition', 'description', 'createdAt', 'updatedAt'] as const;
51
+
52
+ /**
53
+ * Create guarantee node
54
+ * @param namespace - guarantee namespace (queue, api, permission)
55
+ * @param name - guarantee name (e.g., 'orders', 'rate-limit')
56
+ * @param options - optional fields
57
+ */
58
+ static create(
59
+ namespace: GuaranteeNamespace,
60
+ name: string,
61
+ options: GuaranteeNodeOptions = {}
62
+ ): GuaranteeNodeRecord {
63
+ if (!namespace) throw new Error('GuaranteeNode.create: namespace is required');
64
+ if (!name) throw new Error('GuaranteeNode.create: name is required');
65
+ if (!GUARANTEE_NAMESPACES.includes(namespace)) {
66
+ throw new Error(`GuaranteeNode.create: invalid namespace "${namespace}". Valid: ${GUARANTEE_NAMESPACES.join(', ')}`);
67
+ }
68
+
69
+ const type = `guarantee:${namespace}` as GuaranteeType;
70
+ const id = `${type}#${name}`;
71
+ const now = Date.now();
72
+
73
+ return {
74
+ id,
75
+ type,
76
+ name,
77
+ file: '', // Guarantees don't have a source file
78
+ line: undefined,
79
+ priority: options.priority || 'observed',
80
+ status: options.status || 'discovered',
81
+ owner: options.owner,
82
+ schema: options.schema,
83
+ condition: options.condition,
84
+ description: options.description,
85
+ createdAt: now,
86
+ updatedAt: now,
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Validate guarantee node
92
+ * @returns array of error messages, empty if valid
93
+ */
94
+ static validate(node: GuaranteeNodeRecord): string[] {
95
+ const errors: string[] = [];
96
+
97
+ if (!isGuaranteeType(node.type)) {
98
+ errors.push(`Expected guarantee:* type, got ${node.type}`);
99
+ }
100
+
101
+ if (!node.name) {
102
+ errors.push('Missing required field: name');
103
+ }
104
+
105
+ if (!node.priority) {
106
+ errors.push('Missing required field: priority');
107
+ } else if (!['critical', 'important', 'observed', 'tracked'].includes(node.priority)) {
108
+ errors.push(`Invalid priority: ${node.priority}. Valid: critical, important, observed, tracked`);
109
+ }
110
+
111
+ if (!node.status) {
112
+ errors.push('Missing required field: status');
113
+ } else if (!['discovered', 'reviewed', 'active', 'changing', 'deprecated'].includes(node.status)) {
114
+ errors.push(`Invalid status: ${node.status}. Valid: discovered, reviewed, active, changing, deprecated`);
115
+ }
116
+
117
+ return errors;
118
+ }
119
+
120
+ /**
121
+ * Parse guarantee ID into components
122
+ * @param id - full ID (e.g., 'guarantee:queue#orders')
123
+ * @returns { namespace, name } or null if invalid
124
+ */
125
+ static parseId(id: string): { namespace: GuaranteeNamespace; name: string } | null {
126
+ if (!id) return null;
127
+
128
+ // Format: guarantee:namespace#name
129
+ const match = id.match(/^guarantee:(queue|api|permission)#(.+)$/);
130
+ if (!match) return null;
131
+
132
+ return {
133
+ namespace: match[1] as GuaranteeNamespace,
134
+ name: match[2],
135
+ };
136
+ }
137
+
138
+ /**
139
+ * Build ID from components
140
+ */
141
+ static buildId(namespace: GuaranteeNamespace, name: string): string {
142
+ return `guarantee:${namespace}#${name}`;
143
+ }
144
+
145
+ /**
146
+ * Check if node type is a guarantee type
147
+ */
148
+ static isGuaranteeType(type: string): boolean {
149
+ return isGuaranteeType(type);
150
+ }
151
+
152
+ /**
153
+ * Get all valid guarantee types
154
+ */
155
+ static getTypes(): GuaranteeType[] {
156
+ return [
157
+ NAMESPACED_TYPE.GUARANTEE_QUEUE,
158
+ NAMESPACED_TYPE.GUARANTEE_API,
159
+ NAMESPACED_TYPE.GUARANTEE_PERMISSION,
160
+ ];
161
+ }
162
+ }