gitnexus 1.4.8 → 1.4.9

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 (211) hide show
  1. package/README.md +7 -0
  2. package/dist/cli/index-repo.d.ts +15 -0
  3. package/dist/cli/index-repo.js +115 -0
  4. package/dist/cli/index.js +11 -2
  5. package/dist/cli/setup.js +12 -9
  6. package/dist/cli/wiki.d.ts +4 -0
  7. package/dist/cli/wiki.js +174 -53
  8. package/dist/config/supported-languages.d.ts +7 -5
  9. package/dist/config/supported-languages.js +6 -4
  10. package/dist/core/graph/graph.js +9 -1
  11. package/dist/core/graph/types.d.ts +10 -2
  12. package/dist/core/ingestion/call-processor.d.ts +18 -1
  13. package/dist/core/ingestion/call-processor.js +297 -38
  14. package/dist/core/ingestion/call-routing.d.ts +3 -18
  15. package/dist/core/ingestion/call-routing.js +0 -19
  16. package/dist/core/ingestion/cobol/cobol-copy-expander.d.ts +57 -0
  17. package/dist/core/ingestion/cobol/cobol-copy-expander.js +385 -0
  18. package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +210 -0
  19. package/dist/core/ingestion/cobol/cobol-preprocessor.js +1509 -0
  20. package/dist/core/ingestion/cobol/jcl-parser.d.ts +68 -0
  21. package/dist/core/ingestion/cobol/jcl-parser.js +217 -0
  22. package/dist/core/ingestion/cobol/jcl-processor.d.ts +33 -0
  23. package/dist/core/ingestion/cobol/jcl-processor.js +229 -0
  24. package/dist/core/ingestion/cobol-processor.d.ts +54 -0
  25. package/dist/core/ingestion/cobol-processor.js +1186 -0
  26. package/dist/core/ingestion/entry-point-scoring.d.ts +17 -0
  27. package/dist/core/ingestion/entry-point-scoring.js +18 -4
  28. package/dist/core/ingestion/export-detection.d.ts +47 -8
  29. package/dist/core/ingestion/export-detection.js +29 -50
  30. package/dist/core/ingestion/field-extractor.d.ts +29 -0
  31. package/dist/core/ingestion/field-extractor.js +25 -0
  32. package/dist/core/ingestion/field-extractors/configs/c-cpp.d.ts +3 -0
  33. package/dist/core/ingestion/field-extractors/configs/c-cpp.js +108 -0
  34. package/dist/core/ingestion/field-extractors/configs/csharp.d.ts +8 -0
  35. package/dist/core/ingestion/field-extractors/configs/csharp.js +73 -0
  36. package/dist/core/ingestion/field-extractors/configs/dart.d.ts +8 -0
  37. package/dist/core/ingestion/field-extractors/configs/dart.js +76 -0
  38. package/dist/core/ingestion/field-extractors/configs/go.d.ts +11 -0
  39. package/dist/core/ingestion/field-extractors/configs/go.js +64 -0
  40. package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +44 -0
  41. package/dist/core/ingestion/field-extractors/configs/helpers.js +134 -0
  42. package/dist/core/ingestion/field-extractors/configs/jvm.d.ts +3 -0
  43. package/dist/core/ingestion/field-extractors/configs/jvm.js +118 -0
  44. package/dist/core/ingestion/field-extractors/configs/php.d.ts +8 -0
  45. package/dist/core/ingestion/field-extractors/configs/php.js +67 -0
  46. package/dist/core/ingestion/field-extractors/configs/python.d.ts +12 -0
  47. package/dist/core/ingestion/field-extractors/configs/python.js +91 -0
  48. package/dist/core/ingestion/field-extractors/configs/ruby.d.ts +16 -0
  49. package/dist/core/ingestion/field-extractors/configs/ruby.js +75 -0
  50. package/dist/core/ingestion/field-extractors/configs/rust.d.ts +9 -0
  51. package/dist/core/ingestion/field-extractors/configs/rust.js +55 -0
  52. package/dist/core/ingestion/field-extractors/configs/swift.d.ts +8 -0
  53. package/dist/core/ingestion/field-extractors/configs/swift.js +63 -0
  54. package/dist/core/ingestion/field-extractors/configs/typescript-javascript.d.ts +3 -0
  55. package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +60 -0
  56. package/dist/core/ingestion/field-extractors/generic.d.ts +46 -0
  57. package/dist/core/ingestion/field-extractors/generic.js +111 -0
  58. package/dist/core/ingestion/field-extractors/typescript.d.ts +77 -0
  59. package/dist/core/ingestion/field-extractors/typescript.js +291 -0
  60. package/dist/core/ingestion/field-types.d.ts +59 -0
  61. package/dist/core/ingestion/field-types.js +2 -0
  62. package/dist/core/ingestion/framework-detection.d.ts +87 -0
  63. package/dist/core/ingestion/framework-detection.js +65 -2
  64. package/dist/core/ingestion/heritage-processor.js +15 -17
  65. package/dist/core/ingestion/import-processor.d.ts +9 -10
  66. package/dist/core/ingestion/import-processor.js +59 -14
  67. package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.d.ts +6 -9
  68. package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.js +20 -2
  69. package/dist/core/ingestion/import-resolvers/dart.d.ts +7 -0
  70. package/dist/core/ingestion/import-resolvers/dart.js +44 -0
  71. package/dist/core/ingestion/{resolvers → import-resolvers}/go.d.ts +4 -5
  72. package/dist/core/ingestion/{resolvers → import-resolvers}/go.js +17 -0
  73. package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.d.ts +9 -1
  74. package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.js +56 -0
  75. package/dist/core/ingestion/{resolvers → import-resolvers}/php.d.ts +6 -10
  76. package/dist/core/ingestion/{resolvers → import-resolvers}/php.js +7 -2
  77. package/dist/core/ingestion/{resolvers → import-resolvers}/python.d.ts +9 -3
  78. package/dist/core/ingestion/{resolvers → import-resolvers}/python.js +35 -3
  79. package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.d.ts +5 -2
  80. package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.js +7 -2
  81. package/dist/core/ingestion/{resolvers → import-resolvers}/rust.d.ts +5 -2
  82. package/dist/core/ingestion/{resolvers → import-resolvers}/rust.js +41 -2
  83. package/dist/core/ingestion/{resolvers → import-resolvers}/standard.d.ts +15 -7
  84. package/dist/core/ingestion/{resolvers → import-resolvers}/standard.js +22 -3
  85. package/dist/core/ingestion/import-resolvers/swift.d.ts +7 -0
  86. package/dist/core/ingestion/import-resolvers/swift.js +23 -0
  87. package/dist/core/ingestion/import-resolvers/types.d.ts +44 -0
  88. package/dist/core/ingestion/import-resolvers/types.js +6 -0
  89. package/dist/core/ingestion/{resolvers → import-resolvers}/utils.d.ts +0 -3
  90. package/dist/core/ingestion/{resolvers → import-resolvers}/utils.js +0 -9
  91. package/dist/core/ingestion/language-config.d.ts +4 -1
  92. package/dist/core/ingestion/language-provider.d.ts +121 -0
  93. package/dist/core/ingestion/language-provider.js +24 -0
  94. package/dist/core/ingestion/languages/c-cpp.d.ts +12 -0
  95. package/dist/core/ingestion/languages/c-cpp.js +71 -0
  96. package/dist/core/ingestion/languages/cobol.d.ts +1 -0
  97. package/dist/core/ingestion/languages/cobol.js +26 -0
  98. package/dist/core/ingestion/languages/csharp.d.ts +8 -0
  99. package/dist/core/ingestion/languages/csharp.js +49 -0
  100. package/dist/core/ingestion/languages/dart.d.ts +12 -0
  101. package/dist/core/ingestion/languages/dart.js +58 -0
  102. package/dist/core/ingestion/languages/go.d.ts +11 -0
  103. package/dist/core/ingestion/languages/go.js +28 -0
  104. package/dist/core/ingestion/languages/index.d.ts +38 -0
  105. package/dist/core/ingestion/languages/index.js +63 -0
  106. package/dist/core/ingestion/languages/java.d.ts +9 -0
  107. package/dist/core/ingestion/languages/java.js +29 -0
  108. package/dist/core/ingestion/languages/kotlin.d.ts +9 -0
  109. package/dist/core/ingestion/languages/kotlin.js +53 -0
  110. package/dist/core/ingestion/languages/php.d.ts +8 -0
  111. package/dist/core/ingestion/languages/php.js +145 -0
  112. package/dist/core/ingestion/languages/python.d.ts +12 -0
  113. package/dist/core/ingestion/languages/python.js +39 -0
  114. package/dist/core/ingestion/languages/ruby.d.ts +9 -0
  115. package/dist/core/ingestion/languages/ruby.js +44 -0
  116. package/dist/core/ingestion/languages/rust.d.ts +12 -0
  117. package/dist/core/ingestion/languages/rust.js +44 -0
  118. package/dist/core/ingestion/languages/swift.d.ts +12 -0
  119. package/dist/core/ingestion/languages/swift.js +133 -0
  120. package/dist/core/ingestion/languages/typescript.d.ts +10 -0
  121. package/dist/core/ingestion/languages/typescript.js +60 -0
  122. package/dist/core/ingestion/mro-processor.js +14 -15
  123. package/dist/core/ingestion/{named-binding-extraction.d.ts → named-binding-processor.d.ts} +0 -9
  124. package/dist/core/ingestion/named-binding-processor.js +42 -0
  125. package/dist/core/ingestion/named-bindings/csharp.d.ts +3 -0
  126. package/dist/core/ingestion/named-bindings/csharp.js +37 -0
  127. package/dist/core/ingestion/named-bindings/java.d.ts +3 -0
  128. package/dist/core/ingestion/named-bindings/java.js +29 -0
  129. package/dist/core/ingestion/named-bindings/kotlin.d.ts +3 -0
  130. package/dist/core/ingestion/named-bindings/kotlin.js +36 -0
  131. package/dist/core/ingestion/named-bindings/php.d.ts +3 -0
  132. package/dist/core/ingestion/named-bindings/php.js +61 -0
  133. package/dist/core/ingestion/named-bindings/python.d.ts +3 -0
  134. package/dist/core/ingestion/named-bindings/python.js +49 -0
  135. package/dist/core/ingestion/named-bindings/rust.d.ts +3 -0
  136. package/dist/core/ingestion/named-bindings/rust.js +64 -0
  137. package/dist/core/ingestion/named-bindings/types.d.ts +16 -0
  138. package/dist/core/ingestion/named-bindings/types.js +6 -0
  139. package/dist/core/ingestion/named-bindings/typescript.d.ts +3 -0
  140. package/dist/core/ingestion/named-bindings/typescript.js +58 -0
  141. package/dist/core/ingestion/parsing-processor.d.ts +5 -1
  142. package/dist/core/ingestion/parsing-processor.js +115 -16
  143. package/dist/core/ingestion/pipeline.js +925 -424
  144. package/dist/core/ingestion/resolution-context.js +1 -1
  145. package/dist/core/ingestion/route-extractors/expo.d.ts +1 -0
  146. package/dist/core/ingestion/route-extractors/expo.js +36 -0
  147. package/dist/core/ingestion/route-extractors/middleware.d.ts +47 -0
  148. package/dist/core/ingestion/route-extractors/middleware.js +143 -0
  149. package/dist/core/ingestion/route-extractors/nextjs.d.ts +3 -0
  150. package/dist/core/ingestion/route-extractors/nextjs.js +76 -0
  151. package/dist/core/ingestion/route-extractors/php.d.ts +7 -0
  152. package/dist/core/ingestion/route-extractors/php.js +21 -0
  153. package/dist/core/ingestion/route-extractors/response-shapes.d.ts +20 -0
  154. package/dist/core/ingestion/route-extractors/response-shapes.js +290 -0
  155. package/dist/core/ingestion/tree-sitter-queries.d.ts +8 -7
  156. package/dist/core/ingestion/tree-sitter-queries.js +231 -9
  157. package/dist/core/ingestion/type-env.d.ts +14 -17
  158. package/dist/core/ingestion/type-env.js +66 -14
  159. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +1 -1
  160. package/dist/core/ingestion/type-extractors/csharp.js +1 -1
  161. package/dist/core/ingestion/type-extractors/dart.d.ts +15 -0
  162. package/dist/core/ingestion/type-extractors/dart.js +371 -0
  163. package/dist/core/ingestion/type-extractors/jvm.js +1 -1
  164. package/dist/core/ingestion/type-extractors/shared.d.ts +1 -13
  165. package/dist/core/ingestion/type-extractors/shared.js +9 -102
  166. package/dist/core/ingestion/type-extractors/swift.js +334 -4
  167. package/dist/core/ingestion/type-extractors/types.d.ts +3 -1
  168. package/dist/core/ingestion/{ast-helpers.d.ts → utils/ast-helpers.d.ts} +16 -13
  169. package/dist/core/ingestion/{ast-helpers.js → utils/ast-helpers.js} +111 -32
  170. package/dist/core/ingestion/{call-analysis.js → utils/call-analysis.js} +37 -0
  171. package/dist/core/ingestion/utils/event-loop.d.ts +5 -0
  172. package/dist/core/ingestion/utils/event-loop.js +5 -0
  173. package/dist/core/ingestion/utils/language-detection.d.ts +9 -0
  174. package/dist/core/ingestion/utils/language-detection.js +70 -0
  175. package/dist/core/ingestion/utils/verbose.d.ts +1 -0
  176. package/dist/core/ingestion/utils/verbose.js +7 -0
  177. package/dist/core/ingestion/workers/parse-worker.d.ts +43 -2
  178. package/dist/core/ingestion/workers/parse-worker.js +361 -150
  179. package/dist/core/lbug/csv-generator.js +34 -1
  180. package/dist/core/lbug/lbug-adapter.js +6 -0
  181. package/dist/core/lbug/schema.d.ts +5 -3
  182. package/dist/core/lbug/schema.js +39 -2
  183. package/dist/core/tree-sitter/parser-loader.js +7 -1
  184. package/dist/core/wiki/cursor-client.d.ts +31 -0
  185. package/dist/core/wiki/cursor-client.js +127 -0
  186. package/dist/core/wiki/generator.d.ts +28 -9
  187. package/dist/core/wiki/generator.js +115 -18
  188. package/dist/core/wiki/graph-queries.d.ts +4 -0
  189. package/dist/core/wiki/graph-queries.js +7 -1
  190. package/dist/core/wiki/llm-client.d.ts +2 -0
  191. package/dist/core/wiki/llm-client.js +8 -4
  192. package/dist/core/wiki/prompts.d.ts +3 -3
  193. package/dist/core/wiki/prompts.js +6 -0
  194. package/dist/mcp/core/lbug-adapter.d.ts +5 -0
  195. package/dist/mcp/core/lbug-adapter.js +11 -1
  196. package/dist/mcp/local/local-backend.d.ts +16 -5
  197. package/dist/mcp/local/local-backend.js +711 -74
  198. package/dist/mcp/tools.js +71 -2
  199. package/dist/storage/repo-manager.d.ts +3 -0
  200. package/package.json +17 -16
  201. package/dist/core/ingestion/import-resolution.d.ts +0 -101
  202. package/dist/core/ingestion/import-resolution.js +0 -251
  203. package/dist/core/ingestion/named-binding-extraction.js +0 -373
  204. package/dist/core/ingestion/resolvers/index.d.ts +0 -18
  205. package/dist/core/ingestion/resolvers/index.js +0 -13
  206. package/dist/core/ingestion/type-extractors/index.d.ts +0 -22
  207. package/dist/core/ingestion/type-extractors/index.js +0 -31
  208. package/dist/core/ingestion/utils.d.ts +0 -20
  209. package/dist/core/ingestion/utils.js +0 -242
  210. package/scripts/patch-tree-sitter-swift.cjs +0 -74
  211. /package/dist/core/ingestion/{call-analysis.d.ts → utils/call-analysis.d.ts} +0 -0
