entkapp 5.5.0 → 5.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/bin/cli.js +2 -2
  3. package/bin/cli.mjs +175 -0
  4. package/index.cjs +18 -0
  5. package/index.mjs +51 -0
  6. package/package.json +7 -6
  7. package/src/EngineContext.mjs +428 -0
  8. package/src/Initializer.mjs +82 -0
  9. package/src/analyzers/CodeSmellAnalyzer.mjs +106 -0
  10. package/src/analyzers/OxcAnalyzer.mjs +11 -0
  11. package/src/api/HeadlessAPI.js +31 -16
  12. package/src/api/HeadlessAPI.mjs +369 -0
  13. package/src/api/PluginSDK.mjs +135 -0
  14. package/src/ast/ASTAnalyzer.js +17 -3
  15. package/src/ast/ASTAnalyzer.mjs +742 -0
  16. package/src/ast/AdvancedAnalysis.mjs +586 -0
  17. package/src/ast/BarrelParser.mjs +230 -0
  18. package/src/ast/DeadCodeDetector.js +7 -5
  19. package/src/ast/DeadCodeDetector.mjs +92 -0
  20. package/src/ast/MagicDetector.mjs +203 -0
  21. package/src/ast/OxcAnalyzer.mjs +188 -0
  22. package/src/ast/SecretScanner.mjs +374 -0
  23. package/src/healing/GitSandbox.mjs +82 -0
  24. package/src/healing/SelfHealer.mjs +48 -0
  25. package/src/index.js +37 -1
  26. package/src/index.mjs +1176 -0
  27. package/src/performance/GraphCache.mjs +108 -0
  28. package/src/performance/SupplyChainGuard.mjs +92 -0
  29. package/src/performance/WorkerPool.mjs +132 -0
  30. package/src/performance/WorkerTaskRunner.mjs +144 -0
  31. package/src/plugins/BasePlugin.mjs +240 -0
  32. package/src/plugins/PluginRegistry.mjs +203 -0
  33. package/src/plugins/ecosystems/BackendServices.mjs +197 -0
  34. package/src/plugins/ecosystems/GenericPlugins.mjs +142 -0
  35. package/src/plugins/ecosystems/ModernFrameworks.mjs +162 -0
  36. package/src/plugins/ecosystems/MorePlugins.mjs +562 -0
  37. package/src/plugins/ecosystems/NewPlugins.mjs +526 -0
  38. package/src/plugins/ecosystems/NextJsPlugin.mjs +45 -0
  39. package/src/plugins/ecosystems/PluginLoader.mjs +193 -0
  40. package/src/plugins/ecosystems/TypeScriptPlugin.mjs +56 -0
  41. package/src/plugins/ecosystems/UltimateBundle.mjs +1182 -0
  42. package/src/refractor/ImpactAnalyzer.mjs +92 -0
  43. package/src/refractor/SourceRewriter.mjs +86 -0
  44. package/src/refractor/TransactionManager.mjs +5 -0
  45. package/src/refractor/TypeIntegrity.mjs +4 -0
  46. package/src/resolution/BuildOrchestrator.mjs +46 -0
  47. package/src/resolution/CircularDetector.mjs +91 -0
  48. package/src/resolution/ConfigGenerator.mjs +83 -0
  49. package/src/resolution/ConfigLoader.mjs +94 -0
  50. package/src/resolution/DepencyResolver.mjs +66 -0
  51. package/src/resolution/DependencyFixer.mjs +88 -0
  52. package/src/resolution/DependencyProfiler.mjs +286 -0
  53. package/src/resolution/EntryPointDetector.mjs +134 -0
  54. package/src/resolution/FrameworkConfigParser.mjs +119 -0
  55. package/src/resolution/GraphAnalyzer.mjs +80 -0
  56. package/src/resolution/MigrationAnalyzer.mjs +60 -0
  57. package/src/resolution/PathMapper.mjs +82 -0
  58. package/src/resolution/TSConfigLoader.mjs +162 -0
  59. package/src/resolution/WorkSpaceGraph.mjs +183 -0
  60. package/src/resolution/WorkspaceDiagnostic.mjs +139 -0
  61. package/test.js +76 -0
  62. package/wrangler.toml +6 -0
