red64-cli 0.3.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +194 -338
- package/dist/cli/parseArgs.d.ts.map +1 -1
- package/dist/cli/parseArgs.js +5 -13
- package/dist/cli/parseArgs.js.map +1 -1
- package/dist/components/init/types.d.ts +0 -2
- package/dist/components/init/types.d.ts.map +1 -1
- package/dist/components/screens/HelpScreen.d.ts.map +1 -1
- package/dist/components/screens/HelpScreen.js +0 -2
- package/dist/components/screens/HelpScreen.js.map +1 -1
- package/dist/components/screens/InitScreen.d.ts.map +1 -1
- package/dist/components/screens/InitScreen.js +5 -8
- package/dist/components/screens/InitScreen.js.map +1 -1
- package/dist/components/screens/StartScreen.d.ts.map +1 -1
- package/dist/components/screens/StartScreen.js +29 -8
- package/dist/components/screens/StartScreen.js.map +1 -1
- package/dist/components/screens/StatusScreen.d.ts.map +1 -1
- package/dist/components/screens/StatusScreen.js +16 -1
- package/dist/components/screens/StatusScreen.js.map +1 -1
- package/dist/services/AgentInvoker.d.ts.map +1 -1
- package/dist/services/AgentInvoker.js +76 -37
- package/dist/services/AgentInvoker.js.map +1 -1
- package/dist/services/ClaudeErrorDetector.d.ts +1 -1
- package/dist/services/ClaudeErrorDetector.d.ts.map +1 -1
- package/dist/services/ClaudeErrorDetector.js +1 -0
- package/dist/services/ClaudeErrorDetector.js.map +1 -1
- package/dist/services/ClaudeHealthCheck.d.ts +7 -0
- package/dist/services/ClaudeHealthCheck.d.ts.map +1 -1
- package/dist/services/ClaudeHealthCheck.js +76 -12
- package/dist/services/ClaudeHealthCheck.js.map +1 -1
- package/dist/services/ConfigService.d.ts +1 -0
- package/dist/services/ConfigService.d.ts.map +1 -1
- package/dist/services/ConfigService.js.map +1 -1
- package/dist/services/DockerRunner.js +1 -1
- package/dist/services/DockerRunner.js.map +1 -1
- package/dist/services/PhaseExecutor.d.ts.map +1 -1
- package/dist/services/PhaseExecutor.js +2 -1
- package/dist/services/PhaseExecutor.js.map +1 -1
- package/dist/services/TaskRunner.d.ts.map +1 -1
- package/dist/services/TaskRunner.js +2 -1
- package/dist/services/TaskRunner.js.map +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/index.js.map +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/framework/stacks/c/code-quality.md +326 -0
- package/framework/stacks/c/coding-style.md +347 -0
- package/framework/stacks/c/conventions.md +513 -0
- package/framework/stacks/c/error-handling.md +350 -0
- package/framework/stacks/c/feedback.md +158 -0
- package/framework/stacks/c/memory-safety.md +408 -0
- package/framework/stacks/c/tech.md +122 -0
- package/framework/stacks/c/testing.md +472 -0
- package/framework/stacks/cpp/code-quality.md +282 -0
- package/framework/stacks/cpp/coding-style.md +363 -0
- package/framework/stacks/cpp/conventions.md +420 -0
- package/framework/stacks/cpp/error-handling.md +264 -0
- package/framework/stacks/cpp/feedback.md +104 -0
- package/framework/stacks/cpp/memory-safety.md +351 -0
- package/framework/stacks/cpp/tech.md +160 -0
- package/framework/stacks/cpp/testing.md +323 -0
- package/framework/stacks/java/code-quality.md +357 -0
- package/framework/stacks/java/coding-style.md +400 -0
- package/framework/stacks/java/conventions.md +437 -0
- package/framework/stacks/java/error-handling.md +408 -0
- package/framework/stacks/java/feedback.md +180 -0
- package/framework/stacks/java/tech.md +126 -0
- package/framework/stacks/java/testing.md +485 -0
- package/framework/stacks/javascript/async-patterns.md +216 -0
- package/framework/stacks/javascript/code-quality.md +182 -0
- package/framework/stacks/javascript/coding-style.md +293 -0
- package/framework/stacks/javascript/conventions.md +268 -0
- package/framework/stacks/javascript/error-handling.md +216 -0
- package/framework/stacks/javascript/feedback.md +80 -0
- package/framework/stacks/javascript/tech.md +114 -0
- package/framework/stacks/javascript/testing.md +209 -0
- package/framework/stacks/loco/code-quality.md +156 -0
- package/framework/stacks/loco/coding-style.md +247 -0
- package/framework/stacks/loco/error-handling.md +225 -0
- package/framework/stacks/loco/feedback.md +35 -0
- package/framework/stacks/loco/loco.md +342 -0
- package/framework/stacks/loco/structure.md +193 -0
- package/framework/stacks/loco/tech.md +129 -0
- package/framework/stacks/loco/testing.md +211 -0
- package/framework/stacks/rust/code-quality.md +370 -0
- package/framework/stacks/rust/coding-style.md +475 -0
- package/framework/stacks/rust/conventions.md +430 -0
- package/framework/stacks/rust/error-handling.md +399 -0
- package/framework/stacks/rust/feedback.md +152 -0
- package/framework/stacks/rust/memory-safety.md +398 -0
- package/framework/stacks/rust/tech.md +121 -0
- package/framework/stacks/rust/testing.md +528 -0
- package/package.json +14 -2
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Development Conventions
|
|
2
|
+
|
|
3
|
+
General development practices, workflow, and operational standards for JavaScript/Node.js projects.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
- **Predictable process**: Consistent workflows reduce friction and errors
|
|
10
|
+
- **Automated enforcement**: Linters and CI catch what humans miss
|
|
11
|
+
- **Observable systems**: If you cannot see it, you cannot fix it
|
|
12
|
+
- **Documentation as code**: Keep docs next to the code they describe
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Git Workflow
|
|
17
|
+
|
|
18
|
+
### Branch Strategy
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
main # Production-ready, always deployable
|
|
22
|
+
|-- feat/... # Feature branches (short-lived)
|
|
23
|
+
|-- fix/... # Bug fix branches
|
|
24
|
+
|-- chore/... # Maintenance, dependency updates
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Branch Naming
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
feat/add-user-registration
|
|
31
|
+
fix/duplicate-email-validation
|
|
32
|
+
chore/upgrade-fastify
|
|
33
|
+
refactor/extract-payment-service
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Pattern**: `{type}/{short-description}` with lowercase and hyphens.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Commit Conventions
|
|
41
|
+
|
|
42
|
+
### Conventional Commits
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
feat: add user registration endpoint
|
|
46
|
+
fix: prevent duplicate email registration
|
|
47
|
+
refactor: extract password hashing to utility module
|
|
48
|
+
test: add integration tests for payment flow
|
|
49
|
+
docs: update API authentication guide
|
|
50
|
+
chore: upgrade zod to v4
|
|
51
|
+
ci: add lint check to CI pipeline
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Types
|
|
55
|
+
|
|
56
|
+
| Type | Description |
|
|
57
|
+
|------|-------------|
|
|
58
|
+
| `feat` | New feature or capability |
|
|
59
|
+
| `fix` | Bug fix |
|
|
60
|
+
| `refactor` | Code change that neither fixes nor adds |
|
|
61
|
+
| `test` | Adding or updating tests |
|
|
62
|
+
| `docs` | Documentation only |
|
|
63
|
+
| `chore` | Maintenance, dependencies, tooling |
|
|
64
|
+
| `ci` | CI/CD configuration changes |
|
|
65
|
+
| `perf` | Performance improvement |
|
|
66
|
+
|
|
67
|
+
**Rule**: One logical change per commit. If the commit message needs "and", split it.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Project Structure
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
project-root/
|
|
75
|
+
src/
|
|
76
|
+
index.js # Application entry point
|
|
77
|
+
app.js # Framework setup (Express/Fastify)
|
|
78
|
+
config.js # Environment configuration
|
|
79
|
+
routes/
|
|
80
|
+
users.js
|
|
81
|
+
orders.js
|
|
82
|
+
services/
|
|
83
|
+
user-service.js
|
|
84
|
+
order-service.js
|
|
85
|
+
repositories/
|
|
86
|
+
user-repo.js
|
|
87
|
+
middleware/
|
|
88
|
+
auth.js
|
|
89
|
+
error-handler.js
|
|
90
|
+
validate.js
|
|
91
|
+
errors.js # Custom error classes
|
|
92
|
+
logger.js # Logger configuration
|
|
93
|
+
tests/
|
|
94
|
+
unit/
|
|
95
|
+
integration/
|
|
96
|
+
fixtures/
|
|
97
|
+
setup.js
|
|
98
|
+
eslint.config.js
|
|
99
|
+
vitest.config.js
|
|
100
|
+
package.json
|
|
101
|
+
.env.example
|
|
102
|
+
.gitignore
|
|
103
|
+
.prettierrc
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## ESM Module System
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
// package.json
|
|
112
|
+
{
|
|
113
|
+
"type": "module"
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
// GOOD: ESM
|
|
119
|
+
import { readFile } from 'node:fs/promises';
|
|
120
|
+
import express from 'express';
|
|
121
|
+
export function createApp() { /* ... */ }
|
|
122
|
+
|
|
123
|
+
// BAD: CJS (avoid in new projects)
|
|
124
|
+
const { readFile } = require('fs/promises');
|
|
125
|
+
module.exports = { createApp };
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### ESM Gotchas
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
// No __dirname in ESM -- use import.meta
|
|
132
|
+
import { fileURLToPath } from 'node:url';
|
|
133
|
+
import { dirname } from 'node:path';
|
|
134
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
135
|
+
const __dirname = dirname(__filename);
|
|
136
|
+
|
|
137
|
+
// Relative imports MUST include file extensions
|
|
138
|
+
import { userService } from './services/user-service.js'; // .js required
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Environment Configuration
|
|
144
|
+
|
|
145
|
+
### Using dotenv + Zod
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
// src/config.js
|
|
149
|
+
import 'dotenv/config';
|
|
150
|
+
import { z } from 'zod';
|
|
151
|
+
|
|
152
|
+
const envSchema = z.object({
|
|
153
|
+
NODE_ENV: z.enum(['development', 'staging', 'production']).default('development'),
|
|
154
|
+
PORT: z.coerce.number().default(3000),
|
|
155
|
+
DATABASE_URL: z.string().url(),
|
|
156
|
+
JWT_SECRET: z.string().min(32),
|
|
157
|
+
REDIS_URL: z.string().url().default('redis://localhost:6379'),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const parsed = envSchema.safeParse(process.env);
|
|
161
|
+
if (!parsed.success) {
|
|
162
|
+
console.error('Invalid environment variables:', parsed.error.format());
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export const config = Object.freeze(parsed.data);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Rules
|
|
170
|
+
- Never commit `.env` files with real values
|
|
171
|
+
- Always commit `.env.example` with placeholder values
|
|
172
|
+
- Fail fast on missing required variables (no defaults for secrets)
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Logging with pino
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
// src/logger.js
|
|
180
|
+
import pino from 'pino';
|
|
181
|
+
import { config } from './config.js';
|
|
182
|
+
|
|
183
|
+
export const logger = pino({
|
|
184
|
+
level: config.NODE_ENV === 'production' ? 'info' : 'debug',
|
|
185
|
+
transport: config.NODE_ENV !== 'production'
|
|
186
|
+
? { target: 'pino-pretty', options: { colorize: true } }
|
|
187
|
+
: undefined,
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
// GOOD: Structured key-value pairs
|
|
193
|
+
logger.info({ userId: 42, email: 'a@b.com' }, 'user_created');
|
|
194
|
+
logger.error({ orderId: 123, provider: 'stripe', err }, 'payment_failed');
|
|
195
|
+
|
|
196
|
+
// BAD: String interpolation
|
|
197
|
+
logger.info(`User ${userId} created with email ${email}`);
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## API Design Patterns
|
|
203
|
+
|
|
204
|
+
```javascript
|
|
205
|
+
// RESTful conventions
|
|
206
|
+
GET /api/v1/users // List users
|
|
207
|
+
POST /api/v1/users // Create user
|
|
208
|
+
GET /api/v1/users/:id // Get user
|
|
209
|
+
PATCH /api/v1/users/:id // Update user
|
|
210
|
+
DELETE /api/v1/users/:id // Delete user
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Response Formats
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
// Success (single resource)
|
|
217
|
+
{ "data": { "id": 1, "name": "Alice" } }
|
|
218
|
+
|
|
219
|
+
// Success (collection)
|
|
220
|
+
{ "data": [...], "meta": { "total": 100, "page": 1, "limit": 20 } }
|
|
221
|
+
|
|
222
|
+
// Error
|
|
223
|
+
{ "error": { "code": "NOT_FOUND", "message": "User not found", "details": {} } }
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Dependency Management
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
pnpm add fastify zod # Add dependency
|
|
232
|
+
pnpm add -D vitest eslint # Add dev dependency
|
|
233
|
+
pnpm audit # Check vulnerabilities
|
|
234
|
+
pnpm outdated # Check for updates
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### engines Field
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"engines": {
|
|
242
|
+
"node": ">=22.0.0"
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Health Checks
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
app.get('/health', (req, res) => {
|
|
253
|
+
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
app.get('/health/ready', async (req, res) => {
|
|
257
|
+
try {
|
|
258
|
+
await db.query('SELECT 1');
|
|
259
|
+
res.json({ status: 'ready', database: 'connected' });
|
|
260
|
+
} catch {
|
|
261
|
+
res.status(503).json({ status: 'not_ready', database: 'disconnected' });
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
_Conventions reduce cognitive load. Follow them consistently so the team can focus on solving problems, not debating style._
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Error Handling Patterns
|
|
2
|
+
|
|
3
|
+
Structured error handling for Node.js applications with custom exceptions, framework-specific middleware, and observability.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
- **Fail fast**: Validate inputs early, throw immediately on invalid state
|
|
10
|
+
- **Typed exceptions**: Custom error hierarchy over generic `Error`
|
|
11
|
+
- **Centralized handling**: Error middleware at the API boundary, not scattered try/catch
|
|
12
|
+
- **Structured logging**: Machine-readable logs with context, not `console.log`
|
|
13
|
+
- **User-safe messages**: Never expose stack traces or internal details to clients
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Custom Error Hierarchy
|
|
18
|
+
|
|
19
|
+
### Base Errors
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
// src/errors.js
|
|
23
|
+
export class AppError extends Error {
|
|
24
|
+
constructor(message, { code = 'INTERNAL_ERROR', statusCode = 500, details = {} } = {}) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.name = this.constructor.name;
|
|
27
|
+
this.code = code;
|
|
28
|
+
this.statusCode = statusCode;
|
|
29
|
+
this.details = details;
|
|
30
|
+
Error.captureStackTrace(this, this.constructor);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class NotFoundError extends AppError {
|
|
35
|
+
constructor(resource, identifier) {
|
|
36
|
+
super(`${resource} not found: ${identifier}`, {
|
|
37
|
+
code: 'NOT_FOUND',
|
|
38
|
+
statusCode: 404,
|
|
39
|
+
details: { resource, identifier },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class ConflictError extends AppError {
|
|
45
|
+
constructor(message, details = {}) {
|
|
46
|
+
super(message, { code: 'CONFLICT', statusCode: 409, details });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class ValidationError extends AppError {
|
|
51
|
+
constructor(message, fieldErrors = {}) {
|
|
52
|
+
super(message, {
|
|
53
|
+
code: 'VALIDATION_ERROR',
|
|
54
|
+
statusCode: 422,
|
|
55
|
+
details: { fieldErrors },
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export class AuthenticationError extends AppError {
|
|
61
|
+
constructor(message = 'Authentication required') {
|
|
62
|
+
super(message, { code: 'UNAUTHENTICATED', statusCode: 401 });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export class AuthorizationError extends AppError {
|
|
67
|
+
constructor(message = 'Insufficient permissions') {
|
|
68
|
+
super(message, { code: 'FORBIDDEN', statusCode: 403 });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export class ExternalServiceError extends AppError {
|
|
73
|
+
constructor(service, message) {
|
|
74
|
+
super(`External service error (${service}): ${message}`, {
|
|
75
|
+
code: 'EXTERNAL_SERVICE_ERROR',
|
|
76
|
+
statusCode: 502,
|
|
77
|
+
details: { service },
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Centralized Error Handler (Express)
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
// src/middleware/error-handler.js
|
|
89
|
+
import { AppError } from '../errors.js';
|
|
90
|
+
import { logger } from '../logger.js';
|
|
91
|
+
|
|
92
|
+
export function errorHandler(err, req, res, _next) {
|
|
93
|
+
if (err instanceof AppError) {
|
|
94
|
+
logger.warn({ code: err.code, message: err.message, path: req.path });
|
|
95
|
+
return res.status(err.statusCode).json({
|
|
96
|
+
error: { code: err.code, message: err.message, details: err.details },
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Zod validation errors
|
|
101
|
+
if (err.name === 'ZodError') {
|
|
102
|
+
return res.status(422).json({
|
|
103
|
+
error: { code: 'VALIDATION_ERROR', message: 'Request validation failed', details: { issues: err.issues } },
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Unknown errors -- never expose internals
|
|
108
|
+
logger.error({ message: 'Unhandled error', error: err.message, stack: err.stack, path: req.path });
|
|
109
|
+
return res.status(500).json({
|
|
110
|
+
error: { code: 'INTERNAL_ERROR', message: 'An unexpected error occurred' },
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Fastify Error Handling
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
app.setErrorHandler((error, request, reply) => {
|
|
121
|
+
if (error instanceof AppError) {
|
|
122
|
+
request.log.warn({ code: error.code, message: error.message });
|
|
123
|
+
return reply.status(error.statusCode).send({
|
|
124
|
+
error: { code: error.code, message: error.message, details: error.details },
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (error.validation) {
|
|
129
|
+
return reply.status(422).send({
|
|
130
|
+
error: { code: 'VALIDATION_ERROR', message: 'Request validation failed', details: { issues: error.validation } },
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
request.log.error({ error: error.message, stack: error.stack });
|
|
135
|
+
return reply.status(500).send({
|
|
136
|
+
error: { code: 'INTERNAL_ERROR', message: 'An unexpected error occurred' },
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Async Error Handling
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
// GOOD: try/catch at the right level
|
|
147
|
+
async function processOrder(orderId) {
|
|
148
|
+
const order = await orderRepo.findById(orderId);
|
|
149
|
+
if (!order) {
|
|
150
|
+
throw new NotFoundError('Order', orderId);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
await paymentClient.charge(order.totalCents, order.paymentToken);
|
|
155
|
+
} catch (err) {
|
|
156
|
+
throw new ExternalServiceError('payment', err.message);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
order.status = 'paid';
|
|
160
|
+
return orderRepo.save(order);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// BAD: Wrapping everything in try/catch and swallowing
|
|
164
|
+
async function processOrder(orderId) {
|
|
165
|
+
try {
|
|
166
|
+
const order = await orderRepo.findById(orderId);
|
|
167
|
+
// ... 50 lines of logic ...
|
|
168
|
+
} catch (err) {
|
|
169
|
+
console.log(err); // Swallowed, no rethrow
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Process-Level Error Handlers
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
// src/index.js -- register at application startup
|
|
180
|
+
process.on('unhandledRejection', (reason) => {
|
|
181
|
+
logger.error({ message: 'Unhandled promise rejection', reason: reason instanceof Error ? reason.message : reason });
|
|
182
|
+
process.exit(1);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
process.on('uncaughtException', (error) => {
|
|
186
|
+
logger.fatal({ message: 'Uncaught exception', error: error.message, stack: error.stack });
|
|
187
|
+
process.exit(1);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Graceful shutdown
|
|
191
|
+
function gracefulShutdown(signal) {
|
|
192
|
+
logger.info({ message: 'Shutdown signal received', signal });
|
|
193
|
+
server.close(() => process.exit(0));
|
|
194
|
+
setTimeout(() => process.exit(1), 10_000);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
|
198
|
+
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Anti-Patterns
|
|
204
|
+
|
|
205
|
+
| Anti-Pattern | Problem | Correct Approach |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `catch (err) {}` | Silently swallows errors | Log and re-throw or handle specifically |
|
|
208
|
+
| `throw 'something'` | No stack trace, not an Error object | Always `throw new Error(...)` or custom class |
|
|
209
|
+
| Nested try/catch everywhere | Hard to read, hides control flow | Centralized error middleware |
|
|
210
|
+
| `console.log(err)` in catch | No structure, lost in production | Use structured logger (pino) |
|
|
211
|
+
| Stack traces in API responses | Security risk | Return error codes and user-safe messages |
|
|
212
|
+
| Mixing callbacks and promises | Inconsistent error propagation | Use async/await consistently |
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
_Errors are data. Classify them, log them with context, and present them consistently. Never swallow exceptions silently._
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Feedback Configuration
|
|
2
|
+
|
|
3
|
+
Project-specific commands for automated feedback during JavaScript/Node.js implementation.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Test Commands
|
|
8
|
+
|
|
9
|
+
Commands to run tests during implementation. The agent will use these to verify code changes.
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
# Primary test command (REQUIRED)
|
|
13
|
+
test: npx vitest run
|
|
14
|
+
|
|
15
|
+
# Test with coverage report
|
|
16
|
+
test_coverage: npx vitest run --coverage
|
|
17
|
+
|
|
18
|
+
# Run specific test file (use {file} as placeholder)
|
|
19
|
+
test_file: npx vitest run {file}
|
|
20
|
+
|
|
21
|
+
# Watch mode (development)
|
|
22
|
+
test_watch: npx vitest
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Linting Commands
|
|
28
|
+
|
|
29
|
+
Commands for code quality checks.
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
# Primary lint command
|
|
33
|
+
lint: npx eslint .
|
|
34
|
+
|
|
35
|
+
# Lint with auto-fix
|
|
36
|
+
lint_fix: npx eslint . --fix
|
|
37
|
+
|
|
38
|
+
# Format check
|
|
39
|
+
format_check: npx prettier --check .
|
|
40
|
+
|
|
41
|
+
# Format fix
|
|
42
|
+
format_fix: npx prettier --write .
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Build / Syntax Check Commands
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
# Syntax check (Node.js built-in)
|
|
51
|
+
build: node --check src/index.js
|
|
52
|
+
|
|
53
|
+
# Check all source files
|
|
54
|
+
build_all: find src -name '*.js' -exec node --check {} +
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Development Server
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
# Start dev server (with watch mode)
|
|
63
|
+
dev_server: node --watch src/index.js
|
|
64
|
+
|
|
65
|
+
# Dev server port
|
|
66
|
+
dev_port: 3000
|
|
67
|
+
|
|
68
|
+
# Dev server base URL
|
|
69
|
+
dev_url: http://localhost:3000
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Notes
|
|
75
|
+
|
|
76
|
+
- Uses Vitest as the primary test runner (Jest-compatible API, native ESM)
|
|
77
|
+
- ESLint with flat config (`eslint.config.js`) for linting
|
|
78
|
+
- Prettier for formatting (separate from ESLint)
|
|
79
|
+
- Node.js `--watch` flag provides built-in file watching (stable in Node.js 22+)
|
|
80
|
+
- For Biome projects, replace lint + format commands with `npx biome check .`
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Technology Stack
|
|
2
|
+
|
|
3
|
+
## Architecture
|
|
4
|
+
|
|
5
|
+
Modern Node.js application with ESM-first design. Fastify or Express as web framework, PostgreSQL for persistence, Redis for caching and queues, Docker for deployment.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Technologies
|
|
10
|
+
|
|
11
|
+
- **Runtime**: Node.js 22+ (LTS)
|
|
12
|
+
- **Package Manager**: pnpm (fast, disk-efficient) or npm
|
|
13
|
+
- **Module System**: ESM (`"type": "module"` in package.json)
|
|
14
|
+
- **Web Framework**: Fastify (performance-first) or Express (ecosystem) or Hono (edge/serverless)
|
|
15
|
+
- **Database**: PostgreSQL with pg or postgres.js
|
|
16
|
+
- **ORM/Query Builder**: Drizzle ORM (SQL-first) or Prisma (DX-first)
|
|
17
|
+
- **Validation**: Zod (TypeScript-aligned) or Joi (mature, standalone)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Key Libraries
|
|
22
|
+
|
|
23
|
+
### Web & API
|
|
24
|
+
- **Fastify**: High-performance web framework with schema-based validation
|
|
25
|
+
- **Express**: Minimalist framework with massive middleware ecosystem
|
|
26
|
+
- **Hono**: Ultrafast framework for edge/serverless (Cloudflare Workers, Deno, Bun)
|
|
27
|
+
- **cors**: Cross-origin resource sharing middleware
|
|
28
|
+
- **helmet**: Security headers middleware
|
|
29
|
+
|
|
30
|
+
### Database & Storage
|
|
31
|
+
- **Drizzle ORM**: SQL-first, zero-dependency ORM with TypeScript schema-as-code
|
|
32
|
+
- **Prisma**: Full-featured ORM with declarative schema and migrations
|
|
33
|
+
- **postgres.js**: Fastest PostgreSQL client for Node.js
|
|
34
|
+
- **ioredis**: Redis client with cluster support
|
|
35
|
+
|
|
36
|
+
### Validation & Serialization
|
|
37
|
+
- **Zod**: TypeScript-first schema validation with inference
|
|
38
|
+
- **Joi**: Battle-tested validation library
|
|
39
|
+
- **ajv**: JSON Schema validator (used internally by Fastify)
|
|
40
|
+
|
|
41
|
+
### Background Tasks
|
|
42
|
+
- **BullMQ**: Redis-based queue for job processing
|
|
43
|
+
- **node-cron**: Lightweight cron scheduler
|
|
44
|
+
|
|
45
|
+
### Deployment
|
|
46
|
+
- **Docker**: Containerized deployment
|
|
47
|
+
- **Docker Compose**: Multi-service local development
|
|
48
|
+
- **PM2**: Process manager for production Node.js
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Runtime Alternatives
|
|
53
|
+
|
|
54
|
+
| Runtime | Use Case | Notes |
|
|
55
|
+
|---------|----------|-------|
|
|
56
|
+
| **Node.js 22+** | Default, production-proven | LTS until April 2027, native TS support (flag) |
|
|
57
|
+
| **Bun** | Performance-critical, fast scripts | Built-in bundler, test runner, package manager |
|
|
58
|
+
| **Deno** | Security-first, standards-aligned | Built-in TypeScript, permissions model, npm compat |
|
|
59
|
+
|
|
60
|
+
**Default**: Node.js 22 LTS. Use Bun or Deno when their specific advantages are needed.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Development Environment
|
|
65
|
+
|
|
66
|
+
### Required Tools
|
|
67
|
+
- Node.js 22+ (see `.node-version` or `.nvmrc`)
|
|
68
|
+
- pnpm or npm
|
|
69
|
+
- PostgreSQL 16+
|
|
70
|
+
- Redis 7+
|
|
71
|
+
- Docker & Docker Compose
|
|
72
|
+
|
|
73
|
+
### Common Commands
|
|
74
|
+
```bash
|
|
75
|
+
# Environment setup
|
|
76
|
+
pnpm install # Install dependencies
|
|
77
|
+
pnpm run db:migrate # Run migrations
|
|
78
|
+
|
|
79
|
+
# Dev server
|
|
80
|
+
pnpm run dev # Start with watch mode
|
|
81
|
+
node --watch src/index.js # Built-in watch mode
|
|
82
|
+
|
|
83
|
+
# Tests
|
|
84
|
+
pnpm run test # All tests (Vitest)
|
|
85
|
+
npx vitest run tests/unit/ # Unit tests only
|
|
86
|
+
npx vitest run --coverage # With coverage
|
|
87
|
+
|
|
88
|
+
# Code quality
|
|
89
|
+
npx eslint . # Lint
|
|
90
|
+
npx prettier --check . # Format check
|
|
91
|
+
npx prettier --write . # Format fix
|
|
92
|
+
|
|
93
|
+
# Docker
|
|
94
|
+
docker compose up -d # Start services
|
|
95
|
+
docker compose logs -f app # Follow app logs
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Key Technical Decisions
|
|
101
|
+
|
|
102
|
+
| Decision | Rationale |
|
|
103
|
+
|----------|-----------|
|
|
104
|
+
| **ESM over CJS** | Modern standard, tree-shaking, top-level await, aligns with browser JS |
|
|
105
|
+
| **pnpm over npm** | 3x faster installs, strict dependency resolution, disk-efficient |
|
|
106
|
+
| **Fastify over Express** | 2-3x faster, built-in schema validation, better async support |
|
|
107
|
+
| **Drizzle over Prisma** | Zero binary deps, SQL-first, tiny bundle, edge-compatible |
|
|
108
|
+
| **Zod over Joi** | TypeScript inference, composable schemas, smaller bundle |
|
|
109
|
+
| **Vitest over Jest** | Native ESM, faster execution, Vite-powered HMR in watch mode |
|
|
110
|
+
| **Biome as alternative** | Single tool for lint + format, Rust speed, zero config |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
_Document standards and patterns, not every dependency. See `coding-style.md` for detailed JavaScript conventions._
|