wiggum-cli 0.1.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 +21 -0
- package/README.md +341 -0
- package/bin/ralph.js +8 -0
- package/dist/ai/enhancer.d.ts +100 -0
- package/dist/ai/enhancer.d.ts.map +1 -0
- package/dist/ai/enhancer.js +233 -0
- package/dist/ai/enhancer.js.map +1 -0
- package/dist/ai/index.d.ts +8 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +11 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/prompts.d.ts +26 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/prompts.js +201 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/ai/providers.d.ts +35 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +104 -0
- package/dist/ai/providers.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +196 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/init.d.ts +16 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +124 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/monitor.d.ts +17 -0
- package/dist/commands/monitor.d.ts.map +1 -0
- package/dist/commands/monitor.js +342 -0
- package/dist/commands/monitor.js.map +1 -0
- package/dist/commands/new.d.ts +19 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +272 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/run.d.ts +16 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +175 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/generator/config.d.ts +59 -0
- package/dist/generator/config.d.ts.map +1 -0
- package/dist/generator/config.js +68 -0
- package/dist/generator/config.js.map +1 -0
- package/dist/generator/index.d.ts +64 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +147 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/templates.d.ts +70 -0
- package/dist/generator/templates.d.ts.map +1 -0
- package/dist/generator/templates.js +296 -0
- package/dist/generator/templates.js.map +1 -0
- package/dist/generator/writer.d.ts +93 -0
- package/dist/generator/writer.d.ts.map +1 -0
- package/dist/generator/writer.js +213 -0
- package/dist/generator/writer.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/scanner/detectors/core/framework.d.ts +11 -0
- package/dist/scanner/detectors/core/framework.d.ts.map +1 -0
- package/dist/scanner/detectors/core/framework.js +275 -0
- package/dist/scanner/detectors/core/framework.js.map +1 -0
- package/dist/scanner/detectors/core/packageManager.d.ts +11 -0
- package/dist/scanner/detectors/core/packageManager.d.ts.map +1 -0
- package/dist/scanner/detectors/core/packageManager.js +74 -0
- package/dist/scanner/detectors/core/packageManager.js.map +1 -0
- package/dist/scanner/detectors/core/styling.d.ts +12 -0
- package/dist/scanner/detectors/core/styling.d.ts.map +1 -0
- package/dist/scanner/detectors/core/styling.js +230 -0
- package/dist/scanner/detectors/core/styling.js.map +1 -0
- package/dist/scanner/detectors/core/testing.d.ts +12 -0
- package/dist/scanner/detectors/core/testing.d.ts.map +1 -0
- package/dist/scanner/detectors/core/testing.js +190 -0
- package/dist/scanner/detectors/core/testing.js.map +1 -0
- package/dist/scanner/detectors/data/api.d.ts +12 -0
- package/dist/scanner/detectors/data/api.d.ts.map +1 -0
- package/dist/scanner/detectors/data/api.js +261 -0
- package/dist/scanner/detectors/data/api.js.map +1 -0
- package/dist/scanner/detectors/data/database.d.ts +12 -0
- package/dist/scanner/detectors/data/database.d.ts.map +1 -0
- package/dist/scanner/detectors/data/database.js +213 -0
- package/dist/scanner/detectors/data/database.js.map +1 -0
- package/dist/scanner/detectors/data/orm.d.ts +12 -0
- package/dist/scanner/detectors/data/orm.d.ts.map +1 -0
- package/dist/scanner/detectors/data/orm.js +160 -0
- package/dist/scanner/detectors/data/orm.js.map +1 -0
- package/dist/scanner/detectors/frontend/formHandling.d.ts +12 -0
- package/dist/scanner/detectors/frontend/formHandling.d.ts.map +1 -0
- package/dist/scanner/detectors/frontend/formHandling.js +211 -0
- package/dist/scanner/detectors/frontend/formHandling.js.map +1 -0
- package/dist/scanner/detectors/frontend/stateManagement.d.ts +12 -0
- package/dist/scanner/detectors/frontend/stateManagement.d.ts.map +1 -0
- package/dist/scanner/detectors/frontend/stateManagement.js +221 -0
- package/dist/scanner/detectors/frontend/stateManagement.js.map +1 -0
- package/dist/scanner/detectors/frontend/uiComponents.d.ts +12 -0
- package/dist/scanner/detectors/frontend/uiComponents.d.ts.map +1 -0
- package/dist/scanner/detectors/frontend/uiComponents.js +285 -0
- package/dist/scanner/detectors/frontend/uiComponents.js.map +1 -0
- package/dist/scanner/detectors/infra/deployment.d.ts +12 -0
- package/dist/scanner/detectors/infra/deployment.d.ts.map +1 -0
- package/dist/scanner/detectors/infra/deployment.js +301 -0
- package/dist/scanner/detectors/infra/deployment.js.map +1 -0
- package/dist/scanner/detectors/infra/monorepo.d.ts +12 -0
- package/dist/scanner/detectors/infra/monorepo.d.ts.map +1 -0
- package/dist/scanner/detectors/infra/monorepo.js +219 -0
- package/dist/scanner/detectors/infra/monorepo.js.map +1 -0
- package/dist/scanner/detectors/mcp/mcpProject.d.ts +12 -0
- package/dist/scanner/detectors/mcp/mcpProject.d.ts.map +1 -0
- package/dist/scanner/detectors/mcp/mcpProject.js +154 -0
- package/dist/scanner/detectors/mcp/mcpProject.js.map +1 -0
- package/dist/scanner/detectors/mcp/mcpServers.d.ts +17 -0
- package/dist/scanner/detectors/mcp/mcpServers.d.ts.map +1 -0
- package/dist/scanner/detectors/mcp/mcpServers.js +193 -0
- package/dist/scanner/detectors/mcp/mcpServers.js.map +1 -0
- package/dist/scanner/detectors/services/analytics.d.ts +12 -0
- package/dist/scanner/detectors/services/analytics.d.ts.map +1 -0
- package/dist/scanner/detectors/services/analytics.js +236 -0
- package/dist/scanner/detectors/services/analytics.js.map +1 -0
- package/dist/scanner/detectors/services/auth.d.ts +12 -0
- package/dist/scanner/detectors/services/auth.d.ts.map +1 -0
- package/dist/scanner/detectors/services/auth.js +217 -0
- package/dist/scanner/detectors/services/auth.js.map +1 -0
- package/dist/scanner/detectors/services/email.d.ts +12 -0
- package/dist/scanner/detectors/services/email.d.ts.map +1 -0
- package/dist/scanner/detectors/services/email.js +211 -0
- package/dist/scanner/detectors/services/email.js.map +1 -0
- package/dist/scanner/detectors/services/payments.d.ts +12 -0
- package/dist/scanner/detectors/services/payments.d.ts.map +1 -0
- package/dist/scanner/detectors/services/payments.js +185 -0
- package/dist/scanner/detectors/services/payments.js.map +1 -0
- package/dist/scanner/detectors/utils.d.ts +160 -0
- package/dist/scanner/detectors/utils.d.ts.map +1 -0
- package/dist/scanner/detectors/utils.js +222 -0
- package/dist/scanner/detectors/utils.js.map +1 -0
- package/dist/scanner/index.d.ts +42 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +282 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/registry.d.ts +43 -0
- package/dist/scanner/registry.d.ts.map +1 -0
- package/dist/scanner/registry.js +243 -0
- package/dist/scanner/registry.js.map +1 -0
- package/dist/scanner/types.d.ts +112 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +6 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/templates/config/ralph.config.js.tmpl +38 -0
- package/dist/templates/guides/AGENTS.md.tmpl +100 -0
- package/dist/templates/guides/FRONTEND.md.tmpl +523 -0
- package/dist/templates/guides/PERFORMANCE.md.tmpl +264 -0
- package/dist/templates/guides/SECURITY.md.tmpl +100 -0
- package/dist/templates/prompts/PROMPT.md.tmpl +77 -0
- package/dist/templates/prompts/PROMPT_e2e.md.tmpl +234 -0
- package/dist/templates/prompts/PROMPT_feature.md.tmpl +83 -0
- package/dist/templates/prompts/PROMPT_review.md.tmpl +167 -0
- package/dist/templates/prompts/PROMPT_verify.md.tmpl +72 -0
- package/dist/templates/root/.gitignore.tmpl +5 -0
- package/dist/templates/root/LEARNINGS.md.tmpl +24 -0
- package/dist/templates/root/README.md.tmpl +61 -0
- package/dist/templates/scripts/feature-loop.sh.tmpl +267 -0
- package/dist/templates/scripts/loop.sh.tmpl +59 -0
- package/dist/templates/scripts/ralph-monitor.sh.tmpl +244 -0
- package/dist/templates/specs/README.md.tmpl +57 -0
- package/dist/templates/specs/_example.md.tmpl +71 -0
- package/dist/utils/config.d.ts +95 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +148 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/header.d.ts +5 -0
- package/dist/utils/header.d.ts.map +1 -0
- package/dist/utils/header.js +15 -0
- package/dist/utils/header.js.map +1 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +24 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +44 -0
- package/src/ai/enhancer.ts +350 -0
- package/src/ai/index.ts +38 -0
- package/src/ai/prompts.ts +217 -0
- package/src/ai/providers.ts +136 -0
- package/src/cli.ts +255 -0
- package/src/commands/init.ts +149 -0
- package/src/commands/monitor.ts +412 -0
- package/src/commands/new.ts +312 -0
- package/src/commands/run.ts +214 -0
- package/src/generator/config.ts +116 -0
- package/src/generator/index.ts +227 -0
- package/src/generator/templates.ts +412 -0
- package/src/generator/writer.ts +293 -0
- package/src/index.ts +41 -0
- package/src/scanner/detectors/core/framework.ts +332 -0
- package/src/scanner/detectors/core/packageManager.ts +91 -0
- package/src/scanner/detectors/core/styling.ts +261 -0
- package/src/scanner/detectors/core/testing.ts +221 -0
- package/src/scanner/detectors/data/api.ts +303 -0
- package/src/scanner/detectors/data/database.ts +245 -0
- package/src/scanner/detectors/data/orm.ts +180 -0
- package/src/scanner/detectors/frontend/formHandling.ts +244 -0
- package/src/scanner/detectors/frontend/stateManagement.ts +261 -0
- package/src/scanner/detectors/frontend/uiComponents.ts +328 -0
- package/src/scanner/detectors/infra/deployment.ts +343 -0
- package/src/scanner/detectors/infra/monorepo.ts +251 -0
- package/src/scanner/detectors/mcp/mcpProject.ts +176 -0
- package/src/scanner/detectors/mcp/mcpServers.ts +237 -0
- package/src/scanner/detectors/services/analytics.ts +273 -0
- package/src/scanner/detectors/services/auth.ts +254 -0
- package/src/scanner/detectors/services/email.ts +244 -0
- package/src/scanner/detectors/services/payments.ts +213 -0
- package/src/scanner/detectors/utils.ts +251 -0
- package/src/scanner/index.ts +354 -0
- package/src/scanner/registry.ts +301 -0
- package/src/scanner/types.ts +152 -0
- package/src/templates/config/ralph.config.js.tmpl +38 -0
- package/src/templates/guides/AGENTS.md.tmpl +100 -0
- package/src/templates/guides/FRONTEND.md.tmpl +523 -0
- package/src/templates/guides/PERFORMANCE.md.tmpl +264 -0
- package/src/templates/guides/SECURITY.md.tmpl +100 -0
- package/src/templates/prompts/PROMPT.md.tmpl +77 -0
- package/src/templates/prompts/PROMPT_e2e.md.tmpl +234 -0
- package/src/templates/prompts/PROMPT_feature.md.tmpl +83 -0
- package/src/templates/prompts/PROMPT_review.md.tmpl +167 -0
- package/src/templates/prompts/PROMPT_verify.md.tmpl +72 -0
- package/src/templates/root/.gitignore.tmpl +5 -0
- package/src/templates/root/LEARNINGS.md.tmpl +24 -0
- package/src/templates/root/README.md.tmpl +61 -0
- package/src/templates/scripts/feature-loop.sh.tmpl +267 -0
- package/src/templates/scripts/loop.sh.tmpl +59 -0
- package/src/templates/scripts/ralph-monitor.sh.tmpl +244 -0
- package/src/templates/specs/README.md.tmpl +57 -0
- package/src/templates/specs/_example.md.tmpl +71 -0
- package/src/utils/config.ts +221 -0
- package/src/utils/header.ts +15 -0
- package/src/utils/logger.ts +28 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics Detector
|
|
3
|
+
* Detects: PostHog, Mixpanel, Vercel Analytics, Google Analytics
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import type { Detector, DetectionResult } from '../../types.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Read and parse package.json from a directory
|
|
12
|
+
*/
|
|
13
|
+
function readPackageJson(projectRoot: string): Record<string, unknown> | null {
|
|
14
|
+
const packageJsonPath = join(projectRoot, 'package.json');
|
|
15
|
+
if (!existsSync(packageJsonPath)) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const content = readFileSync(packageJsonPath, 'utf-8');
|
|
20
|
+
return JSON.parse(content);
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get all dependencies from package.json (deps + devDeps)
|
|
28
|
+
*/
|
|
29
|
+
function getDependencies(pkg: Record<string, unknown>): Record<string, string> {
|
|
30
|
+
const deps = (pkg.dependencies as Record<string, string>) || {};
|
|
31
|
+
const devDeps = (pkg.devDependencies as Record<string, string>) || {};
|
|
32
|
+
return { ...deps, ...devDeps };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Find all matching dependencies by pattern
|
|
37
|
+
*/
|
|
38
|
+
function findMatchingDeps(deps: Record<string, string>, pattern: string): string[] {
|
|
39
|
+
return Object.keys(deps).filter(name => name.startsWith(pattern));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Detect PostHog
|
|
44
|
+
*/
|
|
45
|
+
function detectPostHog(deps: Record<string, string>): DetectionResult | null {
|
|
46
|
+
const evidence: string[] = [];
|
|
47
|
+
let confidence = 0;
|
|
48
|
+
let variant: string | undefined;
|
|
49
|
+
|
|
50
|
+
// Check for posthog-js (browser)
|
|
51
|
+
if (deps['posthog-js']) {
|
|
52
|
+
evidence.push(`posthog-js@${deps['posthog-js']} in dependencies`);
|
|
53
|
+
confidence += 80;
|
|
54
|
+
variant = 'browser';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Check for posthog-node (server)
|
|
58
|
+
if (deps['posthog-node']) {
|
|
59
|
+
evidence.push(`posthog-node@${deps['posthog-node']} in dependencies`);
|
|
60
|
+
confidence += 80;
|
|
61
|
+
variant = variant ? 'full-stack' : 'server';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Check for Next.js specific package
|
|
65
|
+
if (deps['posthog-react']) {
|
|
66
|
+
evidence.push('posthog-react found');
|
|
67
|
+
confidence += 10;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (confidence === 0) return null;
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
name: 'PostHog',
|
|
74
|
+
version: deps['posthog-js'] || deps['posthog-node'],
|
|
75
|
+
variant,
|
|
76
|
+
confidence: Math.min(confidence, 100),
|
|
77
|
+
evidence,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Detect Mixpanel
|
|
83
|
+
*/
|
|
84
|
+
function detectMixpanel(deps: Record<string, string>): DetectionResult | null {
|
|
85
|
+
const evidence: string[] = [];
|
|
86
|
+
let confidence = 0;
|
|
87
|
+
|
|
88
|
+
// Check for mixpanel packages
|
|
89
|
+
const mixpanelPackages = findMatchingDeps(deps, 'mixpanel');
|
|
90
|
+
if (mixpanelPackages.length > 0) {
|
|
91
|
+
evidence.push(`Mixpanel packages found: ${mixpanelPackages.join(', ')}`);
|
|
92
|
+
confidence += 80;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Check for @mixpanel/* packages
|
|
96
|
+
const mixpanelScopedPackages = findMatchingDeps(deps, '@mixpanel/');
|
|
97
|
+
if (mixpanelScopedPackages.length > 0) {
|
|
98
|
+
evidence.push(`@mixpanel packages found: ${mixpanelScopedPackages.join(', ')}`);
|
|
99
|
+
confidence += 80;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (confidence === 0) return null;
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
name: 'Mixpanel',
|
|
106
|
+
version: deps.mixpanel || deps['mixpanel-browser'],
|
|
107
|
+
confidence: Math.min(confidence, 100),
|
|
108
|
+
evidence,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Detect Vercel Analytics
|
|
114
|
+
*/
|
|
115
|
+
function detectVercelAnalytics(deps: Record<string, string>): DetectionResult | null {
|
|
116
|
+
const evidence: string[] = [];
|
|
117
|
+
let confidence = 0;
|
|
118
|
+
|
|
119
|
+
if (deps['@vercel/analytics']) {
|
|
120
|
+
evidence.push(`@vercel/analytics@${deps['@vercel/analytics']} in dependencies`);
|
|
121
|
+
confidence += 80;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Check for @vercel/speed-insights (often used together)
|
|
125
|
+
if (deps['@vercel/speed-insights']) {
|
|
126
|
+
evidence.push('@vercel/speed-insights found');
|
|
127
|
+
confidence += 10;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (confidence === 0) return null;
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
name: 'Vercel Analytics',
|
|
134
|
+
version: deps['@vercel/analytics'],
|
|
135
|
+
confidence: Math.min(confidence, 100),
|
|
136
|
+
evidence,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Detect Google Analytics
|
|
142
|
+
*/
|
|
143
|
+
function detectGoogleAnalytics(deps: Record<string, string>): DetectionResult | null {
|
|
144
|
+
const evidence: string[] = [];
|
|
145
|
+
let confidence = 0;
|
|
146
|
+
|
|
147
|
+
// Check for various GA packages
|
|
148
|
+
if (deps['@google-analytics/data']) {
|
|
149
|
+
evidence.push('@google-analytics/data found');
|
|
150
|
+
confidence += 70;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (deps['react-ga4'] || deps['react-ga']) {
|
|
154
|
+
evidence.push('React GA package found');
|
|
155
|
+
confidence += 70;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (deps['ga-4-react']) {
|
|
159
|
+
evidence.push('ga-4-react found');
|
|
160
|
+
confidence += 70;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Check for gtag
|
|
164
|
+
if (deps.gtag) {
|
|
165
|
+
evidence.push('gtag found');
|
|
166
|
+
confidence += 60;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (confidence === 0) return null;
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
name: 'Google Analytics',
|
|
173
|
+
version: deps['react-ga4'] || deps['@google-analytics/data'],
|
|
174
|
+
confidence: Math.min(confidence, 100),
|
|
175
|
+
evidence,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Detect Amplitude
|
|
181
|
+
*/
|
|
182
|
+
function detectAmplitude(deps: Record<string, string>): DetectionResult | null {
|
|
183
|
+
const evidence: string[] = [];
|
|
184
|
+
let confidence = 0;
|
|
185
|
+
|
|
186
|
+
// Check for @amplitude/* packages
|
|
187
|
+
const amplitudePackages = findMatchingDeps(deps, '@amplitude/');
|
|
188
|
+
if (amplitudePackages.length > 0) {
|
|
189
|
+
evidence.push(`Amplitude packages found: ${amplitudePackages.join(', ')}`);
|
|
190
|
+
confidence += 80;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Check for amplitude-js
|
|
194
|
+
if (deps['amplitude-js']) {
|
|
195
|
+
evidence.push(`amplitude-js@${deps['amplitude-js']} in dependencies`);
|
|
196
|
+
confidence += 80;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (confidence === 0) return null;
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
name: 'Amplitude',
|
|
203
|
+
version: deps['@amplitude/analytics-browser'] || deps['amplitude-js'],
|
|
204
|
+
confidence: Math.min(confidence, 100),
|
|
205
|
+
evidence,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Detect Plausible
|
|
211
|
+
*/
|
|
212
|
+
function detectPlausible(deps: Record<string, string>): DetectionResult | null {
|
|
213
|
+
const evidence: string[] = [];
|
|
214
|
+
let confidence = 0;
|
|
215
|
+
|
|
216
|
+
if (deps['plausible-tracker']) {
|
|
217
|
+
evidence.push(`plausible-tracker@${deps['plausible-tracker']} in dependencies`);
|
|
218
|
+
confidence += 80;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (deps['next-plausible']) {
|
|
222
|
+
evidence.push('next-plausible found');
|
|
223
|
+
confidence += 80;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (confidence === 0) return null;
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
name: 'Plausible',
|
|
230
|
+
version: deps['plausible-tracker'] || deps['next-plausible'],
|
|
231
|
+
confidence: Math.min(confidence, 100),
|
|
232
|
+
evidence,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Analytics detector
|
|
238
|
+
* Returns all detected analytics solutions (projects often use multiple)
|
|
239
|
+
*/
|
|
240
|
+
export const analyticsDetector: Detector = {
|
|
241
|
+
category: 'analytics',
|
|
242
|
+
name: 'Analytics Detector',
|
|
243
|
+
|
|
244
|
+
async detect(projectRoot: string): Promise<DetectionResult[] | null> {
|
|
245
|
+
const pkg = readPackageJson(projectRoot);
|
|
246
|
+
if (!pkg) {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const deps = getDependencies(pkg);
|
|
251
|
+
const results: DetectionResult[] = [];
|
|
252
|
+
|
|
253
|
+
const detectors = [
|
|
254
|
+
() => detectPostHog(deps),
|
|
255
|
+
() => detectMixpanel(deps),
|
|
256
|
+
() => detectVercelAnalytics(deps),
|
|
257
|
+
() => detectGoogleAnalytics(deps),
|
|
258
|
+
() => detectAmplitude(deps),
|
|
259
|
+
() => detectPlausible(deps),
|
|
260
|
+
];
|
|
261
|
+
|
|
262
|
+
for (const detector of detectors) {
|
|
263
|
+
const result = detector();
|
|
264
|
+
if (result && result.confidence >= 40) {
|
|
265
|
+
results.push(result);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return results.length > 0 ? results : null;
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
export default analyticsDetector;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Provider Detector
|
|
3
|
+
* Detects: NextAuth, Clerk, Auth0, Supabase Auth
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Detector, DetectionResult } from '../../types.js';
|
|
7
|
+
import {
|
|
8
|
+
readPackageJson,
|
|
9
|
+
getDependencies,
|
|
10
|
+
findMatchingDeps,
|
|
11
|
+
type DependencyMap,
|
|
12
|
+
} from '../utils.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Detect NextAuth.js / Auth.js
|
|
16
|
+
*/
|
|
17
|
+
function detectNextAuth(deps: DependencyMap): DetectionResult | null {
|
|
18
|
+
const evidence: string[] = [];
|
|
19
|
+
let confidence = 0;
|
|
20
|
+
let variant: string | undefined;
|
|
21
|
+
|
|
22
|
+
// Check for next-auth (v4 and below)
|
|
23
|
+
if (deps['next-auth']) {
|
|
24
|
+
evidence.push(`next-auth@${deps['next-auth']} in dependencies`);
|
|
25
|
+
confidence += 80;
|
|
26
|
+
variant = 'v4';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check for @auth/* packages (Auth.js v5+)
|
|
30
|
+
const authPackages = findMatchingDeps(deps, '@auth/');
|
|
31
|
+
if (authPackages.length > 0) {
|
|
32
|
+
evidence.push(`Auth.js packages found: ${authPackages.join(', ')}`);
|
|
33
|
+
confidence += 80;
|
|
34
|
+
variant = 'v5';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (confidence === 0) return null;
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
name: 'NextAuth.js',
|
|
41
|
+
version: deps['next-auth'] || deps['@auth/core'],
|
|
42
|
+
variant,
|
|
43
|
+
confidence: Math.min(confidence, 100),
|
|
44
|
+
evidence,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Detect Clerk
|
|
50
|
+
*/
|
|
51
|
+
function detectClerk(deps: DependencyMap): DetectionResult | null {
|
|
52
|
+
const evidence: string[] = [];
|
|
53
|
+
let confidence = 0;
|
|
54
|
+
|
|
55
|
+
// Check for @clerk/* packages
|
|
56
|
+
const clerkPackages = findMatchingDeps(deps, '@clerk/');
|
|
57
|
+
if (clerkPackages.length > 0) {
|
|
58
|
+
const mainVersion = deps['@clerk/nextjs'] || deps['@clerk/clerk-react'] || deps['@clerk/express'];
|
|
59
|
+
evidence.push(`Clerk packages found: ${clerkPackages.join(', ')}`);
|
|
60
|
+
confidence += 80;
|
|
61
|
+
|
|
62
|
+
// Detect framework variant
|
|
63
|
+
let variant: string | undefined;
|
|
64
|
+
if (deps['@clerk/nextjs']) {
|
|
65
|
+
variant = 'nextjs';
|
|
66
|
+
} else if (deps['@clerk/clerk-react']) {
|
|
67
|
+
variant = 'react';
|
|
68
|
+
} else if (deps['@clerk/express']) {
|
|
69
|
+
variant = 'express';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
name: 'Clerk',
|
|
74
|
+
version: mainVersion,
|
|
75
|
+
variant,
|
|
76
|
+
confidence: Math.min(confidence, 100),
|
|
77
|
+
evidence,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Detect Auth0
|
|
86
|
+
*/
|
|
87
|
+
function detectAuth0(deps: DependencyMap): DetectionResult | null {
|
|
88
|
+
const evidence: string[] = [];
|
|
89
|
+
let confidence = 0;
|
|
90
|
+
let variant: string | undefined;
|
|
91
|
+
|
|
92
|
+
// Check for @auth0/* packages
|
|
93
|
+
const auth0Packages = findMatchingDeps(deps, '@auth0/');
|
|
94
|
+
if (auth0Packages.length > 0) {
|
|
95
|
+
evidence.push(`Auth0 packages found: ${auth0Packages.join(', ')}`);
|
|
96
|
+
confidence += 70;
|
|
97
|
+
|
|
98
|
+
if (deps['@auth0/nextjs-auth0']) {
|
|
99
|
+
variant = 'nextjs';
|
|
100
|
+
confidence += 10;
|
|
101
|
+
} else if (deps['@auth0/auth0-react']) {
|
|
102
|
+
variant = 'react';
|
|
103
|
+
confidence += 10;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Check for auth0 package
|
|
108
|
+
if (deps.auth0) {
|
|
109
|
+
evidence.push(`auth0@${deps.auth0} in dependencies`);
|
|
110
|
+
confidence += 60;
|
|
111
|
+
variant = 'node';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (confidence === 0) return null;
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
name: 'Auth0',
|
|
118
|
+
version: deps['@auth0/nextjs-auth0'] || deps['@auth0/auth0-react'] || deps.auth0,
|
|
119
|
+
variant,
|
|
120
|
+
confidence: Math.min(confidence, 100),
|
|
121
|
+
evidence,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Detect Supabase Auth
|
|
127
|
+
*/
|
|
128
|
+
function detectSupabaseAuth(deps: DependencyMap): DetectionResult | null {
|
|
129
|
+
const evidence: string[] = [];
|
|
130
|
+
let confidence = 0;
|
|
131
|
+
|
|
132
|
+
// Check for @supabase/auth-helpers-* packages
|
|
133
|
+
const authHelperPackages = findMatchingDeps(deps, '@supabase/auth-helpers-');
|
|
134
|
+
if (authHelperPackages.length > 0) {
|
|
135
|
+
evidence.push(`Supabase auth helpers found: ${authHelperPackages.join(', ')}`);
|
|
136
|
+
confidence += 70;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Check for @supabase/ssr (newer auth approach)
|
|
140
|
+
if (deps['@supabase/ssr']) {
|
|
141
|
+
evidence.push(`@supabase/ssr@${deps['@supabase/ssr']} in dependencies`);
|
|
142
|
+
confidence += 70;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Check for @supabase/auth-ui-react
|
|
146
|
+
if (deps['@supabase/auth-ui-react']) {
|
|
147
|
+
evidence.push('@supabase/auth-ui-react found');
|
|
148
|
+
confidence += 20;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (confidence === 0) return null;
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
name: 'Supabase Auth',
|
|
155
|
+
version: deps['@supabase/ssr'] || authHelperPackages[0] ? deps[authHelperPackages[0]] : undefined,
|
|
156
|
+
confidence: Math.min(confidence, 100),
|
|
157
|
+
evidence,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Detect Lucia Auth
|
|
163
|
+
*/
|
|
164
|
+
function detectLucia(deps: DependencyMap): DetectionResult | null {
|
|
165
|
+
const evidence: string[] = [];
|
|
166
|
+
let confidence = 0;
|
|
167
|
+
|
|
168
|
+
if (deps.lucia) {
|
|
169
|
+
evidence.push(`lucia@${deps.lucia} in dependencies`);
|
|
170
|
+
confidence += 80;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Check for @lucia-auth/* adapters
|
|
174
|
+
const luciaPackages = findMatchingDeps(deps, '@lucia-auth/');
|
|
175
|
+
if (luciaPackages.length > 0) {
|
|
176
|
+
evidence.push(`Lucia adapters found: ${luciaPackages.join(', ')}`);
|
|
177
|
+
confidence += 10;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (confidence === 0) return null;
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
name: 'Lucia',
|
|
184
|
+
version: deps.lucia,
|
|
185
|
+
confidence: Math.min(confidence, 100),
|
|
186
|
+
evidence,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Detect Better Auth
|
|
192
|
+
*/
|
|
193
|
+
function detectBetterAuth(deps: DependencyMap): DetectionResult | null {
|
|
194
|
+
const evidence: string[] = [];
|
|
195
|
+
let confidence = 0;
|
|
196
|
+
|
|
197
|
+
if (deps['better-auth']) {
|
|
198
|
+
evidence.push(`better-auth@${deps['better-auth']} in dependencies`);
|
|
199
|
+
confidence += 80;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (confidence === 0) return null;
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
name: 'Better Auth',
|
|
206
|
+
version: deps['better-auth'],
|
|
207
|
+
confidence: Math.min(confidence, 100),
|
|
208
|
+
evidence,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Auth provider detector
|
|
214
|
+
* Returns the primary auth solution detected
|
|
215
|
+
*/
|
|
216
|
+
export const authDetector: Detector = {
|
|
217
|
+
category: 'auth',
|
|
218
|
+
name: 'Auth Provider Detector',
|
|
219
|
+
|
|
220
|
+
async detect(projectRoot: string): Promise<DetectionResult | null> {
|
|
221
|
+
const pkg = readPackageJson(projectRoot);
|
|
222
|
+
if (!pkg) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const deps = getDependencies(pkg);
|
|
227
|
+
|
|
228
|
+
// Priority order based on popularity/comprehensiveness
|
|
229
|
+
const detectors = [
|
|
230
|
+
() => detectClerk(deps),
|
|
231
|
+
() => detectNextAuth(deps),
|
|
232
|
+
() => detectAuth0(deps),
|
|
233
|
+
() => detectLucia(deps),
|
|
234
|
+
() => detectBetterAuth(deps),
|
|
235
|
+
() => detectSupabaseAuth(deps),
|
|
236
|
+
];
|
|
237
|
+
|
|
238
|
+
// Find the highest confidence result
|
|
239
|
+
let bestResult: DetectionResult | null = null;
|
|
240
|
+
let bestConfidence = 0;
|
|
241
|
+
|
|
242
|
+
for (const detector of detectors) {
|
|
243
|
+
const result = detector();
|
|
244
|
+
if (result && result.confidence > bestConfidence) {
|
|
245
|
+
bestResult = result;
|
|
246
|
+
bestConfidence = result.confidence;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return bestResult && bestResult.confidence >= 40 ? bestResult : null;
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export default authDetector;
|