claudeship 0.2.24 → 0.2.26
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/apps/server/dist/chat/chat.module.js +8 -1
- package/apps/server/dist/chat/chat.module.js.map +1 -1
- package/apps/server/dist/chat/chat.service.d.ts +5 -1
- package/apps/server/dist/chat/chat.service.js +35 -4
- package/apps/server/dist/chat/chat.service.js.map +1 -1
- package/apps/server/dist/chat/framework-detector.service.d.ts +17 -0
- package/apps/server/dist/chat/framework-detector.service.js +193 -0
- package/apps/server/dist/chat/framework-detector.service.js.map +1 -0
- package/apps/server/dist/chat/prompts/backend/django.d.ts +1 -0
- package/apps/server/dist/chat/prompts/backend/django.js +207 -0
- package/apps/server/dist/chat/prompts/backend/django.js.map +1 -0
- package/apps/server/dist/chat/prompts/backend/express.d.ts +1 -0
- package/apps/server/dist/chat/prompts/backend/express.js +260 -0
- package/apps/server/dist/chat/prompts/backend/express.js.map +1 -0
- package/apps/server/dist/chat/prompts/backend/fastapi.d.ts +1 -0
- package/apps/server/dist/chat/prompts/backend/fastapi.js +246 -0
- package/apps/server/dist/chat/prompts/backend/fastapi.js.map +1 -0
- package/apps/server/dist/chat/prompts/backend/index.d.ts +4 -0
- package/apps/server/dist/chat/prompts/backend/index.js +12 -0
- package/apps/server/dist/chat/prompts/backend/index.js.map +1 -0
- package/apps/server/dist/chat/prompts/backend/nestjs.d.ts +1 -0
- package/apps/server/dist/chat/prompts/backend/nestjs.js +270 -0
- package/apps/server/dist/chat/prompts/backend/nestjs.js.map +1 -0
- package/apps/server/dist/chat/prompts/frontend/expo.d.ts +1 -0
- package/apps/server/dist/chat/prompts/frontend/expo.js +208 -0
- package/apps/server/dist/chat/prompts/frontend/expo.js.map +1 -0
- package/apps/server/dist/chat/prompts/frontend/flutter.d.ts +1 -0
- package/apps/server/dist/chat/prompts/frontend/flutter.js +271 -0
- package/apps/server/dist/chat/prompts/frontend/flutter.js.map +1 -0
- package/apps/server/dist/chat/prompts/frontend/index.d.ts +4 -0
- package/apps/server/dist/chat/prompts/frontend/index.js +12 -0
- package/apps/server/dist/chat/prompts/frontend/index.js.map +1 -0
- package/apps/server/dist/chat/prompts/frontend/nextjs.d.ts +1 -0
- package/apps/server/dist/chat/prompts/frontend/nextjs.js +195 -0
- package/apps/server/dist/chat/prompts/frontend/nextjs.js.map +1 -0
- package/apps/server/dist/chat/prompts/frontend/react-native.d.ts +1 -0
- package/apps/server/dist/chat/prompts/frontend/react-native.js +224 -0
- package/apps/server/dist/chat/prompts/frontend/react-native.js.map +1 -0
- package/apps/server/dist/chat/prompts/frontend/react-vite.d.ts +1 -0
- package/apps/server/dist/chat/prompts/frontend/react-vite.js +187 -0
- package/apps/server/dist/chat/prompts/frontend/react-vite.js.map +1 -0
- package/apps/server/dist/chat/prompts/frontend/svelte.d.ts +1 -0
- package/apps/server/dist/chat/prompts/frontend/svelte.js +255 -0
- package/apps/server/dist/chat/prompts/frontend/svelte.js.map +1 -0
- package/apps/server/dist/chat/prompts/frontend/vue.d.ts +1 -0
- package/apps/server/dist/chat/prompts/frontend/vue.js +267 -0
- package/apps/server/dist/chat/prompts/frontend/vue.js.map +1 -0
- package/apps/server/dist/chat/prompts/index.d.ts +4 -0
- package/apps/server/dist/chat/prompts/index.js +20 -1
- package/apps/server/dist/chat/prompts/index.js.map +1 -1
- package/apps/server/dist/chat/prompts/prompt-builder.service.d.ts +15 -0
- package/apps/server/dist/chat/prompts/prompt-builder.service.js +177 -0
- package/apps/server/dist/chat/prompts/prompt-builder.service.js.map +1 -0
- package/apps/server/dist/chat/prompts/sections/core.d.ts +9 -0
- package/apps/server/dist/chat/prompts/sections/core.js +149 -0
- package/apps/server/dist/chat/prompts/sections/core.js.map +1 -0
- package/apps/server/dist/project/dto/create-project.dto.d.ts +3 -2
- package/apps/server/dist/project/dto/create-project.dto.js.map +1 -1
- package/apps/server/dist/project/project.controller.d.ts +6 -0
- package/apps/server/dist/project/project.service.d.ts +6 -0
- package/apps/server/dist/project/project.service.js +6 -1
- package/apps/server/dist/project/project.service.js.map +1 -1
- package/apps/server/dist/tsconfig.tsbuildinfo +1 -1
- package/apps/server/package.json +1 -1
- package/apps/server/prisma/dev.db +0 -0
- package/apps/server/prisma/migrations/20260127071040_add_frontend_framework/migration.sql +24 -0
- package/apps/server/prisma/migrations/20260127071520_add_app_type_and_mobile/migration.sql +25 -0
- package/apps/server/prisma/schema.prisma +33 -5
- package/apps/web/.next/BUILD_ID +1 -1
- package/apps/web/.next/app-build-manifest.json +5 -3
- package/apps/web/.next/build-manifest.json +2 -2
- package/apps/web/.next/cache/.previewinfo +1 -1
- package/apps/web/.next/cache/.rscinfo +1 -1
- package/apps/web/.next/cache/.tsbuildinfo +1 -1
- package/apps/web/.next/cache/config.json +3 -3
- package/apps/web/.next/cache/eslint/.cache_j3uhuz +1 -1
- package/apps/web/.next/cache/webpack/client-production/0.pack +0 -0
- package/apps/web/.next/cache/webpack/client-production/index.pack +0 -0
- package/apps/web/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/apps/web/.next/cache/webpack/server-production/0.pack +0 -0
- package/apps/web/.next/cache/webpack/server-production/index.pack +0 -0
- package/apps/web/.next/prerender-manifest.json +10 -10
- package/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/server/app/_not-found.html +1 -1
- package/apps/web/.next/server/app/_not-found.rsc +2 -2
- package/apps/web/.next/server/app/index.html +1 -1
- package/apps/web/.next/server/app/index.rsc +3 -3
- package/apps/web/.next/server/app/page.js +2 -2
- package/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/server/app/project/[id]/page.js +2 -2
- package/apps/web/.next/server/app/project/[id]/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/server/app/settings/page.js +1 -1
- package/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/server/app/settings.html +1 -1
- package/apps/web/.next/server/app/settings.rsc +2 -2
- package/apps/web/.next/server/pages/404.html +1 -1
- package/apps/web/.next/server/pages/500.html +1 -1
- package/apps/web/.next/server/server-reference-manifest.json +1 -1
- package/apps/web/.next/static/chunks/18-22b1cf4231121555.js +1 -0
- package/apps/web/.next/static/chunks/app/page-6ea560755549086e.js +1 -0
- package/apps/web/.next/static/chunks/app/project/[id]/page-3e4777b355c4aec9.js +1 -0
- package/apps/web/.next/static/css/45ddb08a7b4470d5.css +3 -0
- package/apps/web/.next/trace +18 -18
- package/apps/web/package.json +1 -1
- package/apps/web/src/app/page.tsx +2 -5
- package/apps/web/src/components/project/CreateProjectModal.tsx +175 -80
- package/apps/web/src/components/project/ProjectCard.tsx +122 -31
- package/apps/web/src/stores/useProjectStore.ts +2 -1
- package/package.json +1 -1
- package/packages/shared/src/index.ts +1 -0
- package/packages/shared/src/types/project.ts +18 -3
- package/packages/shared/src/types/tech-stack.ts +74 -0
- package/apps/web/.next/static/chunks/app/page-f73b6424c8cbf96d.js +0 -1
- package/apps/web/.next/static/chunks/app/project/[id]/page-e9304c25ba897608.js +0 -1
- package/apps/web/.next/static/css/70f2a13cf3d254d8.css +0 -3
- /package/apps/web/.next/static/{fQQI0X4R8kXYUbd-0V8mo → 9j_J3qCBspqfGptLfgt5e}/_buildManifest.js +0 -0
- /package/apps/web/.next/static/{fQQI0X4R8kXYUbd-0V8mo → 9j_J3qCBspqfGptLfgt5e}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EXPRESS_PROMPT = void 0;
|
|
4
|
+
exports.EXPRESS_PROMPT = `## Backend: Express + TypeScript + Prisma
|
|
5
|
+
|
|
6
|
+
You are building an Express.js backend with TypeScript and Prisma ORM.
|
|
7
|
+
|
|
8
|
+
### Technology Stack (Backend)
|
|
9
|
+
|
|
10
|
+
| Category | Technology | Notes |
|
|
11
|
+
|----------|------------|-------|
|
|
12
|
+
| Runtime | Node.js 20+ | LTS version |
|
|
13
|
+
| Framework | Express 4.x | Minimal framework |
|
|
14
|
+
| Language | TypeScript | Strict mode |
|
|
15
|
+
| ORM | Prisma | Type-safe database access |
|
|
16
|
+
| Database | SQLite (dev) / PostgreSQL (prod) | |
|
|
17
|
+
| Validation | Zod | Schema validation |
|
|
18
|
+
|
|
19
|
+
### Project Structure
|
|
20
|
+
|
|
21
|
+
\`\`\`
|
|
22
|
+
backend/
|
|
23
|
+
├── src/
|
|
24
|
+
│ ├── index.ts # Entry point
|
|
25
|
+
│ ├── routes/ # Route handlers
|
|
26
|
+
│ ├── controllers/ # Request/response handling
|
|
27
|
+
│ ├── services/ # Business logic
|
|
28
|
+
│ ├── middleware/ # Express middleware
|
|
29
|
+
│ └── types/ # TypeScript types
|
|
30
|
+
├── prisma/
|
|
31
|
+
│ └── schema.prisma # Database schema
|
|
32
|
+
├── package.json
|
|
33
|
+
└── tsconfig.json
|
|
34
|
+
\`\`\`
|
|
35
|
+
|
|
36
|
+
### Backend Setup
|
|
37
|
+
|
|
38
|
+
\`\`\`bash
|
|
39
|
+
cd backend
|
|
40
|
+
npm init -y
|
|
41
|
+
npm install express cors dotenv zod
|
|
42
|
+
npm install -D typescript @types/express @types/node @types/cors ts-node nodemon
|
|
43
|
+
npm install prisma @prisma/client
|
|
44
|
+
npx prisma init --datasource-provider sqlite
|
|
45
|
+
\`\`\`
|
|
46
|
+
|
|
47
|
+
### package.json scripts
|
|
48
|
+
|
|
49
|
+
\`\`\`json
|
|
50
|
+
{
|
|
51
|
+
"scripts": {
|
|
52
|
+
"dev": "nodemon --exec ts-node src/index.ts",
|
|
53
|
+
"build": "tsc",
|
|
54
|
+
"start": "node dist/index.js",
|
|
55
|
+
"db:push": "prisma db push",
|
|
56
|
+
"db:studio": "prisma studio"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
\`\`\`
|
|
60
|
+
|
|
61
|
+
### tsconfig.json
|
|
62
|
+
|
|
63
|
+
\`\`\`json
|
|
64
|
+
{
|
|
65
|
+
"compilerOptions": {
|
|
66
|
+
"target": "ES2022",
|
|
67
|
+
"module": "commonjs",
|
|
68
|
+
"lib": ["ES2022"],
|
|
69
|
+
"outDir": "./dist",
|
|
70
|
+
"rootDir": "./src",
|
|
71
|
+
"strict": true,
|
|
72
|
+
"esModuleInterop": true,
|
|
73
|
+
"skipLibCheck": true,
|
|
74
|
+
"forceConsistentCasingInFileNames": true,
|
|
75
|
+
"resolveJsonModule": true
|
|
76
|
+
},
|
|
77
|
+
"include": ["src/**/*"],
|
|
78
|
+
"exclude": ["node_modules"]
|
|
79
|
+
}
|
|
80
|
+
\`\`\`
|
|
81
|
+
|
|
82
|
+
### Server Setup Pattern
|
|
83
|
+
|
|
84
|
+
\`\`\`typescript
|
|
85
|
+
// backend/src/index.ts
|
|
86
|
+
import express from 'express';
|
|
87
|
+
import cors from 'cors';
|
|
88
|
+
import { PrismaClient } from '@prisma/client';
|
|
89
|
+
import usersRouter from './routes/users';
|
|
90
|
+
|
|
91
|
+
const app = express();
|
|
92
|
+
const prisma = new PrismaClient();
|
|
93
|
+
const PORT = process.env.PORT || 3001;
|
|
94
|
+
|
|
95
|
+
// Middleware
|
|
96
|
+
app.use(cors({ origin: 'http://localhost:3000' }));
|
|
97
|
+
app.use(express.json());
|
|
98
|
+
|
|
99
|
+
// Health check
|
|
100
|
+
app.get('/api/health', (req, res) => {
|
|
101
|
+
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Routes
|
|
105
|
+
app.use('/api/users', usersRouter);
|
|
106
|
+
|
|
107
|
+
// Error handler
|
|
108
|
+
app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
|
|
109
|
+
console.error(err.stack);
|
|
110
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Graceful shutdown
|
|
114
|
+
process.on('SIGTERM', async () => {
|
|
115
|
+
await prisma.$disconnect();
|
|
116
|
+
process.exit(0);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
app.listen(PORT, () => {
|
|
120
|
+
console.log(\`Server running on http://localhost:\${PORT}\`);
|
|
121
|
+
});
|
|
122
|
+
\`\`\`
|
|
123
|
+
|
|
124
|
+
### Route Pattern with Zod Validation
|
|
125
|
+
|
|
126
|
+
\`\`\`typescript
|
|
127
|
+
// backend/src/routes/users.ts
|
|
128
|
+
import { Router } from 'express';
|
|
129
|
+
import { z } from 'zod';
|
|
130
|
+
import { PrismaClient } from '@prisma/client';
|
|
131
|
+
|
|
132
|
+
const router = Router();
|
|
133
|
+
const prisma = new PrismaClient();
|
|
134
|
+
|
|
135
|
+
const createUserSchema = z.object({
|
|
136
|
+
name: z.string().min(1),
|
|
137
|
+
email: z.string().email(),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// GET /api/users
|
|
141
|
+
router.get('/', async (req, res, next) => {
|
|
142
|
+
try {
|
|
143
|
+
const users = await prisma.user.findMany();
|
|
144
|
+
res.json(users);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
next(error);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// GET /api/users/:id
|
|
151
|
+
router.get('/:id', async (req, res, next) => {
|
|
152
|
+
try {
|
|
153
|
+
const user = await prisma.user.findUnique({
|
|
154
|
+
where: { id: parseInt(req.params.id) },
|
|
155
|
+
});
|
|
156
|
+
if (!user) {
|
|
157
|
+
return res.status(404).json({ error: 'User not found' });
|
|
158
|
+
}
|
|
159
|
+
res.json(user);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
next(error);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// POST /api/users
|
|
166
|
+
router.post('/', async (req, res, next) => {
|
|
167
|
+
try {
|
|
168
|
+
const data = createUserSchema.parse(req.body);
|
|
169
|
+
const user = await prisma.user.create({ data });
|
|
170
|
+
res.status(201).json(user);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
if (error instanceof z.ZodError) {
|
|
173
|
+
return res.status(400).json({ errors: error.errors });
|
|
174
|
+
}
|
|
175
|
+
next(error);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// PUT /api/users/:id
|
|
180
|
+
router.put('/:id', async (req, res, next) => {
|
|
181
|
+
try {
|
|
182
|
+
const data = createUserSchema.partial().parse(req.body);
|
|
183
|
+
const user = await prisma.user.update({
|
|
184
|
+
where: { id: parseInt(req.params.id) },
|
|
185
|
+
data,
|
|
186
|
+
});
|
|
187
|
+
res.json(user);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
if (error instanceof z.ZodError) {
|
|
190
|
+
return res.status(400).json({ errors: error.errors });
|
|
191
|
+
}
|
|
192
|
+
next(error);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// DELETE /api/users/:id
|
|
197
|
+
router.delete('/:id', async (req, res, next) => {
|
|
198
|
+
try {
|
|
199
|
+
await prisma.user.delete({
|
|
200
|
+
where: { id: parseInt(req.params.id) },
|
|
201
|
+
});
|
|
202
|
+
res.status(204).send();
|
|
203
|
+
} catch (error) {
|
|
204
|
+
next(error);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
export default router;
|
|
209
|
+
\`\`\`
|
|
210
|
+
|
|
211
|
+
### Prisma Schema Example
|
|
212
|
+
|
|
213
|
+
\`\`\`prisma
|
|
214
|
+
// backend/prisma/schema.prisma
|
|
215
|
+
generator client {
|
|
216
|
+
provider = "prisma-client-js"
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
datasource db {
|
|
220
|
+
provider = "sqlite"
|
|
221
|
+
url = "file:./dev.db"
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
model User {
|
|
225
|
+
id Int @id @default(autoincrement())
|
|
226
|
+
name String
|
|
227
|
+
email String @unique
|
|
228
|
+
createdAt DateTime @default(now())
|
|
229
|
+
updatedAt DateTime @updatedAt
|
|
230
|
+
posts Post[]
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
model Post {
|
|
234
|
+
id Int @id @default(autoincrement())
|
|
235
|
+
title String
|
|
236
|
+
content String?
|
|
237
|
+
published Boolean @default(false)
|
|
238
|
+
authorId Int
|
|
239
|
+
author User @relation(fields: [authorId], references: [id])
|
|
240
|
+
createdAt DateTime @default(now())
|
|
241
|
+
updatedAt DateTime @updatedAt
|
|
242
|
+
}
|
|
243
|
+
\`\`\`
|
|
244
|
+
|
|
245
|
+
### API Design Guidelines
|
|
246
|
+
|
|
247
|
+
- **RESTful conventions**: GET read, POST create, PUT update, DELETE delete
|
|
248
|
+
- **Consistent response format**: \`{ data, error, message }\`
|
|
249
|
+
- **Proper status codes**: 200 OK, 201 Created, 400 Bad Request, 404 Not Found, 500 Error
|
|
250
|
+
- **Input validation**: Use Zod for all request body validation
|
|
251
|
+
- **Error messages**: User-friendly messages, log technical details
|
|
252
|
+
|
|
253
|
+
### Environment Variables
|
|
254
|
+
|
|
255
|
+
\`\`\`
|
|
256
|
+
# backend/.env
|
|
257
|
+
PORT=3001
|
|
258
|
+
DATABASE_URL="file:./dev.db"
|
|
259
|
+
\`\`\``;
|
|
260
|
+
//# sourceMappingURL=express.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express.js","sourceRoot":"","sources":["../../../../src/chat/prompts/backend/express.ts"],"names":[],"mappings":";;;AAMa,QAAA,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+PvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const FASTAPI_PROMPT = "## Backend: FastAPI + Python + SQLAlchemy\n\nYou are building a FastAPI backend with Python and SQLAlchemy ORM.\n\n### Technology Stack (Backend)\n\n| Category | Technology | Notes |\n|----------|------------|-------|\n| Runtime | Python 3.11+ | Latest stable |\n| Framework | FastAPI | Async-first API framework |\n| ORM | SQLAlchemy 2.0 | Async support |\n| Database | SQLite (dev) / PostgreSQL (prod) | |\n| Validation | Pydantic | Built into FastAPI |\n| Server | Uvicorn | ASGI server |\n\n### Project Structure\n\n```\nbackend/\n\u251C\u2500\u2500 app/\n\u2502 \u251C\u2500\u2500 __init__.py\n\u2502 \u251C\u2500\u2500 main.py # FastAPI app\n\u2502 \u251C\u2500\u2500 config.py # Settings\n\u2502 \u251C\u2500\u2500 database.py # DB connection\n\u2502 \u251C\u2500\u2500 models/ # SQLAlchemy models\n\u2502 \u2502 \u2514\u2500\u2500 user.py\n\u2502 \u251C\u2500\u2500 schemas/ # Pydantic schemas\n\u2502 \u2502 \u2514\u2500\u2500 user.py\n\u2502 \u251C\u2500\u2500 routers/ # API routes\n\u2502 \u2502 \u2514\u2500\u2500 users.py\n\u2502 \u2514\u2500\u2500 services/ # Business logic\n\u2502 \u2514\u2500\u2500 user_service.py\n\u251C\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 .env\n```\n\n### Python Environment Setup (CRITICAL)\n\n**ALWAYS use virtual environment for Python projects:**\n\n```bash\ncd backend\npython -m venv venv\nsource venv/bin/activate # Windows: venv\\Scripts\\activate\n\npip install fastapi uvicorn sqlalchemy aiosqlite python-dotenv\npip freeze > requirements.txt\n```\n\n### Virtual Environment Rules\n\n1. **ALWAYS create venv** in the `backend/` directory\n2. **NEVER install packages globally** - always use venv\n3. **Keep requirements.txt updated** after installing new packages\n4. **Include .gitignore** with venv/ excluded:\n ```\n # backend/.gitignore\n venv/\n __pycache__/\n *.pyc\n .env\n *.db\n ```\n5. **Use python -m pip** to ensure correct pip version:\n ```bash\n python -m pip install <package>\n ```\n\n### Main Application\n\n```python\n# backend/app/main.py\nfrom fastapi import FastAPI\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom app.database import engine, Base\nfrom app.routers import users\n\nBase.metadata.create_all(bind=engine)\n\napp = FastAPI(title=\"API\", version=\"1.0.0\")\n\napp.add_middleware(\n CORSMiddleware,\n allow_origins=[\"http://localhost:3000\"],\n allow_credentials=True,\n allow_methods=[\"*\"],\n allow_headers=[\"*\"],\n)\n\napp.include_router(users.router, prefix=\"/api/users\", tags=[\"users\"])\n\n@app.get(\"/api/health\")\nasync def health_check():\n return {\"status\": \"ok\"}\n```\n\n### Database Configuration\n\n```python\n# backend/app/database.py\nfrom sqlalchemy import create_engine\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy.orm import sessionmaker\nimport os\n\nDATABASE_URL = os.getenv(\"DATABASE_URL\", \"sqlite:///./dev.db\")\n\nengine = create_engine(DATABASE_URL, connect_args={\"check_same_thread\": False})\nSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)\nBase = declarative_base()\n\ndef get_db():\n db = SessionLocal()\n try:\n yield db\n finally:\n db.close()\n```\n\n### SQLAlchemy Model\n\n```python\n# backend/app/models/user.py\nfrom sqlalchemy import Column, Integer, String, DateTime\nfrom sqlalchemy.sql import func\nfrom app.database import Base\n\nclass User(Base):\n __tablename__ = \"users\"\n\n id = Column(Integer, primary_key=True, index=True)\n name = Column(String, nullable=False)\n email = Column(String, unique=True, index=True, nullable=False)\n created_at = Column(DateTime(timezone=True), server_default=func.now())\n updated_at = Column(DateTime(timezone=True), onupdate=func.now())\n```\n\n### Pydantic Schemas\n\n```python\n# backend/app/schemas/user.py\nfrom pydantic import BaseModel, EmailStr\nfrom datetime import datetime\nfrom typing import Optional\n\nclass UserBase(BaseModel):\n name: str\n email: EmailStr\n\nclass UserCreate(UserBase):\n pass\n\nclass UserUpdate(BaseModel):\n name: Optional[str] = None\n email: Optional[EmailStr] = None\n\nclass UserResponse(UserBase):\n id: int\n created_at: datetime\n updated_at: Optional[datetime] = None\n\n class Config:\n from_attributes = True\n```\n\n### Router with CRUD\n\n```python\n# backend/app/routers/users.py\nfrom fastapi import APIRouter, Depends, HTTPException\nfrom sqlalchemy.orm import Session\nfrom typing import List\n\nfrom app.database import get_db\nfrom app.models.user import User\nfrom app.schemas.user import UserCreate, UserUpdate, UserResponse\n\nrouter = APIRouter()\n\n@router.get(\"/\", response_model=List[UserResponse])\ndef get_users(db: Session = Depends(get_db)):\n return db.query(User).all()\n\n@router.get(\"/{user_id}\", response_model=UserResponse)\ndef get_user(user_id: int, db: Session = Depends(get_db)):\n user = db.query(User).filter(User.id == user_id).first()\n if not user:\n raise HTTPException(status_code=404, detail=\"User not found\")\n return user\n\n@router.post(\"/\", response_model=UserResponse, status_code=201)\ndef create_user(user: UserCreate, db: Session = Depends(get_db)):\n db_user = User(**user.model_dump())\n db.add(db_user)\n db.commit()\n db.refresh(db_user)\n return db_user\n\n@router.put(\"/{user_id}\", response_model=UserResponse)\ndef update_user(user_id: int, user: UserUpdate, db: Session = Depends(get_db)):\n db_user = db.query(User).filter(User.id == user_id).first()\n if not db_user:\n raise HTTPException(status_code=404, detail=\"User not found\")\n\n update_data = user.model_dump(exclude_unset=True)\n for key, value in update_data.items():\n setattr(db_user, key, value)\n\n db.commit()\n db.refresh(db_user)\n return db_user\n\n@router.delete(\"/{user_id}\", status_code=204)\ndef delete_user(user_id: int, db: Session = Depends(get_db)):\n db_user = db.query(User).filter(User.id == user_id).first()\n if not db_user:\n raise HTTPException(status_code=404, detail=\"User not found\")\n db.delete(db_user)\n db.commit()\n```\n\n### Run Command\n\n```bash\n# Do NOT run this - the preview system handles it\nuvicorn app.main:app --reload --port 3001\n```\n\n### Environment Variables\n\n```\n# backend/.env\nDATABASE_URL=sqlite:///./dev.db\n```\n\n### API Design Guidelines\n\n- **RESTful conventions**: GET read, POST create, PUT update, DELETE delete\n- **Use Pydantic schemas** for request/response validation\n- **Dependency injection** with `Depends()`\n- **Proper status codes**: 200, 201, 400, 404, 500\n- **HTTPException** for error responses";
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FASTAPI_PROMPT = void 0;
|
|
4
|
+
exports.FASTAPI_PROMPT = `## Backend: FastAPI + Python + SQLAlchemy
|
|
5
|
+
|
|
6
|
+
You are building a FastAPI backend with Python and SQLAlchemy ORM.
|
|
7
|
+
|
|
8
|
+
### Technology Stack (Backend)
|
|
9
|
+
|
|
10
|
+
| Category | Technology | Notes |
|
|
11
|
+
|----------|------------|-------|
|
|
12
|
+
| Runtime | Python 3.11+ | Latest stable |
|
|
13
|
+
| Framework | FastAPI | Async-first API framework |
|
|
14
|
+
| ORM | SQLAlchemy 2.0 | Async support |
|
|
15
|
+
| Database | SQLite (dev) / PostgreSQL (prod) | |
|
|
16
|
+
| Validation | Pydantic | Built into FastAPI |
|
|
17
|
+
| Server | Uvicorn | ASGI server |
|
|
18
|
+
|
|
19
|
+
### Project Structure
|
|
20
|
+
|
|
21
|
+
\`\`\`
|
|
22
|
+
backend/
|
|
23
|
+
├── app/
|
|
24
|
+
│ ├── __init__.py
|
|
25
|
+
│ ├── main.py # FastAPI app
|
|
26
|
+
│ ├── config.py # Settings
|
|
27
|
+
│ ├── database.py # DB connection
|
|
28
|
+
│ ├── models/ # SQLAlchemy models
|
|
29
|
+
│ │ └── user.py
|
|
30
|
+
│ ├── schemas/ # Pydantic schemas
|
|
31
|
+
│ │ └── user.py
|
|
32
|
+
│ ├── routers/ # API routes
|
|
33
|
+
│ │ └── users.py
|
|
34
|
+
│ └── services/ # Business logic
|
|
35
|
+
│ └── user_service.py
|
|
36
|
+
├── requirements.txt
|
|
37
|
+
└── .env
|
|
38
|
+
\`\`\`
|
|
39
|
+
|
|
40
|
+
### Python Environment Setup (CRITICAL)
|
|
41
|
+
|
|
42
|
+
**ALWAYS use virtual environment for Python projects:**
|
|
43
|
+
|
|
44
|
+
\`\`\`bash
|
|
45
|
+
cd backend
|
|
46
|
+
python -m venv venv
|
|
47
|
+
source venv/bin/activate # Windows: venv\\Scripts\\activate
|
|
48
|
+
|
|
49
|
+
pip install fastapi uvicorn sqlalchemy aiosqlite python-dotenv
|
|
50
|
+
pip freeze > requirements.txt
|
|
51
|
+
\`\`\`
|
|
52
|
+
|
|
53
|
+
### Virtual Environment Rules
|
|
54
|
+
|
|
55
|
+
1. **ALWAYS create venv** in the \`backend/\` directory
|
|
56
|
+
2. **NEVER install packages globally** - always use venv
|
|
57
|
+
3. **Keep requirements.txt updated** after installing new packages
|
|
58
|
+
4. **Include .gitignore** with venv/ excluded:
|
|
59
|
+
\`\`\`
|
|
60
|
+
# backend/.gitignore
|
|
61
|
+
venv/
|
|
62
|
+
__pycache__/
|
|
63
|
+
*.pyc
|
|
64
|
+
.env
|
|
65
|
+
*.db
|
|
66
|
+
\`\`\`
|
|
67
|
+
5. **Use python -m pip** to ensure correct pip version:
|
|
68
|
+
\`\`\`bash
|
|
69
|
+
python -m pip install <package>
|
|
70
|
+
\`\`\`
|
|
71
|
+
|
|
72
|
+
### Main Application
|
|
73
|
+
|
|
74
|
+
\`\`\`python
|
|
75
|
+
# backend/app/main.py
|
|
76
|
+
from fastapi import FastAPI
|
|
77
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
78
|
+
from app.database import engine, Base
|
|
79
|
+
from app.routers import users
|
|
80
|
+
|
|
81
|
+
Base.metadata.create_all(bind=engine)
|
|
82
|
+
|
|
83
|
+
app = FastAPI(title="API", version="1.0.0")
|
|
84
|
+
|
|
85
|
+
app.add_middleware(
|
|
86
|
+
CORSMiddleware,
|
|
87
|
+
allow_origins=["http://localhost:3000"],
|
|
88
|
+
allow_credentials=True,
|
|
89
|
+
allow_methods=["*"],
|
|
90
|
+
allow_headers=["*"],
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
app.include_router(users.router, prefix="/api/users", tags=["users"])
|
|
94
|
+
|
|
95
|
+
@app.get("/api/health")
|
|
96
|
+
async def health_check():
|
|
97
|
+
return {"status": "ok"}
|
|
98
|
+
\`\`\`
|
|
99
|
+
|
|
100
|
+
### Database Configuration
|
|
101
|
+
|
|
102
|
+
\`\`\`python
|
|
103
|
+
# backend/app/database.py
|
|
104
|
+
from sqlalchemy import create_engine
|
|
105
|
+
from sqlalchemy.ext.declarative import declarative_base
|
|
106
|
+
from sqlalchemy.orm import sessionmaker
|
|
107
|
+
import os
|
|
108
|
+
|
|
109
|
+
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./dev.db")
|
|
110
|
+
|
|
111
|
+
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
|
|
112
|
+
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
113
|
+
Base = declarative_base()
|
|
114
|
+
|
|
115
|
+
def get_db():
|
|
116
|
+
db = SessionLocal()
|
|
117
|
+
try:
|
|
118
|
+
yield db
|
|
119
|
+
finally:
|
|
120
|
+
db.close()
|
|
121
|
+
\`\`\`
|
|
122
|
+
|
|
123
|
+
### SQLAlchemy Model
|
|
124
|
+
|
|
125
|
+
\`\`\`python
|
|
126
|
+
# backend/app/models/user.py
|
|
127
|
+
from sqlalchemy import Column, Integer, String, DateTime
|
|
128
|
+
from sqlalchemy.sql import func
|
|
129
|
+
from app.database import Base
|
|
130
|
+
|
|
131
|
+
class User(Base):
|
|
132
|
+
__tablename__ = "users"
|
|
133
|
+
|
|
134
|
+
id = Column(Integer, primary_key=True, index=True)
|
|
135
|
+
name = Column(String, nullable=False)
|
|
136
|
+
email = Column(String, unique=True, index=True, nullable=False)
|
|
137
|
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
138
|
+
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
139
|
+
\`\`\`
|
|
140
|
+
|
|
141
|
+
### Pydantic Schemas
|
|
142
|
+
|
|
143
|
+
\`\`\`python
|
|
144
|
+
# backend/app/schemas/user.py
|
|
145
|
+
from pydantic import BaseModel, EmailStr
|
|
146
|
+
from datetime import datetime
|
|
147
|
+
from typing import Optional
|
|
148
|
+
|
|
149
|
+
class UserBase(BaseModel):
|
|
150
|
+
name: str
|
|
151
|
+
email: EmailStr
|
|
152
|
+
|
|
153
|
+
class UserCreate(UserBase):
|
|
154
|
+
pass
|
|
155
|
+
|
|
156
|
+
class UserUpdate(BaseModel):
|
|
157
|
+
name: Optional[str] = None
|
|
158
|
+
email: Optional[EmailStr] = None
|
|
159
|
+
|
|
160
|
+
class UserResponse(UserBase):
|
|
161
|
+
id: int
|
|
162
|
+
created_at: datetime
|
|
163
|
+
updated_at: Optional[datetime] = None
|
|
164
|
+
|
|
165
|
+
class Config:
|
|
166
|
+
from_attributes = True
|
|
167
|
+
\`\`\`
|
|
168
|
+
|
|
169
|
+
### Router with CRUD
|
|
170
|
+
|
|
171
|
+
\`\`\`python
|
|
172
|
+
# backend/app/routers/users.py
|
|
173
|
+
from fastapi import APIRouter, Depends, HTTPException
|
|
174
|
+
from sqlalchemy.orm import Session
|
|
175
|
+
from typing import List
|
|
176
|
+
|
|
177
|
+
from app.database import get_db
|
|
178
|
+
from app.models.user import User
|
|
179
|
+
from app.schemas.user import UserCreate, UserUpdate, UserResponse
|
|
180
|
+
|
|
181
|
+
router = APIRouter()
|
|
182
|
+
|
|
183
|
+
@router.get("/", response_model=List[UserResponse])
|
|
184
|
+
def get_users(db: Session = Depends(get_db)):
|
|
185
|
+
return db.query(User).all()
|
|
186
|
+
|
|
187
|
+
@router.get("/{user_id}", response_model=UserResponse)
|
|
188
|
+
def get_user(user_id: int, db: Session = Depends(get_db)):
|
|
189
|
+
user = db.query(User).filter(User.id == user_id).first()
|
|
190
|
+
if not user:
|
|
191
|
+
raise HTTPException(status_code=404, detail="User not found")
|
|
192
|
+
return user
|
|
193
|
+
|
|
194
|
+
@router.post("/", response_model=UserResponse, status_code=201)
|
|
195
|
+
def create_user(user: UserCreate, db: Session = Depends(get_db)):
|
|
196
|
+
db_user = User(**user.model_dump())
|
|
197
|
+
db.add(db_user)
|
|
198
|
+
db.commit()
|
|
199
|
+
db.refresh(db_user)
|
|
200
|
+
return db_user
|
|
201
|
+
|
|
202
|
+
@router.put("/{user_id}", response_model=UserResponse)
|
|
203
|
+
def update_user(user_id: int, user: UserUpdate, db: Session = Depends(get_db)):
|
|
204
|
+
db_user = db.query(User).filter(User.id == user_id).first()
|
|
205
|
+
if not db_user:
|
|
206
|
+
raise HTTPException(status_code=404, detail="User not found")
|
|
207
|
+
|
|
208
|
+
update_data = user.model_dump(exclude_unset=True)
|
|
209
|
+
for key, value in update_data.items():
|
|
210
|
+
setattr(db_user, key, value)
|
|
211
|
+
|
|
212
|
+
db.commit()
|
|
213
|
+
db.refresh(db_user)
|
|
214
|
+
return db_user
|
|
215
|
+
|
|
216
|
+
@router.delete("/{user_id}", status_code=204)
|
|
217
|
+
def delete_user(user_id: int, db: Session = Depends(get_db)):
|
|
218
|
+
db_user = db.query(User).filter(User.id == user_id).first()
|
|
219
|
+
if not db_user:
|
|
220
|
+
raise HTTPException(status_code=404, detail="User not found")
|
|
221
|
+
db.delete(db_user)
|
|
222
|
+
db.commit()
|
|
223
|
+
\`\`\`
|
|
224
|
+
|
|
225
|
+
### Run Command
|
|
226
|
+
|
|
227
|
+
\`\`\`bash
|
|
228
|
+
# Do NOT run this - the preview system handles it
|
|
229
|
+
uvicorn app.main:app --reload --port 3001
|
|
230
|
+
\`\`\`
|
|
231
|
+
|
|
232
|
+
### Environment Variables
|
|
233
|
+
|
|
234
|
+
\`\`\`
|
|
235
|
+
# backend/.env
|
|
236
|
+
DATABASE_URL=sqlite:///./dev.db
|
|
237
|
+
\`\`\`
|
|
238
|
+
|
|
239
|
+
### API Design Guidelines
|
|
240
|
+
|
|
241
|
+
- **RESTful conventions**: GET read, POST create, PUT update, DELETE delete
|
|
242
|
+
- **Use Pydantic schemas** for request/response validation
|
|
243
|
+
- **Dependency injection** with \`Depends()\`
|
|
244
|
+
- **Proper status codes**: 200, 201, 400, 404, 500
|
|
245
|
+
- **HTTPException** for error responses`;
|
|
246
|
+
//# sourceMappingURL=fastapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastapi.js","sourceRoot":"","sources":["../../../../src/chat/prompts/backend/fastapi.ts"],"names":[],"mappings":";;;AAMa,QAAA,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wCAiPU,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NESTJS_PROMPT = exports.DJANGO_PROMPT = exports.FASTAPI_PROMPT = exports.EXPRESS_PROMPT = void 0;
|
|
4
|
+
var express_1 = require("./express");
|
|
5
|
+
Object.defineProperty(exports, "EXPRESS_PROMPT", { enumerable: true, get: function () { return express_1.EXPRESS_PROMPT; } });
|
|
6
|
+
var fastapi_1 = require("./fastapi");
|
|
7
|
+
Object.defineProperty(exports, "FASTAPI_PROMPT", { enumerable: true, get: function () { return fastapi_1.FASTAPI_PROMPT; } });
|
|
8
|
+
var django_1 = require("./django");
|
|
9
|
+
Object.defineProperty(exports, "DJANGO_PROMPT", { enumerable: true, get: function () { return django_1.DJANGO_PROMPT; } });
|
|
10
|
+
var nestjs_1 = require("./nestjs");
|
|
11
|
+
Object.defineProperty(exports, "NESTJS_PROMPT", { enumerable: true, get: function () { return nestjs_1.NESTJS_PROMPT; } });
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/chat/prompts/backend/index.ts"],"names":[],"mappings":";;;AAMA,qCAA2C;AAAlC,yGAAA,cAAc,OAAA;AACvB,qCAA2C;AAAlC,yGAAA,cAAc,OAAA;AACvB,mCAAyC;AAAhC,uGAAA,aAAa,OAAA;AACtB,mCAAyC;AAAhC,uGAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const NESTJS_PROMPT = "## Backend: NestJS + TypeScript + Prisma\n\nYou are building a NestJS backend with TypeScript and Prisma ORM.\n\n### Technology Stack (Backend)\n\n| Category | Technology | Notes |\n|----------|------------|-------|\n| Runtime | Node.js 20+ | LTS version |\n| Framework | NestJS 10+ | Enterprise-grade |\n| Language | TypeScript | Strict mode |\n| ORM | Prisma | Type-safe database access |\n| Database | SQLite (dev) / PostgreSQL (prod) | |\n| Validation | class-validator | DTO validation |\n\n### Project Structure\n\n```\nbackend/\n\u251C\u2500\u2500 src/\n\u2502 \u251C\u2500\u2500 main.ts # Entry point\n\u2502 \u251C\u2500\u2500 app.module.ts # Root module\n\u2502 \u251C\u2500\u2500 prisma/\n\u2502 \u2502 \u251C\u2500\u2500 prisma.module.ts\n\u2502 \u2502 \u2514\u2500\u2500 prisma.service.ts\n\u2502 \u2514\u2500\u2500 users/\n\u2502 \u251C\u2500\u2500 users.module.ts\n\u2502 \u251C\u2500\u2500 users.controller.ts\n\u2502 \u251C\u2500\u2500 users.service.ts\n\u2502 \u2514\u2500\u2500 dto/\n\u2502 \u251C\u2500\u2500 create-user.dto.ts\n\u2502 \u2514\u2500\u2500 update-user.dto.ts\n\u251C\u2500\u2500 prisma/\n\u2502 \u2514\u2500\u2500 schema.prisma\n\u251C\u2500\u2500 package.json\n\u2514\u2500\u2500 tsconfig.json\n```\n\n### Backend Setup\n\n```bash\ncd backend\nnpm init -y\nnpm install @nestjs/core @nestjs/common @nestjs/platform-express reflect-metadata rxjs\nnpm install class-validator class-transformer\nnpm install prisma @prisma/client\nnpm install -D typescript @types/node @types/express ts-node\nnpx prisma init --datasource-provider sqlite\n```\n\n### Main Entry Point\n\n```typescript\n// backend/src/main.ts\nimport { NestFactory } from '@nestjs/core';\nimport { ValidationPipe } from '@nestjs/common';\nimport { AppModule } from './app.module';\n\nasync function bootstrap() {\n const app = await NestFactory.create(AppModule);\n\n app.enableCors({\n origin: 'http://localhost:3000',\n });\n\n app.setGlobalPrefix('api');\n app.useGlobalPipes(new ValidationPipe({ transform: true }));\n\n await app.listen(3001);\n console.log('Server running on http://localhost:3001');\n}\nbootstrap();\n```\n\n### App Module\n\n```typescript\n// backend/src/app.module.ts\nimport { Module } from '@nestjs/common';\nimport { PrismaModule } from './prisma/prisma.module';\nimport { UsersModule } from './users/users.module';\n\n@Module({\n imports: [PrismaModule, UsersModule],\n})\nexport class AppModule {}\n```\n\n### Prisma Service\n\n```typescript\n// backend/src/prisma/prisma.service.ts\nimport { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';\nimport { PrismaClient } from '@prisma/client';\n\n@Injectable()\nexport class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {\n async onModuleInit() {\n await this.$connect();\n }\n\n async onModuleDestroy() {\n await this.$disconnect();\n }\n}\n```\n\n```typescript\n// backend/src/prisma/prisma.module.ts\nimport { Module, Global } from '@nestjs/common';\nimport { PrismaService } from './prisma.service';\n\n@Global()\n@Module({\n providers: [PrismaService],\n exports: [PrismaService],\n})\nexport class PrismaModule {}\n```\n\n### DTOs with Validation\n\n```typescript\n// backend/src/users/dto/create-user.dto.ts\nimport { IsString, IsEmail, MinLength } from 'class-validator';\n\nexport class CreateUserDto {\n @IsString()\n @MinLength(1)\n name: string;\n\n @IsEmail()\n email: string;\n}\n```\n\n```typescript\n// backend/src/users/dto/update-user.dto.ts\nimport { PartialType } from '@nestjs/common';\nimport { CreateUserDto } from './create-user.dto';\n\nexport class UpdateUserDto extends PartialType(CreateUserDto) {}\n```\n\n### Service\n\n```typescript\n// backend/src/users/users.service.ts\nimport { Injectable, NotFoundException } from '@nestjs/common';\nimport { PrismaService } from '../prisma/prisma.service';\nimport { CreateUserDto } from './dto/create-user.dto';\nimport { UpdateUserDto } from './dto/update-user.dto';\n\n@Injectable()\nexport class UsersService {\n constructor(private prisma: PrismaService) {}\n\n async findAll() {\n return this.prisma.user.findMany();\n }\n\n async findOne(id: number) {\n const user = await this.prisma.user.findUnique({ where: { id } });\n if (!user) {\n throw new NotFoundException(`User #${id} not found`);\n }\n return user;\n }\n\n async create(createUserDto: CreateUserDto) {\n return this.prisma.user.create({ data: createUserDto });\n }\n\n async update(id: number, updateUserDto: UpdateUserDto) {\n await this.findOne(id); // Check existence\n return this.prisma.user.update({\n where: { id },\n data: updateUserDto,\n });\n }\n\n async remove(id: number) {\n await this.findOne(id); // Check existence\n return this.prisma.user.delete({ where: { id } });\n }\n}\n```\n\n### Controller\n\n```typescript\n// backend/src/users/users.controller.ts\nimport {\n Controller,\n Get,\n Post,\n Put,\n Delete,\n Body,\n Param,\n ParseIntPipe,\n HttpCode,\n HttpStatus,\n} from '@nestjs/common';\nimport { UsersService } from './users.service';\nimport { CreateUserDto } from './dto/create-user.dto';\nimport { UpdateUserDto } from './dto/update-user.dto';\n\n@Controller('users')\nexport class UsersController {\n constructor(private readonly usersService: UsersService) {}\n\n @Get()\n findAll() {\n return this.usersService.findAll();\n }\n\n @Get(':id')\n findOne(@Param('id', ParseIntPipe) id: number) {\n return this.usersService.findOne(id);\n }\n\n @Post()\n @HttpCode(HttpStatus.CREATED)\n create(@Body() createUserDto: CreateUserDto) {\n return this.usersService.create(createUserDto);\n }\n\n @Put(':id')\n update(\n @Param('id', ParseIntPipe) id: number,\n @Body() updateUserDto: UpdateUserDto,\n ) {\n return this.usersService.update(id, updateUserDto);\n }\n\n @Delete(':id')\n @HttpCode(HttpStatus.NO_CONTENT)\n remove(@Param('id', ParseIntPipe) id: number) {\n return this.usersService.remove(id);\n }\n}\n```\n\n### Module\n\n```typescript\n// backend/src/users/users.module.ts\nimport { Module } from '@nestjs/common';\nimport { UsersController } from './users.controller';\nimport { UsersService } from './users.service';\n\n@Module({\n controllers: [UsersController],\n providers: [UsersService],\n})\nexport class UsersModule {}\n```\n\n### API Design Guidelines\n\n- **Decorators for everything**: @Controller, @Get, @Post, etc.\n- **DTOs for validation**: Use class-validator decorators\n- **Dependency Injection**: Inject services via constructor\n- **Exception filters**: Use built-in exceptions (NotFoundException, etc.)\n- **Pipes for transformation**: ParseIntPipe, ValidationPipe";
|