create-charcole 2.0.4 → 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/CHANGELOG.md +290 -14
- package/README.md +258 -312
- package/bin/index.js +392 -55
- package/bin/lib/pkgManager.js +8 -25
- package/bin/lib/templateHandler.js +5 -42
- package/create-charcole-2.1.0.tgz +0 -0
- package/package.json +2 -2
- package/packages/swagger/BACKWARD_COMPATIBILITY.md +145 -0
- package/packages/swagger/CHANGELOG.md +404 -0
- package/packages/swagger/README.md +578 -0
- package/packages/swagger/charcole-swagger-1.0.0.tgz +0 -0
- package/packages/swagger/package-lock.json +1715 -0
- package/packages/swagger/package.json +44 -0
- package/packages/swagger/src/helpers.js +427 -0
- package/packages/swagger/src/index.d.ts +126 -0
- package/packages/swagger/src/index.js +12 -0
- package/packages/swagger/src/setup.js +100 -0
- package/template/js/.env.example +8 -0
- package/template/js/README.md +128 -5
- package/template/js/basePackage.json +11 -13
- package/template/js/src/app.js +8 -2
- package/template/js/src/config/swagger.config.js +15 -0
- package/template/js/src/lib/swagger/SWAGGER_GUIDE.md +561 -0
- package/template/js/src/modules/auth/auth.constants.js +3 -0
- package/template/js/src/modules/auth/auth.controller.js +29 -0
- package/template/js/src/modules/auth/auth.middlewares.js +19 -0
- package/template/js/src/modules/auth/auth.routes.js +131 -0
- package/template/js/src/modules/auth/auth.schemas.js +60 -0
- package/template/js/src/modules/auth/auth.service.js +67 -0
- package/template/js/src/modules/auth/package.json +6 -0
- package/template/js/src/modules/health/controller.js +104 -3
- package/template/js/src/modules/swagger/charcole-swagger-1.0.0.tgz +0 -0
- package/template/js/src/modules/swagger/package.json +5 -0
- package/template/js/src/repositories/user.repo.js +19 -0
- package/template/js/src/routes/index.js +25 -0
- package/template/js/src/routes/protected.js +57 -0
- package/template/ts/.env.example +8 -0
- package/template/ts/README.md +128 -5
- package/template/ts/basePackage.json +19 -15
- package/template/ts/build.js +46 -0
- package/template/ts/src/app.ts +12 -7
- package/template/ts/src/config/swagger.config.ts +30 -0
- package/template/ts/src/lib/swagger/SWAGGER_GUIDE.md +561 -0
- package/template/ts/src/middlewares/errorHandler.ts +15 -23
- package/template/ts/src/middlewares/requestLogger.ts +1 -1
- package/template/ts/src/middlewares/validateRequest.ts +1 -1
- package/template/ts/src/modules/auth/auth.constants.ts +6 -0
- package/template/ts/src/modules/auth/auth.controller.ts +32 -0
- package/template/ts/src/modules/auth/auth.middlewares.ts +46 -0
- package/template/ts/src/modules/auth/auth.routes.ts +52 -0
- package/template/ts/src/modules/auth/auth.schemas.ts +73 -0
- package/template/ts/src/modules/auth/auth.service.ts +106 -0
- package/template/ts/src/modules/auth/package.json +10 -0
- package/template/ts/src/modules/health/controller.ts +61 -45
- package/template/ts/src/modules/swagger/charcole-swagger-1.0.0.tgz +0 -0
- package/template/ts/src/modules/swagger/package.json +5 -0
- package/template/ts/src/repositories/user.repo.ts +33 -0
- package/template/ts/src/routes/index.ts +24 -0
- package/template/ts/src/routes/protected.ts +46 -0
- package/template/ts/src/server.ts +3 -4
- package/template/ts/src/utils/logger.ts +1 -1
- package/template/ts/tsconfig.json +14 -7
- package/tmpclaude-1049-cwd +1 -0
- package/tmpclaude-3e37-cwd +1 -0
- package/tmpclaude-4d73-cwd +1 -0
- package/tmpclaude-8a8e-cwd +1 -0
- package/template/js/ARCHITECTURE_DIAGRAMS.md +0 -283
- package/template/js/CHECKLIST.md +0 -279
- package/template/js/COMPLETE.md +0 -405
- package/template/js/ERROR_HANDLING.md +0 -393
- package/template/js/IMPLEMENTATION.md +0 -368
- package/template/js/IMPLEMENTATION_COMPLETE.md +0 -363
- package/template/js/INDEX.md +0 -290
- package/template/js/QUICK_REFERENCE.md +0 -270
- package/template/js/package.json +0 -28
- package/template/js/src/routes.js +0 -17
- package/template/js/test-api.js +0 -100
- package/template/ts/ARCHITECTURE_DIAGRAMS.md +0 -283
- package/template/ts/CHECKLIST.md +0 -279
- package/template/ts/COMPLETE.md +0 -405
- package/template/ts/ERROR_HANDLING.md +0 -393
- package/template/ts/IMPLEMENTATION.md +0 -368
- package/template/ts/IMPLEMENTATION_COMPLETE.md +0 -363
- package/template/ts/INDEX.md +0 -290
- package/template/ts/QUICK_REFERENCE.md +0 -270
- package/template/ts/package.json +0 -32
- package/template/ts/src/app.js +0 -75
- package/template/ts/src/config/constants.js +0 -20
- package/template/ts/src/config/env.js +0 -26
- package/template/ts/src/middlewares/errorHandler.js +0 -180
- package/template/ts/src/middlewares/requestLogger.js +0 -33
- package/template/ts/src/middlewares/validateRequest.js +0 -42
- package/template/ts/src/modules/health/controller.js +0 -50
- package/template/ts/src/routes.js +0 -17
- package/template/ts/src/routes.ts +0 -16
- package/template/ts/src/server.js +0 -38
- package/template/ts/src/utils/AppError.js +0 -182
- package/template/ts/src/utils/logger.js +0 -73
- package/template/ts/src/utils/response.js +0 -51
- package/template/ts/test-api.js +0 -100
package/README.md
CHANGED
|
@@ -1,408 +1,354 @@
|
|
|
1
|
-
# Charcole API
|
|
1
|
+
# Charcole API v2.2
|
|
2
2
|
|
|
3
|
-
> **Charcole is a production-grade Node.js backend starter CLI that scaffolds enterprise-ready Express APIs with first-class TypeScript or JavaScript support, centralized error handling, Zod validation,
|
|
3
|
+
> **Charcole v2.2 is a production-grade Node.js backend starter CLI that scaffolds enterprise-ready Express APIs with first-class TypeScript or JavaScript support, centralized error handling, Zod validation, structured logging, optional JWT authentication, **auto-generated Swagger documentation**, and a revolutionary repository pattern for database abstraction.**
|
|
4
4
|
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
[](https://expressjs.com/)
|
|
7
7
|
[](https://zod.dev/)
|
|
8
|
+
[](https://www.typescriptlang.org/)
|
|
8
9
|
[](LICENSE)
|
|
9
10
|
|
|
10
|
-
##
|
|
11
|
+
## What's New in v2.2
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
### 🎯 Auto-Generated Swagger Documentation (@charcoles/swagger)
|
|
13
14
|
|
|
14
|
-
-
|
|
15
|
-
- ✅ **Centralized Error Handling** - Every error flows through one place
|
|
16
|
-
- ✅ **Error Classification** - Operational vs Programmer errors distinguished
|
|
17
|
-
- ✅ **Zod Validation** - Type-safe schema validation with automatic error formatting
|
|
18
|
-
- ✅ **Structured Logging** - Color-coded logs with context and stack traces
|
|
19
|
-
- ✅ **Consistent JSON Responses** - Standardized format across all endpoints
|
|
20
|
-
- ✅ **Production-Safe** - Internal details hidden from clients in production
|
|
21
|
-
- ✅ **Async Error Handling** - Promise rejection leaks prevented with asyncHandler
|
|
22
|
-
- ✅ **Graceful Shutdown** - Proper cleanup on SIGTERM/SIGINT
|
|
23
|
-
- ✅ **Request Logging** - Method, path, status, duration, IP automatically tracked
|
|
24
|
-
- ✅ **Unhandled Exception Catching** - All edge cases caught and logged
|
|
15
|
+
The game-changing feature that eliminates 60-80% of API documentation overhead:
|
|
25
16
|
|
|
26
|
-
|
|
17
|
+
- **Zero schema duplication** - Define Zod schemas once, auto-generate OpenAPI specs
|
|
18
|
+
- **Effortless documentation** - Minimal JSDoc comments with `$ref` to Zod schemas
|
|
19
|
+
- **Built-in response templates** - Common responses (Success, ValidationError, Unauthorized, NotFound) included
|
|
20
|
+
- **Always in sync** - Impossible for docs to drift from validation schemas
|
|
21
|
+
- **Optional module** - Include/exclude during project creation
|
|
22
|
+
- **Framework agnostic** - Works with any Express.js project via `npm install @charcoles/swagger`
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
**Before (76 lines of manual duplication):**
|
|
29
25
|
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
# Start development server (with auto-reload)
|
|
38
|
-
npm run dev
|
|
39
|
-
|
|
40
|
-
# OR start production server
|
|
41
|
-
npm start
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Server runs on `http://localhost:3000` by default.
|
|
45
|
-
|
|
46
|
-
## 📋 Key Features
|
|
47
|
-
|
|
48
|
-
### 🛡️ Enterprise-Grade Error Handling
|
|
49
|
-
|
|
50
|
-
**No More `res.status(500).json(...)`**
|
|
51
|
-
|
|
52
|
-
Every error in your application flows through a centralized global error handler that:
|
|
53
|
-
|
|
54
|
-
1. **Normalizes** all error types (ZodError, TypeError, custom AppError, etc.)
|
|
55
|
-
2. **Classifies** errors as operational (expected) or programmer (bugs)
|
|
56
|
-
3. **Logs** appropriately (WARN for operational, ERROR with stack for programmer)
|
|
57
|
-
4. **Sanitizes** responses (hides details in production, shows context in dev)
|
|
58
|
-
|
|
59
|
-
```javascript
|
|
60
|
-
// ✅ Throw AppError - ALWAYS
|
|
61
|
-
throw new NotFoundError("User", { id: userId });
|
|
62
|
-
throw new ValidationError("Invalid input", errors);
|
|
63
|
-
throw new ConflictError("Email already exists");
|
|
26
|
+
```typescript
|
|
27
|
+
// Zod schema for validation
|
|
28
|
+
const registerSchema = z.object({
|
|
29
|
+
email: z.string().email(),
|
|
30
|
+
password: z.string().min(8),
|
|
31
|
+
});
|
|
64
32
|
|
|
65
|
-
//
|
|
66
|
-
|
|
33
|
+
// Manual OpenAPI schema (duplicate!)
|
|
34
|
+
/**
|
|
35
|
+
* @swagger
|
|
36
|
+
* /api/auth/register:
|
|
37
|
+
* post:
|
|
38
|
+
* requestBody:
|
|
39
|
+
* schema:
|
|
40
|
+
* type: object
|
|
41
|
+
* properties:
|
|
42
|
+
* email:
|
|
43
|
+
* type: string
|
|
44
|
+
* format: email
|
|
45
|
+
* password:
|
|
46
|
+
* type: string
|
|
47
|
+
* minLength: 8
|
|
48
|
+
* ... 60 more lines
|
|
49
|
+
*/
|
|
67
50
|
```
|
|
68
51
|
|
|
69
|
-
|
|
52
|
+
**After with @charcoles/swagger (20 lines, zero duplication):**
|
|
70
53
|
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const createUserSchema = z.object({
|
|
76
|
-
body: z.object({
|
|
77
|
-
email: z.string().email(),
|
|
78
|
-
name: z.string().min(1),
|
|
79
|
-
}),
|
|
54
|
+
```typescript
|
|
55
|
+
// 1. Register schema once in swagger.config.ts
|
|
56
|
+
setupSwagger(app, {
|
|
57
|
+
schemas: { registerSchema }, // Auto-converted!
|
|
80
58
|
});
|
|
81
59
|
|
|
82
|
-
|
|
60
|
+
// 2. Reference in JSDoc
|
|
61
|
+
/**
|
|
62
|
+
* @swagger
|
|
63
|
+
* /api/auth/register:
|
|
64
|
+
* post:
|
|
65
|
+
* summary: Register user
|
|
66
|
+
* requestBody:
|
|
67
|
+
* content:
|
|
68
|
+
* application/json:
|
|
69
|
+
* schema:
|
|
70
|
+
* $ref: '#/components/schemas/registerSchema'
|
|
71
|
+
* responses:
|
|
72
|
+
* 201:
|
|
73
|
+
* $ref: '#/components/responses/Success'
|
|
74
|
+
* 400:
|
|
75
|
+
* $ref: '#/components/responses/ValidationError'
|
|
76
|
+
*/
|
|
83
77
|
```
|
|
84
78
|
|
|
85
|
-
|
|
79
|
+
**Result:** Change your Zod schema → Swagger updates automatically! 🎉
|
|
86
80
|
|
|
87
|
-
|
|
88
|
-
import { logger } from "./utils/logger.js";
|
|
81
|
+
### Previous Features (v2.1)
|
|
89
82
|
|
|
90
|
-
|
|
91
|
-
logger.info("Info message", { data: true });
|
|
92
|
-
logger.warn("Warning message", { data: true });
|
|
93
|
-
logger.error("Error message", { data: true });
|
|
94
|
-
```
|
|
83
|
+
#### Revolutionary Repository Pattern
|
|
95
84
|
|
|
96
|
-
|
|
85
|
+
- **Database abstraction layer** - Switch databases without changing business logic
|
|
86
|
+
- **In-memory repository included** - Test APIs instantly without database setup
|
|
87
|
+
- **Clean separation** - Business logic stays independent of database implementation
|
|
88
|
+
- **Future-proof** - Easy migration between MongoDB, PostgreSQL, MySQL, etc.
|
|
97
89
|
|
|
98
|
-
|
|
90
|
+
#### Optional JWT Authentication Module
|
|
99
91
|
|
|
100
|
-
**
|
|
92
|
+
- **Complete auth system** - Register, login, logout, protected routes
|
|
93
|
+
- **JWT-based authentication** - Stateless, scalable token management
|
|
94
|
+
- **Password hashing** - Secure bcrypt password handling
|
|
95
|
+
- **Ready-to-use** - Production-ready auth APIs out of the box
|
|
96
|
+
- **Modular design** - Include/exclude during project creation
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"timestamp": "2024-01-20T12:00:00.000Z"
|
|
108
|
-
}
|
|
109
|
-
```
|
|
98
|
+
## Quick Start
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Create your charcole app now (with or without project name)
|
|
102
|
+
npx create-charcole@latest my-awesome-api
|
|
110
103
|
|
|
111
|
-
|
|
104
|
+
# OR (interactive mode)
|
|
105
|
+
npx create-charcole@latest
|
|
112
106
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
"code": "NOT_FOUND",
|
|
118
|
-
"statusCode": 404,
|
|
119
|
-
"context": { "id": "999" },
|
|
120
|
-
"timestamp": "2024-01-20T12:00:00.000Z"
|
|
121
|
-
}
|
|
122
|
-
```
|
|
107
|
+
# Follow prompts to select:
|
|
108
|
+
# 1. Language: TypeScript or JavaScript
|
|
109
|
+
# 2. JWT Authentication: Yes/No (includes complete auth system)
|
|
110
|
+
# 3. Swagger Documentation: Yes/No (auto-generated from Zod schemas)
|
|
123
111
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
```json
|
|
127
|
-
{
|
|
128
|
-
"success": false,
|
|
129
|
-
"message": "Validation failed",
|
|
130
|
-
"code": "VALIDATION_ERROR",
|
|
131
|
-
"statusCode": 422,
|
|
132
|
-
"errors": [
|
|
133
|
-
{ "field": "email", "message": "Invalid email", "code": "invalid_email" }
|
|
134
|
-
],
|
|
135
|
-
"timestamp": "2024-01-20T12:00:00.000Z"
|
|
136
|
-
}
|
|
137
|
-
```
|
|
112
|
+
# Configure environment
|
|
113
|
+
cp .env.example .env
|
|
138
114
|
|
|
139
|
-
|
|
115
|
+
# Start development server (with auto-reload)
|
|
116
|
+
npm run dev
|
|
140
117
|
|
|
141
|
-
|
|
118
|
+
# Visit Swagger UI (if swagger enabled)
|
|
119
|
+
# http://localhost:3000/api-docs
|
|
142
120
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
AppError, // Base class
|
|
146
|
-
ValidationError, // 422 - Input validation failed
|
|
147
|
-
BadRequestError, // 400 - Malformed request
|
|
148
|
-
AuthenticationError, // 401 - Invalid credentials
|
|
149
|
-
AuthorizationError, // 403 - Permission denied
|
|
150
|
-
NotFoundError, // 404 - Resource not found
|
|
151
|
-
ConflictError, // 409 - Duplicate/conflict
|
|
152
|
-
InternalServerError, // 500 - Unexpected error
|
|
153
|
-
} from "./middlewares/errorHandler.js";
|
|
121
|
+
# OR start production server
|
|
122
|
+
npm start
|
|
154
123
|
```
|
|
155
124
|
|
|
156
|
-
|
|
125
|
+
Server runs on http://localhost:3000 by default.
|
|
157
126
|
|
|
158
|
-
|
|
159
|
-
| ------------------------------------------------- | --------------------------------- |
|
|
160
|
-
| [Getting Started](template/README.md) | Setup & directory structure guide |
|
|
161
|
-
| [Quick Reference](QUICK_REFERENCE.md) | Quick patterns & golden rules |
|
|
162
|
-
| [Error Handling Guide](ERROR_HANDLING.md) | Comprehensive error documentation |
|
|
163
|
-
| [Architecture Diagrams](ARCHITECTURE_DIAGRAMS.md) | Visual system architecture |
|
|
164
|
-
| [Full Implementation](IMPLEMENTATION_COMPLETE.md) | Complete implementation details |
|
|
127
|
+
## Swagger Documentation (New in v2.2)
|
|
165
128
|
|
|
166
|
-
|
|
129
|
+
### The Problem
|
|
167
130
|
|
|
168
|
-
|
|
131
|
+
Traditional API documentation requires writing the same schema twice:
|
|
169
132
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
```
|
|
133
|
+
1. Once in Zod for validation
|
|
134
|
+
2. Again in OpenAPI/Swagger YAML
|
|
173
135
|
|
|
174
|
-
|
|
136
|
+
This leads to:
|
|
175
137
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
138
|
+
- ❌ Massive duplication (76+ lines per endpoint)
|
|
139
|
+
- ❌ Out-of-sync documentation
|
|
140
|
+
- ❌ High maintenance burden
|
|
179
141
|
|
|
180
|
-
|
|
142
|
+
### The Solution
|
|
181
143
|
|
|
182
|
-
|
|
183
|
-
router.post("/users", validateRequest(schema), handler);
|
|
184
|
-
```
|
|
144
|
+
@charcoles/swagger automatically converts your Zod schemas to OpenAPI:
|
|
185
145
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
```
|
|
146
|
+
```typescript
|
|
147
|
+
// Before: Register schema in swagger.config.ts
|
|
148
|
+
import { registerSchema, loginSchema } from "./schemas";
|
|
190
149
|
|
|
191
|
-
|
|
150
|
+
setupSwagger(app, {
|
|
151
|
+
schemas: {
|
|
152
|
+
registerSchema, // Auto-converted to OpenAPI!
|
|
153
|
+
loginSchema,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
192
156
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
│ ├── errorHandler.js # ⭐ Global error handler + asyncHandler
|
|
200
|
-
│ ├── validateRequest.js # Request validation middleware
|
|
201
|
-
│ └── requestLogger.js # Request logging
|
|
202
|
-
├── modules/
|
|
203
|
-
│ └── health/
|
|
204
|
-
│ └── controller.js # Example handlers
|
|
205
|
-
├── utils/
|
|
206
|
-
│ ├── AppError.js # ⭐ Error class hierarchy
|
|
207
|
-
│ ├── logger.js # Structured logging
|
|
208
|
-
│ └── response.js # Success response helpers
|
|
209
|
-
├── app.js # Express app setup
|
|
210
|
-
├── routes.js # API routes
|
|
211
|
-
└── server.js # Server entry point
|
|
157
|
+
// After: Use $ref everywhere
|
|
158
|
+
/**
|
|
159
|
+
* @swagger
|
|
160
|
+
* schema:
|
|
161
|
+
* $ref: '#/components/schemas/registerSchema'
|
|
162
|
+
*/
|
|
212
163
|
```
|
|
213
164
|
|
|
214
|
-
|
|
165
|
+
### Benefits
|
|
215
166
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
167
|
+
| Aspect | Before | After | Improvement |
|
|
168
|
+
| ---------------------- | --------------- | -------------- | ------------------ |
|
|
169
|
+
| **Lines per endpoint** | 45-76 lines | 10-20 lines | **60-75% less** |
|
|
170
|
+
| **Schema duplication** | 100% | 0% | **Eliminated** |
|
|
171
|
+
| **Maintenance** | Update 2 places | Update 1 place | **50% less work** |
|
|
172
|
+
| **Sync issues** | Common | Impossible | **Always in sync** |
|
|
219
173
|
|
|
220
|
-
|
|
221
|
-
npm start
|
|
174
|
+
**See complete guide:** `src/lib/swagger/SWAGGER_GUIDE.md` (when swagger is enabled)
|
|
222
175
|
|
|
223
|
-
|
|
224
|
-
node test-api.js
|
|
225
|
-
```
|
|
176
|
+
## Repository Pattern: A Game Changer
|
|
226
177
|
|
|
227
|
-
|
|
178
|
+
### The Problem
|
|
228
179
|
|
|
229
|
-
|
|
180
|
+
Traditional apps mix database logic with business logic. Switching databases means rewriting everything.
|
|
230
181
|
|
|
231
|
-
|
|
232
|
-
NODE_ENV=development # development, production, test
|
|
233
|
-
PORT=3000 # Server port
|
|
234
|
-
LOG_LEVEL=info # debug, info, warn, error
|
|
235
|
-
CORS_ORIGIN=* # CORS allowed origins
|
|
236
|
-
REQUEST_TIMEOUT=30000 # Request timeout in milliseconds
|
|
237
|
-
```
|
|
182
|
+
### The Solution
|
|
238
183
|
|
|
239
|
-
|
|
184
|
+
Charcole introduces a Repository Pattern that abstracts database operations:
|
|
240
185
|
|
|
241
186
|
```javascript
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
import
|
|
245
|
-
import { z } from "zod";
|
|
246
|
-
|
|
247
|
-
// 1. Define validation schema
|
|
248
|
-
const createUserSchema = z.object({
|
|
249
|
-
body: z.object({
|
|
250
|
-
email: z.string().email("Invalid email"),
|
|
251
|
-
name: z.string().min(1, "Name required").max(100),
|
|
252
|
-
}),
|
|
253
|
-
});
|
|
187
|
+
// Traditional approach (tightly coupled)
|
|
188
|
+
// app.ts
|
|
189
|
+
import mongoose from 'mongoose';
|
|
254
190
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
191
|
+
async function getUser(id: string) {
|
|
192
|
+
return await UserModel.findById(id); // ❌ Direct MongoDB dependency
|
|
193
|
+
}
|
|
258
194
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
195
|
+
// Charcole v2.2 approach (abstracted)
|
|
196
|
+
// repositories/user.repo.ts
|
|
197
|
+
const users: User[] = [];
|
|
198
|
+
|
|
199
|
+
type CreateUserData = {
|
|
200
|
+
email: string;
|
|
201
|
+
name: string;
|
|
202
|
+
passwordHash: string;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export const userRepo = {
|
|
206
|
+
async findByEmail(email: string): Promise<User | undefined> {
|
|
207
|
+
return users.find((u) => u.email === email);
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
async create(data: CreateUserData): Promise<User> {
|
|
211
|
+
const user: User = {
|
|
212
|
+
id: randomUUID(),
|
|
213
|
+
email: data.email,
|
|
214
|
+
name: data.name,
|
|
215
|
+
passwordHash: data.passwordHash,
|
|
216
|
+
role: "user",
|
|
217
|
+
provider: "credentials",
|
|
218
|
+
isEmailVerified: false,
|
|
219
|
+
createdAt: new Date(),
|
|
220
|
+
updatedAt: new Date(),
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
users.push(user);
|
|
224
|
+
return user;
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// controller.js
|
|
229
|
+
async login(req, res) {
|
|
230
|
+
try {
|
|
231
|
+
const result = await AuthService.login(req.body, req.app.locals.userRepo);
|
|
232
|
+
|
|
233
|
+
res.json(result);
|
|
234
|
+
} catch (err) {
|
|
235
|
+
res.status(401).json({ message: err.message });
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
```
|
|
264
239
|
|
|
265
|
-
|
|
266
|
-
const user = await User.create({ email, name });
|
|
240
|
+
### Benefits
|
|
267
241
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
242
|
+
- ✅ Test instantly - In-memory repository works without database setup
|
|
243
|
+
- ✅ Switch databases easily - Change MongoDB to PostgreSQL by updating one file
|
|
244
|
+
- ✅ Clean architecture - Business logic stays pure
|
|
245
|
+
- ✅ Better testing - Mock repositories for unit tests
|
|
246
|
+
- ✅ Future-proof - Adapt to any database technology
|
|
271
247
|
|
|
272
|
-
|
|
273
|
-
router.post("/users", validateRequest(createUserSchema), createUser);
|
|
274
|
-
```
|
|
248
|
+
## JWT Authentication Module (Optional)
|
|
275
249
|
|
|
276
|
-
|
|
250
|
+
### What's Included
|
|
277
251
|
|
|
278
|
-
|
|
279
|
-
- ✅ Invalid email → 422 with field errors
|
|
280
|
-
- ✅ Duplicate email → 409 conflict
|
|
281
|
-
- ✅ Database error → 500 (logged, generic message sent in prod)
|
|
252
|
+
When you select "Yes" for authentication during project creation:
|
|
282
253
|
|
|
283
|
-
|
|
254
|
+
```
|
|
255
|
+
src/modules/auth/
|
|
256
|
+
│ ├── auth.controller.ts # Register, login, logout, me endpoints
|
|
257
|
+
│ ├── auth.middleware.ts # JWT verification, protected routes
|
|
258
|
+
│ ├── auth.service.ts # Business logic for authentication
|
|
259
|
+
│ ├── auth.routes.ts # Auth API routes
|
|
260
|
+
│ ├── auth.schemas.ts # Auth API Schemas (auto-documented if Swagger enabled!)
|
|
261
|
+
│ └── auth.constants.ts # Auth API constants
|
|
262
|
+
```
|
|
284
263
|
|
|
285
|
-
|
|
264
|
+
### Available Endpoints
|
|
286
265
|
|
|
287
266
|
```
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
267
|
+
POST /api/auth/register # Create new account
|
|
268
|
+
POST /api/auth/login # Get JWT token
|
|
269
|
+
GET /api/protected/me # Get current user (protected)
|
|
291
270
|
```
|
|
292
271
|
|
|
293
|
-
##
|
|
272
|
+
## Golden Rules (Updated for v2.2)
|
|
294
273
|
|
|
295
|
-
|
|
274
|
+
1. **Wrap async handlers with asyncHandler**
|
|
296
275
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
- ✅ **Logs with full context** - Debugging is easy
|
|
301
|
-
- ✅ **Validates everything** - Zod integration prevents bad data
|
|
302
|
-
- ✅ **Consistent responses** - Predictable format for every endpoint
|
|
303
|
-
- ✅ **Production-ready** - Graceful shutdown, signal handling, etc.
|
|
276
|
+
```typescript
|
|
277
|
+
router.get("/users/:id", asyncHandler(async (req, res) => { ... }))
|
|
278
|
+
```
|
|
304
279
|
|
|
305
|
-
|
|
280
|
+
2. **Throw AppError (never use res.status().json())**
|
|
306
281
|
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
Handler (wrapped with asyncHandler)
|
|
311
|
-
├─ Success → sendSuccess() → Response sent ✓
|
|
312
|
-
└─ Error thrown ✘
|
|
313
|
-
↓
|
|
314
|
-
Global error handler catches it
|
|
315
|
-
↓
|
|
316
|
-
Error normalized & classified
|
|
317
|
-
↓
|
|
318
|
-
Logged (WARN for operational, ERROR with stack for programmer)
|
|
319
|
-
↓
|
|
320
|
-
Consistent JSON response sent
|
|
321
|
-
```
|
|
282
|
+
```typescript
|
|
283
|
+
throw new NotFoundError("User", { id });
|
|
284
|
+
```
|
|
322
285
|
|
|
323
|
-
|
|
286
|
+
3. **Validate requests with validateRequest**
|
|
324
287
|
|
|
325
|
-
|
|
288
|
+
```typescript
|
|
289
|
+
router.post("/users", validateRequest(schema), handler);
|
|
290
|
+
```
|
|
326
291
|
|
|
327
|
-
|
|
328
|
-
[2024-01-20T12:00:00.000Z] WARN: Operational Error: NOT_FOUND
|
|
329
|
-
{ "code": "NOT_FOUND", "message": "User not found", "statusCode": 404 }
|
|
330
|
-
```
|
|
292
|
+
4. **Use repositories for database operations**
|
|
331
293
|
|
|
332
|
-
|
|
294
|
+
```typescript
|
|
295
|
+
// ❌ Direct database calls
|
|
296
|
+
const user = await UserModel.findById(id);
|
|
333
297
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
ReferenceError: user is not defined
|
|
338
|
-
at handler.js:15:3
|
|
339
|
-
...
|
|
340
|
-
```
|
|
298
|
+
// ✅ Repository pattern
|
|
299
|
+
const user = await AuthService.login(req.body, req.app.locals.userRepo);
|
|
300
|
+
```
|
|
341
301
|
|
|
342
|
-
|
|
302
|
+
5. **Define schemas once in Zod (if Swagger enabled)**
|
|
343
303
|
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
|
|
304
|
+
```typescript
|
|
305
|
+
// ✅ Single source of truth
|
|
306
|
+
const userSchema = z.object({ ... });
|
|
347
307
|
|
|
348
|
-
|
|
349
|
-
|
|
308
|
+
// Register in swagger.config.ts
|
|
309
|
+
setupSwagger(app, { schemas: { userSchema } });
|
|
350
310
|
|
|
351
|
-
|
|
352
|
-
|
|
311
|
+
// ❌ Never duplicate in JSDoc
|
|
312
|
+
```
|
|
353
313
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
314
|
+
## Why Choose Charcole v2.2?
|
|
315
|
+
|
|
316
|
+
### For Startups
|
|
357
317
|
|
|
358
|
-
|
|
318
|
+
- **Launch faster** - Production-ready API with auto-generated docs in minutes
|
|
319
|
+
- **Test without DB** - In-memory repository for rapid prototyping
|
|
320
|
+
- **Built-in auth** - User management out of the box
|
|
321
|
+
- **Clean code** - Follows best practices from day one
|
|
322
|
+
- **Free documentation** - Swagger UI generated automatically
|
|
359
323
|
|
|
360
|
-
|
|
361
|
-
- **Zod** - Schema validation
|
|
362
|
-
- **CORS** - Cross-origin requests
|
|
363
|
-
- **dotenv** - Environment variables
|
|
364
|
-
- **nodemon** - Auto-reload (dev only)
|
|
324
|
+
### For Enterprises
|
|
365
325
|
|
|
366
|
-
|
|
326
|
+
- **Maintainable** - Repository pattern enables easy database migrations
|
|
327
|
+
- **Scalable** - Modular architecture grows with your needs
|
|
328
|
+
- **Reliable** - Battle-tested error handling
|
|
329
|
+
- **Type-safe** - Full TypeScript support reduces bugs
|
|
330
|
+
- **Always in sync** - Documentation can't get outdated
|
|
367
331
|
|
|
368
|
-
|
|
332
|
+
### For Developers
|
|
369
333
|
|
|
370
|
-
-
|
|
371
|
-
-
|
|
372
|
-
-
|
|
373
|
-
-
|
|
374
|
-
-
|
|
375
|
-
- [ ] Add rate limiting
|
|
376
|
-
- [ ] Set up error monitoring (e.g., Sentry)
|
|
377
|
-
- [ ] Configure reverse proxy (nginx/apache)
|
|
378
|
-
- [ ] Test all error scenarios
|
|
379
|
-
- [ ] Verify no secrets in error responses
|
|
334
|
+
- **Learn best practices** - Production patterns built-in
|
|
335
|
+
- **Effortless docs** - 60-80% less documentation work
|
|
336
|
+
- **Easy to extend** - Add modules, databases, features
|
|
337
|
+
- **Great DX** - Excellent error messages and logging
|
|
338
|
+
- **Future-proof** - Designed for long-term maintenance
|
|
380
339
|
|
|
381
340
|
## 🤝 Contributing
|
|
382
341
|
|
|
383
|
-
|
|
342
|
+
We welcome contributions! Please:
|
|
384
343
|
|
|
385
|
-
1.
|
|
386
|
-
2.
|
|
387
|
-
3.
|
|
388
|
-
4. Include
|
|
389
|
-
5.
|
|
344
|
+
1. Fork the repository, create new branch and raise a pull request. If it fits with the goals of **charcole** we'll merge it
|
|
345
|
+
2. Follow the repository pattern for database operations
|
|
346
|
+
3. Use TypeScript for new features
|
|
347
|
+
4. Include tests with in-memory repositories
|
|
348
|
+
5. Document new modules thoroughly
|
|
349
|
+
6. Update README.md for significant changes
|
|
350
|
+
7. If adding Swagger docs, use Zod schemas as single source of truth
|
|
390
351
|
|
|
391
352
|
## 📄 License
|
|
392
353
|
|
|
393
354
|
ISC
|
|
394
|
-
|
|
395
|
-
---
|
|
396
|
-
|
|
397
|
-
**Made for teams that care about code quality and production reliability.** 🚀
|
|
398
|
-
|
|
399
|
-
Need help? See the [Getting Started Guide](template/README.md) or [Full Documentation](ERROR_HANDLING.md).
|
|
400
|
-
|
|
401
|
-
## 🆕 What’s New in v2.0
|
|
402
|
-
|
|
403
|
-
- 🚀 **First-class TypeScript & JavaScript support**
|
|
404
|
-
- 🧠 CLI-driven language selection
|
|
405
|
-
- 🧩 Modular template architecture (future feature expansion)
|
|
406
|
-
- 🧼 Cleaner project generation flow
|
|
407
|
-
- 📦 Improved dependency handling
|
|
408
|
-
- 🏗️ Foundation for built-in auth, Swagger, Docker modules
|