@kernlang/evolve 3.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.
- package/LICENSE +661 -0
- package/dist/concept-gap-adapter.d.ts +17 -0
- package/dist/concept-gap-adapter.js +43 -0
- package/dist/concept-gap-adapter.js.map +1 -0
- package/dist/detector-registry.d.ts +31 -0
- package/dist/detector-registry.js +89 -0
- package/dist/detector-registry.js.map +1 -0
- package/dist/detectors/animation.d.ts +5 -0
- package/dist/detectors/animation.js +67 -0
- package/dist/detectors/animation.js.map +1 -0
- package/dist/detectors/data-fetching.d.ts +5 -0
- package/dist/detectors/data-fetching.js +117 -0
- package/dist/detectors/data-fetching.js.map +1 -0
- package/dist/detectors/express-middleware.d.ts +5 -0
- package/dist/detectors/express-middleware.js +52 -0
- package/dist/detectors/express-middleware.js.map +1 -0
- package/dist/detectors/react-forms.d.ts +5 -0
- package/dist/detectors/react-forms.js +89 -0
- package/dist/detectors/react-forms.js.map +1 -0
- package/dist/detectors/schema-validation.d.ts +5 -0
- package/dist/detectors/schema-validation.js +92 -0
- package/dist/detectors/schema-validation.js.map +1 -0
- package/dist/detectors/state-mgmt.d.ts +5 -0
- package/dist/detectors/state-mgmt.js +102 -0
- package/dist/detectors/state-mgmt.js.map +1 -0
- package/dist/detectors/structural.d.ts +10 -0
- package/dist/detectors/structural.js +271 -0
- package/dist/detectors/structural.js.map +1 -0
- package/dist/detectors/testing.d.ts +5 -0
- package/dist/detectors/testing.js +56 -0
- package/dist/detectors/testing.js.map +1 -0
- package/dist/detectors/vue-composables.d.ts +5 -0
- package/dist/detectors/vue-composables.js +57 -0
- package/dist/detectors/vue-composables.js.map +1 -0
- package/dist/evolve-dedup.d.ts +12 -0
- package/dist/evolve-dedup.js +50 -0
- package/dist/evolve-dedup.js.map +1 -0
- package/dist/evolve-rollback.d.ts +58 -0
- package/dist/evolve-rollback.js +242 -0
- package/dist/evolve-rollback.js.map +1 -0
- package/dist/evolve-runner.d.ts +22 -0
- package/dist/evolve-runner.js +183 -0
- package/dist/evolve-runner.js.map +1 -0
- package/dist/evolve-validator-v4.d.ts +11 -0
- package/dist/evolve-validator-v4.js +253 -0
- package/dist/evolve-validator-v4.js.map +1 -0
- package/dist/evolved-node-loader.d.ts +61 -0
- package/dist/evolved-node-loader.js +228 -0
- package/dist/evolved-node-loader.js.map +1 -0
- package/dist/evolved-types.d.ts +110 -0
- package/dist/evolved-types.js +8 -0
- package/dist/evolved-types.js.map +1 -0
- package/dist/expressibility-scorer.d.ts +19 -0
- package/dist/expressibility-scorer.js +78 -0
- package/dist/expressibility-scorer.js.map +1 -0
- package/dist/gap-detector.d.ts +26 -0
- package/dist/gap-detector.js +141 -0
- package/dist/gap-detector.js.map +1 -0
- package/dist/golden-test-runner.d.ts +27 -0
- package/dist/golden-test-runner.js +120 -0
- package/dist/golden-test-runner.js.map +1 -0
- package/dist/graduation.d.ts +36 -0
- package/dist/graduation.js +175 -0
- package/dist/graduation.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/llm-discovery.d.ts +55 -0
- package/dist/llm-discovery.js +352 -0
- package/dist/llm-discovery.js.map +1 -0
- package/dist/llm-provider.d.ts +35 -0
- package/dist/llm-provider.js +143 -0
- package/dist/llm-provider.js.map +1 -0
- package/dist/node-governance.d.ts +23 -0
- package/dist/node-governance.js +45 -0
- package/dist/node-governance.js.map +1 -0
- package/dist/node-proposer.d.ts +27 -0
- package/dist/node-proposer.js +127 -0
- package/dist/node-proposer.js.map +1 -0
- package/dist/node-validator.d.ts +16 -0
- package/dist/node-validator.js +74 -0
- package/dist/node-validator.js.map +1 -0
- package/dist/pattern-analyzer.d.ts +28 -0
- package/dist/pattern-analyzer.js +181 -0
- package/dist/pattern-analyzer.js.map +1 -0
- package/dist/quality-scorer.d.ts +16 -0
- package/dist/quality-scorer.js +79 -0
- package/dist/quality-scorer.js.map +1 -0
- package/dist/sandboxed-generator.d.ts +26 -0
- package/dist/sandboxed-generator.js +133 -0
- package/dist/sandboxed-generator.js.map +1 -0
- package/dist/staging.d.ts +81 -0
- package/dist/staging.js +414 -0
- package/dist/staging.js.map +1 -0
- package/dist/template-proposer.d.ts +24 -0
- package/dist/template-proposer.js +103 -0
- package/dist/template-proposer.js.map +1 -0
- package/dist/template-validator.d.ts +18 -0
- package/dist/template-validator.js +174 -0
- package/dist/template-validator.js.map +1 -0
- package/dist/types.d.ts +169 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +27 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detector pack: Schema validation (yup, valibot)
|
|
3
|
+
*/
|
|
4
|
+
const yupSchemaDetector = {
|
|
5
|
+
id: 'yup-schema',
|
|
6
|
+
libraryName: 'Yup',
|
|
7
|
+
packageNames: ['yup'],
|
|
8
|
+
patternKind: 'schema-validation',
|
|
9
|
+
detect(sourceFile, fullText) {
|
|
10
|
+
const results = [];
|
|
11
|
+
// Pattern: yup.object({ field: yup.string().required() })
|
|
12
|
+
const schemaRe = /(?:export\s+)?const\s+(\w+)\s*=\s*(?:yup\s*\.\s*)?object\s*\(\s*\{/g;
|
|
13
|
+
let match;
|
|
14
|
+
while ((match = schemaRe.exec(fullText)) !== null) {
|
|
15
|
+
const hasYupImport = sourceFile.getImportDeclarations().some(imp => imp.getModuleSpecifierValue() === 'yup');
|
|
16
|
+
if (!hasYupImport)
|
|
17
|
+
continue;
|
|
18
|
+
const varName = match[1];
|
|
19
|
+
const startLine = fullText.substring(0, match.index).split('\n').length;
|
|
20
|
+
let pos = match.index + match[0].length;
|
|
21
|
+
let braceDepth = 1;
|
|
22
|
+
while (pos < fullText.length && braceDepth > 0) {
|
|
23
|
+
if (fullText[pos] === '{')
|
|
24
|
+
braceDepth++;
|
|
25
|
+
if (fullText[pos] === '}')
|
|
26
|
+
braceDepth--;
|
|
27
|
+
pos++;
|
|
28
|
+
}
|
|
29
|
+
// Skip closing parens
|
|
30
|
+
while (pos < fullText.length && (fullText[pos] === ')' || fullText[pos] === ';'))
|
|
31
|
+
pos++;
|
|
32
|
+
const endLine = fullText.substring(0, pos).split('\n').length;
|
|
33
|
+
const snippet = fullText.substring(match.index, Math.min(pos, match.index + 400));
|
|
34
|
+
results.push({
|
|
35
|
+
anchorImport: 'yup',
|
|
36
|
+
startLine,
|
|
37
|
+
endLine,
|
|
38
|
+
snippet,
|
|
39
|
+
extractedParams: [
|
|
40
|
+
{ name: 'schemaName', slotType: 'identifier', value: varName.replace(/Schema$/, ''), optional: false },
|
|
41
|
+
],
|
|
42
|
+
confidencePct: 82,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return results;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
const valibotDetector = {
|
|
49
|
+
id: 'valibot-schema',
|
|
50
|
+
libraryName: 'Valibot',
|
|
51
|
+
packageNames: ['valibot'],
|
|
52
|
+
patternKind: 'schema-validation',
|
|
53
|
+
detect(sourceFile, fullText) {
|
|
54
|
+
const results = [];
|
|
55
|
+
// Pattern: v.object({ field: v.string() })
|
|
56
|
+
const schemaRe = /(?:export\s+)?const\s+(\w+)\s*=\s*v\s*\.\s*object\s*\(\s*\{/g;
|
|
57
|
+
let match;
|
|
58
|
+
while ((match = schemaRe.exec(fullText)) !== null) {
|
|
59
|
+
const hasImport = sourceFile.getImportDeclarations().some(imp => imp.getModuleSpecifierValue() === 'valibot');
|
|
60
|
+
if (!hasImport)
|
|
61
|
+
continue;
|
|
62
|
+
const varName = match[1];
|
|
63
|
+
const startLine = fullText.substring(0, match.index).split('\n').length;
|
|
64
|
+
let pos = match.index + match[0].length;
|
|
65
|
+
let braceDepth = 1;
|
|
66
|
+
while (pos < fullText.length && braceDepth > 0) {
|
|
67
|
+
if (fullText[pos] === '{')
|
|
68
|
+
braceDepth++;
|
|
69
|
+
if (fullText[pos] === '}')
|
|
70
|
+
braceDepth--;
|
|
71
|
+
pos++;
|
|
72
|
+
}
|
|
73
|
+
while (pos < fullText.length && (fullText[pos] === ')' || fullText[pos] === ';'))
|
|
74
|
+
pos++;
|
|
75
|
+
const endLine = fullText.substring(0, pos).split('\n').length;
|
|
76
|
+
const snippet = fullText.substring(match.index, Math.min(pos, match.index + 400));
|
|
77
|
+
results.push({
|
|
78
|
+
anchorImport: 'valibot',
|
|
79
|
+
startLine,
|
|
80
|
+
endLine,
|
|
81
|
+
snippet,
|
|
82
|
+
extractedParams: [
|
|
83
|
+
{ name: 'schemaName', slotType: 'identifier', value: varName.replace(/Schema$/, ''), optional: false },
|
|
84
|
+
],
|
|
85
|
+
confidencePct: 80,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return results;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
export const detectors = [yupSchemaDetector, valibotDetector];
|
|
92
|
+
//# sourceMappingURL=schema-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-validation.js","sourceRoot":"","sources":["../../src/detectors/schema-validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detector pack: State management (recoil, redux-toolkit, mobx)
|
|
3
|
+
*/
|
|
4
|
+
const recoilAtomDetector = {
|
|
5
|
+
id: 'recoil-atom',
|
|
6
|
+
libraryName: 'Recoil',
|
|
7
|
+
packageNames: ['recoil'],
|
|
8
|
+
patternKind: 'state-management',
|
|
9
|
+
detect(sourceFile, fullText) {
|
|
10
|
+
const results = [];
|
|
11
|
+
// Pattern: atom({ key, default }) or atom<Type>({ key, default })
|
|
12
|
+
const atomRe = /(?:export\s+)?const\s+(\w+)\s*=\s*atom\s*(?:<\s*([^>]+)\s*>)?\s*\(\s*\{/g;
|
|
13
|
+
let match;
|
|
14
|
+
while ((match = atomRe.exec(fullText)) !== null) {
|
|
15
|
+
// Make sure it's recoil atom, not jotai
|
|
16
|
+
const imports = sourceFile.getImportDeclarations();
|
|
17
|
+
const isRecoil = imports.some(imp => imp.getModuleSpecifierValue() === 'recoil' &&
|
|
18
|
+
imp.getNamedImports().some(n => n.getName() === 'atom'));
|
|
19
|
+
if (!isRecoil)
|
|
20
|
+
continue;
|
|
21
|
+
const varName = match[1];
|
|
22
|
+
const typeParam = match[2] || 'unknown';
|
|
23
|
+
const startLine = fullText.substring(0, match.index).split('\n').length;
|
|
24
|
+
// Extract key value
|
|
25
|
+
const afterMatch = fullText.substring(match.index);
|
|
26
|
+
const keyMatch = afterMatch.match(/key\s*:\s*['"]([^'"]+)['"]/);
|
|
27
|
+
const defaultMatch = afterMatch.match(/default\s*:\s*([^,\n}]+)/);
|
|
28
|
+
let pos = match.index + match[0].length;
|
|
29
|
+
let braceDepth = 1;
|
|
30
|
+
while (pos < fullText.length && braceDepth > 0) {
|
|
31
|
+
if (fullText[pos] === '{')
|
|
32
|
+
braceDepth++;
|
|
33
|
+
if (fullText[pos] === '}')
|
|
34
|
+
braceDepth--;
|
|
35
|
+
pos++;
|
|
36
|
+
}
|
|
37
|
+
if (pos < fullText.length && fullText[pos] === ')')
|
|
38
|
+
pos++;
|
|
39
|
+
const endLine = fullText.substring(0, pos).split('\n').length;
|
|
40
|
+
const snippet = fullText.substring(match.index, Math.min(pos, match.index + 300));
|
|
41
|
+
results.push({
|
|
42
|
+
anchorImport: 'atom',
|
|
43
|
+
startLine,
|
|
44
|
+
endLine,
|
|
45
|
+
snippet,
|
|
46
|
+
extractedParams: [
|
|
47
|
+
{ name: 'atomName', slotType: 'identifier', value: varName.replace(/State$|Atom$/, ''), optional: false },
|
|
48
|
+
{ name: 'atomType', slotType: 'type', value: typeParam.trim(), optional: false },
|
|
49
|
+
{ name: 'atomKey', slotType: 'expr', value: keyMatch?.[1] || varName, optional: false },
|
|
50
|
+
{ name: 'defaultValue', slotType: 'expr', value: defaultMatch?.[1]?.trim() || 'null', optional: true },
|
|
51
|
+
],
|
|
52
|
+
confidencePct: 85,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return results;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
const reduxSliceDetector = {
|
|
59
|
+
id: 'redux-toolkit-slice',
|
|
60
|
+
libraryName: 'Redux Toolkit',
|
|
61
|
+
packageNames: ['@reduxjs/toolkit'],
|
|
62
|
+
patternKind: 'state-management',
|
|
63
|
+
detect(sourceFile, fullText) {
|
|
64
|
+
const results = [];
|
|
65
|
+
// Pattern: createSlice({ name, initialState, reducers })
|
|
66
|
+
const sliceRe = /(?:export\s+)?const\s+(\w+)\s*=\s*createSlice\s*\(\s*\{/g;
|
|
67
|
+
let match;
|
|
68
|
+
while ((match = sliceRe.exec(fullText)) !== null) {
|
|
69
|
+
const varName = match[1];
|
|
70
|
+
const startLine = fullText.substring(0, match.index).split('\n').length;
|
|
71
|
+
const afterMatch = fullText.substring(match.index);
|
|
72
|
+
const nameMatch = afterMatch.match(/name\s*:\s*['"]([^'"]+)['"]/);
|
|
73
|
+
let pos = match.index + match[0].length;
|
|
74
|
+
let braceDepth = 1;
|
|
75
|
+
while (pos < fullText.length && braceDepth > 0) {
|
|
76
|
+
if (fullText[pos] === '{')
|
|
77
|
+
braceDepth++;
|
|
78
|
+
if (fullText[pos] === '}')
|
|
79
|
+
braceDepth--;
|
|
80
|
+
pos++;
|
|
81
|
+
}
|
|
82
|
+
if (pos < fullText.length && fullText[pos] === ')')
|
|
83
|
+
pos++;
|
|
84
|
+
const endLine = fullText.substring(0, pos).split('\n').length;
|
|
85
|
+
const snippet = fullText.substring(match.index, Math.min(pos, match.index + 400));
|
|
86
|
+
results.push({
|
|
87
|
+
anchorImport: 'createSlice',
|
|
88
|
+
startLine,
|
|
89
|
+
endLine,
|
|
90
|
+
snippet,
|
|
91
|
+
extractedParams: [
|
|
92
|
+
{ name: 'sliceName', slotType: 'identifier', value: varName.replace(/Slice$/, ''), optional: false },
|
|
93
|
+
{ name: 'sliceKey', slotType: 'expr', value: nameMatch?.[1] || varName, optional: false },
|
|
94
|
+
],
|
|
95
|
+
confidencePct: 88,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return results;
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
export const detectors = [recoilAtomDetector, reduxSliceDetector];
|
|
102
|
+
//# sourceMappingURL=state-mgmt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-mgmt.js","sourceRoot":"","sources":["../../src/detectors/state-mgmt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural Detectors — import-agnostic pattern detection.
|
|
3
|
+
*
|
|
4
|
+
* These detectors find structural patterns (models, repositories, DI, caching,
|
|
5
|
+
* conditionals, selects) regardless of which library is used.
|
|
6
|
+
* They have empty packageNames[] so they run on all files.
|
|
7
|
+
*/
|
|
8
|
+
import type { DetectorPack } from '../types.js';
|
|
9
|
+
/** All structural detectors for registration. */
|
|
10
|
+
export declare const detectors: DetectorPack[];
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural Detectors — import-agnostic pattern detection.
|
|
3
|
+
*
|
|
4
|
+
* These detectors find structural patterns (models, repositories, DI, caching,
|
|
5
|
+
* conditionals, selects) regardless of which library is used.
|
|
6
|
+
* They have empty packageNames[] so they run on all files.
|
|
7
|
+
*/
|
|
8
|
+
function lineOf(fullText, index) {
|
|
9
|
+
return fullText.substring(0, index).split('\n').length;
|
|
10
|
+
}
|
|
11
|
+
function extractSnippet(fullText, start, maxLen = 300) {
|
|
12
|
+
return fullText.substring(start, Math.min(start + maxLen, fullText.length));
|
|
13
|
+
}
|
|
14
|
+
// ── structural-model ─────────────────────────────────────────────────────
|
|
15
|
+
// Detects Prisma models, TypeORM entities, Drizzle tables, plain TS class entities
|
|
16
|
+
const structuralModel = {
|
|
17
|
+
id: 'structural-model',
|
|
18
|
+
libraryName: 'structural',
|
|
19
|
+
packageNames: [],
|
|
20
|
+
patternKind: 'structural',
|
|
21
|
+
detect(sourceFile, fullText) {
|
|
22
|
+
const results = [];
|
|
23
|
+
// Prisma-style: model in schema, or TS interface/class with @Entity, @model decorators
|
|
24
|
+
// Pattern: class with decorators like @Entity, @Table, or Prisma model references
|
|
25
|
+
const entityPatterns = [
|
|
26
|
+
// TypeORM/MikroORM @Entity() class
|
|
27
|
+
/@Entity\s*\([^)]*\)\s*(?:export\s+)?class\s+(\w+)/g,
|
|
28
|
+
// Sequelize @Table class
|
|
29
|
+
/@Table\s*(?:\([^)]*\))?\s*(?:export\s+)?class\s+(\w+)/g,
|
|
30
|
+
// Drizzle pgTable/mysqlTable/sqliteTable
|
|
31
|
+
/(?:const|export\s+const)\s+(\w+)\s*=\s*(?:pgTable|mysqlTable|sqliteTable)\s*\(/g,
|
|
32
|
+
// Prisma client usage: prisma.user.findMany() etc
|
|
33
|
+
/prisma\.(\w+)\.\w+\s{0,20}\(/g,
|
|
34
|
+
];
|
|
35
|
+
for (const pattern of entityPatterns) {
|
|
36
|
+
let match;
|
|
37
|
+
while ((match = pattern.exec(fullText)) !== null) {
|
|
38
|
+
const startLine = lineOf(fullText, match.index);
|
|
39
|
+
const params = [{
|
|
40
|
+
name: 'modelName',
|
|
41
|
+
slotType: 'identifier',
|
|
42
|
+
value: match[1],
|
|
43
|
+
optional: false,
|
|
44
|
+
}];
|
|
45
|
+
results.push({
|
|
46
|
+
anchorImport: '',
|
|
47
|
+
startLine,
|
|
48
|
+
endLine: startLine + 5,
|
|
49
|
+
snippet: extractSnippet(fullText, match.index),
|
|
50
|
+
extractedParams: params,
|
|
51
|
+
confidencePct: 75,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return results;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
// ── structural-repository ────────────────────────────────────────────────
|
|
59
|
+
// Detects CRUD wrapper classes/functions
|
|
60
|
+
const structuralRepository = {
|
|
61
|
+
id: 'structural-repository',
|
|
62
|
+
libraryName: 'structural',
|
|
63
|
+
packageNames: [],
|
|
64
|
+
patternKind: 'structural',
|
|
65
|
+
detect(sourceFile, fullText) {
|
|
66
|
+
const results = [];
|
|
67
|
+
// Classes ending in Repository, Repo, Store, DAO
|
|
68
|
+
const repoPattern = /(?:export\s+)?class\s+(\w+(?:Repository|Repo|Store|DAO))\s*(?:extends|implements|{)/g;
|
|
69
|
+
let match;
|
|
70
|
+
while ((match = repoPattern.exec(fullText)) !== null) {
|
|
71
|
+
const startLine = lineOf(fullText, match.index);
|
|
72
|
+
results.push({
|
|
73
|
+
anchorImport: '',
|
|
74
|
+
startLine,
|
|
75
|
+
endLine: startLine + 10,
|
|
76
|
+
snippet: extractSnippet(fullText, match.index),
|
|
77
|
+
extractedParams: [{
|
|
78
|
+
name: 'repoName',
|
|
79
|
+
slotType: 'identifier',
|
|
80
|
+
value: match[1],
|
|
81
|
+
optional: false,
|
|
82
|
+
}],
|
|
83
|
+
confidencePct: 80,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return results;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
// ── structural-dependency ────────────────────────────────────────────────
|
|
90
|
+
// Detects constructor injection, factory functions
|
|
91
|
+
const structuralDependency = {
|
|
92
|
+
id: 'structural-dependency',
|
|
93
|
+
libraryName: 'structural',
|
|
94
|
+
packageNames: [],
|
|
95
|
+
patternKind: 'structural',
|
|
96
|
+
detect(sourceFile, fullText) {
|
|
97
|
+
const results = [];
|
|
98
|
+
// Constructor injection: constructor(private readonly userRepo: UserRepository)
|
|
99
|
+
const ctorInjection = /constructor\s{0,20}\(\s{0,20}((?:private|protected|public)\s+(?:readonly\s+)?\w+\s{0,10}:\s{0,10}\w+(?:\s{0,10},\s{0,10}(?:private|protected|public)\s+(?:readonly\s+)?\w+\s{0,10}:\s{0,10}\w+){0,20})\s{0,20}\)/g;
|
|
100
|
+
let match;
|
|
101
|
+
while ((match = ctorInjection.exec(fullText)) !== null) {
|
|
102
|
+
const params = match[1].split(',').map(p => p.trim());
|
|
103
|
+
if (params.length >= 2) {
|
|
104
|
+
const startLine = lineOf(fullText, match.index);
|
|
105
|
+
results.push({
|
|
106
|
+
anchorImport: '',
|
|
107
|
+
startLine,
|
|
108
|
+
endLine: startLine + 3,
|
|
109
|
+
snippet: extractSnippet(fullText, match.index),
|
|
110
|
+
extractedParams: [{
|
|
111
|
+
name: 'injectionCount',
|
|
112
|
+
slotType: 'expr',
|
|
113
|
+
value: String(params.length),
|
|
114
|
+
optional: false,
|
|
115
|
+
}],
|
|
116
|
+
confidencePct: 70,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// @Injectable() / @Inject() decorators
|
|
121
|
+
const injectPattern = /@(?:Injectable|Inject)\s*\(/g;
|
|
122
|
+
while ((match = injectPattern.exec(fullText)) !== null) {
|
|
123
|
+
const startLine = lineOf(fullText, match.index);
|
|
124
|
+
results.push({
|
|
125
|
+
anchorImport: '',
|
|
126
|
+
startLine,
|
|
127
|
+
endLine: startLine + 2,
|
|
128
|
+
snippet: extractSnippet(fullText, match.index),
|
|
129
|
+
extractedParams: [],
|
|
130
|
+
confidencePct: 85,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return results;
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
// ── structural-cache ─────────────────────────────────────────────────────
|
|
137
|
+
// Detects Redis/memory cache patterns
|
|
138
|
+
const structuralCache = {
|
|
139
|
+
id: 'structural-cache',
|
|
140
|
+
libraryName: 'structural',
|
|
141
|
+
packageNames: [],
|
|
142
|
+
patternKind: 'structural',
|
|
143
|
+
detect(sourceFile, fullText) {
|
|
144
|
+
const results = [];
|
|
145
|
+
const cachePatterns = [
|
|
146
|
+
// Redis client usage
|
|
147
|
+
/(?:redis|cache|cacheClient|cacheManager)\s*\.\s*(?:get|set|del|setex|expire|hget|hset)\s*\(/g,
|
|
148
|
+
// Cache decorator
|
|
149
|
+
/@(?:Cache|Cacheable|CacheEvict|CacheInvalidate)\s*\(/g,
|
|
150
|
+
// Map/Object as cache with TTL
|
|
151
|
+
/new\s+Map\s*<[^>]+>\s*\(\)\s*;?\s*\/\/\s*cache/gi,
|
|
152
|
+
];
|
|
153
|
+
for (const pattern of cachePatterns) {
|
|
154
|
+
let match;
|
|
155
|
+
while ((match = pattern.exec(fullText)) !== null) {
|
|
156
|
+
const startLine = lineOf(fullText, match.index);
|
|
157
|
+
results.push({
|
|
158
|
+
anchorImport: '',
|
|
159
|
+
startLine,
|
|
160
|
+
endLine: startLine + 3,
|
|
161
|
+
snippet: extractSnippet(fullText, match.index),
|
|
162
|
+
extractedParams: [],
|
|
163
|
+
confidencePct: 70,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return results;
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
// ── structural-conditional ───────────────────────────────────────────────
|
|
171
|
+
// Detects conditional rendering, feature flags
|
|
172
|
+
const structuralConditional = {
|
|
173
|
+
id: 'structural-conditional',
|
|
174
|
+
libraryName: 'structural',
|
|
175
|
+
packageNames: [],
|
|
176
|
+
patternKind: 'structural',
|
|
177
|
+
detect(sourceFile, fullText) {
|
|
178
|
+
const results = [];
|
|
179
|
+
// Feature flag patterns: if (featureFlag) / isEnabled('feature') / useFeatureFlag
|
|
180
|
+
const featureFlagPatterns = [
|
|
181
|
+
/(?:useFeatureFlag|useFeature|isFeatureEnabled|featureFlags)\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
182
|
+
/if\s*\(\s*(?:features|flags)\s*\.\s*(\w+)\s*\)/g,
|
|
183
|
+
];
|
|
184
|
+
for (const pattern of featureFlagPatterns) {
|
|
185
|
+
let match;
|
|
186
|
+
while ((match = pattern.exec(fullText)) !== null) {
|
|
187
|
+
const startLine = lineOf(fullText, match.index);
|
|
188
|
+
results.push({
|
|
189
|
+
anchorImport: '',
|
|
190
|
+
startLine,
|
|
191
|
+
endLine: startLine + 5,
|
|
192
|
+
snippet: extractSnippet(fullText, match.index),
|
|
193
|
+
extractedParams: [{
|
|
194
|
+
name: 'flagName',
|
|
195
|
+
slotType: 'identifier',
|
|
196
|
+
value: match[1],
|
|
197
|
+
optional: false,
|
|
198
|
+
}],
|
|
199
|
+
confidencePct: 65,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// JSX conditional rendering: {condition && <Component />}
|
|
204
|
+
const jsxConditional = /\{(\w+)\s*&&\s*</g;
|
|
205
|
+
let match;
|
|
206
|
+
while ((match = jsxConditional.exec(fullText)) !== null) {
|
|
207
|
+
const startLine = lineOf(fullText, match.index);
|
|
208
|
+
results.push({
|
|
209
|
+
anchorImport: '',
|
|
210
|
+
startLine,
|
|
211
|
+
endLine: startLine + 3,
|
|
212
|
+
snippet: extractSnippet(fullText, match.index),
|
|
213
|
+
extractedParams: [{
|
|
214
|
+
name: 'condition',
|
|
215
|
+
slotType: 'expr',
|
|
216
|
+
value: match[1],
|
|
217
|
+
optional: false,
|
|
218
|
+
}],
|
|
219
|
+
confidencePct: 60,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
return results;
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
// ── structural-select ────────────────────────────────────────────────────
|
|
226
|
+
// Detects HTML select/option, headless UI selects
|
|
227
|
+
const structuralSelect = {
|
|
228
|
+
id: 'structural-select',
|
|
229
|
+
libraryName: 'structural',
|
|
230
|
+
packageNames: [],
|
|
231
|
+
patternKind: 'structural',
|
|
232
|
+
detect(sourceFile, fullText) {
|
|
233
|
+
const results = [];
|
|
234
|
+
const selectPatterns = [
|
|
235
|
+
// HTML <select> tag
|
|
236
|
+
/<select\s[^>]*name=['"](\w+)['"]/g,
|
|
237
|
+
// Headless UI Listbox
|
|
238
|
+
/(?:Listbox|Select|Dropdown)\s{0,20}(?:\.\w+\s{0,20})?(?:value|onChange)\s{0,20}=/g,
|
|
239
|
+
];
|
|
240
|
+
for (const pattern of selectPatterns) {
|
|
241
|
+
let match;
|
|
242
|
+
while ((match = pattern.exec(fullText)) !== null) {
|
|
243
|
+
const startLine = lineOf(fullText, match.index);
|
|
244
|
+
results.push({
|
|
245
|
+
anchorImport: '',
|
|
246
|
+
startLine,
|
|
247
|
+
endLine: startLine + 8,
|
|
248
|
+
snippet: extractSnippet(fullText, match.index),
|
|
249
|
+
extractedParams: match[1] ? [{
|
|
250
|
+
name: 'selectName',
|
|
251
|
+
slotType: 'identifier',
|
|
252
|
+
value: match[1],
|
|
253
|
+
optional: false,
|
|
254
|
+
}] : [],
|
|
255
|
+
confidencePct: 65,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return results;
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
/** All structural detectors for registration. */
|
|
263
|
+
export const detectors = [
|
|
264
|
+
structuralModel,
|
|
265
|
+
structuralRepository,
|
|
266
|
+
structuralDependency,
|
|
267
|
+
structuralCache,
|
|
268
|
+
structuralConditional,
|
|
269
|
+
structuralSelect,
|
|
270
|
+
];
|
|
271
|
+
//# sourceMappingURL=structural.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structural.js","sourceRoot":"","sources":["../../src/detectors/structural.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detector pack: Testing libraries (@testing-library/*)
|
|
3
|
+
*/
|
|
4
|
+
const testingLibraryDetector = {
|
|
5
|
+
id: 'testing-library',
|
|
6
|
+
libraryName: 'Testing Library',
|
|
7
|
+
packageNames: ['@testing-library/react', '@testing-library/vue', '@testing-library/user-event'],
|
|
8
|
+
patternKind: 'testing',
|
|
9
|
+
detect(sourceFile, fullText) {
|
|
10
|
+
const results = [];
|
|
11
|
+
// Pattern: render(<Component />) with screen.getByX queries
|
|
12
|
+
const renderBlockRe = /render\s*\(\s*<\s*(\w+)/g;
|
|
13
|
+
let match;
|
|
14
|
+
while ((match = renderBlockRe.exec(fullText)) !== null) {
|
|
15
|
+
const componentName = match[1];
|
|
16
|
+
const startLine = fullText.substring(0, match.index).split('\n').length;
|
|
17
|
+
// Find the test block this render is in
|
|
18
|
+
const beforeRender = fullText.substring(0, match.index);
|
|
19
|
+
const testMatch = beforeRender.match(/(?:it|test)\s*\(\s*['"]([^'"]+)['"]\s*,\s*(?:async\s*)?\(\)\s*=>\s*\{[^]*$/);
|
|
20
|
+
// Count screen.getBy/findBy/queryBy calls after render
|
|
21
|
+
const afterRender = fullText.substring(match.index);
|
|
22
|
+
const screenCalls = (afterRender.match(/screen\.(getBy|findBy|queryBy)\w+/g) || []).length;
|
|
23
|
+
if (screenCalls < 2)
|
|
24
|
+
continue; // Not enough pattern to template
|
|
25
|
+
// Find end of test block
|
|
26
|
+
let pos = match.index;
|
|
27
|
+
let braceDepth = 0;
|
|
28
|
+
while (pos < fullText.length) {
|
|
29
|
+
if (fullText[pos] === '{')
|
|
30
|
+
braceDepth++;
|
|
31
|
+
if (fullText[pos] === '}') {
|
|
32
|
+
braceDepth--;
|
|
33
|
+
if (braceDepth <= 0)
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
pos++;
|
|
37
|
+
}
|
|
38
|
+
const endLine = fullText.substring(0, pos).split('\n').length;
|
|
39
|
+
const snippet = fullText.substring(match.index, Math.min(pos, match.index + 300));
|
|
40
|
+
results.push({
|
|
41
|
+
anchorImport: 'render',
|
|
42
|
+
startLine,
|
|
43
|
+
endLine,
|
|
44
|
+
snippet,
|
|
45
|
+
extractedParams: [
|
|
46
|
+
{ name: 'componentName', slotType: 'identifier', value: componentName, optional: false },
|
|
47
|
+
{ name: 'testDescription', slotType: 'expr', value: testMatch?.[1] || 'renders correctly', optional: true },
|
|
48
|
+
],
|
|
49
|
+
confidencePct: 70,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return results;
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
export const detectors = [testingLibraryDetector];
|
|
56
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../../src/detectors/testing.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,sBAAsB,GAAiB;IAC3C,EAAE,EAAE,iBAAiB;IACrB,WAAW,EAAE,iBAAiB;IAC9B,YAAY,EAAE,CAAC,wBAAwB,EAAE,sBAAsB,EAAE,6BAA6B,CAAC;IAC/F,WAAW,EAAE,SAAS;IACtB,MAAM,CAAC,UAAsB,EAAE,QAAgB;QAC7C,MAAM,OAAO,GAAsB,EAAE,CAAC;QAEtC,4DAA4D;QAC5D,MAAM,aAAa,GAAG,0BAA0B,CAAC;QACjD,IAAI,KAA6B,CAAC;QAClC,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACvD,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;YAExE,wCAAwC;YACxC,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YACxD,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,4EAA4E,CAAC,CAAC;YAEnH,uDAAuD;YACvD,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACpD,MAAM,WAAW,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,oCAAoC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YAE3F,IAAI,WAAW,GAAG,CAAC;gBAAE,SAAS,CAAC,iCAAiC;YAEhE,yBAAyB;YACzB,IAAI,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;YACtB,IAAI,UAAU,GAAG,CAAC,CAAC;YACnB,OAAO,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,GAAG;oBAAE,UAAU,EAAE,CAAC;gBACxC,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;oBAC1B,UAAU,EAAE,CAAC;oBACb,IAAI,UAAU,IAAI,CAAC;wBAAE,MAAM;gBAC7B,CAAC;gBACD,GAAG,EAAE,CAAC;YACR,CAAC;YACD,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;YAC9D,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC;YAElF,OAAO,CAAC,IAAI,CAAC;gBACX,YAAY,EAAE,QAAQ;gBACtB,SAAS;gBACT,OAAO;gBACP,OAAO;gBACP,eAAe,EAAE;oBACf,EAAE,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE;oBACxF,EAAE,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,mBAAmB,EAAE,QAAQ,EAAE,IAAI,EAAE;iBAC5G;gBACD,aAAa,EAAE,EAAE;aAClB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAmB,CAAC,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detector pack: Vue composables (@vueuse/*)
|
|
3
|
+
*/
|
|
4
|
+
const vueUseDetector = {
|
|
5
|
+
id: 'vueuse-composable',
|
|
6
|
+
libraryName: 'VueUse',
|
|
7
|
+
packageNames: ['@vueuse/core', '@vueuse/integrations'],
|
|
8
|
+
patternKind: 'composable',
|
|
9
|
+
detect(sourceFile, fullText) {
|
|
10
|
+
const results = [];
|
|
11
|
+
// Detect custom composables that wrap VueUse primitives
|
|
12
|
+
// Pattern: function useX() { ... useSomeVueUse(...) ... return { ... } }
|
|
13
|
+
const composableRe = /(?:export\s+)?function\s+(use\w+)\s*\([^)]*\)\s*\{/g;
|
|
14
|
+
let match;
|
|
15
|
+
while ((match = composableRe.exec(fullText)) !== null) {
|
|
16
|
+
const fnName = match[1];
|
|
17
|
+
const startLine = fullText.substring(0, match.index).split('\n').length;
|
|
18
|
+
// Find the function body
|
|
19
|
+
let pos = match.index + match[0].length;
|
|
20
|
+
let braceDepth = 1;
|
|
21
|
+
while (pos < fullText.length && braceDepth > 0) {
|
|
22
|
+
if (fullText[pos] === '{')
|
|
23
|
+
braceDepth++;
|
|
24
|
+
if (fullText[pos] === '}')
|
|
25
|
+
braceDepth--;
|
|
26
|
+
pos++;
|
|
27
|
+
}
|
|
28
|
+
const fnBody = fullText.substring(match.index, pos);
|
|
29
|
+
const endLine = fullText.substring(0, pos).split('\n').length;
|
|
30
|
+
// Check if the function body uses any @vueuse import
|
|
31
|
+
const vueUseImports = sourceFile.getImportDeclarations().filter(imp => {
|
|
32
|
+
const mod = imp.getModuleSpecifierValue();
|
|
33
|
+
return mod.startsWith('@vueuse/');
|
|
34
|
+
});
|
|
35
|
+
if (vueUseImports.length === 0)
|
|
36
|
+
continue;
|
|
37
|
+
const usedVueUseApis = vueUseImports.flatMap(imp => imp.getNamedImports().map(n => n.getName())).filter(name => fnBody.includes(name));
|
|
38
|
+
if (usedVueUseApis.length === 0)
|
|
39
|
+
continue;
|
|
40
|
+
const snippet = fnBody.substring(0, Math.min(fnBody.length, 300));
|
|
41
|
+
results.push({
|
|
42
|
+
anchorImport: usedVueUseApis[0],
|
|
43
|
+
startLine,
|
|
44
|
+
endLine,
|
|
45
|
+
snippet,
|
|
46
|
+
extractedParams: [
|
|
47
|
+
{ name: 'composableName', slotType: 'identifier', value: fnName, optional: false },
|
|
48
|
+
{ name: 'wrappedApis', slotType: 'expr', value: usedVueUseApis.join(', '), optional: false },
|
|
49
|
+
],
|
|
50
|
+
confidencePct: 75,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return results;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
export const detectors = [vueUseDetector];
|
|
57
|
+
//# sourceMappingURL=vue-composables.js.map
|