@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.
Files changed (104) hide show
  1. package/LICENSE +661 -0
  2. package/dist/concept-gap-adapter.d.ts +17 -0
  3. package/dist/concept-gap-adapter.js +43 -0
  4. package/dist/concept-gap-adapter.js.map +1 -0
  5. package/dist/detector-registry.d.ts +31 -0
  6. package/dist/detector-registry.js +89 -0
  7. package/dist/detector-registry.js.map +1 -0
  8. package/dist/detectors/animation.d.ts +5 -0
  9. package/dist/detectors/animation.js +67 -0
  10. package/dist/detectors/animation.js.map +1 -0
  11. package/dist/detectors/data-fetching.d.ts +5 -0
  12. package/dist/detectors/data-fetching.js +117 -0
  13. package/dist/detectors/data-fetching.js.map +1 -0
  14. package/dist/detectors/express-middleware.d.ts +5 -0
  15. package/dist/detectors/express-middleware.js +52 -0
  16. package/dist/detectors/express-middleware.js.map +1 -0
  17. package/dist/detectors/react-forms.d.ts +5 -0
  18. package/dist/detectors/react-forms.js +89 -0
  19. package/dist/detectors/react-forms.js.map +1 -0
  20. package/dist/detectors/schema-validation.d.ts +5 -0
  21. package/dist/detectors/schema-validation.js +92 -0
  22. package/dist/detectors/schema-validation.js.map +1 -0
  23. package/dist/detectors/state-mgmt.d.ts +5 -0
  24. package/dist/detectors/state-mgmt.js +102 -0
  25. package/dist/detectors/state-mgmt.js.map +1 -0
  26. package/dist/detectors/structural.d.ts +10 -0
  27. package/dist/detectors/structural.js +271 -0
  28. package/dist/detectors/structural.js.map +1 -0
  29. package/dist/detectors/testing.d.ts +5 -0
  30. package/dist/detectors/testing.js +56 -0
  31. package/dist/detectors/testing.js.map +1 -0
  32. package/dist/detectors/vue-composables.d.ts +5 -0
  33. package/dist/detectors/vue-composables.js +57 -0
  34. package/dist/detectors/vue-composables.js.map +1 -0
  35. package/dist/evolve-dedup.d.ts +12 -0
  36. package/dist/evolve-dedup.js +50 -0
  37. package/dist/evolve-dedup.js.map +1 -0
  38. package/dist/evolve-rollback.d.ts +58 -0
  39. package/dist/evolve-rollback.js +242 -0
  40. package/dist/evolve-rollback.js.map +1 -0
  41. package/dist/evolve-runner.d.ts +22 -0
  42. package/dist/evolve-runner.js +183 -0
  43. package/dist/evolve-runner.js.map +1 -0
  44. package/dist/evolve-validator-v4.d.ts +11 -0
  45. package/dist/evolve-validator-v4.js +253 -0
  46. package/dist/evolve-validator-v4.js.map +1 -0
  47. package/dist/evolved-node-loader.d.ts +61 -0
  48. package/dist/evolved-node-loader.js +228 -0
  49. package/dist/evolved-node-loader.js.map +1 -0
  50. package/dist/evolved-types.d.ts +110 -0
  51. package/dist/evolved-types.js +8 -0
  52. package/dist/evolved-types.js.map +1 -0
  53. package/dist/expressibility-scorer.d.ts +19 -0
  54. package/dist/expressibility-scorer.js +78 -0
  55. package/dist/expressibility-scorer.js.map +1 -0
  56. package/dist/gap-detector.d.ts +26 -0
  57. package/dist/gap-detector.js +141 -0
  58. package/dist/gap-detector.js.map +1 -0
  59. package/dist/golden-test-runner.d.ts +27 -0
  60. package/dist/golden-test-runner.js +120 -0
  61. package/dist/golden-test-runner.js.map +1 -0
  62. package/dist/graduation.d.ts +36 -0
  63. package/dist/graduation.js +175 -0
  64. package/dist/graduation.js.map +1 -0
  65. package/dist/index.d.ts +40 -0
  66. package/dist/index.js +58 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/llm-discovery.d.ts +55 -0
  69. package/dist/llm-discovery.js +352 -0
  70. package/dist/llm-discovery.js.map +1 -0
  71. package/dist/llm-provider.d.ts +35 -0
  72. package/dist/llm-provider.js +143 -0
  73. package/dist/llm-provider.js.map +1 -0
  74. package/dist/node-governance.d.ts +23 -0
  75. package/dist/node-governance.js +45 -0
  76. package/dist/node-governance.js.map +1 -0
  77. package/dist/node-proposer.d.ts +27 -0
  78. package/dist/node-proposer.js +127 -0
  79. package/dist/node-proposer.js.map +1 -0
  80. package/dist/node-validator.d.ts +16 -0
  81. package/dist/node-validator.js +74 -0
  82. package/dist/node-validator.js.map +1 -0
  83. package/dist/pattern-analyzer.d.ts +28 -0
  84. package/dist/pattern-analyzer.js +181 -0
  85. package/dist/pattern-analyzer.js.map +1 -0
  86. package/dist/quality-scorer.d.ts +16 -0
  87. package/dist/quality-scorer.js +79 -0
  88. package/dist/quality-scorer.js.map +1 -0
  89. package/dist/sandboxed-generator.d.ts +26 -0
  90. package/dist/sandboxed-generator.js +133 -0
  91. package/dist/sandboxed-generator.js.map +1 -0
  92. package/dist/staging.d.ts +81 -0
  93. package/dist/staging.js +414 -0
  94. package/dist/staging.js.map +1 -0
  95. package/dist/template-proposer.d.ts +24 -0
  96. package/dist/template-proposer.js +103 -0
  97. package/dist/template-proposer.js.map +1 -0
  98. package/dist/template-validator.d.ts +18 -0
  99. package/dist/template-validator.js +174 -0
  100. package/dist/template-validator.js.map +1 -0
  101. package/dist/types.d.ts +169 -0
  102. package/dist/types.js +7 -0
  103. package/dist/types.js.map +1 -0
  104. 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,5 @@
1
+ /**
2
+ * Detector pack: State management (recoil, redux-toolkit, mobx)
3
+ */
4
+ import type { DetectorPack } from '../types.js';
5
+ export declare const detectors: DetectorPack[];
@@ -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,5 @@
1
+ /**
2
+ * Detector pack: Testing libraries (@testing-library/*)
3
+ */
4
+ import type { DetectorPack } from '../types.js';
5
+ export declare const detectors: DetectorPack[];
@@ -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,5 @@
1
+ /**
2
+ * Detector pack: Vue composables (@vueuse/*)
3
+ */
4
+ import type { DetectorPack } from '../types.js';
5
+ export declare const detectors: DetectorPack[];
@@ -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