gitnexus 1.5.2 → 1.6.0

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 (207) hide show
  1. package/README.md +10 -0
  2. package/dist/_shared/graph/types.d.ts +1 -1
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +1 -0
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/language-detection.d.ts.map +1 -1
  7. package/dist/_shared/language-detection.js +2 -0
  8. package/dist/_shared/language-detection.js.map +1 -1
  9. package/dist/_shared/languages.d.ts +1 -0
  10. package/dist/_shared/languages.d.ts.map +1 -1
  11. package/dist/_shared/languages.js +1 -0
  12. package/dist/_shared/languages.js.map +1 -1
  13. package/dist/_shared/lbug/schema-constants.d.ts +1 -1
  14. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  15. package/dist/_shared/lbug/schema-constants.js +3 -1
  16. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  17. package/dist/_shared/mro-strategy.d.ts +19 -0
  18. package/dist/_shared/mro-strategy.d.ts.map +1 -0
  19. package/dist/_shared/mro-strategy.js +2 -0
  20. package/dist/_shared/mro-strategy.js.map +1 -0
  21. package/dist/cli/ai-context.d.ts +1 -0
  22. package/dist/cli/ai-context.js +28 -4
  23. package/dist/cli/analyze.d.ts +2 -0
  24. package/dist/cli/analyze.js +2 -1
  25. package/dist/cli/group.d.ts +2 -0
  26. package/dist/cli/group.js +233 -0
  27. package/dist/cli/index.js +3 -0
  28. package/dist/cli/serve.js +4 -1
  29. package/dist/cli/setup.js +34 -3
  30. package/dist/cli/wiki.js +15 -44
  31. package/dist/config/ignore-service.js +8 -3
  32. package/dist/core/augmentation/engine.js +1 -1
  33. package/dist/core/git-staleness.d.ts +13 -0
  34. package/dist/core/git-staleness.js +29 -0
  35. package/dist/core/group/bridge-db.d.ts +82 -0
  36. package/dist/core/group/bridge-db.js +460 -0
  37. package/dist/core/group/bridge-schema.d.ts +27 -0
  38. package/dist/core/group/bridge-schema.js +55 -0
  39. package/dist/core/group/config-parser.d.ts +3 -0
  40. package/dist/core/group/config-parser.js +83 -0
  41. package/dist/core/group/contract-extractor.d.ts +7 -0
  42. package/dist/core/group/contract-extractor.js +1 -0
  43. package/dist/core/group/extractors/grpc-extractor.d.ts +16 -0
  44. package/dist/core/group/extractors/grpc-extractor.js +264 -0
  45. package/dist/core/group/extractors/http-route-extractor.d.ts +24 -0
  46. package/dist/core/group/extractors/http-route-extractor.js +428 -0
  47. package/dist/core/group/extractors/topic-extractor.d.ts +9 -0
  48. package/dist/core/group/extractors/topic-extractor.js +234 -0
  49. package/dist/core/group/matching.d.ts +13 -0
  50. package/dist/core/group/matching.js +198 -0
  51. package/dist/core/group/normalization.d.ts +3 -0
  52. package/dist/core/group/normalization.js +115 -0
  53. package/dist/core/group/service-boundary-detector.d.ts +8 -0
  54. package/dist/core/group/service-boundary-detector.js +155 -0
  55. package/dist/core/group/service.d.ts +46 -0
  56. package/dist/core/group/service.js +160 -0
  57. package/dist/core/group/storage.d.ts +9 -0
  58. package/dist/core/group/storage.js +91 -0
  59. package/dist/core/group/sync.d.ts +21 -0
  60. package/dist/core/group/sync.js +148 -0
  61. package/dist/core/group/types.d.ts +130 -0
  62. package/dist/core/group/types.js +1 -0
  63. package/dist/core/ingestion/binding-accumulator.d.ts +207 -0
  64. package/dist/core/ingestion/binding-accumulator.js +332 -0
  65. package/dist/core/ingestion/call-processor.d.ts +155 -24
  66. package/dist/core/ingestion/call-processor.js +1129 -247
  67. package/dist/core/ingestion/class-extractors/generic.d.ts +2 -0
  68. package/dist/core/ingestion/class-extractors/generic.js +135 -0
  69. package/dist/core/ingestion/class-types.d.ts +34 -0
  70. package/dist/core/ingestion/class-types.js +1 -0
  71. package/dist/core/ingestion/entry-point-scoring.d.ts +1 -0
  72. package/dist/core/ingestion/entry-point-scoring.js +1 -0
  73. package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +5 -1
  74. package/dist/core/ingestion/field-extractors/configs/helpers.js +13 -3
  75. package/dist/core/ingestion/field-types.d.ts +2 -2
  76. package/dist/core/ingestion/filesystem-walker.js +8 -0
  77. package/dist/core/ingestion/framework-detection.d.ts +1 -0
  78. package/dist/core/ingestion/framework-detection.js +1 -0
  79. package/dist/core/ingestion/heritage-processor.d.ts +8 -15
  80. package/dist/core/ingestion/heritage-processor.js +15 -28
  81. package/dist/core/ingestion/import-processor.d.ts +1 -11
  82. package/dist/core/ingestion/import-processor.js +0 -12
  83. package/dist/core/ingestion/import-resolvers/utils.js +1 -0
  84. package/dist/core/ingestion/import-resolvers/vue.d.ts +8 -0
  85. package/dist/core/ingestion/import-resolvers/vue.js +9 -0
  86. package/dist/core/ingestion/language-provider.d.ts +6 -3
  87. package/dist/core/ingestion/languages/c-cpp.js +168 -1
  88. package/dist/core/ingestion/languages/csharp.js +20 -0
  89. package/dist/core/ingestion/languages/dart.js +26 -4
  90. package/dist/core/ingestion/languages/go.js +22 -0
  91. package/dist/core/ingestion/languages/index.d.ts +1 -0
  92. package/dist/core/ingestion/languages/index.js +2 -0
  93. package/dist/core/ingestion/languages/java.js +17 -0
  94. package/dist/core/ingestion/languages/kotlin.js +24 -1
  95. package/dist/core/ingestion/languages/php.js +23 -11
  96. package/dist/core/ingestion/languages/python.js +9 -0
  97. package/dist/core/ingestion/languages/ruby.js +28 -0
  98. package/dist/core/ingestion/languages/rust.js +38 -0
  99. package/dist/core/ingestion/languages/swift.js +31 -0
  100. package/dist/core/ingestion/languages/typescript.d.ts +1 -0
  101. package/dist/core/ingestion/languages/typescript.js +54 -1
  102. package/dist/core/ingestion/languages/vue.d.ts +13 -0
  103. package/dist/core/ingestion/languages/vue.js +81 -0
  104. package/dist/core/ingestion/method-extractors/configs/c-cpp.d.ts +3 -0
  105. package/dist/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
  106. package/dist/core/ingestion/method-extractors/configs/csharp.js +5 -1
  107. package/dist/core/ingestion/method-extractors/configs/dart.d.ts +2 -0
  108. package/dist/core/ingestion/method-extractors/configs/dart.js +376 -0
  109. package/dist/core/ingestion/method-extractors/configs/go.d.ts +2 -0
  110. package/dist/core/ingestion/method-extractors/configs/go.js +176 -0
  111. package/dist/core/ingestion/method-extractors/configs/jvm.js +13 -4
  112. package/dist/core/ingestion/method-extractors/configs/php.d.ts +2 -0
  113. package/dist/core/ingestion/method-extractors/configs/php.js +304 -0
  114. package/dist/core/ingestion/method-extractors/configs/python.d.ts +2 -0
  115. package/dist/core/ingestion/method-extractors/configs/python.js +309 -0
  116. package/dist/core/ingestion/method-extractors/configs/ruby.d.ts +2 -0
  117. package/dist/core/ingestion/method-extractors/configs/ruby.js +285 -0
  118. package/dist/core/ingestion/method-extractors/configs/rust.d.ts +2 -0
  119. package/dist/core/ingestion/method-extractors/configs/rust.js +195 -0
  120. package/dist/core/ingestion/method-extractors/configs/swift.d.ts +2 -0
  121. package/dist/core/ingestion/method-extractors/configs/swift.js +277 -0
  122. package/dist/core/ingestion/method-extractors/configs/typescript-javascript.d.ts +3 -0
  123. package/dist/core/ingestion/method-extractors/configs/typescript-javascript.js +338 -0
  124. package/dist/core/ingestion/method-extractors/generic.js +38 -15
  125. package/dist/core/ingestion/method-types.d.ts +25 -0
  126. package/dist/core/ingestion/model/field-registry.d.ts +18 -0
  127. package/dist/core/ingestion/model/field-registry.js +22 -0
  128. package/dist/core/ingestion/model/heritage-map.d.ts +70 -0
  129. package/dist/core/ingestion/model/heritage-map.js +159 -0
  130. package/dist/core/ingestion/model/index.d.ts +20 -0
  131. package/dist/core/ingestion/model/index.js +41 -0
  132. package/dist/core/ingestion/model/method-registry.d.ts +62 -0
  133. package/dist/core/ingestion/model/method-registry.js +130 -0
  134. package/dist/core/ingestion/model/registration-table.d.ts +139 -0
  135. package/dist/core/ingestion/model/registration-table.js +224 -0
  136. package/dist/core/ingestion/model/resolution-context.d.ts +93 -0
  137. package/dist/core/ingestion/model/resolution-context.js +337 -0
  138. package/dist/core/ingestion/model/resolve.d.ts +56 -0
  139. package/dist/core/ingestion/model/resolve.js +242 -0
  140. package/dist/core/ingestion/model/semantic-model.d.ts +86 -0
  141. package/dist/core/ingestion/model/semantic-model.js +120 -0
  142. package/dist/core/ingestion/model/symbol-table.d.ts +222 -0
  143. package/dist/core/ingestion/model/symbol-table.js +206 -0
  144. package/dist/core/ingestion/model/type-registry.d.ts +39 -0
  145. package/dist/core/ingestion/model/type-registry.js +62 -0
  146. package/dist/core/ingestion/mro-processor.d.ts +4 -3
  147. package/dist/core/ingestion/mro-processor.js +310 -106
  148. package/dist/core/ingestion/parsing-processor.d.ts +5 -4
  149. package/dist/core/ingestion/parsing-processor.js +210 -85
  150. package/dist/core/ingestion/pipeline.d.ts +2 -0
  151. package/dist/core/ingestion/pipeline.js +192 -68
  152. package/dist/core/ingestion/tree-sitter-queries.d.ts +6 -6
  153. package/dist/core/ingestion/tree-sitter-queries.js +37 -0
  154. package/dist/core/ingestion/type-env.d.ts +15 -2
  155. package/dist/core/ingestion/type-env.js +163 -102
  156. package/dist/core/ingestion/type-extractors/csharp.js +17 -0
  157. package/dist/core/ingestion/type-extractors/jvm.js +11 -0
  158. package/dist/core/ingestion/type-extractors/php.js +0 -55
  159. package/dist/core/ingestion/type-extractors/ruby.js +0 -32
  160. package/dist/core/ingestion/type-extractors/swift.js +13 -0
  161. package/dist/core/ingestion/type-extractors/types.d.ts +8 -8
  162. package/dist/core/ingestion/type-extractors/typescript.js +66 -69
  163. package/dist/core/ingestion/utils/ast-helpers.d.ts +33 -43
  164. package/dist/core/ingestion/utils/ast-helpers.js +129 -565
  165. package/dist/core/ingestion/utils/method-props.d.ts +32 -0
  166. package/dist/core/ingestion/utils/method-props.js +147 -0
  167. package/dist/core/ingestion/vue-sfc-extractor.d.ts +44 -0
  168. package/dist/core/ingestion/vue-sfc-extractor.js +94 -0
  169. package/dist/core/ingestion/workers/parse-worker.d.ts +31 -19
  170. package/dist/core/ingestion/workers/parse-worker.js +463 -198
  171. package/dist/core/lbug/lbug-adapter.d.ts +6 -0
  172. package/dist/core/lbug/lbug-adapter.js +68 -3
  173. package/dist/core/lbug/pool-adapter.d.ts +76 -0
  174. package/dist/core/lbug/pool-adapter.js +522 -0
  175. package/dist/core/run-analyze.d.ts +2 -0
  176. package/dist/core/run-analyze.js +1 -1
  177. package/dist/core/search/bm25-index.js +1 -1
  178. package/dist/core/tree-sitter/parser-loader.js +1 -0
  179. package/dist/core/wiki/graph-queries.js +1 -1
  180. package/dist/core/wiki/html-viewer.js +6 -4
  181. package/dist/core/wiki/llm-client.js +4 -6
  182. package/dist/mcp/core/embedder.js +6 -5
  183. package/dist/mcp/core/lbug-adapter.d.ts +3 -63
  184. package/dist/mcp/core/lbug-adapter.js +3 -484
  185. package/dist/mcp/local/local-backend.d.ts +31 -2
  186. package/dist/mcp/local/local-backend.js +255 -46
  187. package/dist/mcp/resources.js +5 -4
  188. package/dist/mcp/staleness.d.ts +3 -13
  189. package/dist/mcp/staleness.js +2 -31
  190. package/dist/mcp/tools.js +80 -4
  191. package/dist/server/analyze-job.d.ts +2 -0
  192. package/dist/server/analyze-job.js +4 -0
  193. package/dist/server/api.d.ts +20 -1
  194. package/dist/server/api.js +306 -71
  195. package/dist/server/git-clone.d.ts +2 -1
  196. package/dist/server/git-clone.js +98 -5
  197. package/dist/storage/git.d.ts +13 -0
  198. package/dist/storage/git.js +25 -0
  199. package/dist/storage/repo-manager.js +1 -1
  200. package/package.json +8 -2
  201. package/scripts/patch-tree-sitter-swift.cjs +78 -0
  202. package/dist/core/ingestion/named-binding-processor.d.ts +0 -18
  203. package/dist/core/ingestion/named-binding-processor.js +0 -42
  204. package/dist/core/ingestion/resolution-context.d.ts +0 -58
  205. package/dist/core/ingestion/resolution-context.js +0 -135
  206. package/dist/core/ingestion/symbol-table.d.ts +0 -79
  207. package/dist/core/ingestion/symbol-table.js +0 -115
