create-charcole 2.0.4 β 2.1.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 +200 -14
- package/README.md +137 -332
- package/bin/index.js +236 -55
- package/bin/lib/pkgManager.js +8 -25
- package/bin/lib/templateHandler.js +5 -42
- package/package.json +2 -2
- package/plans/V2_1_PLAN.md +20 -0
- package/template/js/.env.example +8 -0
- package/template/js/basePackage.json +11 -13
- package/template/js/src/app.js +4 -1
- 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 +9 -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/repositories/user.repo.js +19 -0
- package/template/js/src/routes/index.js +25 -0
- package/template/js/src/routes/protected.js +13 -0
- package/template/ts/.env.example +8 -0
- package/template/ts/basePackage.json +19 -15
- package/template/ts/build.js +46 -0
- package/template/ts/src/app.ts +5 -4
- 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 +9 -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 +3 -3
- 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 +13 -0
- package/template/ts/src/server.ts +0 -1
- package/template/ts/src/utils/logger.ts +1 -1
- package/template/ts/tsconfig.json +14 -7
- 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,35 +1,49 @@
|
|
|
1
|
-
# Charcole API
|
|
1
|
+
# Charcole API v2.1
|
|
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.1 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, 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.1
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
### Revolutionary Repository Pattern
|
|
13
14
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
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
|
+
- **Database abstraction layer** - Switch databases without changing business logic
|
|
16
|
+
- **In-memory repository included** - Test APIs instantly without database setup
|
|
17
|
+
- **Clean separation** - Business logic stays independent of database implementation
|
|
18
|
+
- **Future-proof** - Easy migration between MongoDB, PostgreSQL, MySQL, etc.
|
|
25
19
|
|
|
26
|
-
|
|
20
|
+
### Optional JWT Authentication Module
|
|
27
21
|
|
|
28
|
-
|
|
22
|
+
- **Complete auth system** - Register, login, logout, protected routes
|
|
23
|
+
- **JWT-based authentication** - Stateless, scalable token management
|
|
24
|
+
- **Password hashing** - Secure bcrypt password handling
|
|
25
|
+
- **Ready-to-use** - Production-ready auth APIs out of the box
|
|
26
|
+
- **Modular design** - Include/exclude during project creation
|
|
27
|
+
|
|
28
|
+
### Bug Fixes & Improvements
|
|
29
|
+
|
|
30
|
+
- **Fixed TypeScript compilation** - Clean builds with proper type definitions
|
|
31
|
+
- **Enhanced error handling** - Better error messages and debugging
|
|
32
|
+
- **Improved CLI experience** - Smoother project creation flow
|
|
33
|
+
- **Better dependency management** - Cleaner package.json merging
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
29
36
|
|
|
30
37
|
```bash
|
|
31
|
-
# Create your charcole app now
|
|
32
|
-
npx create-charcole@latest
|
|
38
|
+
# Create your charcole app now (with or without project name)
|
|
39
|
+
npx create-charcole@latest my-awesome-api
|
|
40
|
+
|
|
41
|
+
# OR (interactive mode)
|
|
42
|
+
npx create-charcole@latest
|
|
43
|
+
|
|
44
|
+
# Follow prompts to select:
|
|
45
|
+
# 1. Language: TypeScript or JavaScript
|
|
46
|
+
# 2. JWT Authentication: Yes/No (includes complete auth system)
|
|
33
47
|
|
|
34
48
|
# Configure environment
|
|
35
49
|
cp .env.example .env
|
|
@@ -41,368 +55,159 @@ npm run dev
|
|
|
41
55
|
npm start
|
|
42
56
|
```
|
|
43
57
|
|
|
44
|
-
Server runs on
|
|
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:
|
|
58
|
+
Server runs on http://localhost:3000 by default.
|
|
53
59
|
|
|
54
|
-
|
|
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)
|
|
60
|
+
## Repository Pattern: A Game Changer
|
|
58
61
|
|
|
59
|
-
|
|
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");
|
|
62
|
+
### The Problem
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
res.status(404).json({ error: "Not found" });
|
|
67
|
-
```
|
|
64
|
+
Traditional apps mix database logic with business logic. Switching databases means rewriting everything.
|
|
68
65
|
|
|
69
|
-
###
|
|
66
|
+
### The Solution
|
|
70
67
|
|
|
71
|
-
|
|
72
|
-
import { z } from "zod";
|
|
73
|
-
import { validateRequest } from "./middlewares/validateRequest.js";
|
|
74
|
-
|
|
75
|
-
const createUserSchema = z.object({
|
|
76
|
-
body: z.object({
|
|
77
|
-
email: z.string().email(),
|
|
78
|
-
name: z.string().min(1),
|
|
79
|
-
}),
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
router.post("/users", validateRequest(createUserSchema), handler);
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### π Structured Logging
|
|
68
|
+
Charcole v2.1 introduces a Repository Pattern that abstracts database operations:
|
|
86
69
|
|
|
87
70
|
```javascript
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
logger.info("Info message", { data: true });
|
|
92
|
-
logger.warn("Warning message", { data: true });
|
|
93
|
-
logger.error("Error message", { data: true });
|
|
94
|
-
```
|
|
71
|
+
// Traditional approach (tightly coupled)
|
|
72
|
+
// app.ts
|
|
73
|
+
import mongoose from 'mongoose';
|
|
95
74
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
All responses follow the same format:
|
|
99
|
-
|
|
100
|
-
**Success:**
|
|
101
|
-
|
|
102
|
-
```json
|
|
103
|
-
{
|
|
104
|
-
"success": true,
|
|
105
|
-
"message": "User created successfully",
|
|
106
|
-
"data": { "id": "123", "name": "John" },
|
|
107
|
-
"timestamp": "2024-01-20T12:00:00.000Z"
|
|
75
|
+
async function getUser(id: string) {
|
|
76
|
+
Β Β return await UserModel.findById(id); // Direct MongoDB dependency
|
|
108
77
|
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
**Error:**
|
|
112
|
-
|
|
113
|
-
```json
|
|
114
|
-
{
|
|
115
|
-
"success": false,
|
|
116
|
-
"message": "User not found",
|
|
117
|
-
"code": "NOT_FOUND",
|
|
118
|
-
"statusCode": 404,
|
|
119
|
-
"context": { "id": "999" },
|
|
120
|
-
"timestamp": "2024-01-20T12:00:00.000Z"
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
**Validation Error:**
|
|
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
|
-
```
|
|
138
|
-
|
|
139
|
-
## ποΈ Error Classes
|
|
140
|
-
|
|
141
|
-
Use these specialized error classes:
|
|
142
|
-
|
|
143
|
-
```javascript
|
|
144
|
-
import {
|
|
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";
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
## π Documentation
|
|
157
78
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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 |
|
|
79
|
+
// Charcole v2.1 approach (abstracted)
|
|
80
|
+
// repositories/user.repo.ts
|
|
81
|
+
const users: User[] = [];
|
|
165
82
|
|
|
166
|
-
|
|
83
|
+
type CreateUserData = {
|
|
84
|
+
Β Β email: string;
|
|
85
|
+
Β Β name: string;
|
|
86
|
+
Β Β passwordHash: string;
|
|
87
|
+
};
|
|
167
88
|
|
|
168
|
-
|
|
89
|
+
export const userRepo = {
|
|
90
|
+
Β Β async findByEmail(email: string): Promise<User | undefined> {
|
|
91
|
+
Β Β Β Β return users.find((u) => u.email === email);
|
|
92
|
+
Β Β },
|
|
169
93
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
94
|
+
Β Β async create(data: CreateUserData): Promise<User> {
|
|
95
|
+
Β Β Β Β const user: User = {
|
|
96
|
+
Β Β Β Β Β Β id: randomUUID(),
|
|
97
|
+
Β Β Β Β Β Β email: data.email,
|
|
98
|
+
Β Β Β Β Β Β name: data.name,
|
|
99
|
+
Β Β Β Β Β Β passwordHash: data.passwordHash,
|
|
100
|
+
Β Β Β Β Β Β role: "user",
|
|
101
|
+
Β Β Β Β Β Β provider: "credentials",
|
|
102
|
+
Β Β Β Β Β Β isEmailVerified: false,
|
|
103
|
+
Β Β Β Β Β Β createdAt: new Date(),
|
|
104
|
+
Β Β Β Β Β Β updatedAt: new Date(),
|
|
105
|
+
Β Β Β Β };
|
|
173
106
|
|
|
174
|
-
|
|
107
|
+
Β Β Β Β users.push(user);
|
|
108
|
+
Β Β Β Β return user;
|
|
109
|
+
Β Β },
|
|
110
|
+
};
|
|
175
111
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
112
|
+
// controller.js
|
|
113
|
+
async login(req, res) {
|
|
114
|
+
Β Β Β Β try {
|
|
115
|
+
Β Β Β Β Β Β const result = await AuthService.login(req.body, req.app.locals.userRepo);
|
|
179
116
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
4. **Send success** with `sendSuccess`
|
|
187
|
-
```javascript
|
|
188
|
-
sendSuccess(res, data, 201, "User created");
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## π Project Structure
|
|
192
|
-
|
|
193
|
-
```
|
|
194
|
-
src/
|
|
195
|
-
βββ config/
|
|
196
|
-
β βββ env.js # Environment validation with Zod
|
|
197
|
-
β βββ constants.js # HTTP status codes & error messages
|
|
198
|
-
βββ middlewares/
|
|
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
|
|
117
|
+
Β Β Β Β Β Β res.json(result);
|
|
118
|
+
Β Β Β Β } catch (err) {
|
|
119
|
+
Β Β Β Β Β Β res.status(401).json({ message: err.message });
|
|
120
|
+
Β Β Β Β }
|
|
121
|
+
Β Β },
|
|
212
122
|
```
|
|
213
123
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
```bash
|
|
217
|
-
# Development (with auto-reload and full logging)
|
|
218
|
-
npm run dev
|
|
219
|
-
|
|
220
|
-
# Production (optimized, minimal logging)
|
|
221
|
-
npm start
|
|
124
|
+
### Benefits
|
|
222
125
|
|
|
223
|
-
|
|
224
|
-
node test-api.js
|
|
225
|
-
```
|
|
126
|
+
- Test instantly - In-memory repository works without database setup
|
|
226
127
|
|
|
227
|
-
|
|
128
|
+
- Switch databases easily - Change MongoDB to PostgreSQL by updating one file
|
|
228
129
|
|
|
229
|
-
|
|
130
|
+
- Clean architecture - Business logic stays pure
|
|
230
131
|
|
|
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
|
-
```
|
|
132
|
+
- Better testing - Mock repositories for unit tests
|
|
238
133
|
|
|
239
|
-
|
|
134
|
+
- Future-proof - Adapt to any database technology
|
|
240
135
|
|
|
241
|
-
|
|
242
|
-
import { asyncHandler, ConflictError } from "./middlewares/errorHandler.js";
|
|
243
|
-
import { validateRequest } from "./middlewares/validateRequest.js";
|
|
244
|
-
import { sendSuccess } from "./utils/response.js";
|
|
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
|
-
});
|
|
254
|
-
|
|
255
|
-
// 2. Define handler (wrapped with asyncHandler)
|
|
256
|
-
export const createUser = asyncHandler(async (req, res) => {
|
|
257
|
-
const { email, name } = req.validatedData.body;
|
|
258
|
-
|
|
259
|
-
// Check for duplicate
|
|
260
|
-
const exists = await User.findOne({ email });
|
|
261
|
-
if (exists) {
|
|
262
|
-
throw new ConflictError("Email already exists", { email });
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// Create user (any error is automatically caught)
|
|
266
|
-
const user = await User.create({ email, name });
|
|
267
|
-
|
|
268
|
-
// Send success
|
|
269
|
-
sendSuccess(res, user, 201, "User created successfully");
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
// 3. Use in routes
|
|
273
|
-
router.post("/users", validateRequest(createUserSchema), createUser);
|
|
274
|
-
```
|
|
136
|
+
## JWT Authentication Module (Optional)
|
|
275
137
|
|
|
276
|
-
|
|
138
|
+
### What's Included
|
|
277
139
|
|
|
278
|
-
|
|
279
|
-
- β
Invalid email β 422 with field errors
|
|
280
|
-
- β
Duplicate email β 409 conflict
|
|
281
|
-
- β
Database error β 500 (logged, generic message sent in prod)
|
|
140
|
+
When you select "Yes" for authentication during project creation:
|
|
282
141
|
|
|
283
|
-
|
|
142
|
+
src/modules/auth/
|
|
143
|
+
β βββ auth.controller.ts # Register, login, logout, me endpoints
|
|
144
|
+
β βββ auth.middleware.ts # JWT verification, protected routes
|
|
145
|
+
β βββ auth.service.ts # Business logic for authentication
|
|
146
|
+
| βββ auth.routes.ts # Auth API routes
|
|
147
|
+
| βββ auth.schemas.ts # Auth API Schemas
|
|
148
|
+
| βββ auth.constants.ts # Auth API constants
|
|
284
149
|
|
|
285
|
-
|
|
150
|
+
### Available Endpoints
|
|
286
151
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
GET
|
|
290
|
-
POST /api/items # Create item (example)
|
|
291
|
-
```
|
|
152
|
+
POST /api/auth/register # Create new account
|
|
153
|
+
POST /api/auth/login # Get JWT token
|
|
154
|
+
GET /api/protected/me # Get current user (protected)
|
|
292
155
|
|
|
293
|
-
##
|
|
156
|
+
## Golder Rules (Updated for v2.1)
|
|
294
157
|
|
|
295
|
-
|
|
158
|
+
1. Wrap async handlers with asyncHandler
|
|
159
|
+
Β Β Β `router.get("/users/:id", asyncHandler(async (req, res) => { ... }))`
|
|
160
|
+
2. Throw AppError (never use res.status().json())
|
|
161
|
+
Β Β Β `throw new NotFoundError("User", { id });`
|
|
162
|
+
3. Validate requests with validateRequest
|
|
163
|
+
Β Β Β `router.post("/users", validateRequest(schema), handler);`
|
|
164
|
+
4. Use repositories for database operations
|
|
296
165
|
|
|
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.
|
|
166
|
+
```typescript
|
|
167
|
+
// Direct database calls
|
|
168
|
+
const user = await UserModel.findById(id);
|
|
304
169
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
```
|
|
308
|
-
Request arrives
|
|
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
|
|
170
|
+
// Repository pattern
|
|
171
|
+
const user = await AuthService.login(req.body, req.app.locals.userRepo);
|
|
321
172
|
```
|
|
322
173
|
|
|
323
|
-
##
|
|
174
|
+
## Why Choose Charcole v2.1?
|
|
324
175
|
|
|
325
|
-
###
|
|
176
|
+
### For Startups
|
|
326
177
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
178
|
+
- Launch faster - Production-ready API in minutes
|
|
179
|
+
- Test without DB - In-memory repository for rapid prototyping
|
|
180
|
+
- Built-in auth - User management out of the box
|
|
181
|
+
- Clean code - Follows best practices from day one
|
|
331
182
|
|
|
332
|
-
###
|
|
183
|
+
### For Enterprises
|
|
333
184
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
at handler.js:15:3
|
|
339
|
-
...
|
|
340
|
-
```
|
|
185
|
+
- Maintainable - Repository pattern enables easy database migrations
|
|
186
|
+
- Scalable - Modular architecture grows with your needs
|
|
187
|
+
- Reliable - Battle-tested error handling
|
|
188
|
+
- Type-safe - Full TypeScript support reduces bugs
|
|
341
189
|
|
|
342
|
-
|
|
190
|
+
### For Developers
|
|
343
191
|
|
|
344
|
-
|
|
345
|
-
# Install dependencies
|
|
346
|
-
npm install
|
|
192
|
+
- Learn best practices - Production patterns built-in
|
|
347
193
|
|
|
348
|
-
|
|
349
|
-
npm run dev
|
|
350
|
-
|
|
351
|
-
# Check for syntax errors
|
|
352
|
-
npm run lint
|
|
353
|
-
|
|
354
|
-
# Run tests
|
|
355
|
-
npm test
|
|
356
|
-
```
|
|
194
|
+
- Easy to extend - Add modules, databases, features
|
|
357
195
|
|
|
358
|
-
|
|
196
|
+
- Great DX - Excellent error messages and logging
|
|
359
197
|
|
|
360
|
-
-
|
|
361
|
-
- **Zod** - Schema validation
|
|
362
|
-
- **CORS** - Cross-origin requests
|
|
363
|
-
- **dotenv** - Environment variables
|
|
364
|
-
- **nodemon** - Auto-reload (dev only)
|
|
365
|
-
|
|
366
|
-
## π’ Production Checklist
|
|
367
|
-
|
|
368
|
-
Before deploying:
|
|
369
|
-
|
|
370
|
-
- [ ] Set `NODE_ENV=production`
|
|
371
|
-
- [ ] Configure `CORS_ORIGIN` for your domain
|
|
372
|
-
- [ ] Set `LOG_LEVEL=warn` or higher
|
|
373
|
-
- [ ] Add database connection
|
|
374
|
-
- [ ] Implement authentication
|
|
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
|
|
198
|
+
- Future-proof - Designed for long-term maintenance
|
|
380
199
|
|
|
381
200
|
## π€ Contributing
|
|
382
201
|
|
|
383
|
-
|
|
202
|
+
We welcome contributions! Please:
|
|
384
203
|
|
|
385
|
-
1.
|
|
386
|
-
2.
|
|
387
|
-
3.
|
|
388
|
-
4. Include
|
|
389
|
-
5.
|
|
204
|
+
1. Fork the repository, create new branch and raise a pull request. If it fits with the goals of **charcole** we'll merge it
|
|
205
|
+
2. Follow the repository pattern for database operations
|
|
206
|
+
3. Use TypeScript for new features
|
|
207
|
+
4. Include tests with in-memory repositories
|
|
208
|
+
5. Document new modules thoroughly
|
|
209
|
+
6. Update README.md for significant changes
|
|
390
210
|
|
|
391
211
|
## π License
|
|
392
212
|
|
|
393
213
|
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
|