@rigour-labs/core 3.0.5 → 4.0.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 (85) hide show
  1. package/dist/deep/fact-extractor.d.ts +80 -0
  2. package/dist/deep/fact-extractor.js +626 -0
  3. package/dist/deep/index.d.ts +14 -0
  4. package/dist/deep/index.js +12 -0
  5. package/dist/deep/prompts.d.ts +22 -0
  6. package/dist/deep/prompts.js +374 -0
  7. package/dist/deep/verifier.d.ts +16 -0
  8. package/dist/deep/verifier.js +388 -0
  9. package/dist/gates/deep-analysis.d.ts +28 -0
  10. package/dist/gates/deep-analysis.js +302 -0
  11. package/dist/gates/deprecated-apis-rules-lang.d.ts +21 -0
  12. package/dist/gates/deprecated-apis-rules-lang.js +311 -0
  13. package/dist/gates/deprecated-apis-rules-node.d.ts +19 -0
  14. package/dist/gates/deprecated-apis-rules-node.js +199 -0
  15. package/dist/gates/deprecated-apis-rules.d.ts +6 -0
  16. package/dist/gates/deprecated-apis-rules.js +6 -0
  17. package/dist/gates/deprecated-apis.js +1 -502
  18. package/dist/gates/hallucinated-imports-lang.d.ts +16 -0
  19. package/dist/gates/hallucinated-imports-lang.js +374 -0
  20. package/dist/gates/hallucinated-imports-stdlib.d.ts +12 -0
  21. package/dist/gates/hallucinated-imports-stdlib.js +228 -0
  22. package/dist/gates/hallucinated-imports.d.ts +0 -98
  23. package/dist/gates/hallucinated-imports.js +10 -678
  24. package/dist/gates/phantom-apis-data.d.ts +33 -0
  25. package/dist/gates/phantom-apis-data.js +398 -0
  26. package/dist/gates/phantom-apis.js +1 -393
  27. package/dist/gates/phantom-apis.test.js +52 -0
  28. package/dist/gates/promise-safety-helpers.d.ts +19 -0
  29. package/dist/gates/promise-safety-helpers.js +101 -0
  30. package/dist/gates/promise-safety-rules.d.ts +7 -0
  31. package/dist/gates/promise-safety-rules.js +19 -0
  32. package/dist/gates/promise-safety.d.ts +1 -21
  33. package/dist/gates/promise-safety.js +51 -257
  34. package/dist/gates/runner.d.ts +4 -2
  35. package/dist/gates/runner.js +46 -1
  36. package/dist/gates/test-quality-lang.d.ts +30 -0
  37. package/dist/gates/test-quality-lang.js +188 -0
  38. package/dist/gates/test-quality.d.ts +0 -14
  39. package/dist/gates/test-quality.js +13 -186
  40. package/dist/index.d.ts +10 -0
  41. package/dist/index.js +12 -2
  42. package/dist/inference/cloud-provider.d.ts +34 -0
  43. package/dist/inference/cloud-provider.js +126 -0
  44. package/dist/inference/index.d.ts +17 -0
  45. package/dist/inference/index.js +23 -0
  46. package/dist/inference/model-manager.d.ts +26 -0
  47. package/dist/inference/model-manager.js +106 -0
  48. package/dist/inference/sidecar-provider.d.ts +15 -0
  49. package/dist/inference/sidecar-provider.js +153 -0
  50. package/dist/inference/types.d.ts +77 -0
  51. package/dist/inference/types.js +19 -0
  52. package/dist/pattern-index/indexer-helpers.d.ts +38 -0
  53. package/dist/pattern-index/indexer-helpers.js +111 -0
  54. package/dist/pattern-index/indexer-lang.d.ts +13 -0
  55. package/dist/pattern-index/indexer-lang.js +244 -0
  56. package/dist/pattern-index/indexer-ts.d.ts +22 -0
  57. package/dist/pattern-index/indexer-ts.js +258 -0
  58. package/dist/pattern-index/indexer.d.ts +4 -106
  59. package/dist/pattern-index/indexer.js +58 -707
  60. package/dist/pattern-index/staleness-data.d.ts +6 -0
  61. package/dist/pattern-index/staleness-data.js +262 -0
  62. package/dist/pattern-index/staleness.js +1 -258
  63. package/dist/settings.d.ts +104 -0
  64. package/dist/settings.js +186 -0
  65. package/dist/storage/db.d.ts +16 -0
  66. package/dist/storage/db.js +132 -0
  67. package/dist/storage/findings.d.ts +14 -0
  68. package/dist/storage/findings.js +38 -0
  69. package/dist/storage/index.d.ts +9 -0
  70. package/dist/storage/index.js +8 -0
  71. package/dist/storage/patterns.d.ts +35 -0
  72. package/dist/storage/patterns.js +62 -0
  73. package/dist/storage/scans.d.ts +42 -0
  74. package/dist/storage/scans.js +55 -0
  75. package/dist/templates/index.d.ts +12 -16
  76. package/dist/templates/index.js +11 -527
  77. package/dist/templates/paradigms.d.ts +2 -0
  78. package/dist/templates/paradigms.js +46 -0
  79. package/dist/templates/presets.d.ts +14 -0
  80. package/dist/templates/presets.js +227 -0
  81. package/dist/templates/universal-config.d.ts +2 -0
  82. package/dist/templates/universal-config.js +190 -0
  83. package/dist/types/index.d.ts +438 -15
  84. package/dist/types/index.js +41 -1
  85. package/package.json +6 -2
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Pattern Indexer — Language-Specific Extractors
3
+ *
4
+ * Standalone extraction functions for Go, Rust, JVM (Java/Kotlin/C#),
5
+ * Python, and a generic C-style fallback. Each function is pure and
6
+ * receives all required context as parameters.
7
+ */
8
+ import * as path from 'path';
9
+ import { createPatternEntry, extractKeywords, getCOMLineComments, getJavaDoc, findBraceBlockEnd, getBraceBlockContent, } from './indexer-helpers.js';
10
+ // ---------------------------------------------------------------------------
11
+ // Go
12
+ // ---------------------------------------------------------------------------
13
+ export function extractGoPatterns(filePath, content, rootDir) {
14
+ const patterns = [];
15
+ const relativePath = path.relative(rootDir, filePath);
16
+ const lines = content.split('\n');
17
+ const funcRegex = /^func\s+(?:\([^)]*\)\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*([^\{]*)\s*\{/;
18
+ const typeRegex = /^type\s+([A-Za-z_][A-Za-z0-9_]*)\s+(struct|interface)/;
19
+ for (let i = 0; i < lines.length; i++) {
20
+ const line = lines[i];
21
+ const funcMatch = line.match(funcRegex);
22
+ if (funcMatch) {
23
+ const name = funcMatch[1];
24
+ patterns.push(createPatternEntry({
25
+ type: 'function',
26
+ name,
27
+ file: relativePath,
28
+ line: i + 1,
29
+ endLine: findBraceBlockEnd(lines, i),
30
+ signature: `func ${name}(${funcMatch[2]}) ${funcMatch[3].trim()}`,
31
+ description: getCOMLineComments(lines, i - 1),
32
+ keywords: extractKeywords(name),
33
+ content: getBraceBlockContent(lines, i),
34
+ exported: /^[A-Z]/.test(name),
35
+ }));
36
+ }
37
+ const typeMatch = line.match(typeRegex);
38
+ if (typeMatch) {
39
+ const name = typeMatch[1];
40
+ patterns.push(createPatternEntry({
41
+ type: typeMatch[2],
42
+ name,
43
+ file: relativePath,
44
+ line: i + 1,
45
+ endLine: findBraceBlockEnd(lines, i),
46
+ signature: `type ${name} ${typeMatch[2]}`,
47
+ description: getCOMLineComments(lines, i - 1),
48
+ keywords: extractKeywords(name),
49
+ content: getBraceBlockContent(lines, i),
50
+ exported: /^[A-Z]/.test(name),
51
+ }));
52
+ }
53
+ }
54
+ return patterns;
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // Rust
58
+ // ---------------------------------------------------------------------------
59
+ export function extractRustPatterns(filePath, content, rootDir) {
60
+ const patterns = [];
61
+ const relativePath = path.relative(rootDir, filePath);
62
+ const lines = content.split('\n');
63
+ const fnRegex = /^(?:pub\s+)?(?:async\s+)?fn\s+([A-Za-z_][A-Za-z0-9_]*)\s*[<(][^)]*[>)]\s*(?:->\s*[^\{]+)?\s*\{/;
64
+ for (let i = 0; i < lines.length; i++) {
65
+ const line = lines[i];
66
+ const fnMatch = line.match(fnRegex);
67
+ if (fnMatch) {
68
+ const name = fnMatch[1];
69
+ patterns.push(createPatternEntry({
70
+ type: 'function',
71
+ name,
72
+ file: relativePath,
73
+ line: i + 1,
74
+ endLine: findBraceBlockEnd(lines, i),
75
+ signature: line.split('{')[0].trim(),
76
+ description: getCOMLineComments(lines, i - 1),
77
+ keywords: extractKeywords(name),
78
+ content: getBraceBlockContent(lines, i),
79
+ exported: line.startsWith('pub'),
80
+ }));
81
+ }
82
+ }
83
+ return patterns;
84
+ }
85
+ // ---------------------------------------------------------------------------
86
+ // JVM-style (Java, Kotlin, C#)
87
+ // ---------------------------------------------------------------------------
88
+ export function extractJVMStylePatterns(filePath, content, rootDir) {
89
+ const patterns = [];
90
+ const relativePath = path.relative(rootDir, filePath);
91
+ const lines = content.split('\n');
92
+ const classRegex = /^(?:public|private|protected|internal)?\s*(?:static\s+)?(?:final\s+)?(?:class|interface|enum)\s+([A-Za-z0-9_]+)/;
93
+ for (let i = 0; i < lines.length; i++) {
94
+ const line = lines[i].trim();
95
+ const classMatch = line.match(classRegex);
96
+ if (classMatch) {
97
+ patterns.push(createPatternEntry({
98
+ type: 'class',
99
+ name: classMatch[1],
100
+ file: relativePath,
101
+ line: i + 1,
102
+ endLine: findBraceBlockEnd(lines, i),
103
+ signature: line,
104
+ description: getJavaDoc(lines, i - 1),
105
+ keywords: extractKeywords(classMatch[1]),
106
+ content: getBraceBlockContent(lines, i),
107
+ exported: line.includes('public'),
108
+ }));
109
+ }
110
+ }
111
+ return patterns;
112
+ }
113
+ // ---------------------------------------------------------------------------
114
+ // Generic C-style fallback (C++, PHP, etc.)
115
+ // ---------------------------------------------------------------------------
116
+ export function extractGenericCPatterns(_filePath, _content) {
117
+ return [];
118
+ }
119
+ // ---------------------------------------------------------------------------
120
+ // Python
121
+ // ---------------------------------------------------------------------------
122
+ export function extractPythonPatterns(filePath, content, rootDir, minNameLength) {
123
+ const patterns = [];
124
+ const relativePath = path.relative(rootDir, filePath);
125
+ const lines = content.split('\n');
126
+ const classRegex = /^class\s+([A-Za-z_][A-Za-z0-9_]*)\s*(\([^)]*\))?\s*:/;
127
+ const funcRegex = /^(?:async\s+)?def\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*(?:->\s*[^:]+)?\s*:/;
128
+ const constRegex = /^([A-Z][A-Z0-9_]*)\s*=\s*(.+)$/;
129
+ for (let i = 0; i < lines.length; i++) {
130
+ const originalLine = lines[i];
131
+ const lineNum = i + 1;
132
+ const classMatch = originalLine.match(classRegex);
133
+ if (classMatch) {
134
+ const name = classMatch[1];
135
+ if (name.length >= minNameLength) {
136
+ patterns.push(createPatternEntry({
137
+ type: detectPythonClassType(name),
138
+ name,
139
+ file: relativePath,
140
+ line: lineNum,
141
+ endLine: findPythonBlockEnd(lines, i),
142
+ signature: `class ${name}${classMatch[2] || ''}`,
143
+ description: getPythonDocstring(lines, i + 1),
144
+ keywords: extractKeywords(name),
145
+ content: getPythonBlockContent(lines, i),
146
+ exported: !name.startsWith('_'),
147
+ }));
148
+ continue;
149
+ }
150
+ }
151
+ const funcMatch = originalLine.match(funcRegex);
152
+ if (funcMatch) {
153
+ const name = funcMatch[1];
154
+ if (name.length >= minNameLength) {
155
+ patterns.push(createPatternEntry({
156
+ type: detectPythonFunctionType(name),
157
+ name,
158
+ file: relativePath,
159
+ line: lineNum,
160
+ endLine: findPythonBlockEnd(lines, i),
161
+ signature: `def ${name}(${funcMatch[2]})`,
162
+ description: getPythonDocstring(lines, i + 1),
163
+ keywords: extractKeywords(name),
164
+ content: getPythonBlockContent(lines, i),
165
+ exported: !name.startsWith('_'),
166
+ }));
167
+ continue;
168
+ }
169
+ }
170
+ const constMatch = originalLine.match(constRegex);
171
+ if (constMatch) {
172
+ const name = constMatch[1];
173
+ if (name.length >= minNameLength) {
174
+ patterns.push(createPatternEntry({
175
+ type: 'constant',
176
+ name,
177
+ file: relativePath,
178
+ line: lineNum,
179
+ endLine: lineNum,
180
+ signature: `${name} = ...`,
181
+ description: '',
182
+ keywords: extractKeywords(name),
183
+ content: originalLine,
184
+ exported: !name.startsWith('_'),
185
+ }));
186
+ }
187
+ }
188
+ }
189
+ return patterns;
190
+ }
191
+ // ---------------------------------------------------------------------------
192
+ // Python helpers (private to this module)
193
+ // ---------------------------------------------------------------------------
194
+ function detectPythonClassType(name) {
195
+ if (name.endsWith('Error') || name.endsWith('Exception'))
196
+ return 'error';
197
+ if (name.endsWith('Model'))
198
+ return 'model';
199
+ if (name.endsWith('Schema'))
200
+ return 'schema';
201
+ return 'class';
202
+ }
203
+ function detectPythonFunctionType(name) {
204
+ if (name.includes('middleware'))
205
+ return 'middleware';
206
+ if (name.includes('handler'))
207
+ return 'handler';
208
+ return 'function';
209
+ }
210
+ function getPythonDocstring(lines, startIndex) {
211
+ if (startIndex >= lines.length)
212
+ return '';
213
+ const nextLine = lines[startIndex].trim();
214
+ if (nextLine.startsWith('"""') || nextLine.startsWith("'''")) {
215
+ const quote = nextLine.startsWith('"""') ? '"""' : "'''";
216
+ let doc = nextLine.replace(quote, '');
217
+ if (doc.endsWith(quote))
218
+ return doc.replace(quote, '').trim();
219
+ for (let i = startIndex + 1; i < lines.length; i++) {
220
+ if (lines[i].includes(quote)) {
221
+ doc += ' ' + lines[i].split(quote)[0].trim();
222
+ break;
223
+ }
224
+ doc += ' ' + lines[i].trim();
225
+ }
226
+ return doc.trim();
227
+ }
228
+ return '';
229
+ }
230
+ function findPythonBlockEnd(lines, startIndex) {
231
+ const startIndent = lines[startIndex].search(/\S/);
232
+ for (let i = startIndex + 1; i < lines.length; i++) {
233
+ if (lines[i].trim() === '')
234
+ continue;
235
+ const currentIndent = lines[i].search(/\S/);
236
+ if (currentIndent <= startIndent)
237
+ return i;
238
+ }
239
+ return lines.length;
240
+ }
241
+ function getPythonBlockContent(lines, startIndex) {
242
+ const endLine = findPythonBlockEnd(lines, startIndex);
243
+ return lines.slice(startIndex, endLine).join('\n');
244
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Pattern Indexer — TypeScript / JavaScript AST Helpers
3
+ *
4
+ * Standalone functions for converting TypeScript AST nodes into PatternEntry
5
+ * records and extracting type metadata. No class state is referenced here.
6
+ */
7
+ import ts from 'typescript';
8
+ import type { PatternEntry, PatternType } from './types.js';
9
+ /**
10
+ * Attempt to convert an AST node into a PatternEntry.
11
+ * Returns `null` for unrecognised node kinds.
12
+ */
13
+ export declare function nodeToPattern(node: ts.Node, sourceFile: ts.SourceFile, filePath: string, _content: string, minNameLength: number): PatternEntry | null;
14
+ export declare function detectFunctionType(name: string, node: ts.Node): PatternType;
15
+ export declare function detectClassType(name: string, node: ts.ClassDeclaration): PatternType;
16
+ export declare function getFunctionSignature(node: ts.FunctionDeclaration, sourceFile: ts.SourceFile): string;
17
+ export declare function getArrowFunctionSignature(node: ts.ArrowFunction | ts.FunctionExpression, sourceFile: ts.SourceFile): string;
18
+ export declare function getClassSignature(node: ts.ClassDeclaration, sourceFile: ts.SourceFile): string;
19
+ export declare function getInterfaceSignature(node: ts.InterfaceDeclaration, sourceFile: ts.SourceFile): string;
20
+ export declare function getJSDocDescription(node: ts.Node, sourceFile: ts.SourceFile): string;
21
+ export declare function isExported(node: ts.Node): boolean;
22
+ export declare function containsJSX(node: ts.Node): boolean;
@@ -0,0 +1,258 @@
1
+ /**
2
+ * Pattern Indexer — TypeScript / JavaScript AST Helpers
3
+ *
4
+ * Standalone functions for converting TypeScript AST nodes into PatternEntry
5
+ * records and extracting type metadata. No class state is referenced here.
6
+ */
7
+ import ts from 'typescript';
8
+ import { createPatternEntry, extractKeywords } from './indexer-helpers.js';
9
+ // ---------------------------------------------------------------------------
10
+ // Main node → PatternEntry dispatcher
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Attempt to convert an AST node into a PatternEntry.
14
+ * Returns `null` for unrecognised node kinds.
15
+ */
16
+ export function nodeToPattern(node, sourceFile, filePath, _content, minNameLength) {
17
+ const startPos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
18
+ const endPos = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
19
+ const line = startPos.line + 1;
20
+ const endLine = endPos.line + 1;
21
+ // Function declarations
22
+ if (ts.isFunctionDeclaration(node) && node.name) {
23
+ const name = node.name.text;
24
+ if (name.length < minNameLength)
25
+ return null;
26
+ return createPatternEntry({
27
+ type: detectFunctionType(name, node),
28
+ name,
29
+ file: filePath,
30
+ line,
31
+ endLine,
32
+ signature: getFunctionSignature(node, sourceFile),
33
+ description: getJSDocDescription(node, sourceFile),
34
+ keywords: extractKeywords(name),
35
+ content: node.getText(sourceFile),
36
+ exported: isExported(node),
37
+ });
38
+ }
39
+ // Variable declarations with arrow functions or function expressions
40
+ if (ts.isVariableStatement(node)) {
41
+ for (const decl of node.declarationList.declarations) {
42
+ if (ts.isIdentifier(decl.name) && decl.initializer) {
43
+ const name = decl.name.text;
44
+ if (name.length < minNameLength)
45
+ continue;
46
+ if (ts.isArrowFunction(decl.initializer) ||
47
+ ts.isFunctionExpression(decl.initializer)) {
48
+ return createPatternEntry({
49
+ type: detectFunctionType(name, decl.initializer),
50
+ name,
51
+ file: filePath,
52
+ line,
53
+ endLine,
54
+ signature: getArrowFunctionSignature(decl.initializer, sourceFile),
55
+ description: getJSDocDescription(node, sourceFile),
56
+ keywords: extractKeywords(name),
57
+ content: node.getText(sourceFile),
58
+ exported: isExported(node),
59
+ });
60
+ }
61
+ // Constants — UPPER_CASE `const` declarations with a simple initialiser
62
+ const isConst = node.declarationList.flags & ts.NodeFlags.Const;
63
+ if (isConst &&
64
+ name === name.toUpperCase() &&
65
+ (ts.isStringLiteral(decl.initializer) ||
66
+ ts.isNumericLiteral(decl.initializer) ||
67
+ ts.isObjectLiteralExpression(decl.initializer))) {
68
+ return createPatternEntry({
69
+ type: 'constant',
70
+ name,
71
+ file: filePath,
72
+ line,
73
+ endLine,
74
+ signature: '',
75
+ description: getJSDocDescription(node, sourceFile),
76
+ keywords: extractKeywords(name),
77
+ content: node.getText(sourceFile),
78
+ exported: isExported(node),
79
+ });
80
+ }
81
+ }
82
+ }
83
+ }
84
+ // Class declarations
85
+ if (ts.isClassDeclaration(node) && node.name) {
86
+ const name = node.name.text;
87
+ if (name.length < minNameLength)
88
+ return null;
89
+ return createPatternEntry({
90
+ type: detectClassType(name, node),
91
+ name,
92
+ file: filePath,
93
+ line,
94
+ endLine,
95
+ signature: getClassSignature(node, sourceFile),
96
+ description: getJSDocDescription(node, sourceFile),
97
+ keywords: extractKeywords(name),
98
+ content: node.getText(sourceFile),
99
+ exported: isExported(node),
100
+ });
101
+ }
102
+ // Interface declarations
103
+ if (ts.isInterfaceDeclaration(node)) {
104
+ const name = node.name.text;
105
+ if (name.length < minNameLength)
106
+ return null;
107
+ return createPatternEntry({
108
+ type: 'interface',
109
+ name,
110
+ file: filePath,
111
+ line,
112
+ endLine,
113
+ signature: getInterfaceSignature(node, sourceFile),
114
+ description: getJSDocDescription(node, sourceFile),
115
+ keywords: extractKeywords(name),
116
+ content: node.getText(sourceFile),
117
+ exported: isExported(node),
118
+ });
119
+ }
120
+ // Type alias declarations
121
+ if (ts.isTypeAliasDeclaration(node)) {
122
+ const name = node.name.text;
123
+ if (name.length < minNameLength)
124
+ return null;
125
+ return createPatternEntry({
126
+ type: 'type',
127
+ name,
128
+ file: filePath,
129
+ line,
130
+ endLine,
131
+ signature: node.getText(sourceFile).split('=')[0].trim(),
132
+ description: getJSDocDescription(node, sourceFile),
133
+ keywords: extractKeywords(name),
134
+ content: node.getText(sourceFile),
135
+ exported: isExported(node),
136
+ });
137
+ }
138
+ // Enum declarations
139
+ if (ts.isEnumDeclaration(node)) {
140
+ const name = node.name.text;
141
+ if (name.length < minNameLength)
142
+ return null;
143
+ return createPatternEntry({
144
+ type: 'enum',
145
+ name,
146
+ file: filePath,
147
+ line,
148
+ endLine,
149
+ signature: `enum ${name}`,
150
+ description: getJSDocDescription(node, sourceFile),
151
+ keywords: extractKeywords(name),
152
+ content: node.getText(sourceFile),
153
+ exported: isExported(node),
154
+ });
155
+ }
156
+ return null;
157
+ }
158
+ // ---------------------------------------------------------------------------
159
+ // Type detection
160
+ // ---------------------------------------------------------------------------
161
+ export function detectFunctionType(name, node) {
162
+ // React hooks — useXxx
163
+ if (name.startsWith('use') && name.length > 3 && name[3] === name[3].toUpperCase()) {
164
+ return 'hook';
165
+ }
166
+ // React components — PascalCase returning JSX
167
+ if (name[0] === name[0].toUpperCase() && containsJSX(node)) {
168
+ return 'component';
169
+ }
170
+ if (name.includes('Middleware') || name.includes('middleware'))
171
+ return 'middleware';
172
+ if (name.includes('Handler') || name.includes('handler'))
173
+ return 'handler';
174
+ if (name.startsWith('create') || name.startsWith('make') || name.includes('Factory'))
175
+ return 'factory';
176
+ return 'function';
177
+ }
178
+ export function detectClassType(name, node) {
179
+ if (name.endsWith('Error') || name.endsWith('Exception'))
180
+ return 'error';
181
+ if (node.heritageClauses) {
182
+ for (const clause of node.heritageClauses) {
183
+ const text = clause.getText();
184
+ if (text.includes('Component') || text.includes('PureComponent'))
185
+ return 'component';
186
+ }
187
+ }
188
+ if (name.endsWith('Store') || name.endsWith('State'))
189
+ return 'store';
190
+ if (name.endsWith('Model') || name.endsWith('Entity'))
191
+ return 'model';
192
+ return 'class';
193
+ }
194
+ // ---------------------------------------------------------------------------
195
+ // Signature helpers
196
+ // ---------------------------------------------------------------------------
197
+ export function getFunctionSignature(node, sourceFile) {
198
+ const params = node.parameters.map(p => p.getText(sourceFile)).join(', ');
199
+ const returnType = node.type ? `: ${node.type.getText(sourceFile)}` : '';
200
+ return `(${params})${returnType}`;
201
+ }
202
+ export function getArrowFunctionSignature(node, sourceFile) {
203
+ const params = node.parameters.map(p => p.getText(sourceFile)).join(', ');
204
+ const returnType = node.type ? `: ${node.type.getText(sourceFile)}` : '';
205
+ return `(${params})${returnType}`;
206
+ }
207
+ export function getClassSignature(node, sourceFile) {
208
+ let sig = `class ${node.name?.text || 'Anonymous'}`;
209
+ if (node.heritageClauses) {
210
+ sig += ' ' + node.heritageClauses.map(c => c.getText(sourceFile)).join(' ');
211
+ }
212
+ return sig;
213
+ }
214
+ export function getInterfaceSignature(node, sourceFile) {
215
+ let sig = `interface ${node.name.text}`;
216
+ if (node.typeParameters) {
217
+ sig += `<${node.typeParameters.map(p => p.getText(sourceFile)).join(', ')}>`;
218
+ }
219
+ return sig;
220
+ }
221
+ // ---------------------------------------------------------------------------
222
+ // JSDoc / export helpers
223
+ // ---------------------------------------------------------------------------
224
+ export function getJSDocDescription(node, sourceFile) {
225
+ const jsDocComment = ts.getJSDocCommentsAndTags(node);
226
+ for (const tag of jsDocComment) {
227
+ if (ts.isJSDoc(tag) && tag.comment) {
228
+ if (typeof tag.comment === 'string')
229
+ return tag.comment;
230
+ return tag.comment.map(c => c.getText(sourceFile)).join(' ');
231
+ }
232
+ }
233
+ return '';
234
+ }
235
+ export function isExported(node) {
236
+ if (ts.canHaveModifiers(node)) {
237
+ const modifiers = ts.getModifiers(node);
238
+ if (modifiers) {
239
+ return modifiers.some(m => m.kind === ts.SyntaxKind.ExportKeyword);
240
+ }
241
+ }
242
+ return false;
243
+ }
244
+ // ---------------------------------------------------------------------------
245
+ // JSX detection
246
+ // ---------------------------------------------------------------------------
247
+ export function containsJSX(node) {
248
+ let hasJSX = false;
249
+ const visit = (n) => {
250
+ if (ts.isJsxElement(n) || ts.isJsxSelfClosingElement(n) || ts.isJsxFragment(n)) {
251
+ hasJSX = true;
252
+ return;
253
+ }
254
+ ts.forEachChild(n, visit);
255
+ };
256
+ visit(node);
257
+ return hasJSX;
258
+ }
@@ -3,125 +3,23 @@
3
3
  *
4
4
  * Scans the codebase and extracts patterns using AST parsing.
5
5
  * This is the core engine of the Pattern Index system.
6
+ *
7
+ * Language-specific extractors live in indexer-lang.ts.
8
+ * TypeScript/JS AST helpers live in indexer-ts.ts.
9
+ * Pure utility functions live in indexer-helpers.ts.
6
10
  */
7
11
  import type { PatternIndex, PatternIndexConfig } from './types.js';
8
- /**
9
- * Pattern Indexer class.
10
- * Responsible for scanning and indexing code patterns.
11
- */
12
12
  export declare class PatternIndexer {
13
13
  private config;
14
14
  private rootDir;
15
15
  constructor(rootDir: string, config?: Partial<PatternIndexConfig>);
16
16
  buildIndex(): Promise<PatternIndex>;
17
- /**
18
- * Incremental index update - only reindex changed files.
19
- */
20
17
  updateIndex(existingIndex: PatternIndex): Promise<PatternIndex>;
21
- /**
22
- * Find all files to index based on configuration.
23
- */
24
18
  private findFiles;
25
- /**
26
- * Extract patterns from a single file using TypeScript AST.
27
- */
28
19
  private extractPatterns;
29
- /**
30
- * Extract patterns from Go files.
31
- */
32
- private extractGoPatterns;
33
- /**
34
- * Extract patterns from Rust files.
35
- */
36
- private extractRustPatterns;
37
- /**
38
- * Generic extraction for C-style languages (Java, C++, PHP, etc.)
39
- */
40
- private extractJVMStylePatterns;
41
- private extractGenericCPatterns;
42
- private getCOMLineComments;
43
- private getJavaDoc;
44
- private findBraceBlockEnd;
45
- private getBraceBlockContent;
46
- /**
47
- * Extract patterns from Python files using regex.
48
- */
49
- private extractPythonPatterns;
50
- private detectPythonClassType;
51
- private detectPythonFunctionType;
52
- private getPythonDocstring;
53
- private findPythonBlockEnd;
54
- private getPythonBlockContent;
55
- /**
56
- * Convert an AST node to a PatternEntry if applicable.
57
- */
58
- private nodeToPattern;
59
- /**
60
- * Detect the specific type of a function based on naming conventions.
61
- */
62
- private detectFunctionType;
63
- /**
64
- * Detect the specific type of a class.
65
- */
66
- private detectClassType;
67
- /**
68
- * Check if a node contains JSX.
69
- */
70
- private containsJSX;
71
- /**
72
- * Get function signature.
73
- */
74
- private getFunctionSignature;
75
- /**
76
- * Get arrow function signature.
77
- */
78
- private getArrowFunctionSignature;
79
- /**
80
- * Get class signature.
81
- */
82
- private getClassSignature;
83
- /**
84
- * Get interface signature.
85
- */
86
- private getInterfaceSignature;
87
- /**
88
- * Extract JSDoc description from a node.
89
- */
90
- private getJSDocDescription;
91
- /**
92
- * Check if a node is exported.
93
- */
94
- private isExported;
95
- /**
96
- * Extract keywords from a name for semantic matching.
97
- */
98
- private extractKeywords;
99
- /**
100
- * Create a PatternEntry with computed fields.
101
- */
102
- private createPatternEntry;
103
- /**
104
- * Get the TypeScript ScriptKind for a file.
105
- */
106
20
  private getScriptKind;
107
- /**
108
- * Calculate index statistics.
109
- */
110
21
  private calculateStats;
111
- /**
112
- * Hash content using SHA-256.
113
- */
114
- private hashContent;
115
22
  }
116
- /**
117
- * Save a pattern index to disk.
118
- */
119
23
  export declare function savePatternIndex(index: PatternIndex, outputPath: string): Promise<void>;
120
- /**
121
- * Load a pattern index from disk.
122
- */
123
24
  export declare function loadPatternIndex(indexPath: string): Promise<PatternIndex | null>;
124
- /**
125
- * Get the default index path for a project.
126
- */
127
25
  export declare function getDefaultIndexPath(rootDir: string): string;