@@ -0,0 +1,264 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { glob } from 'glob';
4
+ function readSafe(repoPath, rel) {
5
+ const abs = path.resolve(repoPath, rel);
6
+ const base = path.resolve(repoPath);
7
+ const relToBase = path.relative(base, abs);
8
+ if (relToBase.startsWith('..') || path.isAbsolute(relToBase))
9
+ return null;
10
+ try {
11
+ return fs.readFileSync(abs, 'utf-8');
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ function contractId(pkg, service, method) {
18
+ const prefix = pkg ? `${pkg}.${service}` : service;
19
+ return `grpc::${prefix}/${method}`;
20
+ }
21
+ function serviceOnlyContractId(serviceName) {
22
+ return `grpc::${serviceName}/*`;
23
+ }
24
+ function extractServiceBlocks(content) {
25
+ const results = [];
26
+ // v1: brace-depth only — braces inside comments or string literals are not filtered (see spec Fix 2)
27
+ const headerRe = /service\s+(\w+)\s*\{/g;
28
+ let headerMatch;
29
+ while ((headerMatch = headerRe.exec(content)) !== null) {
30
+ const serviceName = headerMatch[1];
31
+ const bodyStart = headerMatch.index + headerMatch[0].length;
32
+ let depth = 1;
33
+ let pos = bodyStart;
34
+ while (pos < content.length && depth > 0) {
35
+ const ch = content[pos];
36
+ if (ch === '{')
37
+ depth++;
38
+ else if (ch === '}')
39
+ depth--;
40
+ pos++;
41
+ }
42
+ // If EOF before depth returns to 0, skip incomplete service
43
+ if (depth !== 0)
44
+ continue;
45
+ // body is between opening { (consumed by regex) and closing } (pos is one past it)
46
+ const body = content.slice(bodyStart, pos - 1);
47
+ results.push({ name: serviceName, body });
48
+ }
49
+ return results;
50
+ }
51
+ function makeContract(cid, role, filePath, symbolName, confidence, meta) {
52
+ return {
53
+ contractId: cid,
54
+ type: 'grpc',
55
+ role,
56
+ symbolUid: '',
57
+ symbolRef: { filePath: filePath.replace(/\\/g, '/'), name: symbolName },
58
+ symbolName,
59
+ confidence,
60
+ meta: { ...meta, extractionStrategy: 'source_scan' },
61
+ };
62
+ }
63
+ export class GrpcExtractor {
64
+ type = 'grpc';
65
+ async canExtract(_repo) {
66
+ return true;
67
+ }
68
+ async extract(_dbExecutor, repoPath, _repo) {
69
+ const out = [];
70
+ // Proto files — definitive provider source
71
+ const protoFiles = await glob('**/*.proto', {
72
+ cwd: repoPath,
73
+ ignore: ['**/node_modules/**', '**/.git/**', '**/vendor/**'],
74
+ nodir: true,
75
+ });
76
+ for (const rel of protoFiles) {
77
+ const content = readSafe(repoPath, rel);
78
+ if (content)
79
+ out.push(...this.parseProtoFile(content, rel));
80
+ }
81
+ // Source files — server/client detection
82
+ const sourceFiles = await glob('**/*.{go,java,py,ts,tsx,js,jsx}', {
83
+ cwd: repoPath,
84
+ ignore: ['**/node_modules/**', '**/.git/**', '**/vendor/**', '**/dist/**', '**/build/**'],
85
+ nodir: true,
86
+ });
87
+ for (const rel of sourceFiles) {
88
+ const content = readSafe(repoPath, rel);
89
+ if (!content)
90
+ continue;
91
+ const ext = path.extname(rel).toLowerCase();
92
+ if (ext === '.go') {
93
+ out.push(...this.scanGoProviders(content, rel));
94
+ out.push(...this.scanGoConsumers(content, rel));
95
+ }
96
+ else if (ext === '.java') {
97
+ out.push(...this.scanJavaProviders(content, rel));
98
+ out.push(...this.scanJavaConsumers(content, rel));
99
+ }
100
+ else if (ext === '.py') {
101
+ out.push(...this.scanPythonProviders(content, rel));
102
+ out.push(...this.scanPythonConsumers(content, rel));
103
+ }
104
+ else if (['.ts', '.tsx', '.js', '.jsx'].includes(ext)) {
105
+ out.push(...this.scanTsProviders(content, rel));
106
+ }
107
+ }
108
+ return this.dedupe(out);
109
+ }
110
+ parseProtoFile(content, filePath) {
111
+ const out = [];
112
+ const pkgMatch = content.match(/^package\s+([\w.]+)\s*;/m);
113
+ const pkg = pkgMatch ? pkgMatch[1] : '';
114
+ for (const { name: serviceName, body } of extractServiceBlocks(content)) {
115
+ const rpcRe = /rpc\s+(\w+)\s*\(/g;
116
+ let rpcMatch;
117
+ while ((rpcMatch = rpcRe.exec(body)) !== null) {
118
+ const methodName = rpcMatch[1];
119
+ const cid = contractId(pkg, serviceName, methodName);
120
+ out.push(makeContract(cid, 'provider', filePath, `${serviceName}.${methodName}`, 0.85, {
121
+ package: pkg,
122
+ service: serviceName,
123
+ method: methodName,
124
+ source: 'proto',
125
+ }));
126
+ }
127
+ }
128
+ return out;
129
+ }
130
+ scanGoProviders(content, filePath) {
131
+ const out = [];
132
+ // pb.RegisterXxxServer(
133
+ const registerRe = /\w+\.Register(\w+)Server\s*\(/g;
134
+ let m;
135
+ while ((m = registerRe.exec(content)) !== null) {
136
+ const serviceName = m[1];
137
+ out.push(makeContract(serviceOnlyContractId(serviceName), 'provider', filePath, `Register${serviceName}Server`, 0.8, { service: serviceName, source: 'go_register' }));
138
+ }
139
+ // pb.UnimplementedXxxServer
140
+ const unimplRe = /\w+\.Unimplemented(\w+)Server\b/g;
141
+ while ((m = unimplRe.exec(content)) !== null) {
142
+ const serviceName = m[1];
143
+ out.push(makeContract(serviceOnlyContractId(serviceName), 'provider', filePath, `Unimplemented${serviceName}Server`, 0.8, { service: serviceName, source: 'go_unimplemented' }));
144
+ }
145
+ return out;
146
+ }
147
+ scanGoConsumers(content, filePath) {
148
+ const out = [];
149
+ const re = /\w+\.New(\w+)Client\s*\(/g;
150
+ let m;
151
+ while ((m = re.exec(content)) !== null) {
152
+ const serviceName = m[1];
153
+ out.push(makeContract(serviceOnlyContractId(serviceName), 'consumer', filePath, `New${serviceName}Client`, 0.7, { service: serviceName, source: 'go_client' }));
154
+ }
155
+ return out;
156
+ }
157
+ scanJavaProviders(content, filePath) {
158
+ const out = [];
159
+ // @GrpcService
160
+ if (content.includes('@GrpcService')) {
161
+ const implBaseRe = /extends\s+(\w+)Grpc\.(\w+)ImplBase/;
162
+ const m = content.match(implBaseRe);
163
+ if (m) {
164
+ out.push(makeContract(serviceOnlyContractId(m[1]), 'provider', filePath, m[2], 0.8, {
165
+ service: m[1],
166
+ source: 'java_grpc_service',
167
+ }));
168
+ }
169
+ else {
170
+ // Try extracting service name from class name
171
+ const classRe = /class\s+(\w*?)(?:Grpc)?(?:Service)?\s+extends\s+(\w+)(?:Grpc\.(\w+))?ImplBase/;
172
+ const cm = content.match(classRe);
173
+ if (cm) {
174
+ const svcName = cm[2].replace(/Grpc$/, '');
175
+ out.push(makeContract(serviceOnlyContractId(svcName), 'provider', filePath, cm[1], 0.8, {
176
+ service: svcName,
177
+ source: 'java_grpc_service',
178
+ }));
179
+ }
180
+ }
181
+ }
182
+ // extends XxxImplBase (without @GrpcService)
183
+ if (!content.includes('@GrpcService')) {
184
+ const implRe = /extends\s+(\w+?)(?:Grpc\.(\w+))?ImplBase/;
185
+ const m = content.match(implRe);
186
+ if (m) {
187
+ const svcName = m[2] || m[1].replace(/Grpc$/, '');
188
+ out.push(makeContract(serviceOnlyContractId(svcName), 'provider', filePath, svcName, 0.8, {
189
+ service: svcName,
190
+ source: 'java_impl_base',
191
+ }));
192
+ }
193
+ }
194
+ return out;
195
+ }
196
+ scanJavaConsumers(content, filePath) {
197
+ const out = [];
198
+ // XxxGrpc.newBlockingStub( or XxxGrpc.newStub(
199
+ const re = /(\w+)Grpc\.new(?:Blocking)?Stub\s*\(/g;
200
+ let m;
201
+ while ((m = re.exec(content)) !== null) {
202
+ const serviceName = m[1];
203
+ out.push(makeContract(serviceOnlyContractId(serviceName), 'consumer', filePath, `${serviceName}Stub`, 0.7, { service: serviceName, source: 'java_stub' }));
204
+ }
205
+ return out;
206
+ }
207
+ scanPythonProviders(content, filePath) {
208
+ const out = [];
209
+ // add_XxxServicer_to_server(
210
+ const re = /add_(\w+?)Servicer_to_server\s*\(/g;
211
+ let m;
212
+ while ((m = re.exec(content)) !== null) {
213
+ const serviceName = m[1];
214
+ out.push(makeContract(serviceOnlyContractId(serviceName), 'provider', filePath, `add_${serviceName}Servicer_to_server`, 0.8, { service: serviceName, source: 'python_servicer' }));
215
+ }
216
+ return out;
217
+ }
218
+ scanPythonConsumers(content, filePath) {
219
+ const out = [];
220
+ // XxxStub(
221
+ const re = /(\w+)Stub\s*\(/g;
222
+ let m;
223
+ while ((m = re.exec(content)) !== null) {
224
+ const name = m[1];
225
+ // Filter out common false positives
226
+ if (['Mock', 'Test', 'Fake', 'Stub'].includes(name))
227
+ continue;
228
+ out.push(makeContract(serviceOnlyContractId(name), 'consumer', filePath, `${name}Stub`, 0.7, {
229
+ service: name,
230
+ source: 'python_stub',
231
+ }));
232
+ }
233
+ return out;
234
+ }
235
+ scanTsProviders(content, filePath) {
236
+ const out = [];
237
+ // @GrpcMethod('ServiceName', 'MethodName')
238
+ const re = /@GrpcMethod\s*\(\s*['"](\w+)['"]\s*,\s*['"](\w+)['"]\s*\)/g;
239
+ let m;
240
+ while ((m = re.exec(content)) !== null) {
241
+ const serviceName = m[1];
242
+ const methodName = m[2];
243
+ const cid = contractId('', serviceName, methodName);
244
+ out.push(makeContract(cid, 'provider', filePath, `${serviceName}.${methodName}`, 0.8, {
245
+ service: serviceName,
246
+ method: methodName,
247
+ source: 'ts_grpc_method',
248
+ }));
249
+ }
250
+ return out;
251
+ }
252
+ dedupe(items) {
253
+ const seen = new Set();
254
+ const out = [];
255
+ for (const c of items) {
256
+ const k = `${c.contractId}|${c.role}|${c.symbolRef.filePath}`;
257
+ if (seen.has(k))
258
+ continue;
259
+ seen.add(k);
260
+ out.push(c);
261
+ }
262
+ return out;
263
+ }
264
+ }
@@ -0,0 +1,24 @@
1
+ import type { ContractExtractor, CypherExecutor } from '../contract-extractor.js';
2
+ import type { ExtractedContract, RepoHandle } from '../types.js';
3
+ export declare function normalizeHttpPath(p: string): string;
4
+ export declare class HttpRouteExtractor implements ContractExtractor {
5
+ type: "http";
6
+ canExtract(_repo: RepoHandle): Promise<boolean>;
7
+ extract(dbExecutor: CypherExecutor | null, repoPath: string, repo: RepoHandle): Promise<ExtractedContract[]>;
8
+ private extractProvidersGraph;
9
+ private inferMethodFromFileScan;
10
+ private extractProvidersSourceScan;
11
+ private dedupeContracts;
12
+ private scanSpringProviders;
13
+ private scanExpressProviders;
14
+ private scanLaravelProviders;
15
+ private scanFastApiProviders;
16
+ private makeProvider;
17
+ private extractConsumersGraph;
18
+ private inferFetchMethod;
19
+ private extractConsumersSourceScan;
20
+ private scanFetchConsumers;
21
+ private templateToPattern;
22
+ private scanAxiosConsumers;
23
+ private makeConsumer;
24
+ }