@@ -0,0 +1,55 @@
1
+ // gitnexus/src/core/ingestion/field-extractors/configs/rust.ts
2
+ import { SupportedLanguages } from '../../../../config/supported-languages.js';
3
+ import { extractSimpleTypeName } from '../../type-extractors/shared.js';
4
+ import { hasKeyword } from './helpers.js';
5
+ /**
6
+ * Rust field extraction config.
7
+ *
8
+ * Handles struct fields (named and tuple variants are out of scope).
9
+ * Visibility: `pub` keyword = public, otherwise private (crate-private).
10
+ * All fields are immutable by default in Rust (mutability is on the binding).
11
+ */
12
+ export const rustConfig = {
13
+ language: SupportedLanguages.Rust,
14
+ typeDeclarationNodes: [
15
+ 'struct_item',
16
+ 'enum_item',
17
+ ],
18
+ fieldNodeTypes: ['field_declaration'],
19
+ bodyNodeTypes: ['field_declaration_list'],
20
+ defaultVisibility: 'private',
21
+ extractName(node) {
22
+ const name = node.childForFieldName('name');
23
+ if (name)
24
+ return name.text;
25
+ // fallback: first field_identifier
26
+ for (let i = 0; i < node.namedChildCount; i++) {
27
+ const child = node.namedChild(i);
28
+ if (child?.type === 'field_identifier')
29
+ return child.text;
30
+ }
31
+ return undefined;
32
+ },
33
+ extractType(node) {
34
+ const typeNode = node.childForFieldName('type');
35
+ if (typeNode)
36
+ return extractSimpleTypeName(typeNode) ?? typeNode.text?.trim();
37
+ return undefined;
38
+ },
39
+ extractVisibility(node) {
40
+ // Check for visibility_modifier named child (pub, pub(crate), pub(super))
41
+ for (let i = 0; i < node.namedChildCount; i++) {
42
+ const child = node.namedChild(i);
43
+ if (child?.type === 'visibility_modifier')
44
+ return 'public';
45
+ }
46
+ return hasKeyword(node, 'pub') ? 'public' : 'private';
47
+ },
48
+ isStatic(_node) {
49
+ return false; // Rust struct fields are never static
50
+ },
51
+ isReadonly(_node) {
52
+ // All Rust fields are immutable by default (mutability is per-binding)
53
+ return true;
54
+ },
55
+ };
@@ -0,0 +1,8 @@
1
+ import type { FieldExtractionConfig } from '../generic.js';
2
+ /**
3
+ * Swift field extraction config.
4
+ *
5
+ * Handles property_declaration inside class_body / protocol_body.
6
+ * tree-sitter-swift uses property_declaration for stored/computed properties.
7
+ */
8
+ export declare const swiftConfig: FieldExtractionConfig;
@@ -0,0 +1,63 @@
1
+ // gitnexus/src/core/ingestion/field-extractors/configs/swift.ts
2
+ import { SupportedLanguages } from '../../../../config/supported-languages.js';
3
+ import { hasKeyword, findVisibility } from './helpers.js';
4
+ import { extractSimpleTypeName } from '../../type-extractors/shared.js';
5
+ const SWIFT_VIS = new Set(['public', 'private', 'fileprivate', 'internal', 'open']);
6
+ /**
7
+ * Swift field extraction config.
8
+ *
9
+ * Handles property_declaration inside class_body / protocol_body.
10
+ * tree-sitter-swift uses property_declaration for stored/computed properties.
11
+ */
12
+ export const swiftConfig = {
13
+ language: SupportedLanguages.Swift,
14
+ typeDeclarationNodes: [
15
+ 'class_declaration',
16
+ 'struct_declaration',
17
+ 'protocol_declaration',
18
+ ],
19
+ fieldNodeTypes: ['property_declaration'],
20
+ bodyNodeTypes: ['class_body', 'protocol_body'],
21
+ defaultVisibility: 'internal',
22
+ extractName(node) {
23
+ // property_declaration > pattern > simple_identifier
24
+ for (let i = 0; i < node.namedChildCount; i++) {
25
+ const child = node.namedChild(i);
26
+ if (child?.type === 'pattern') {
27
+ for (let j = 0; j < child.namedChildCount; j++) {
28
+ const ident = child.namedChild(j);
29
+ if (ident?.type === 'simple_identifier')
30
+ return ident.text;
31
+ }
32
+ return child.text;
33
+ }
34
+ if (child?.type === 'simple_identifier')
35
+ return child.text;
36
+ }
37
+ // fallback: childForFieldName('name')
38
+ const name = node.childForFieldName('name');
39
+ return name?.text;
40
+ },
41
+ extractType(node) {
42
+ // property_declaration > type_annotation > type_identifier
43
+ for (let i = 0; i < node.namedChildCount; i++) {
44
+ const child = node.namedChild(i);
45
+ if (child?.type === 'type_annotation') {
46
+ const inner = child.firstNamedChild;
47
+ if (inner)
48
+ return extractSimpleTypeName(inner) ?? inner.text?.trim();
49
+ }
50
+ }
51
+ return undefined;
52
+ },
53
+ extractVisibility(node) {
54
+ return findVisibility(node, SWIFT_VIS, 'internal', 'modifiers');
55
+ },
56
+ isStatic(node) {
57
+ return hasKeyword(node, 'static') || hasKeyword(node, 'class');
58
+ },
59
+ isReadonly(node) {
60
+ // 'let' = constant/readonly, 'var' = variable
61
+ return hasKeyword(node, 'let');
62
+ },
63
+ };
@@ -0,0 +1,3 @@
1
+ import type { FieldExtractionConfig } from '../generic.js';
2
+ export declare const typescriptConfig: FieldExtractionConfig;
3
+ export declare const javascriptConfig: FieldExtractionConfig;
@@ -0,0 +1,60 @@
1
+ // gitnexus/src/core/ingestion/field-extractors/configs/typescript-javascript.ts
2
+ import { SupportedLanguages } from '../../../../config/supported-languages.js';
3
+ import { hasKeyword, findVisibility, typeFromAnnotation } from './helpers.js';
4
+ const VISIBILITY_KEYWORDS = new Set(['public', 'private', 'protected']);
5
+ const shared = {
6
+ typeDeclarationNodes: [
7
+ 'class_declaration',
8
+ 'abstract_class_declaration',
9
+ 'interface_declaration',
10
+ ],
11
+ fieldNodeTypes: [
12
+ 'public_field_definition',
13
+ 'property_signature',
14
+ 'field_definition',
15
+ ],
16
+ bodyNodeTypes: ['class_body', 'interface_body', 'object_type'],
17
+ defaultVisibility: 'public',
18
+ extractName(node) {
19
+ const nameNode = node.childForFieldName('name') ?? node.childForFieldName('property');
20
+ return nameNode?.text;
21
+ },
22
+ extractType(node) {
23
+ // tree-sitter TS uses a named 'type' field for type_annotation
24
+ const typeField = node.childForFieldName('type');
25
+ if (typeField) {
26
+ if (typeField.type === 'type_annotation') {
27
+ const inner = typeField.firstNamedChild;
28
+ return inner?.text?.trim();
29
+ }
30
+ return typeField.text?.trim();
31
+ }
32
+ return typeFromAnnotation(node);
33
+ },
34
+ extractVisibility(node) {
35
+ // TypeScript accessibility_modifier
36
+ for (let i = 0; i < node.namedChildCount; i++) {
37
+ const child = node.namedChild(i);
38
+ if (child && child.type === 'accessibility_modifier') {
39
+ const t = child.text.trim();
40
+ if (VISIBILITY_KEYWORDS.has(t))
41
+ return t;
42
+ }
43
+ }
44
+ return findVisibility(node, VISIBILITY_KEYWORDS, 'public', 'modifiers');
45
+ },
46
+ isStatic(node) {
47
+ return hasKeyword(node, 'static');
48
+ },
49
+ isReadonly(node) {
50
+ return hasKeyword(node, 'readonly');
51
+ },
52
+ };
53
+ export const typescriptConfig = {
54
+ ...shared,
55
+ language: SupportedLanguages.TypeScript,
56
+ };
57
+ export const javascriptConfig = {
58
+ ...shared,
59
+ language: SupportedLanguages.JavaScript,
60
+ };
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Generic table-driven field extractor factory.
3
+ *
4
+ * Instead of 14 separate 300-line files, define a config per language and
5
+ * generate extractors from configs. The factory creates a class extending
6
+ * BaseFieldExtractor whose behaviour is entirely driven by FieldExtractionConfig.
7
+ */
8
+ import type { SyntaxNode } from '../utils/ast-helpers.js';
9
+ import { SupportedLanguages } from '../../../config/supported-languages.js';
10
+ import type { FieldExtractor } from '../field-extractor.js';
11
+ import type { FieldVisibility } from '../field-types.js';
12
+ export interface FieldExtractionConfig {
13
+ language: SupportedLanguages;
14
+ /** AST node types that are class/struct/interface declarations */
15
+ typeDeclarationNodes: string[];
16
+ /** AST node types that represent field/property declarations inside a body */
17
+ fieldNodeTypes: string[];
18
+ /** AST node type(s) for the class body container (e.g., 'class_body', 'declaration_list') */
19
+ bodyNodeTypes: string[];
20
+ /** Default visibility when no modifier is present */
21
+ defaultVisibility: FieldVisibility;
22
+ /**
23
+ * Extract field name from a field declaration node.
24
+ * Use this for nodes that declare exactly one field.
25
+ */
26
+ extractName: (node: SyntaxNode) => string | undefined;
27
+ /**
28
+ * Extract multiple field names from a single declaration node.
29
+ * Optional override for languages where one AST node can declare
30
+ * several fields (e.g. Ruby `attr_accessor :foo, :bar`).
31
+ * When present, the factory uses this instead of `extractName`.
32
+ */
33
+ extractNames?: (node: SyntaxNode) => string[];
34
+ /** Extract type annotation from a field declaration node */
35
+ extractType: (node: SyntaxNode) => string | undefined;
36
+ /** Extract visibility from a field declaration node */
37
+ extractVisibility: (node: SyntaxNode) => FieldVisibility;
38
+ /** Check if a field is static */
39
+ isStatic: (node: SyntaxNode) => boolean;
40
+ /** Check if a field is readonly/final/const */
41
+ isReadonly: (node: SyntaxNode) => boolean;
42
+ }
43
+ /**
44
+ * Create a FieldExtractor from a declarative config.
45
+ */
46
+ export declare function createFieldExtractor(config: FieldExtractionConfig): FieldExtractor;
@@ -0,0 +1,111 @@
1
+ // gitnexus/src/core/ingestion/field-extractors/generic.ts
2
+ import { BaseFieldExtractor } from '../field-extractor.js';
3
+ // ---------------------------------------------------------------------------
4
+ // Factory
5
+ // ---------------------------------------------------------------------------
6
+ /**
7
+ * Create a FieldExtractor from a declarative config.
8
+ */
9
+ export function createFieldExtractor(config) {
10
+ const typeDeclarationSet = new Set(config.typeDeclarationNodes);
11
+ const fieldNodeSet = new Set(config.fieldNodeTypes);
12
+ const bodyNodeSet = new Set(config.bodyNodeTypes);
13
+ class GenericFieldExtractor extends BaseFieldExtractor {
14
+ language = config.language;
15
+ isTypeDeclaration(node) {
16
+ return typeDeclarationSet.has(node.type);
17
+ }
18
+ extractVisibility(node) {
19
+ return config.extractVisibility(node);
20
+ }
21
+ extract(node, context) {
22
+ if (!this.isTypeDeclaration(node))
23
+ return null;
24
+ const nameNode = node.childForFieldName('name');
25
+ if (!nameNode)
26
+ return null;
27
+ const ownerFqn = nameNode.text;
28
+ const fields = [];
29
+ // Find body container(s)
30
+ const bodies = this.findBodies(node);
31
+ for (const body of bodies) {
32
+ this.extractFieldsFromBody(body, context, fields);
33
+ }
34
+ return { ownerFqn, fields, nestedTypes: [] };
35
+ }
36
+ // ------------------------------------------------------------------
37
+ // private helpers
38
+ // ------------------------------------------------------------------
39
+ findBodies(node) {
40
+ const result = [];
41
+ // Try named 'body' field first
42
+ const bodyField = node.childForFieldName('body');
43
+ if (bodyField && bodyNodeSet.has(bodyField.type)) {
44
+ result.push(bodyField);
45
+ return result;
46
+ }
47
+ // Walk immediate children for matching body node types
48
+ for (let i = 0; i < node.namedChildCount; i++) {
49
+ const child = node.namedChild(i);
50
+ if (child && bodyNodeSet.has(child.type)) {
51
+ result.push(child);
52
+ }
53
+ }
54
+ // Fallback: use the body field even if its type is not in bodyNodeSet
55
+ if (result.length === 0 && bodyField) {
56
+ result.push(bodyField);
57
+ }
58
+ return result;
59
+ }
60
+ extractFieldsFromBody(body, context, out) {
61
+ for (let i = 0; i < body.namedChildCount; i++) {
62
+ const child = body.namedChild(i);
63
+ if (!child)
64
+ continue;
65
+ if (fieldNodeSet.has(child.type)) {
66
+ if (config.extractNames) {
67
+ // Multi-name path: one node may declare several fields (e.g. Ruby attr_accessor)
68
+ const names = config.extractNames(child);
69
+ for (const name of names) {
70
+ const field = this.buildField(child, name, context);
71
+ if (field)
72
+ out.push(field);
73
+ }
74
+ }
75
+ else {
76
+ const field = this.extractSingleField(child, context);
77
+ if (field)
78
+ out.push(field);
79
+ }
80
+ }
81
+ }
82
+ }
83
+ extractSingleField(node, context) {
84
+ const name = config.extractName(node);
85
+ if (!name)
86
+ return null;
87
+ return this.buildField(node, name, context);
88
+ }
89
+ buildField(node, name, context) {
90
+ if (!name)
91
+ return null;
92
+ let type = config.extractType(node) ?? null;
93
+ if (type) {
94
+ type = this.normalizeType(type);
95
+ const resolved = this.resolveType(type, context);
96
+ if (resolved)
97
+ type = resolved;
98
+ }
99
+ return {
100
+ name,
101
+ type,
102
+ visibility: config.extractVisibility(node),
103
+ isStatic: config.isStatic(node),
104
+ isReadonly: config.isReadonly(node),
105
+ sourceFile: context.filePath,
106
+ line: node.startPosition.row + 1,
107
+ };
108
+ }
109
+ }
110
+ return new GenericFieldExtractor();
111
+ }
@@ -0,0 +1,77 @@
1
+ import type { SyntaxNode } from '../utils/ast-helpers.js';
2
+ import { SupportedLanguages } from '../../../config/supported-languages.js';
3
+ import { BaseFieldExtractor } from '../field-extractor.js';
4
+ import type { FieldExtractorContext, ExtractedFields, FieldVisibility } from '../field-types.js';
5
+ /**
6
+ * Hand-written TypeScript field extractor.
7
+ *
8
+ * This exists alongside the config-based extractor in configs/typescript-javascript.ts
9
+ * (used for JavaScript) because TypeScript has unique requirements:
10
+ * 1. type_alias_declaration with object type literals (e.g., type Config = { key: string })
11
+ * 2. Optional property detection appending '| undefined' to types
12
+ * 3. Nested type discovery within class/interface bodies
13
+ *
14
+ * The config-based extractor cannot express these TS-specific capabilities.
15
+ * JavaScript uses the config-based version since it lacks type syntax.
16
+ */
17
+ export declare class TypeScriptFieldExtractor extends BaseFieldExtractor {
18
+ language: SupportedLanguages;
19
+ /**
20
+ * Node types that represent type declarations with fields in TypeScript
21
+ */
22
+ private static readonly TYPE_DECLARATION_NODES;
23
+ /**
24
+ * Node types that contain field definitions within class bodies
25
+ */
26
+ private static readonly FIELD_NODE_TYPES;
27
+ /**
28
+ * Visibility modifiers in TypeScript
29
+ */
30
+ private static readonly VISIBILITY_MODIFIERS;
31
+ /**
32
+ * Check if this node represents a type declaration with fields
33
+ */
34
+ isTypeDeclaration(node: SyntaxNode): boolean;
35
+ /**
36
+ * Extract visibility modifier from a field node
37
+ */
38
+ protected extractVisibility(node: SyntaxNode): FieldVisibility;
39
+ /**
40
+ * Check if a field has the static modifier
41
+ */
42
+ private isStatic;
43
+ /**
44
+ * Check if a field has the readonly modifier
45
+ */
46
+ private isReadonly;
47
+ /**
48
+ * Check if a property is optional (has ?: syntax)
49
+ */
50
+ private isOptional;
51
+ /**
52
+ * Extract the full type text, handling complex generic types.
53
+ *
54
+ * type_annotation nodes wrap the literal ': SomeType' — only that branch
55
+ * needs special handling to unwrap the inner child and skip the colon.
56
+ * All other node kinds are already the type text itself, so normalizeType
57
+ * is applied directly.
58
+ */
59
+ private extractFullType;
60
+ /**
61
+ * Extract a single field from a field definition node
62
+ */
63
+ private extractField;
64
+ /**
65
+ * Extract fields from a class body or interface body
66
+ */
67
+ private extractFieldsFromBody;
68
+ /**
69
+ * Extract fields from an object type (used in type aliases)
70
+ */
71
+ private extractFieldsFromObjectType;
72
+ /**
73
+ * Extract fields from a class or interface declaration
74
+ */
75
+ extract(node: SyntaxNode, context: FieldExtractorContext): ExtractedFields | null;
76
+ }
77
+ export declare const typescriptFieldExtractor: TypeScriptFieldExtractor;