@vibecheckai/cli 3.0.2 → 3.0.3
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/package.json +9 -1
- package/bin/cli-hygiene.js +0 -241
- package/bin/guardrail.js +0 -834
- package/bin/runners/cli-utils.js +0 -1070
- package/bin/runners/context/ai-task-decomposer.js +0 -337
- package/bin/runners/context/analyzer.js +0 -462
- package/bin/runners/context/api-contracts.js +0 -427
- package/bin/runners/context/context-diff.js +0 -342
- package/bin/runners/context/context-pruner.js +0 -291
- package/bin/runners/context/dependency-graph.js +0 -414
- package/bin/runners/context/generators/claude.js +0 -107
- package/bin/runners/context/generators/codex.js +0 -108
- package/bin/runners/context/generators/copilot.js +0 -119
- package/bin/runners/context/generators/cursor.js +0 -514
- package/bin/runners/context/generators/mcp.js +0 -151
- package/bin/runners/context/generators/windsurf.js +0 -180
- package/bin/runners/context/git-context.js +0 -302
- package/bin/runners/context/index.js +0 -1042
- package/bin/runners/context/insights.js +0 -173
- package/bin/runners/context/mcp-server/generate-rules.js +0 -337
- package/bin/runners/context/mcp-server/index.js +0 -1176
- package/bin/runners/context/mcp-server/package.json +0 -24
- package/bin/runners/context/memory.js +0 -200
- package/bin/runners/context/monorepo.js +0 -215
- package/bin/runners/context/multi-repo-federation.js +0 -404
- package/bin/runners/context/patterns.js +0 -253
- package/bin/runners/context/proof-context.js +0 -972
- package/bin/runners/context/security-scanner.js +0 -303
- package/bin/runners/context/semantic-search.js +0 -350
- package/bin/runners/context/shared.js +0 -264
- package/bin/runners/context/team-conventions.js +0 -310
- package/bin/runners/lib/ai-bridge.js +0 -416
- package/bin/runners/lib/analysis-core.js +0 -271
- package/bin/runners/lib/analyzers.js +0 -541
- package/bin/runners/lib/audit-bridge.js +0 -391
- package/bin/runners/lib/auth-truth.js +0 -193
- package/bin/runners/lib/auth.js +0 -215
- package/bin/runners/lib/backup.js +0 -62
- package/bin/runners/lib/billing.js +0 -107
- package/bin/runners/lib/claims.js +0 -118
- package/bin/runners/lib/cli-ui.js +0 -540
- package/bin/runners/lib/compliance-bridge-new.js +0 -0
- package/bin/runners/lib/compliance-bridge.js +0 -165
- package/bin/runners/lib/contracts/auth-contract.js +0 -194
- package/bin/runners/lib/contracts/env-contract.js +0 -178
- package/bin/runners/lib/contracts/external-contract.js +0 -198
- package/bin/runners/lib/contracts/guard.js +0 -168
- package/bin/runners/lib/contracts/index.js +0 -89
- package/bin/runners/lib/contracts/plan-validator.js +0 -311
- package/bin/runners/lib/contracts/route-contract.js +0 -192
- package/bin/runners/lib/detect.js +0 -89
- package/bin/runners/lib/doctor/autofix.js +0 -254
- package/bin/runners/lib/doctor/index.js +0 -37
- package/bin/runners/lib/doctor/modules/dependencies.js +0 -325
- package/bin/runners/lib/doctor/modules/index.js +0 -46
- package/bin/runners/lib/doctor/modules/network.js +0 -250
- package/bin/runners/lib/doctor/modules/project.js +0 -312
- package/bin/runners/lib/doctor/modules/runtime.js +0 -224
- package/bin/runners/lib/doctor/modules/security.js +0 -348
- package/bin/runners/lib/doctor/modules/system.js +0 -213
- package/bin/runners/lib/doctor/modules/vibecheck.js +0 -394
- package/bin/runners/lib/doctor/reporter.js +0 -262
- package/bin/runners/lib/doctor/service.js +0 -262
- package/bin/runners/lib/doctor/types.js +0 -113
- package/bin/runners/lib/doctor/ui.js +0 -263
- package/bin/runners/lib/doctor-enhanced.js +0 -233
- package/bin/runners/lib/doctor-v2.js +0 -608
- package/bin/runners/lib/enforcement.js +0 -72
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GitHub Copilot Instructions Generator
|
|
3
|
-
* Generates .github/copilot-instructions.md
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Generate Copilot instructions
|
|
8
|
-
*/
|
|
9
|
-
function generateCopilotInstructions(analysis) {
|
|
10
|
-
const p = analysis.patterns || {};
|
|
11
|
-
const m = analysis.monorepo || {};
|
|
12
|
-
|
|
13
|
-
return `# GitHub Copilot Instructions - ${analysis.name}
|
|
14
|
-
|
|
15
|
-
## Project Overview
|
|
16
|
-
|
|
17
|
-
This is a **${analysis.framework || "JavaScript"}** project using **${analysis.language || "JavaScript"}**.
|
|
18
|
-
Architecture: ${analysis.architecture}
|
|
19
|
-
${m.isMonorepo ? `Monorepo: ${m.type} with ${m.workspaces?.length || 0} workspaces` : ""}
|
|
20
|
-
|
|
21
|
-
## Tech Stack
|
|
22
|
-
|
|
23
|
-
${analysis.hasNextjs ? "- Next.js (App Router)" : ""}
|
|
24
|
-
${analysis.hasReact ? "- React" : ""}
|
|
25
|
-
${analysis.hasTypescript ? "- TypeScript (strict mode)" : ""}
|
|
26
|
-
${analysis.hasPrisma ? "- Prisma ORM" : ""}
|
|
27
|
-
${analysis.hasTailwind ? "- Tailwind CSS" : ""}
|
|
28
|
-
${p.stateManagement ? `- State Management: ${p.stateManagement}` : ""}
|
|
29
|
-
${p.validation ? `- Validation: ${p.validation}` : ""}
|
|
30
|
-
${p.authentication ? `- Authentication: ${p.authentication}` : ""}
|
|
31
|
-
${p.dataFetching?.length ? `- Data Fetching: ${p.dataFetching.join(", ")}` : ""}
|
|
32
|
-
${p.testing?.length ? `- Testing: ${p.testing.join(", ")}` : ""}
|
|
33
|
-
|
|
34
|
-
## Project Structure
|
|
35
|
-
|
|
36
|
-
\`\`\`
|
|
37
|
-
${analysis.directories.map(d => `${d}/`).join("\n")}
|
|
38
|
-
\`\`\`
|
|
39
|
-
|
|
40
|
-
${m.isMonorepo && m.workspaces?.length > 0 ? `## Workspaces
|
|
41
|
-
|
|
42
|
-
${m.workspaces.slice(0, 8).map(w => `- \`${w.path}\` - ${w.name}`).join("\n")}
|
|
43
|
-
` : ""}
|
|
44
|
-
|
|
45
|
-
## Existing Components
|
|
46
|
-
|
|
47
|
-
When generating UI code, prefer using these existing components:
|
|
48
|
-
${analysis.components.slice(0, 25).map(c => `- ${c}`).join("\n") || "None detected"}
|
|
49
|
-
|
|
50
|
-
${p.hooks?.length > 0 ? `## Custom Hooks
|
|
51
|
-
|
|
52
|
-
Use these existing hooks instead of creating new ones:
|
|
53
|
-
${p.hooks.slice(0, 15).map(h => `- \`${h}\``).join("\n")}
|
|
54
|
-
` : ""}
|
|
55
|
-
|
|
56
|
-
## API Routes
|
|
57
|
-
|
|
58
|
-
${analysis.apiRoutes.slice(0, 15).map(r => `- ${r}`).join("\n") || "None detected"}
|
|
59
|
-
|
|
60
|
-
${analysis.models.length > 0 ? `## Data Models (Prisma)
|
|
61
|
-
|
|
62
|
-
${analysis.models.map(m => `- ${m}`).join("\n")}
|
|
63
|
-
` : ""}
|
|
64
|
-
|
|
65
|
-
${analysis.envVars?.variables?.length > 0 ? `## Environment Variables
|
|
66
|
-
|
|
67
|
-
Required variables:
|
|
68
|
-
${analysis.envVars.variables.slice(0, 15).map(v => `- \`${v}\``).join("\n")}
|
|
69
|
-
` : ""}
|
|
70
|
-
|
|
71
|
-
## Code Conventions
|
|
72
|
-
|
|
73
|
-
### File Naming
|
|
74
|
-
- Components: ${analysis.conventions.naming.components || "PascalCase"} (e.g., \`Button.tsx\`)
|
|
75
|
-
- Utilities: camelCase (e.g., \`formatDate.ts\`)
|
|
76
|
-
- Types: PascalCase with \`.types.ts\` suffix
|
|
77
|
-
|
|
78
|
-
### Import Aliases
|
|
79
|
-
- Use \`@/\` for src imports (e.g., \`@/components/Button\`)
|
|
80
|
-
- Never use deep relative imports like \`../../../\`
|
|
81
|
-
|
|
82
|
-
### TypeScript
|
|
83
|
-
${analysis.hasTypescript ? `- Enable strict mode
|
|
84
|
-
- No \`any\` types - use \`unknown\` or proper types
|
|
85
|
-
- Define interfaces for all props and API responses` : "- Use JSDoc comments for type hints"}
|
|
86
|
-
|
|
87
|
-
## Critical Rules
|
|
88
|
-
|
|
89
|
-
1. **Security**: Never hardcode API keys, secrets, or credentials
|
|
90
|
-
2. **Types**: ${analysis.hasTypescript ? "No `any` types allowed" : "Use JSDoc for type hints"}
|
|
91
|
-
3. **Components**: Check existing components before creating new ones
|
|
92
|
-
4. **Hooks**: Use existing custom hooks when available
|
|
93
|
-
5. **Validation**: ${p.validation ? `Always validate input with ${p.validation}` : "Always validate user input"}
|
|
94
|
-
6. **Styling**: ${analysis.hasTailwind ? "Use Tailwind CSS classes" : "Follow existing styling patterns"}
|
|
95
|
-
7. **State**: ${p.stateManagement ? `Use ${p.stateManagement} for global state` : "Keep state minimal and local"}
|
|
96
|
-
|
|
97
|
-
${p.antiPatterns?.length > 0 ? `## Anti-Patterns to Avoid
|
|
98
|
-
|
|
99
|
-
${p.antiPatterns.map(ap => `- ❌ ${ap.message} → ${ap.suggestion}`).join("\n")}
|
|
100
|
-
` : ""}
|
|
101
|
-
|
|
102
|
-
## When Writing Code
|
|
103
|
-
|
|
104
|
-
1. Follow existing patterns in the codebase
|
|
105
|
-
2. Use TypeScript strict types
|
|
106
|
-
3. Add proper error handling
|
|
107
|
-
4. Use existing utilities and helpers
|
|
108
|
-
5. Keep functions small and focused
|
|
109
|
-
6. Write self-documenting code
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
*Context Enhanced by vibecheck AI*
|
|
114
|
-
`;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
module.exports = {
|
|
118
|
-
generateCopilotInstructions,
|
|
119
|
-
};
|
|
@@ -1,514 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cursor Rules Generator
|
|
3
|
-
* Generates .cursorrules and .cursor/rules/*.mdc files
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Get directory purpose description
|
|
8
|
-
*/
|
|
9
|
-
function getDirectoryPurpose(dir) {
|
|
10
|
-
const purposes = {
|
|
11
|
-
"src": "Source code root",
|
|
12
|
-
"app": "Next.js App Router pages",
|
|
13
|
-
"pages": "Next.js Pages Router",
|
|
14
|
-
"components": "Reusable UI components",
|
|
15
|
-
"lib": "Utility functions and shared logic",
|
|
16
|
-
"utils": "Helper functions",
|
|
17
|
-
"hooks": "Custom React hooks",
|
|
18
|
-
"services": "API and external service integrations",
|
|
19
|
-
"api": "API route handlers",
|
|
20
|
-
"server": "Server-side code",
|
|
21
|
-
"prisma": "Database schema and migrations",
|
|
22
|
-
"public": "Static assets",
|
|
23
|
-
"styles": "CSS and styling",
|
|
24
|
-
"types": "TypeScript type definitions",
|
|
25
|
-
"config": "Configuration files",
|
|
26
|
-
"test": "Test files",
|
|
27
|
-
"__tests__": "Test files",
|
|
28
|
-
};
|
|
29
|
-
return purposes[dir] || "Project files";
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Generate main .cursorrules file
|
|
34
|
-
*/
|
|
35
|
-
function generateCursorRules(analysis) {
|
|
36
|
-
const p = analysis.patterns || {};
|
|
37
|
-
const t = analysis.types || {};
|
|
38
|
-
const s = analysis.stats || {};
|
|
39
|
-
const env = analysis.envVars || {};
|
|
40
|
-
const m = analysis.monorepo || {};
|
|
41
|
-
|
|
42
|
-
return `# vibecheck AI - Project Context for Cursor
|
|
43
|
-
|
|
44
|
-
> Auto-generated by \`vibecheck context\`. Regenerate when your codebase changes.
|
|
45
|
-
|
|
46
|
-
## Project Overview
|
|
47
|
-
|
|
48
|
-
- **Name**: ${analysis.name}
|
|
49
|
-
- **Framework**: ${analysis.framework || "Unknown"}
|
|
50
|
-
- **Language**: ${analysis.language || "JavaScript"}
|
|
51
|
-
- **Architecture**: ${analysis.architecture}
|
|
52
|
-
${s.totalFiles ? `- **Size**: ${s.totalFiles} files, ~${Math.round(s.totalLines / 1000)}k lines` : ""}
|
|
53
|
-
${m.isMonorepo ? `- **Monorepo**: ${m.type} with ${m.workspaces?.length || 0} workspaces` : ""}
|
|
54
|
-
|
|
55
|
-
## Tech Stack
|
|
56
|
-
|
|
57
|
-
${analysis.hasNextjs ? "- Next.js (App Router)" : ""}
|
|
58
|
-
${analysis.hasReact ? "- React" : ""}
|
|
59
|
-
${analysis.hasTypescript ? "- TypeScript" : ""}
|
|
60
|
-
${analysis.hasPrisma ? "- Prisma ORM" : ""}
|
|
61
|
-
${analysis.hasTailwind ? "- Tailwind CSS" : ""}
|
|
62
|
-
${p.stateManagement ? `- State: ${p.stateManagement}` : ""}
|
|
63
|
-
${p.validation ? `- Validation: ${p.validation}` : ""}
|
|
64
|
-
${p.authentication ? `- Auth: ${p.authentication}` : ""}
|
|
65
|
-
${p.dataFetching?.length ? `- Data Fetching: ${p.dataFetching.join(", ")}` : ""}
|
|
66
|
-
|
|
67
|
-
## Project Structure
|
|
68
|
-
|
|
69
|
-
\`\`\`
|
|
70
|
-
${analysis.directories.map(d => `${d}/`).join("\n")}
|
|
71
|
-
\`\`\`
|
|
72
|
-
|
|
73
|
-
${m.isMonorepo && m.workspaces?.length > 0 ? `## Workspaces
|
|
74
|
-
|
|
75
|
-
${m.workspaces.slice(0, 10).map(w => `- \`${w.path}\` - ${w.name}`).join("\n")}
|
|
76
|
-
` : ""}
|
|
77
|
-
|
|
78
|
-
${p.hooks?.length > 0 ? `## Custom Hooks (Use These!)
|
|
79
|
-
|
|
80
|
-
${p.hooks.slice(0, 15).map(h => `- \`${h}\``).join("\n")}
|
|
81
|
-
|
|
82
|
-
${p.codeExamples?.hooks ? `### Example: ${p.codeExamples.hooks.name}
|
|
83
|
-
\`\`\`typescript
|
|
84
|
-
// From: ${p.codeExamples.hooks.file}
|
|
85
|
-
${p.codeExamples.hooks.code}
|
|
86
|
-
\`\`\`
|
|
87
|
-
` : ""}
|
|
88
|
-
` : ""}
|
|
89
|
-
|
|
90
|
-
${analysis.apiRoutes.length > 0 ? `## API Routes
|
|
91
|
-
|
|
92
|
-
${analysis.apiRoutes.slice(0, 20).map(r => `- \`${r}\``).join("\n")}
|
|
93
|
-
${analysis.apiRoutes.length > 20 ? `\n... and ${analysis.apiRoutes.length - 20} more` : ""}
|
|
94
|
-
` : ""}
|
|
95
|
-
|
|
96
|
-
${analysis.components.length > 0 ? `## Components (Check Before Creating New)
|
|
97
|
-
|
|
98
|
-
${analysis.components.slice(0, 30).map(c => `- \`${c}\``).join("\n")}
|
|
99
|
-
${analysis.components.length > 30 ? `\n... and ${analysis.components.length - 30} more` : ""}
|
|
100
|
-
` : ""}
|
|
101
|
-
|
|
102
|
-
${analysis.models.length > 0 ? `## Data Models (Prisma)
|
|
103
|
-
|
|
104
|
-
${analysis.models.map(m => `- \`${m}\``).join("\n")}
|
|
105
|
-
` : ""}
|
|
106
|
-
|
|
107
|
-
${t.interfaces?.length > 0 || t.types?.length > 0 ? `## Key Types & Interfaces
|
|
108
|
-
|
|
109
|
-
${t.interfaces?.slice(0, 15).map(i => `- \`interface ${i}\``).join("\n") || ""}
|
|
110
|
-
${t.types?.slice(0, 10).map(ty => `- \`type ${ty}\``).join("\n") || ""}
|
|
111
|
-
${t.enums?.length > 0 ? `\nEnums: ${t.enums.slice(0, 5).map(e => `\`${e}\``).join(", ")}` : ""}
|
|
112
|
-
` : ""}
|
|
113
|
-
|
|
114
|
-
${env.variables?.length > 0 ? `## Environment Variables
|
|
115
|
-
|
|
116
|
-
Required env vars:
|
|
117
|
-
${env.variables.slice(0, 20).map(v => `- \`${v}\``).join("\n")}
|
|
118
|
-
${env.files?.length ? `\nEnv files: ${env.files.join(", ")}` : ""}
|
|
119
|
-
` : ""}
|
|
120
|
-
|
|
121
|
-
${analysis.scripts?.length > 0 ? `## NPM Scripts
|
|
122
|
-
|
|
123
|
-
${analysis.scripts.slice(0, 10).map(s => `- \`npm run ${s.name}\` - ${s.command}`).join("\n")}
|
|
124
|
-
` : ""}
|
|
125
|
-
|
|
126
|
-
## Coding Conventions
|
|
127
|
-
|
|
128
|
-
### File Naming
|
|
129
|
-
- Components: ${analysis.conventions.naming.components || "PascalCase"} (e.g., \`Button.tsx\`, \`UserCard.tsx\`)
|
|
130
|
-
- Utilities: camelCase (e.g., \`formatDate.ts\`, \`apiClient.ts\`)
|
|
131
|
-
- Types: PascalCase with \`.d.ts\` or \`.types.ts\` suffix
|
|
132
|
-
|
|
133
|
-
### Import Order
|
|
134
|
-
1. React/Next.js imports
|
|
135
|
-
2. Third-party libraries
|
|
136
|
-
3. Internal components (\`@/components/\`)
|
|
137
|
-
4. Internal utilities (\`@/lib/\`, \`@/utils/\`)
|
|
138
|
-
5. Types
|
|
139
|
-
6. Styles
|
|
140
|
-
|
|
141
|
-
### Code Style
|
|
142
|
-
- Use ${analysis.hasTypescript ? "TypeScript with strict mode" : "JavaScript with JSDoc comments"}
|
|
143
|
-
- Prefer functional components with hooks
|
|
144
|
-
- Use path aliases (\`@/\`) for imports
|
|
145
|
-
${analysis.hasTailwind ? "- Use Tailwind CSS for styling (no inline styles)" : ""}
|
|
146
|
-
${analysis.hasPrisma ? "- Use Prisma client for database operations" : ""}
|
|
147
|
-
${p.stateManagement ? `- Use ${p.stateManagement} for state management` : ""}
|
|
148
|
-
${p.validation ? `- Use ${p.validation} for input validation` : ""}
|
|
149
|
-
|
|
150
|
-
## Critical Rules
|
|
151
|
-
|
|
152
|
-
1. **Never hardcode secrets** - Use environment variables
|
|
153
|
-
2. **No mock data in production** - Check for \`demo\`, \`fake\`, \`mock\` patterns
|
|
154
|
-
3. **Type everything** - No \`any\` types${analysis.hasTypescript ? "" : " (use JSDoc)"}
|
|
155
|
-
4. **Follow existing patterns** - Match the codebase style
|
|
156
|
-
5. **Use existing components** - Don't recreate what exists
|
|
157
|
-
6. **API routes must validate input** - Never trust client data
|
|
158
|
-
${p.hooks?.length ? `7. **Use existing hooks** - Check custom hooks list above` : ""}
|
|
159
|
-
|
|
160
|
-
${p.antiPatterns?.length > 0 ? `## ⚠️ Avoid These Patterns
|
|
161
|
-
|
|
162
|
-
${p.antiPatterns.map(ap => `- **${ap.message}** - ${ap.suggestion}`).join("\n")}
|
|
163
|
-
` : ""}
|
|
164
|
-
|
|
165
|
-
## When Creating New Files
|
|
166
|
-
|
|
167
|
-
1. Check if similar file exists first
|
|
168
|
-
2. Place in correct directory based on type
|
|
169
|
-
3. Follow naming conventions
|
|
170
|
-
4. Import from correct paths
|
|
171
|
-
5. Add proper types/interfaces
|
|
172
|
-
${p.hooks?.length ? `6. Check if there's an existing hook you can use` : ""}
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
|
|
176
|
-
*Context Enhanced by vibecheck AI*
|
|
177
|
-
`;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Generate modular Cursor rules (.cursor/rules/*.mdc)
|
|
182
|
-
*/
|
|
183
|
-
function generateCursorModularRules(analysis) {
|
|
184
|
-
const rules = {};
|
|
185
|
-
const p = analysis.patterns || {};
|
|
186
|
-
const t = analysis.types || {};
|
|
187
|
-
const env = analysis.envVars || {};
|
|
188
|
-
const m = analysis.monorepo || {};
|
|
189
|
-
|
|
190
|
-
// Architecture rules
|
|
191
|
-
rules["architecture"] = `---
|
|
192
|
-
description: Project architecture and structure guidelines
|
|
193
|
-
globs: ["**/*.{ts,tsx,js,jsx}"]
|
|
194
|
-
alwaysApply: true
|
|
195
|
-
---
|
|
196
|
-
|
|
197
|
-
# Architecture Guidelines
|
|
198
|
-
|
|
199
|
-
## Project Type: ${analysis.architecture}
|
|
200
|
-
|
|
201
|
-
${analysis.hasNextjs ? `### Next.js App Router Structure
|
|
202
|
-
- Pages go in \`app/\` directory
|
|
203
|
-
- API routes in \`app/api/\`
|
|
204
|
-
- Layouts use \`layout.tsx\`
|
|
205
|
-
- Loading states use \`loading.tsx\`
|
|
206
|
-
- Error boundaries use \`error.tsx\`
|
|
207
|
-
` : ""}
|
|
208
|
-
|
|
209
|
-
${m.isMonorepo ? `### Monorepo Structure (${m.type})
|
|
210
|
-
|
|
211
|
-
Workspaces:
|
|
212
|
-
${m.workspaces?.slice(0, 8).map(w => `- \`${w.path}\` - ${w.name}`).join("\n") || "None detected"}
|
|
213
|
-
|
|
214
|
-
${m.sharedPackages?.length > 0 ? `Shared Packages:
|
|
215
|
-
${m.sharedPackages.slice(0, 5).map(p => `- ${p.name} (used in ${p.usedIn} workspaces)`).join("\n")}` : ""}
|
|
216
|
-
` : ""}
|
|
217
|
-
|
|
218
|
-
### Directory Purpose
|
|
219
|
-
${analysis.directories.map(d => `- \`${d}/\` - ${getDirectoryPurpose(d)}`).join("\n")}
|
|
220
|
-
|
|
221
|
-
### Import Aliases
|
|
222
|
-
- Use \`@/\` for src directory imports
|
|
223
|
-
- Never use relative imports deeper than \`../\`
|
|
224
|
-
`;
|
|
225
|
-
|
|
226
|
-
// Data flow rules
|
|
227
|
-
if (analysis.hasPrisma || analysis.apiRoutes.length > 0 || p.dataFetching?.length) {
|
|
228
|
-
rules["data-flow"] = `---
|
|
229
|
-
description: Data fetching and API interaction patterns
|
|
230
|
-
globs: ["**/api/**", "**/lib/**", "**/services/**", "**/hooks/**"]
|
|
231
|
-
alwaysApply: false
|
|
232
|
-
---
|
|
233
|
-
|
|
234
|
-
# Data Flow Guidelines
|
|
235
|
-
|
|
236
|
-
${p.dataFetching?.length ? `## Data Fetching: ${p.dataFetching.join(", ")}
|
|
237
|
-
|
|
238
|
-
${p.dataFetching.includes("TanStack Query") ? `### TanStack Query Pattern
|
|
239
|
-
- Use \`useQuery\` for GET requests
|
|
240
|
-
- Use \`useMutation\` for POST/PUT/DELETE
|
|
241
|
-
- Define query keys consistently
|
|
242
|
-
- Invalidate queries after mutations
|
|
243
|
-
` : ""}
|
|
244
|
-
${p.dataFetching.includes("SWR") ? `### SWR Pattern
|
|
245
|
-
- Use \`useSWR\` for data fetching
|
|
246
|
-
- Define fetcher functions
|
|
247
|
-
- Handle loading and error states
|
|
248
|
-
` : ""}
|
|
249
|
-
${p.dataFetching.includes("tRPC") ? `### tRPC Pattern
|
|
250
|
-
- Use tRPC procedures for type-safe API calls
|
|
251
|
-
- Define routers in \`server/api/routers\`
|
|
252
|
-
- Use \`api.*.useQuery()\` pattern
|
|
253
|
-
` : ""}
|
|
254
|
-
` : ""}
|
|
255
|
-
|
|
256
|
-
${analysis.hasPrisma ? `## Database (Prisma)
|
|
257
|
-
|
|
258
|
-
Models: ${analysis.models.join(", ")}
|
|
259
|
-
|
|
260
|
-
Rules:
|
|
261
|
-
- Use Prisma client from \`@/lib/prisma\` or \`@/server/db\`
|
|
262
|
-
- Use transactions for multi-step operations
|
|
263
|
-
- Handle errors with try/catch
|
|
264
|
-
- Never expose raw database errors
|
|
265
|
-
` : ""}
|
|
266
|
-
|
|
267
|
-
${analysis.apiRoutes.length > 0 ? `## API Routes
|
|
268
|
-
|
|
269
|
-
${analysis.apiRoutes.slice(0, 15).map(r => `- ${r}`).join("\n")}
|
|
270
|
-
|
|
271
|
-
Rules:
|
|
272
|
-
${p.validation ? `- Validate all input with ${p.validation}` : "- Validate all input"}
|
|
273
|
-
- Return consistent response shapes
|
|
274
|
-
- Use proper HTTP status codes
|
|
275
|
-
` : ""}
|
|
276
|
-
`;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Component rules
|
|
280
|
-
if (analysis.components.length > 0) {
|
|
281
|
-
rules["components"] = `---
|
|
282
|
-
description: Component creation and styling guidelines
|
|
283
|
-
globs: ["**/components/**/*.{tsx,jsx}"]
|
|
284
|
-
alwaysApply: false
|
|
285
|
-
---
|
|
286
|
-
|
|
287
|
-
# Component Guidelines
|
|
288
|
-
|
|
289
|
-
## Existing Components (${analysis.components.length})
|
|
290
|
-
${analysis.components.slice(0, 20).map(c => `- \`${c}\``).join("\n")}
|
|
291
|
-
|
|
292
|
-
## Before Creating New Components
|
|
293
|
-
|
|
294
|
-
1. **Check if it exists above**
|
|
295
|
-
2. Place in \`components/\` or feature folder
|
|
296
|
-
3. Use ${analysis.conventions.naming.components || "PascalCase"} naming
|
|
297
|
-
4. Export as named export
|
|
298
|
-
${analysis.hasTailwind ? "5. Use Tailwind CSS for styling" : ""}
|
|
299
|
-
${p.styling?.length ? `6. Styling: ${p.styling.join(", ")}` : ""}
|
|
300
|
-
|
|
301
|
-
## Component Template
|
|
302
|
-
|
|
303
|
-
\`\`\`tsx
|
|
304
|
-
interface Props {
|
|
305
|
-
// Define props with types
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
export function ComponentName({ ...props }: Props) {
|
|
309
|
-
return (
|
|
310
|
-
// JSX
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
\`\`\`
|
|
314
|
-
`;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Hooks rules
|
|
318
|
-
if (p.hooks?.length > 0) {
|
|
319
|
-
rules["hooks"] = `---
|
|
320
|
-
description: Custom hooks patterns and usage
|
|
321
|
-
globs: ["**/hooks/**/*.{ts,tsx}", "**/use*.{ts,tsx}"]
|
|
322
|
-
alwaysApply: false
|
|
323
|
-
---
|
|
324
|
-
|
|
325
|
-
# Custom Hooks
|
|
326
|
-
|
|
327
|
-
## Available Hooks (${p.hooks.length})
|
|
328
|
-
|
|
329
|
-
${p.hooks.map(h => `- \`${h}\``).join("\n")}
|
|
330
|
-
|
|
331
|
-
## Before Creating a New Hook
|
|
332
|
-
|
|
333
|
-
1. **Check the list above first**
|
|
334
|
-
2. Name it \`use[Feature]\`
|
|
335
|
-
3. Place in \`hooks/\` or \`lib/hooks/\`
|
|
336
|
-
4. Return a consistent shape
|
|
337
|
-
|
|
338
|
-
${p.codeExamples?.hooks ? `## Example
|
|
339
|
-
|
|
340
|
-
\`\`\`typescript
|
|
341
|
-
// ${p.codeExamples.hooks.file}
|
|
342
|
-
${p.codeExamples.hooks.code}
|
|
343
|
-
\`\`\`
|
|
344
|
-
` : ""}
|
|
345
|
-
`;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// State management rules
|
|
349
|
-
if (p.stateManagement) {
|
|
350
|
-
rules["state"] = `---
|
|
351
|
-
description: State management patterns
|
|
352
|
-
globs: ["**/store/**", "**/state/**", "**/context/**"]
|
|
353
|
-
alwaysApply: false
|
|
354
|
-
---
|
|
355
|
-
|
|
356
|
-
# State Management: ${p.stateManagement}
|
|
357
|
-
|
|
358
|
-
${p.stateManagement === "Zustand" ? `## Zustand Pattern
|
|
359
|
-
|
|
360
|
-
\`\`\`typescript
|
|
361
|
-
import { create } from 'zustand'
|
|
362
|
-
|
|
363
|
-
interface Store {
|
|
364
|
-
count: number
|
|
365
|
-
increment: () => void
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
export const useStore = create<Store>((set) => ({
|
|
369
|
-
count: 0,
|
|
370
|
-
increment: () => set((state) => ({ count: state.count + 1 })),
|
|
371
|
-
}))
|
|
372
|
-
\`\`\`
|
|
373
|
-
|
|
374
|
-
- Create stores in \`store/\` directory
|
|
375
|
-
- Use typed store interfaces
|
|
376
|
-
- Keep stores focused and small
|
|
377
|
-
` : ""}
|
|
378
|
-
${p.stateManagement === "Redux Toolkit" ? `## Redux Toolkit Pattern
|
|
379
|
-
|
|
380
|
-
\`\`\`typescript
|
|
381
|
-
import { createSlice } from '@reduxjs/toolkit'
|
|
382
|
-
|
|
383
|
-
const slice = createSlice({
|
|
384
|
-
name: 'feature',
|
|
385
|
-
initialState: {},
|
|
386
|
-
reducers: {}
|
|
387
|
-
})
|
|
388
|
-
\`\`\`
|
|
389
|
-
|
|
390
|
-
- Use createSlice for reducers
|
|
391
|
-
- Use createAsyncThunk for async
|
|
392
|
-
` : ""}
|
|
393
|
-
${p.stateManagement === "React Context" ? `## Context Pattern
|
|
394
|
-
|
|
395
|
-
\`\`\`typescript
|
|
396
|
-
const Context = createContext<Type | null>(null)
|
|
397
|
-
|
|
398
|
-
export function useFeature() {
|
|
399
|
-
const context = useContext(Context)
|
|
400
|
-
if (!context) throw new Error('Must be used within Provider')
|
|
401
|
-
return context
|
|
402
|
-
}
|
|
403
|
-
\`\`\`
|
|
404
|
-
` : ""}
|
|
405
|
-
`;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// Types rules
|
|
409
|
-
if (t.interfaces?.length > 0 || t.types?.length > 0) {
|
|
410
|
-
rules["types"] = `---
|
|
411
|
-
description: Type definitions and interfaces
|
|
412
|
-
globs: ["**/*.d.ts", "**/types/**", "**/*.types.ts"]
|
|
413
|
-
alwaysApply: false
|
|
414
|
-
---
|
|
415
|
-
|
|
416
|
-
# Type Definitions
|
|
417
|
-
|
|
418
|
-
## Interfaces (${t.interfaces?.length || 0})
|
|
419
|
-
${t.interfaces?.slice(0, 20).map(i => `- \`${i}\``).join("\n") || "None"}
|
|
420
|
-
|
|
421
|
-
## Types (${t.types?.length || 0})
|
|
422
|
-
${t.types?.slice(0, 15).map(ty => `- \`${ty}\``).join("\n") || "None"}
|
|
423
|
-
|
|
424
|
-
${t.enums?.length > 0 ? `## Enums
|
|
425
|
-
${t.enums.map(e => `- \`${e}\``).join("\n")}` : ""}
|
|
426
|
-
|
|
427
|
-
## Conventions
|
|
428
|
-
- Interfaces for object shapes
|
|
429
|
-
- Type aliases for unions
|
|
430
|
-
- No \`any\` - use \`unknown\`
|
|
431
|
-
`;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// Environment rules
|
|
435
|
-
if (env.variables?.length > 0) {
|
|
436
|
-
rules["environment"] = `---
|
|
437
|
-
description: Environment variables
|
|
438
|
-
globs: ["**/*.env*", "**/config/**"]
|
|
439
|
-
alwaysApply: false
|
|
440
|
-
---
|
|
441
|
-
|
|
442
|
-
# Environment Variables (${env.variables?.length || 0})
|
|
443
|
-
|
|
444
|
-
${env.variables?.slice(0, 25).map(v => `- \`${v}\``).join("\n")}
|
|
445
|
-
|
|
446
|
-
## Rules
|
|
447
|
-
- Never commit \`.env\` files
|
|
448
|
-
- Access via \`process.env.VAR_NAME\`
|
|
449
|
-
- Prefix client-side vars with \`NEXT_PUBLIC_\`
|
|
450
|
-
`;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// Anti-patterns rules
|
|
454
|
-
if (p.antiPatterns?.length > 0) {
|
|
455
|
-
rules["avoid"] = `---
|
|
456
|
-
description: Patterns to avoid
|
|
457
|
-
globs: ["**/*.{ts,tsx,js,jsx}"]
|
|
458
|
-
alwaysApply: true
|
|
459
|
-
---
|
|
460
|
-
|
|
461
|
-
# ⚠️ Patterns to Avoid
|
|
462
|
-
|
|
463
|
-
${p.antiPatterns.map(ap => `## ${ap.severity === 'error' ? '🔴' : '🟡'} ${ap.message}
|
|
464
|
-
**Fix:** ${ap.suggestion}
|
|
465
|
-
`).join("\n")}
|
|
466
|
-
|
|
467
|
-
## General
|
|
468
|
-
- ❌ No \`any\` type
|
|
469
|
-
- ❌ No hardcoded secrets
|
|
470
|
-
- ❌ No console.log in production
|
|
471
|
-
- ❌ No mock data in production
|
|
472
|
-
`;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// Testing rules
|
|
476
|
-
if (p.testing?.length > 0) {
|
|
477
|
-
rules["testing"] = `---
|
|
478
|
-
description: Testing patterns
|
|
479
|
-
globs: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"]
|
|
480
|
-
alwaysApply: false
|
|
481
|
-
---
|
|
482
|
-
|
|
483
|
-
# Testing: ${p.testing.join(", ")}
|
|
484
|
-
|
|
485
|
-
${p.testing.includes("Jest") || p.testing.includes("Vitest") ? `## Unit Tests
|
|
486
|
-
|
|
487
|
-
\`\`\`typescript
|
|
488
|
-
describe('Feature', () => {
|
|
489
|
-
it('should work', () => {
|
|
490
|
-
expect(result).toBe('expected')
|
|
491
|
-
})
|
|
492
|
-
})
|
|
493
|
-
\`\`\`
|
|
494
|
-
` : ""}
|
|
495
|
-
${p.testing.includes("Playwright") ? `## E2E Tests
|
|
496
|
-
|
|
497
|
-
\`\`\`typescript
|
|
498
|
-
test('user flow', async ({ page }) => {
|
|
499
|
-
await page.goto('/')
|
|
500
|
-
await page.click('button')
|
|
501
|
-
})
|
|
502
|
-
\`\`\`
|
|
503
|
-
` : ""}
|
|
504
|
-
`;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
return rules;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
module.exports = {
|
|
511
|
-
generateCursorRules,
|
|
512
|
-
generateCursorModularRules,
|
|
513
|
-
getDirectoryPurpose,
|
|
514
|
-
};
|