@@ -0,0 +1,562 @@
1
+ /**
2
+ * ============================================================================
3
+ * More Ecosystem Plugins for entkapp v5.0.0
4
+ * ============================================================================
5
+ * Build tools, testing, linting, formatting, and dev tooling plugins.
6
+ * v5.0.0: All plugins implement getRequiredPackages() for dependency detection.
7
+ */
8
+ import path from 'path';
9
+ import fs from 'fs/promises';
10
+ import { BasePlugin } from '../BasePlugin.mjs';
11
+
12
+ // ─── BUILD TOOLS ────────────────────────────────────────────────────────────
13
+
14
+ export class VitePlugin extends BasePlugin {
15
+ get name() { return 'vite'; }
16
+ getConfigFiles() { return ['vite.config.mjs', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs']; }
17
+ getRequiredPackages() { return [{ name: 'vite', dev: true }]; }
18
+ async isActive(baseDir) {
19
+ for (const f of this.getConfigFiles()) {
20
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
21
+ }
22
+ return false;
23
+ }
24
+ }
25
+
26
+ export class EsbuildPlugin extends BasePlugin {
27
+ get name() { return 'esbuild'; }
28
+ getConfigFiles() { return ['esbuild.config.mjs', 'esbuild.config.mjs', 'esbuild.config.ts']; }
29
+ getRequiredPackages() { return [{ name: 'esbuild', dev: true }]; }
30
+ async isActive(baseDir) {
31
+ for (const f of this.getConfigFiles()) {
32
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
33
+ }
34
+ try {
35
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
36
+ return !!(pkgJson.dependencies?.esbuild || pkgJson.devDependencies?.esbuild);
37
+ } catch { return false; }
38
+ }
39
+ }
40
+
41
+ export class RollupPlugin extends BasePlugin {
42
+ get name() { return 'rollup'; }
43
+ getConfigFiles() { return ['rollup.config.mjs', 'rollup.config.mjs', 'rollup.config.ts']; }
44
+ getRequiredPackages() { return [{ name: 'rollup', dev: true }]; }
45
+ async isActive(baseDir) {
46
+ for (const f of this.getConfigFiles()) {
47
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
48
+ }
49
+ try {
50
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
51
+ return !!(pkgJson.dependencies?.rollup || pkgJson.devDependencies?.rollup);
52
+ } catch { return false; }
53
+ }
54
+ }
55
+
56
+ export class WebpackPlugin extends BasePlugin {
57
+ get name() { return 'webpack'; }
58
+ getConfigFiles() { return ['webpack.config.mjs', 'webpack.config.ts', 'webpack.config.mjs', 'webpack.config.cjs']; }
59
+ getRequiredPackages() { return [{ name: 'webpack', dev: true }]; }
60
+ async isActive(baseDir) {
61
+ for (const f of this.getConfigFiles()) {
62
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
63
+ }
64
+ try {
65
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
66
+ return !!(pkgJson.dependencies?.webpack || pkgJson.devDependencies?.webpack);
67
+ } catch { return false; }
68
+ }
69
+ }
70
+
71
+ export class ParcelPlugin extends BasePlugin {
72
+ get name() { return 'parcel'; }
73
+ getConfigFiles() { return ['.parcelrc', '.parcelrc.json']; }
74
+ getRequiredPackages() { return [{ name: 'parcel', dev: true }]; }
75
+ async isActive(baseDir) {
76
+ for (const f of this.getConfigFiles()) {
77
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
78
+ }
79
+ try {
80
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
81
+ return !!(pkgJson.dependencies?.parcel || pkgJson.devDependencies?.parcel);
82
+ } catch { return false; }
83
+ }
84
+ }
85
+
86
+ export class TurboPlugin extends BasePlugin {
87
+ get name() { return 'turbo'; }
88
+ getConfigFiles() { return ['turbo.json']; }
89
+ getRequiredPackages() { return [{ name: 'turbo', dev: true }]; }
90
+ async isActive(baseDir) {
91
+ try { await fs.access(path.join(baseDir, 'turbo.json')); return true; } catch { return false; }
92
+ }
93
+ }
94
+
95
+ export class NxPlugin extends BasePlugin {
96
+ get name() { return 'nx'; }
97
+ getConfigFiles() { return ['nx.json', 'workspace.json']; }
98
+ getRequiredPackages() { return [{ name: 'nx', dev: true }]; }
99
+ async isActive(baseDir) {
100
+ try { await fs.access(path.join(baseDir, 'nx.json')); return true; } catch { return false; }
101
+ }
102
+ }
103
+
104
+ // ─── CSS / STYLING ───────────────────────────────────────────────────────────
105
+
106
+ export class TailwindPlugin extends BasePlugin {
107
+ get name() { return 'tailwind'; }
108
+ getConfigFiles() { return ['tailwind.config.mjs', 'tailwind.config.ts', 'tailwind.config.mjs', 'tailwind.config.cjs']; }
109
+ getRequiredPackages() { return [{ name: 'tailwindcss', dev: true }]; }
110
+ async isActive(baseDir) {
111
+ for (const f of this.getConfigFiles()) {
112
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
113
+ }
114
+ try {
115
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
116
+ return !!(pkgJson.dependencies?.tailwindcss || pkgJson.devDependencies?.tailwindcss);
117
+ } catch { return false; }
118
+ }
119
+ }
120
+
121
+ export class PostcssPlugin extends BasePlugin {
122
+ get name() { return 'postcss'; }
123
+ getConfigFiles() { return ['postcss.config.mjs', 'postcss.config.cjs', 'postcss.config.mjs', 'postcss.config.ts', '.postcssrc', '.postcssrc.json', '.postcssrc.mjs']; }
124
+ getRequiredPackages() { return [{ name: 'postcss', dev: true }]; }
125
+ async isActive(baseDir) {
126
+ for (const f of this.getConfigFiles()) {
127
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
128
+ }
129
+ try {
130
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
131
+ return !!(pkgJson.dependencies?.postcss || pkgJson.devDependencies?.postcss);
132
+ } catch { return false; }
133
+ }
134
+ }
135
+
136
+ export class UnoCSSPlugin extends BasePlugin {
137
+ get name() { return 'unocss'; }
138
+ getConfigFiles() { return ['uno.config.ts', 'uno.config.mjs', 'unocss.config.ts', 'unocss.config.mjs']; }
139
+ getRequiredPackages() { return [{ name: 'unocss', dev: true }]; }
140
+ async isActive(baseDir) {
141
+ for (const f of this.getConfigFiles()) {
142
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
143
+ }
144
+ return false;
145
+ }
146
+ }
147
+
148
+ export class StylelintPlugin extends BasePlugin {
149
+ get name() { return 'stylelint'; }
150
+ getConfigFiles() { return ['.stylelintrc', '.stylelintrc.mjs', '.stylelintrc.cjs', '.stylelintrc.json', '.stylelintrc.yml', '.stylelintrc.yaml', 'stylelint.config.mjs', 'stylelint.config.cjs']; }
151
+ getRequiredPackages() { return [{ name: 'stylelint', dev: true }]; }
152
+ async isActive(baseDir) {
153
+ for (const f of this.getConfigFiles()) {
154
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
155
+ }
156
+ try {
157
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
158
+ return !!(pkgJson.dependencies?.stylelint || pkgJson.devDependencies?.stylelint);
159
+ } catch { return false; }
160
+ }
161
+ }
162
+
163
+ // ─── LINTING / FORMATTING ────────────────────────────────────────────────────
164
+
165
+ export class EslintPlugin extends BasePlugin {
166
+ get name() { return 'eslint'; }
167
+ getConfigFiles() { return ['.eslintrc', '.eslintrc.mjs', '.eslintrc.cjs', '.eslintrc.json', '.eslintrc.yml', '.eslintrc.yaml', 'eslint.config.mjs', 'eslint.config.mjs', 'eslint.config.cjs']; }
168
+ getRequiredPackages() { return [{ name: 'eslint', dev: true }]; }
169
+ async isActive(baseDir) {
170
+ for (const f of this.getConfigFiles()) {
171
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
172
+ }
173
+ try {
174
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
175
+ return !!(pkgJson.dependencies?.eslint || pkgJson.devDependencies?.eslint);
176
+ } catch { return false; }
177
+ }
178
+ }
179
+
180
+ export class PrettierPlugin extends BasePlugin {
181
+ get name() { return 'prettier'; }
182
+ getConfigFiles() { return ['.prettierrc', '.prettierrc.mjs', '.prettierrc.cjs', '.prettierrc.json', '.prettierrc.yml', '.prettierrc.yaml', '.prettierrc.toml', 'prettier.config.mjs', 'prettier.config.cjs', 'prettier.config.mjs']; }
183
+ getRequiredPackages() { return [{ name: 'prettier', dev: true }]; }
184
+ async isActive(baseDir) {
185
+ for (const f of this.getConfigFiles()) {
186
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
187
+ }
188
+ try {
189
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
190
+ return !!(pkgJson.dependencies?.prettier || pkgJson.devDependencies?.prettier);
191
+ } catch { return false; }
192
+ }
193
+ }
194
+
195
+ export class BiomePlugin extends BasePlugin {
196
+ get name() { return 'biome'; }
197
+ getConfigFiles() { return ['biome.json', 'biome.jsonc']; }
198
+ getRequiredPackages() { return [{ name: '@biomejs/biome', dev: true }]; }
199
+ async isActive(baseDir) {
200
+ for (const f of this.getConfigFiles()) {
201
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
202
+ }
203
+ return false;
204
+ }
205
+ }
206
+
207
+ export class OxlintPlugin extends BasePlugin {
208
+ get name() { return 'oxlint'; }
209
+ getConfigFiles() { return ['.oxlintrc', '.oxlintrc.json', 'oxlint.json']; }
210
+ getRequiredPackages() { return [{ name: 'oxlint', dev: true }]; }
211
+ async isActive(baseDir) {
212
+ for (const f of this.getConfigFiles()) {
213
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
214
+ }
215
+ try {
216
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
217
+ return !!(pkgJson.dependencies?.oxlint || pkgJson.devDependencies?.oxlint);
218
+ } catch { return false; }
219
+ }
220
+ }
221
+
222
+ // ─── GIT HOOKS / COMMIT TOOLING ──────────────────────────────────────────────
223
+
224
+ export class HuskyPlugin extends BasePlugin {
225
+ get name() { return 'husky'; }
226
+ getConfigFiles() { return ['.husky/pre-commit', '.husky/pre-push', '.husky/commit-msg', '.husky/_/husky.sh']; }
227
+ getRequiredPackages() { return [{ name: 'husky', dev: true }]; }
228
+ async isActive(baseDir) {
229
+ for (const f of this.getConfigFiles()) {
230
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
231
+ }
232
+ try {
233
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
234
+ return !!(pkgJson.dependencies?.husky || pkgJson.devDependencies?.husky);
235
+ } catch { return false; }
236
+ }
237
+ }
238
+
239
+ export class LintStagedPlugin extends BasePlugin {
240
+ get name() { return 'lint-staged'; }
241
+ getConfigFiles() { return ['.lintstagedrc', '.lintstagedrc.mjs', '.lintstagedrc.cjs', '.lintstagedrc.json', '.lintstagedrc.yml', '.lintstagedrc.yaml', 'lint-staged.config.mjs', 'lint-staged.config.cjs']; }
242
+ getRequiredPackages() { return [{ name: 'lint-staged', dev: true }]; }
243
+ async isActive(baseDir) {
244
+ for (const f of this.getConfigFiles()) {
245
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
246
+ }
247
+ try {
248
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
249
+ if (pkgJson['lint-staged']) return true;
250
+ return !!(pkgJson.dependencies?.['lint-staged'] || pkgJson.devDependencies?.['lint-staged']);
251
+ } catch { return false; }
252
+ }
253
+ }
254
+
255
+ export class CommitlintPlugin extends BasePlugin {
256
+ get name() { return 'commitlint'; }
257
+ getConfigFiles() { return ['.commitlintrc', '.commitlintrc.mjs', '.commitlintrc.cjs', '.commitlintrc.json', '.commitlintrc.yml', '.commitlintrc.yaml', 'commitlint.config.mjs', 'commitlint.config.cjs', 'commitlint.config.ts']; }
258
+ getRequiredPackages() { return [{ name: '@commitlint/cli', dev: true }, { name: '@commitlint/config-conventional', dev: true, optional: true }]; }
259
+ async isActive(baseDir) {
260
+ for (const f of this.getConfigFiles()) {
261
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
262
+ }
263
+ try {
264
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
265
+ return !!(pkgJson.dependencies?.['@commitlint/cli'] || pkgJson.devDependencies?.['@commitlint/cli']);
266
+ } catch { return false; }
267
+ }
268
+ }
269
+
270
+ export class ChangesetPlugin extends BasePlugin {
271
+ get name() { return 'changeset'; }
272
+ getConfigFiles() { return ['.changeset/config.json']; }
273
+ getRequiredPackages() { return [{ name: '@changesets/cli', dev: true }]; }
274
+ async isActive(baseDir) {
275
+ try { await fs.access(path.join(baseDir, '.changeset/config.json')); return true; } catch { return false; }
276
+ }
277
+ }
278
+
279
+ // ─── TRANSPILERS ─────────────────────────────────────────────────────────────
280
+
281
+ export class BabelPlugin extends BasePlugin {
282
+ get name() { return 'babel'; }
283
+ getConfigFiles() { return ['.babelrc', '.babelrc.mjs', '.babelrc.cjs', '.babelrc.json', '.babelrc.mjs', 'babel.config.mjs', 'babel.config.cjs', 'babel.config.json', 'babel.config.mjs']; }
284
+ getRequiredPackages() { return [{ name: '@babel/core', dev: true }]; }
285
+ async isActive(baseDir) {
286
+ for (const f of this.getConfigFiles()) {
287
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
288
+ }
289
+ try {
290
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
291
+ return !!(pkgJson.dependencies?.['@babel/core'] || pkgJson.devDependencies?.['@babel/core']);
292
+ } catch { return false; }
293
+ }
294
+ }
295
+
296
+ export class SWCPlugin extends BasePlugin {
297
+ get name() { return 'swc'; }
298
+ getConfigFiles() { return ['.swcrc', '.swcrc.json']; }
299
+ getRequiredPackages() { return [{ name: '@swc/core', dev: true }]; }
300
+ async isActive(baseDir) {
301
+ for (const f of this.getConfigFiles()) {
302
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
303
+ }
304
+ try {
305
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
306
+ return !!(pkgJson.dependencies?.['@swc/core'] || pkgJson.devDependencies?.['@swc/core']);
307
+ } catch { return false; }
308
+ }
309
+ }
310
+
311
+ // ─── TESTING ─────────────────────────────────────────────────────────────────
312
+
313
+ export class JestPlugin extends BasePlugin {
314
+ get name() { return 'jest'; }
315
+ getConfigFiles() { return ['jest.config.mjs', 'jest.config.ts', 'jest.config.mjs', 'jest.config.cjs', 'jest.config.json']; }
316
+ getRequiredPackages() { return [{ name: 'jest', dev: true }]; }
317
+ getRoutePatterns() { return [/\.test\.[jt]sx?$/, /\.spec\.[jt]sx?$/]; }
318
+ async isActive(baseDir) {
319
+ for (const f of this.getConfigFiles()) {
320
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
321
+ }
322
+ try {
323
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
324
+ if (pkgJson.jest) return true;
325
+ return !!(pkgJson.dependencies?.jest || pkgJson.devDependencies?.jest);
326
+ } catch { return false; }
327
+ }
328
+ }
329
+
330
+ export class VitestPlugin extends BasePlugin {
331
+ get name() { return 'vitest'; }
332
+ getConfigFiles() { return ['vitest.config.mjs', 'vitest.config.ts', 'vitest.config.mjs', 'vitest.workspace.ts', 'vitest.workspace.mjs']; }
333
+ getRequiredPackages() { return [{ name: 'vitest', dev: true }]; }
334
+ getRoutePatterns() { return [/\.test\.[jt]sx?$/, /\.spec\.[jt]sx?$/]; }
335
+ async isActive(baseDir) {
336
+ for (const f of this.getConfigFiles()) {
337
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
338
+ }
339
+ try {
340
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
341
+ return !!(pkgJson.dependencies?.vitest || pkgJson.devDependencies?.vitest);
342
+ } catch { return false; }
343
+ }
344
+ }
345
+
346
+ export class PlaywrightPlugin extends BasePlugin {
347
+ get name() { return 'playwright'; }
348
+ getConfigFiles() { return ['playwright.config.ts', 'playwright.config.mjs']; }
349
+ getRequiredPackages() { return [{ name: '@playwright/test', dev: true }]; }
350
+ getRoutePatterns() { return [/\.spec\.ts$/, /\.spec\.js$/]; }
351
+ async isActive(baseDir) {
352
+ for (const f of this.getConfigFiles()) {
353
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
354
+ }
355
+ try {
356
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
357
+ return !!(pkgJson.dependencies?.['@playwright/test'] || pkgJson.devDependencies?.['@playwright/test']);
358
+ } catch { return false; }
359
+ }
360
+ }
361
+
362
+ export class CypressPlugin extends BasePlugin {
363
+ get name() { return 'cypress'; }
364
+ getConfigFiles() { return ['cypress.config.ts', 'cypress.config.mjs', 'cypress.json']; }
365
+ getRequiredPackages() { return [{ name: 'cypress', dev: true }]; }
366
+ getRoutePatterns() { return [/cypress\/e2e\/.*\.cy\.[jt]s$/]; }
367
+ async isActive(baseDir) {
368
+ for (const f of this.getConfigFiles()) {
369
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
370
+ }
371
+ try {
372
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
373
+ return !!(pkgJson.dependencies?.cypress || pkgJson.devDependencies?.cypress);
374
+ } catch { return false; }
375
+ }
376
+ }
377
+
378
+ export class StorybookPlugin extends BasePlugin {
379
+ get name() { return 'storybook'; }
380
+ getConfigFiles() { return ['.storybook/main.mjs', '.storybook/main.ts', '.storybook/main.cjs', '.storybook/preview.mjs', '.storybook/preview.ts']; }
381
+ getRequiredPackages() { return [{ name: 'storybook', dev: true, optional: true }, { name: '@storybook/react', dev: true, optional: true }]; }
382
+ getRoutePatterns() { return [/\.stories\.[jt]sx?$/]; }
383
+ async isActive(baseDir) {
384
+ for (const f of this.getConfigFiles()) {
385
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
386
+ }
387
+ try {
388
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
389
+ const allDeps = { ...(pkgJson.dependencies || {}), ...(pkgJson.devDependencies || {}) };
390
+ return Object.keys(allDeps).some(k => k.startsWith('@storybook/') || k === 'storybook');
391
+ } catch { return false; }
392
+ }
393
+ }
394
+
395
+ export class MswPlugin extends BasePlugin {
396
+ get name() { return 'msw'; }
397
+ getConfigFiles() { return ['msw.config.ts', 'msw.config.mjs', 'public/mockServiceWorker.mjs']; }
398
+ getRequiredPackages() { return [{ name: 'msw', dev: true }]; }
399
+ async isActive(baseDir) {
400
+ for (const f of this.getConfigFiles()) {
401
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
402
+ }
403
+ try {
404
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
405
+ return !!(pkgJson.dependencies?.msw || pkgJson.devDependencies?.msw);
406
+ } catch { return false; }
407
+ }
408
+ }
409
+
410
+ // ─── CI / INFRA ──────────────────────────────────────────────────────────────
411
+
412
+ export class GithubActionsPlugin extends BasePlugin {
413
+ get name() { return 'github-actions'; }
414
+ getConfigFiles() { return ['.github/workflows']; }
415
+ async isActive(baseDir) {
416
+ try { await fs.access(path.join(baseDir, '.github/workflows')); return true; } catch { return false; }
417
+ }
418
+ }
419
+
420
+ export class DockerPlugin extends BasePlugin {
421
+ get name() { return 'docker'; }
422
+ getConfigFiles() { return ['Dockerfile', 'docker-compose.yml', 'docker-compose.yaml', 'docker-compose.dev.yml', '.dockerignore']; }
423
+ async isActive(baseDir) {
424
+ for (const f of this.getConfigFiles()) {
425
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
426
+ }
427
+ return false;
428
+ }
429
+ }
430
+
431
+ export class TerraformPlugin extends BasePlugin {
432
+ get name() { return 'terraform'; }
433
+ getConfigFiles() { return ['main.tf', 'variables.tf', 'outputs.tf', 'terraform.tfvars']; }
434
+ getRoutePatterns() { return [/\.tf$/]; }
435
+ async isActive(baseDir) {
436
+ for (const f of this.getConfigFiles()) {
437
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
438
+ }
439
+ return false;
440
+ }
441
+ }
442
+
443
+ // ─── DEV ENVIRONMENT ─────────────────────────────────────────────────────────
444
+
445
+ export class EditorConfigPlugin extends BasePlugin {
446
+ get name() { return 'editorconfig'; }
447
+ getConfigFiles() { return ['.editorconfig']; }
448
+ async isActive(baseDir) {
449
+ try { await fs.access(path.join(baseDir, '.editorconfig')); return true; } catch { return false; }
450
+ }
451
+ }
452
+
453
+ export class NvmPlugin extends BasePlugin {
454
+ get name() { return 'nvm'; }
455
+ getConfigFiles() { return ['.nvmrc', '.node-version']; }
456
+ async isActive(baseDir) {
457
+ for (const f of this.getConfigFiles()) {
458
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
459
+ }
460
+ return false;
461
+ }
462
+ }
463
+
464
+ export class VoltaPlugin extends BasePlugin {
465
+ get name() { return 'volta'; }
466
+ getConfigFiles() { return ['package.json']; }
467
+ async isActive(baseDir) {
468
+ try {
469
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
470
+ return !!(pkgJson.volta);
471
+ } catch { return false; }
472
+ }
473
+ }
474
+
475
+ export class DotenvPlugin extends BasePlugin {
476
+ get name() { return 'dotenv'; }
477
+ getConfigFiles() { return ['.env', '.env.local', '.env.development', '.env.production', '.env.test', '.env.example', '.env.sample']; }
478
+ getRequiredPackages() { return [{ name: 'dotenv', dev: false, optional: true }]; }
479
+ async isActive(baseDir) {
480
+ for (const f of this.getConfigFiles()) {
481
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
482
+ }
483
+ return false;
484
+ }
485
+ }
486
+
487
+ // ─── PACKAGE MANAGERS ────────────────────────────────────────────────────────
488
+
489
+ export class PnpmPlugin extends BasePlugin {
490
+ get name() { return 'pnpm'; }
491
+ getConfigFiles() { return ['pnpm-lock.yaml', 'pnpm-workspace.yaml']; }
492
+ async isActive(baseDir) {
493
+ try { await fs.access(path.join(baseDir, 'pnpm-lock.yaml')); return true; } catch { return false; }
494
+ }
495
+ }
496
+
497
+ export class YarnPlugin extends BasePlugin {
498
+ get name() { return 'yarn'; }
499
+ getConfigFiles() { return ['yarn.lock', '.yarnrc.yml', '.yarnrc']; }
500
+ async isActive(baseDir) {
501
+ try { await fs.access(path.join(baseDir, 'yarn.lock')); return true; } catch { return false; }
502
+ }
503
+ }
504
+
505
+ export class BunPlugin extends BasePlugin {
506
+ get name() { return 'bun'; }
507
+ getConfigFiles() { return ['bun.lockb', 'bunfig.toml']; }
508
+ async isActive(baseDir) {
509
+ for (const f of this.getConfigFiles()) {
510
+ try { await fs.access(path.join(baseDir, f)); return true; } catch {}
511
+ }
512
+ return false;
513
+ }
514
+ }
515
+
516
+ // ─── MISC UTILITIES ──────────────────────────────────────────────────────────
517
+
518
+ export class SwiperPlugin extends BasePlugin {
519
+ get name() { return 'swiper'; }
520
+ getConfigFiles() { return ['package.json']; }
521
+ getRequiredPackages() { return [{ name: 'swiper', dev: false }]; }
522
+ async isActive(baseDir) {
523
+ try {
524
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
525
+ return !!(pkgJson.dependencies?.swiper || pkgJson.devDependencies?.swiper);
526
+ } catch { return false; }
527
+ }
528
+ async analyze(node) {
529
+ if (node.rawCode?.includes('new Swiper(')) node.isEntry = true;
530
+ }
531
+ }
532
+
533
+ export class QuillPlugin extends BasePlugin {
534
+ get name() { return 'quill'; }
535
+ getConfigFiles() { return ['package.json']; }
536
+ getRequiredPackages() { return [{ name: 'quill', dev: false }]; }
537
+ async isActive(baseDir) {
538
+ try {
539
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
540
+ return !!(pkgJson.dependencies?.quill || pkgJson.devDependencies?.quill);
541
+ } catch { return false; }
542
+ }
543
+ async analyze(node) {
544
+ if (node.rawCode?.includes('new Quill(')) node.isEntry = true;
545
+ }
546
+ }
547
+
548
+ export class EnvelopPlugin extends BasePlugin {
549
+ get name() { return 'envelop'; }
550
+ getConfigFiles() { return ['package.json']; }
551
+ getRequiredPackages() { return [{ name: '@envelop/core', dev: false }]; }
552
+ async isActive(baseDir) {
553
+ try {
554
+ const pkgJson = JSON.parse(await fs.readFile(path.join(baseDir, 'package.json'), 'utf8'));
555
+ const allDeps = { ...(pkgJson.dependencies || {}), ...(pkgJson.devDependencies || {}) };
556
+ return Object.keys(allDeps).some(k => k.startsWith('@envelop/'));
557
+ } catch { return false; }
558
+ }
559
+ async analyze(node) {
560
+ if (node.rawCode?.includes('useEnvelop(')) node.isEntry = true;
561
+ }
562
+ }