ai-factory 2.0.0 → 2.2.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/README.md +17 -4
- package/dist/cli/commands/extension.d.ts +4 -0
- package/dist/cli/commands/extension.d.ts.map +1 -0
- package/dist/cli/commands/extension.js +288 -0
- package/dist/cli/commands/extension.js.map +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +31 -35
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +86 -7
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/upgrade.d.ts.map +1 -1
- package/dist/cli/commands/upgrade.js +44 -41
- package/dist/cli/commands/upgrade.js.map +1 -1
- package/dist/cli/index.js +48 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/wizard/prompts.d.ts +2 -1
- package/dist/cli/wizard/prompts.d.ts.map +1 -1
- package/dist/cli/wizard/prompts.js +13 -20
- package/dist/cli/wizard/prompts.js.map +1 -1
- package/dist/core/agents.d.ts.map +1 -1
- package/dist/core/agents.js +9 -0
- package/dist/core/agents.js.map +1 -1
- package/dist/core/config.d.ts +8 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +5 -8
- package/dist/core/config.js.map +1 -1
- package/dist/core/extension-ops.d.ts +32 -0
- package/dist/core/extension-ops.d.ts.map +1 -0
- package/dist/core/extension-ops.js +83 -0
- package/dist/core/extension-ops.js.map +1 -0
- package/dist/core/extensions.d.ts +53 -0
- package/dist/core/extensions.d.ts.map +1 -0
- package/dist/core/extensions.js +141 -0
- package/dist/core/extensions.js.map +1 -0
- package/dist/core/injections.d.ts +10 -0
- package/dist/core/injections.d.ts.map +1 -0
- package/dist/core/injections.js +154 -0
- package/dist/core/injections.js.map +1 -0
- package/dist/core/installer.d.ts +7 -3
- package/dist/core/installer.d.ts.map +1 -1
- package/dist/core/installer.js +68 -26
- package/dist/core/installer.js.map +1 -1
- package/dist/core/mcp.d.ts +12 -0
- package/dist/core/mcp.d.ts.map +1 -1
- package/dist/core/mcp.js +112 -67
- package/dist/core/mcp.js.map +1 -1
- package/dist/core/transformer.d.ts +10 -1
- package/dist/core/transformer.d.ts.map +1 -1
- package/dist/core/transformer.js +19 -1
- package/dist/core/transformer.js.map +1 -1
- package/dist/core/transformers/antigravity.d.ts +1 -0
- package/dist/core/transformers/antigravity.d.ts.map +1 -1
- package/dist/core/transformers/antigravity.js +19 -4
- package/dist/core/transformers/antigravity.js.map +1 -1
- package/dist/core/transformers/codex.d.ts +7 -0
- package/dist/core/transformers/codex.d.ts.map +1 -0
- package/dist/core/transformers/codex.js +24 -0
- package/dist/core/transformers/codex.js.map +1 -0
- package/dist/core/transformers/default.d.ts +1 -0
- package/dist/core/transformers/default.d.ts.map +1 -1
- package/dist/core/transformers/default.js +6 -0
- package/dist/core/transformers/default.js.map +1 -1
- package/dist/core/transformers/kilocode.js +1 -1
- package/dist/core/transformers/kilocode.js.map +1 -1
- package/dist/core/transformers/qwen.d.ts +7 -0
- package/dist/core/transformers/qwen.d.ts.map +1 -0
- package/dist/core/transformers/qwen.js +25 -0
- package/dist/core/transformers/qwen.js.map +1 -0
- package/dist/utils/fs.d.ts +0 -2
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +1 -5
- package/dist/utils/fs.js.map +1 -1
- package/mcp/templates/playwright.json +4 -0
- package/package.json +16 -1
- package/skills/aif/SKILL.md +27 -52
- package/skills/aif-commit/SKILL.md +13 -1
- package/skills/aif-grounded/SKILL.md +90 -0
- package/skills/aif-implement/SKILL.md +39 -2
- package/skills/aif-implement/references/IMPLEMENTATION-GUIDE.md +16 -0
- package/skills/aif-loop/SKILL.md +2 -2
- package/dist/cli/wizard/detector.d.ts +0 -10
- package/dist/cli/wizard/detector.d.ts.map +0 -1
- package/dist/cli/wizard/detector.js +0 -231
- package/dist/cli/wizard/detector.js.map +0 -1
- package/skills/_templates/nextjs/nextjs-patterns/SKILL.md +0 -146
- package/skills/_templates/node-api/api-patterns/SKILL.md +0 -245
- package/skills/_templates/php/php-patterns/SKILL.md +0 -491
- package/skills/_templates/python/python-patterns/SKILL.md +0 -236
- package/skills/_templates/react/react-patterns/SKILL.md +0 -181
- package/skills/aif-deploy/SKILL.md +0 -138
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import { readJsonFile, readTextFile, fileExists } from '../../utils/fs.js';
|
|
3
|
-
export async function detectStack(projectDir) {
|
|
4
|
-
const packageJsonPath = path.join(projectDir, 'package.json');
|
|
5
|
-
const composerJsonPath = path.join(projectDir, 'composer.json');
|
|
6
|
-
const requirementsPath = path.join(projectDir, 'requirements.txt');
|
|
7
|
-
const pyprojectPath = path.join(projectDir, 'pyproject.toml');
|
|
8
|
-
const goModPath = path.join(projectDir, 'go.mod');
|
|
9
|
-
const cargoTomlPath = path.join(projectDir, 'Cargo.toml');
|
|
10
|
-
if (await fileExists(packageJsonPath)) {
|
|
11
|
-
const packageJson = await readJsonFile(packageJsonPath);
|
|
12
|
-
if (packageJson) {
|
|
13
|
-
return detectJavaScriptStack(packageJson, projectDir);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
if (await fileExists(composerJsonPath)) {
|
|
17
|
-
const composerJson = await readJsonFile(composerJsonPath);
|
|
18
|
-
if (composerJson) {
|
|
19
|
-
return detectPhpStack(composerJson);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
if (await fileExists(requirementsPath) || await fileExists(pyprojectPath)) {
|
|
23
|
-
return detectPythonStack(projectDir);
|
|
24
|
-
}
|
|
25
|
-
if (await fileExists(goModPath)) {
|
|
26
|
-
return {
|
|
27
|
-
name: 'go',
|
|
28
|
-
confidence: 'high',
|
|
29
|
-
frameworks: [],
|
|
30
|
-
languages: ['go'],
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
if (await fileExists(cargoTomlPath)) {
|
|
34
|
-
return {
|
|
35
|
-
name: 'rust',
|
|
36
|
-
confidence: 'high',
|
|
37
|
-
frameworks: [],
|
|
38
|
-
languages: ['rust'],
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
async function detectJavaScriptStack(packageJson, projectDir) {
|
|
44
|
-
const allDeps = {
|
|
45
|
-
...packageJson.dependencies,
|
|
46
|
-
...packageJson.devDependencies,
|
|
47
|
-
};
|
|
48
|
-
const frameworks = [];
|
|
49
|
-
const languages = ['javascript'];
|
|
50
|
-
if (allDeps['typescript']) {
|
|
51
|
-
languages.push('typescript');
|
|
52
|
-
}
|
|
53
|
-
if (allDeps['next']) {
|
|
54
|
-
frameworks.push('next.js');
|
|
55
|
-
const hasAppDir = await fileExists(path.join(projectDir, 'app'));
|
|
56
|
-
const hasPagesDir = await fileExists(path.join(projectDir, 'pages'));
|
|
57
|
-
return {
|
|
58
|
-
name: 'nextjs',
|
|
59
|
-
confidence: 'high',
|
|
60
|
-
frameworks,
|
|
61
|
-
languages,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
if (allDeps['react']) {
|
|
65
|
-
frameworks.push('react');
|
|
66
|
-
if (allDeps['vite']) {
|
|
67
|
-
frameworks.push('vite');
|
|
68
|
-
}
|
|
69
|
-
return {
|
|
70
|
-
name: 'react',
|
|
71
|
-
confidence: 'high',
|
|
72
|
-
frameworks,
|
|
73
|
-
languages,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
if (allDeps['vue']) {
|
|
77
|
-
frameworks.push('vue');
|
|
78
|
-
return {
|
|
79
|
-
name: 'vue',
|
|
80
|
-
confidence: 'high',
|
|
81
|
-
frameworks,
|
|
82
|
-
languages,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
if (allDeps['express'] || allDeps['fastify'] || allDeps['koa'] || allDeps['hono']) {
|
|
86
|
-
if (allDeps['express'])
|
|
87
|
-
frameworks.push('express');
|
|
88
|
-
if (allDeps['fastify'])
|
|
89
|
-
frameworks.push('fastify');
|
|
90
|
-
if (allDeps['koa'])
|
|
91
|
-
frameworks.push('koa');
|
|
92
|
-
if (allDeps['hono'])
|
|
93
|
-
frameworks.push('hono');
|
|
94
|
-
return {
|
|
95
|
-
name: 'node-api',
|
|
96
|
-
confidence: 'high',
|
|
97
|
-
frameworks,
|
|
98
|
-
languages,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
name: 'node',
|
|
103
|
-
confidence: 'medium',
|
|
104
|
-
frameworks,
|
|
105
|
-
languages,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
function detectPhpStack(composerJson) {
|
|
109
|
-
const allDeps = {
|
|
110
|
-
...composerJson.require,
|
|
111
|
-
...composerJson['require-dev'],
|
|
112
|
-
};
|
|
113
|
-
const frameworks = [];
|
|
114
|
-
const languages = ['php'];
|
|
115
|
-
if (allDeps['laravel/framework']) {
|
|
116
|
-
frameworks.push('laravel');
|
|
117
|
-
return {
|
|
118
|
-
name: 'laravel',
|
|
119
|
-
confidence: 'high',
|
|
120
|
-
frameworks,
|
|
121
|
-
languages,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
if (allDeps['symfony/framework-bundle'] || allDeps['symfony/symfony']) {
|
|
125
|
-
frameworks.push('symfony');
|
|
126
|
-
return {
|
|
127
|
-
name: 'symfony',
|
|
128
|
-
confidence: 'high',
|
|
129
|
-
frameworks,
|
|
130
|
-
languages,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
if (allDeps['slim/slim']) {
|
|
134
|
-
frameworks.push('slim');
|
|
135
|
-
return {
|
|
136
|
-
name: 'slim',
|
|
137
|
-
confidence: 'high',
|
|
138
|
-
frameworks,
|
|
139
|
-
languages,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
return {
|
|
143
|
-
name: 'php',
|
|
144
|
-
confidence: 'medium',
|
|
145
|
-
frameworks,
|
|
146
|
-
languages,
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
async function detectPythonStack(projectDir) {
|
|
150
|
-
const frameworks = [];
|
|
151
|
-
const languages = ['python'];
|
|
152
|
-
const requirementsPath = path.join(projectDir, 'requirements.txt');
|
|
153
|
-
const requirements = await readTextFile(requirementsPath);
|
|
154
|
-
if (requirements) {
|
|
155
|
-
const lowerReqs = requirements.toLowerCase();
|
|
156
|
-
if (lowerReqs.includes('django')) {
|
|
157
|
-
frameworks.push('django');
|
|
158
|
-
return {
|
|
159
|
-
name: 'django',
|
|
160
|
-
confidence: 'high',
|
|
161
|
-
frameworks,
|
|
162
|
-
languages,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
if (lowerReqs.includes('fastapi')) {
|
|
166
|
-
frameworks.push('fastapi');
|
|
167
|
-
return {
|
|
168
|
-
name: 'fastapi',
|
|
169
|
-
confidence: 'high',
|
|
170
|
-
frameworks,
|
|
171
|
-
languages,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
if (lowerReqs.includes('flask')) {
|
|
175
|
-
frameworks.push('flask');
|
|
176
|
-
return {
|
|
177
|
-
name: 'flask',
|
|
178
|
-
confidence: 'high',
|
|
179
|
-
frameworks,
|
|
180
|
-
languages,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return {
|
|
185
|
-
name: 'python',
|
|
186
|
-
confidence: 'medium',
|
|
187
|
-
frameworks,
|
|
188
|
-
languages,
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
export function getRecommendedSkills(stack) {
|
|
192
|
-
const baseSkills = [
|
|
193
|
-
'aif',
|
|
194
|
-
'aif-skill-generator',
|
|
195
|
-
'aif-plan',
|
|
196
|
-
'aif-implement',
|
|
197
|
-
'aif-commit',
|
|
198
|
-
'aif-review',
|
|
199
|
-
'aif-best-practices',
|
|
200
|
-
'aif-architecture',
|
|
201
|
-
'aif-security-checklist',
|
|
202
|
-
];
|
|
203
|
-
if (!stack) {
|
|
204
|
-
return baseSkills;
|
|
205
|
-
}
|
|
206
|
-
const skills = [...baseSkills];
|
|
207
|
-
if (['nextjs', 'react', 'vue', 'node-api', 'fastapi', 'django', 'flask', 'laravel', 'symfony'].includes(stack.name)) {
|
|
208
|
-
skills.push('aif-deploy');
|
|
209
|
-
}
|
|
210
|
-
return skills;
|
|
211
|
-
}
|
|
212
|
-
export function getRecommendedTemplate(stack) {
|
|
213
|
-
if (!stack)
|
|
214
|
-
return null;
|
|
215
|
-
const templateMap = {
|
|
216
|
-
'nextjs': 'nextjs',
|
|
217
|
-
'react': 'react',
|
|
218
|
-
'node-api': 'node-api',
|
|
219
|
-
'node': 'node-api',
|
|
220
|
-
'python': 'python',
|
|
221
|
-
'django': 'python',
|
|
222
|
-
'fastapi': 'python',
|
|
223
|
-
'flask': 'python',
|
|
224
|
-
'php': 'php',
|
|
225
|
-
'laravel': 'php',
|
|
226
|
-
'symfony': 'php',
|
|
227
|
-
'slim': 'php',
|
|
228
|
-
};
|
|
229
|
-
return templateMap[stack.name] || null;
|
|
230
|
-
}
|
|
231
|
-
//# sourceMappingURL=detector.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"detector.js","sourceRoot":"","sources":["../../../src/cli/wizard/detector.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAmB3E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB;IAClD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAC9D,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IAChE,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IACnE,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAClD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAE1D,IAAI,MAAM,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACtC,MAAM,WAAW,GAAG,MAAM,YAAY,CAAc,eAAe,CAAC,CAAC;QACrE,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,qBAAqB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,IAAI,MAAM,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACvC,MAAM,YAAY,GAAG,MAAM,YAAY,CAAe,gBAAgB,CAAC,CAAC;QACxE,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,cAAc,CAAC,YAAY,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,IAAI,MAAM,UAAU,CAAC,gBAAgB,CAAC,IAAI,MAAM,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC1E,OAAO,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,OAAO;YACL,IAAI,EAAE,IAAI;YACV,UAAU,EAAE,MAAM;YAClB,UAAU,EAAE,EAAE;YACd,SAAS,EAAE,CAAC,IAAI,CAAC;SAClB,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACpC,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,MAAM;YAClB,UAAU,EAAE,EAAE;YACd,SAAS,EAAE,CAAC,MAAM,CAAC;SACpB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,WAAwB,EAAE,UAAkB;IAC/E,MAAM,OAAO,GAAG;QACd,GAAG,WAAW,CAAC,YAAY;QAC3B,GAAG,WAAW,CAAC,eAAe;KAC/B,CAAC;IAEF,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,SAAS,GAAa,CAAC,YAAY,CAAC,CAAC;IAE3C,IAAI,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1B,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACpB,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3B,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;QACjE,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QAErE,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,MAAM;YAClB,UAAU;YACV,SAAS;SACV,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACrB,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEzB,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACpB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QAED,OAAO;YACL,IAAI,EAAE,OAAO;YACb,UAAU,EAAE,MAAM;YAClB,UAAU;YACV,SAAS;SACV,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,OAAO;YACL,IAAI,EAAE,KAAK;YACX,UAAU,EAAE,MAAM;YAClB,UAAU;YACV,SAAS;SACV,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClF,IAAI,OAAO,CAAC,SAAS,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,OAAO,CAAC,SAAS,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,OAAO,CAAC,KAAK,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,OAAO,CAAC,MAAM,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE7C,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,MAAM;YAClB,UAAU;YACV,SAAS;SACV,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,UAAU,EAAE,QAAQ;QACpB,UAAU;QACV,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,YAA0B;IAChD,MAAM,OAAO,GAAG;QACd,GAAG,YAAY,CAAC,OAAO;QACvB,GAAG,YAAY,CAAC,aAAa,CAAC;KAC/B,CAAC;IAEF,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,SAAS,GAAa,CAAC,KAAK,CAAC,CAAC;IAEpC,IAAI,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACjC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3B,OAAO;YACL,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,MAAM;YAClB,UAAU;YACV,SAAS;SACV,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,0BAA0B,CAAC,IAAI,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACtE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3B,OAAO;YACL,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,MAAM;YAClB,UAAU;YACV,SAAS;SACV,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACzB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,MAAM;YAClB,UAAU;YACV,SAAS;SACV,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,KAAK;QACX,UAAU,EAAE,QAAQ;QACpB,UAAU;QACV,SAAS;KACV,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IACjD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,SAAS,GAAa,CAAC,QAAQ,CAAC,CAAC;IAEvC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IACnE,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAE1D,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;QAE7C,IAAI,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC1B,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,MAAM;gBAClB,UAAU;gBACV,SAAS;aACV,CAAC;QACJ,CAAC;QAED,IAAI,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAClC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3B,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,UAAU,EAAE,MAAM;gBAClB,UAAU;gBACV,SAAS;aACV,CAAC;QACJ,CAAC;QAED,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzB,OAAO;gBACL,IAAI,EAAE,OAAO;gBACb,UAAU,EAAE,MAAM;gBAClB,UAAU;gBACV,SAAS;aACV,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,QAAQ;QACpB,UAAU;QACV,SAAS;KACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAA2B;IAC9D,MAAM,UAAU,GAAG;QACjB,KAAK;QACL,qBAAqB;QACrB,UAAU;QACV,eAAe;QACf,YAAY;QACZ,YAAY;QACZ,oBAAoB;QACpB,kBAAkB;QAClB,wBAAwB;KACzB,CAAC;IAEF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC;IAE/B,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpH,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAA2B;IAChE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,WAAW,GAA2B;QAC1C,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,UAAU;QACtB,MAAM,EAAE,UAAU;QAClB,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,QAAQ;QAClB,SAAS,EAAE,QAAQ;QACnB,OAAO,EAAE,QAAQ;QACjB,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,KAAK;QAChB,MAAM,EAAE,KAAK;KACd,CAAC;IAEF,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACzC,CAAC"}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: nextjs-patterns
|
|
3
|
-
description: Next.js development patterns and best practices. Helps with App Router, Server Components, API routes, and data fetching.
|
|
4
|
-
argument-hint: "[topic: routing|data|api|auth|forms]"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Next.js Patterns Guide
|
|
8
|
-
|
|
9
|
-
Expert guidance on Next.js patterns using the App Router and React Server Components.
|
|
10
|
-
|
|
11
|
-
## Topics
|
|
12
|
-
|
|
13
|
-
### Routing (`/nextjs-patterns routing`)
|
|
14
|
-
|
|
15
|
-
**App Router Structure:**
|
|
16
|
-
```
|
|
17
|
-
app/
|
|
18
|
-
├── layout.tsx # Root layout
|
|
19
|
-
├── page.tsx # Home page
|
|
20
|
-
├── loading.tsx # Loading UI
|
|
21
|
-
├── error.tsx # Error boundary
|
|
22
|
-
├── not-found.tsx # 404 page
|
|
23
|
-
├── dashboard/
|
|
24
|
-
│ ├── layout.tsx # Nested layout
|
|
25
|
-
│ ├── page.tsx # /dashboard
|
|
26
|
-
│ └── [id]/
|
|
27
|
-
│ └── page.tsx # /dashboard/[id]
|
|
28
|
-
└── api/
|
|
29
|
-
└── route.ts # API route
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
**Key Patterns:**
|
|
33
|
-
- Use `layout.tsx` for shared UI and data fetching
|
|
34
|
-
- Use `loading.tsx` with Suspense for streaming
|
|
35
|
-
- Dynamic routes with `[param]` folders
|
|
36
|
-
- Route groups with `(group)` folders
|
|
37
|
-
- Parallel routes with `@slot` folders
|
|
38
|
-
|
|
39
|
-
### Data Fetching (`/nextjs-patterns data`)
|
|
40
|
-
|
|
41
|
-
**Server Components (default):**
|
|
42
|
-
```typescript
|
|
43
|
-
// Fetch directly in component - no useEffect needed
|
|
44
|
-
async function Page() {
|
|
45
|
-
const data = await fetch('https://api.example.com/data');
|
|
46
|
-
return <div>{data}</div>;
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
**Caching:**
|
|
51
|
-
```typescript
|
|
52
|
-
// Cache options
|
|
53
|
-
fetch(url, { cache: 'force-cache' }); // Default - cached
|
|
54
|
-
fetch(url, { cache: 'no-store' }); // Never cache
|
|
55
|
-
fetch(url, { next: { revalidate: 60 } }); // Revalidate every 60s
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
**Server Actions:**
|
|
59
|
-
```typescript
|
|
60
|
-
'use server';
|
|
61
|
-
|
|
62
|
-
export async function createItem(formData: FormData) {
|
|
63
|
-
const name = formData.get('name');
|
|
64
|
-
await db.items.create({ name });
|
|
65
|
-
revalidatePath('/items');
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### API Routes (`/nextjs-patterns api`)
|
|
70
|
-
|
|
71
|
-
**Route Handlers:**
|
|
72
|
-
```typescript
|
|
73
|
-
// app/api/users/route.ts
|
|
74
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
75
|
-
|
|
76
|
-
export async function GET(request: NextRequest) {
|
|
77
|
-
const users = await db.users.findMany();
|
|
78
|
-
return NextResponse.json(users);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export async function POST(request: NextRequest) {
|
|
82
|
-
const body = await request.json();
|
|
83
|
-
const user = await db.users.create(body);
|
|
84
|
-
return NextResponse.json(user, { status: 201 });
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Authentication (`/nextjs-patterns auth`)
|
|
89
|
-
|
|
90
|
-
**Middleware Protection:**
|
|
91
|
-
```typescript
|
|
92
|
-
// middleware.ts
|
|
93
|
-
import { NextResponse } from 'next/server';
|
|
94
|
-
import type { NextRequest } from 'next/server';
|
|
95
|
-
|
|
96
|
-
export function middleware(request: NextRequest) {
|
|
97
|
-
const token = request.cookies.get('token');
|
|
98
|
-
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
|
|
99
|
-
return NextResponse.redirect(new URL('/login', request.url));
|
|
100
|
-
}
|
|
101
|
-
return NextResponse.next();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export const config = {
|
|
105
|
-
matcher: '/dashboard/:path*',
|
|
106
|
-
};
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Forms (`/nextjs-patterns forms`)
|
|
110
|
-
|
|
111
|
-
**Server Action Forms:**
|
|
112
|
-
```typescript
|
|
113
|
-
// Using server actions
|
|
114
|
-
export default function Form() {
|
|
115
|
-
async function handleSubmit(formData: FormData) {
|
|
116
|
-
'use server';
|
|
117
|
-
await saveData(formData);
|
|
118
|
-
redirect('/success');
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return (
|
|
122
|
-
<form action={handleSubmit}>
|
|
123
|
-
<input name="email" type="email" required />
|
|
124
|
-
<button type="submit">Submit</button>
|
|
125
|
-
</form>
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## Best Practices
|
|
131
|
-
|
|
132
|
-
1. **Default to Server Components** - Only use `'use client'` when needed
|
|
133
|
-
2. **Colocate data fetching** - Fetch data where it's used
|
|
134
|
-
3. **Use streaming** - Add `loading.tsx` for better UX
|
|
135
|
-
4. **Validate on server** - Never trust client input
|
|
136
|
-
5. **Use TypeScript** - Full type safety with Next.js
|
|
137
|
-
6. **Image optimization** - Always use `next/image`
|
|
138
|
-
7. **Font optimization** - Use `next/font`
|
|
139
|
-
|
|
140
|
-
## Common Mistakes
|
|
141
|
-
|
|
142
|
-
- Adding `'use client'` unnecessarily
|
|
143
|
-
- Fetching data in client components when server would work
|
|
144
|
-
- Not using proper error boundaries
|
|
145
|
-
- Missing loading states
|
|
146
|
-
- Over-fetching with multiple small requests
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: api-patterns
|
|
3
|
-
description: Node.js API development patterns. Covers REST design, validation, error handling, authentication, and database access.
|
|
4
|
-
argument-hint: "[topic: rest|validation|errors|auth|database]"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Node.js API Patterns Guide
|
|
8
|
-
|
|
9
|
-
Best practices for building robust Node.js APIs.
|
|
10
|
-
|
|
11
|
-
## Topics
|
|
12
|
-
|
|
13
|
-
### REST Design (`/api-patterns rest`)
|
|
14
|
-
|
|
15
|
-
**Resource Naming:**
|
|
16
|
-
```
|
|
17
|
-
GET /users # List users
|
|
18
|
-
GET /users/:id # Get single user
|
|
19
|
-
POST /users # Create user
|
|
20
|
-
PUT /users/:id # Replace user
|
|
21
|
-
PATCH /users/:id # Update user partially
|
|
22
|
-
DELETE /users/:id # Delete user
|
|
23
|
-
|
|
24
|
-
# Nested resources
|
|
25
|
-
GET /users/:id/posts # User's posts
|
|
26
|
-
POST /users/:id/posts # Create post for user
|
|
27
|
-
|
|
28
|
-
# Filtering, sorting, pagination
|
|
29
|
-
GET /users?role=admin&sort=-createdAt&page=2&limit=20
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
**Response Format:**
|
|
33
|
-
```typescript
|
|
34
|
-
// Success response
|
|
35
|
-
{
|
|
36
|
-
"data": { ... },
|
|
37
|
-
"meta": {
|
|
38
|
-
"page": 1,
|
|
39
|
-
"limit": 20,
|
|
40
|
-
"total": 100
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Error response
|
|
45
|
-
{
|
|
46
|
-
"error": {
|
|
47
|
-
"code": "VALIDATION_ERROR",
|
|
48
|
-
"message": "Invalid input",
|
|
49
|
-
"details": [
|
|
50
|
-
{ "field": "email", "message": "Invalid email format" }
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### Validation (`/api-patterns validation`)
|
|
57
|
-
|
|
58
|
-
**Zod Schema Validation:**
|
|
59
|
-
```typescript
|
|
60
|
-
import { z } from 'zod';
|
|
61
|
-
|
|
62
|
-
const createUserSchema = z.object({
|
|
63
|
-
email: z.string().email(),
|
|
64
|
-
password: z.string().min(8),
|
|
65
|
-
name: z.string().min(1).max(100),
|
|
66
|
-
role: z.enum(['user', 'admin']).default('user'),
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Middleware
|
|
70
|
-
function validate(schema: z.ZodSchema) {
|
|
71
|
-
return (req, res, next) => {
|
|
72
|
-
const result = schema.safeParse(req.body);
|
|
73
|
-
if (!result.success) {
|
|
74
|
-
return res.status(400).json({
|
|
75
|
-
error: {
|
|
76
|
-
code: 'VALIDATION_ERROR',
|
|
77
|
-
details: result.error.flatten(),
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
req.body = result.data;
|
|
82
|
-
next();
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Usage
|
|
87
|
-
app.post('/users', validate(createUserSchema), createUser);
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### Error Handling (`/api-patterns errors`)
|
|
91
|
-
|
|
92
|
-
**Custom Error Classes:**
|
|
93
|
-
```typescript
|
|
94
|
-
class AppError extends Error {
|
|
95
|
-
constructor(
|
|
96
|
-
public statusCode: number,
|
|
97
|
-
public code: string,
|
|
98
|
-
message: string,
|
|
99
|
-
public details?: unknown
|
|
100
|
-
) {
|
|
101
|
-
super(message);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
class NotFoundError extends AppError {
|
|
106
|
-
constructor(resource: string) {
|
|
107
|
-
super(404, 'NOT_FOUND', `${resource} not found`);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
class ValidationError extends AppError {
|
|
112
|
-
constructor(details: unknown) {
|
|
113
|
-
super(400, 'VALIDATION_ERROR', 'Invalid input', details);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**Global Error Handler:**
|
|
119
|
-
```typescript
|
|
120
|
-
function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
|
|
121
|
-
console.error(err);
|
|
122
|
-
|
|
123
|
-
if (err instanceof AppError) {
|
|
124
|
-
return res.status(err.statusCode).json({
|
|
125
|
-
error: {
|
|
126
|
-
code: err.code,
|
|
127
|
-
message: err.message,
|
|
128
|
-
details: err.details,
|
|
129
|
-
},
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Unexpected error
|
|
134
|
-
res.status(500).json({
|
|
135
|
-
error: {
|
|
136
|
-
code: 'INTERNAL_ERROR',
|
|
137
|
-
message: 'Something went wrong',
|
|
138
|
-
},
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
app.use(errorHandler);
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### Authentication (`/api-patterns auth`)
|
|
146
|
-
|
|
147
|
-
**JWT Authentication:**
|
|
148
|
-
```typescript
|
|
149
|
-
import jwt from 'jsonwebtoken';
|
|
150
|
-
|
|
151
|
-
// Generate token
|
|
152
|
-
function generateToken(user: User) {
|
|
153
|
-
return jwt.sign(
|
|
154
|
-
{ id: user.id, role: user.role },
|
|
155
|
-
process.env.JWT_SECRET!,
|
|
156
|
-
{ expiresIn: '7d' }
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Auth middleware
|
|
161
|
-
function authenticate(req: Request, res: Response, next: NextFunction) {
|
|
162
|
-
const token = req.headers.authorization?.replace('Bearer ', '');
|
|
163
|
-
|
|
164
|
-
if (!token) {
|
|
165
|
-
throw new AppError(401, 'UNAUTHORIZED', 'No token provided');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
try {
|
|
169
|
-
const payload = jwt.verify(token, process.env.JWT_SECRET!);
|
|
170
|
-
req.user = payload;
|
|
171
|
-
next();
|
|
172
|
-
} catch {
|
|
173
|
-
throw new AppError(401, 'UNAUTHORIZED', 'Invalid token');
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Role-based access
|
|
178
|
-
function authorize(...roles: string[]) {
|
|
179
|
-
return (req: Request, res: Response, next: NextFunction) => {
|
|
180
|
-
if (!roles.includes(req.user.role)) {
|
|
181
|
-
throw new AppError(403, 'FORBIDDEN', 'Insufficient permissions');
|
|
182
|
-
}
|
|
183
|
-
next();
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### Database (`/api-patterns database`)
|
|
189
|
-
|
|
190
|
-
**Repository Pattern:**
|
|
191
|
-
```typescript
|
|
192
|
-
// Abstract database operations
|
|
193
|
-
class UserRepository {
|
|
194
|
-
async findById(id: string): Promise<User | null> {
|
|
195
|
-
return db.user.findUnique({ where: { id } });
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
async findByEmail(email: string): Promise<User | null> {
|
|
199
|
-
return db.user.findUnique({ where: { email } });
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
async create(data: CreateUserInput): Promise<User> {
|
|
203
|
-
return db.user.create({ data });
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
async update(id: string, data: UpdateUserInput): Promise<User> {
|
|
207
|
-
return db.user.update({ where: { id }, data });
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
async delete(id: string): Promise<void> {
|
|
211
|
-
await db.user.delete({ where: { id } });
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
**Transaction Pattern:**
|
|
217
|
-
```typescript
|
|
218
|
-
async function transferFunds(fromId: string, toId: string, amount: number) {
|
|
219
|
-
return db.$transaction(async (tx) => {
|
|
220
|
-
const from = await tx.account.update({
|
|
221
|
-
where: { id: fromId },
|
|
222
|
-
data: { balance: { decrement: amount } },
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
if (from.balance < 0) {
|
|
226
|
-
throw new AppError(400, 'INSUFFICIENT_FUNDS', 'Not enough balance');
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
await tx.account.update({
|
|
230
|
-
where: { id: toId },
|
|
231
|
-
data: { balance: { increment: amount } },
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
## Best Practices
|
|
238
|
-
|
|
239
|
-
1. **Validate all input** - Never trust client data
|
|
240
|
-
2. **Use async/await** - Avoid callback hell
|
|
241
|
-
3. **Handle errors centrally** - Single error handler
|
|
242
|
-
4. **Log appropriately** - Structured logging
|
|
243
|
-
5. **Rate limit** - Protect against abuse
|
|
244
|
-
6. **Use CORS properly** - Restrict origins
|
|
245
|
-
7. **Keep secrets safe** - Use environment variables
|