create-charcole
v2.2.0
Published
CLI to create production-ready Node.js Express APIs with TypeScript/JavaScript, JWT auth, auto-generated Swagger docs, and repository pattern
Maintainers
Readme
Charcole API v2.2
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.
What's New in v2.2
🎯 Auto-Generated Swagger Documentation (@charcoles/swagger)
The game-changing feature that eliminates 60-80% of API documentation overhead:
- Zero schema duplication - Define Zod schemas once, auto-generate OpenAPI specs
- Effortless documentation - Minimal JSDoc comments with
$refto Zod schemas - Built-in response templates - Common responses (Success, ValidationError, Unauthorized, NotFound) included
- Always in sync - Impossible for docs to drift from validation schemas
- Optional module - Include/exclude during project creation
- Framework agnostic - Works with any Express.js project via
npm install @charcoles/swagger
Before (76 lines of manual duplication):
// Zod schema for validation
const registerSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
// Manual OpenAPI schema (duplicate!)
/**
* @swagger
* /api/auth/register:
* post:
* requestBody:
* schema:
* type: object
* properties:
* email:
* type: string
* format: email
* password:
* type: string
* minLength: 8
* ... 60 more lines
*/After with @charcoles/swagger (20 lines, zero duplication):
// 1. Register schema once in swagger.config.ts
setupSwagger(app, {
schemas: { registerSchema }, // Auto-converted!
});
// 2. Reference in JSDoc
/**
* @swagger
* /api/auth/register:
* post:
* summary: Register user
* requestBody:
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/registerSchema'
* responses:
* 201:
* $ref: '#/components/responses/Success'
* 400:
* $ref: '#/components/responses/ValidationError'
*/Result: Change your Zod schema → Swagger updates automatically! 🎉
Previous Features (v2.1)
Revolutionary Repository Pattern
- Database abstraction layer - Switch databases without changing business logic
- In-memory repository included - Test APIs instantly without database setup
- Clean separation - Business logic stays independent of database implementation
- Future-proof - Easy migration between MongoDB, PostgreSQL, MySQL, etc.
Optional JWT Authentication Module
- Complete auth system - Register, login, logout, protected routes
- JWT-based authentication - Stateless, scalable token management
- Password hashing - Secure bcrypt password handling
- Ready-to-use - Production-ready auth APIs out of the box
- Modular design - Include/exclude during project creation
Quick Start
# Create your charcole app now (with or without project name)
npx create-charcole@latest my-awesome-api
# OR (interactive mode)
npx create-charcole@latest
# Follow prompts to select:
# 1. Language: TypeScript or JavaScript
# 2. JWT Authentication: Yes/No (includes complete auth system)
# 3. Swagger Documentation: Yes/No (auto-generated from Zod schemas)
# Configure environment
cp .env.example .env
# Start development server (with auto-reload)
npm run dev
# Visit Swagger UI (if swagger enabled)
# http://localhost:3000/api-docs
# OR start production server
npm startServer runs on http://localhost:3000 by default.
Swagger Documentation (New in v2.2)
The Problem
Traditional API documentation requires writing the same schema twice:
- Once in Zod for validation
- Again in OpenAPI/Swagger YAML
This leads to:
- ❌ Massive duplication (76+ lines per endpoint)
- ❌ Out-of-sync documentation
- ❌ High maintenance burden
The Solution
@charcoles/swagger automatically converts your Zod schemas to OpenAPI:
// Before: Register schema in swagger.config.ts
import { registerSchema, loginSchema } from "./schemas";
setupSwagger(app, {
schemas: {
registerSchema, // Auto-converted to OpenAPI!
loginSchema,
},
});
// After: Use $ref everywhere
/**
* @swagger
* schema:
* $ref: '#/components/schemas/registerSchema'
*/Benefits
| Aspect | Before | After | Improvement | | ---------------------- | --------------- | -------------- | ------------------ | | Lines per endpoint | 45-76 lines | 10-20 lines | 60-75% less | | Schema duplication | 100% | 0% | Eliminated | | Maintenance | Update 2 places | Update 1 place | 50% less work | | Sync issues | Common | Impossible | Always in sync |
See complete guide: src/lib/swagger/SWAGGER_GUIDE.md (when swagger is enabled)
Repository Pattern: A Game Changer
The Problem
Traditional apps mix database logic with business logic. Switching databases means rewriting everything.
The Solution
Charcole introduces a Repository Pattern that abstracts database operations:
// Traditional approach (tightly coupled)
// app.ts
import mongoose from 'mongoose';
async function getUser(id: string) {
return await UserModel.findById(id); // ❌ Direct MongoDB dependency
}
// Charcole v2.2 approach (abstracted)
// repositories/user.repo.ts
const users: User[] = [];
type CreateUserData = {
email: string;
name: string;
passwordHash: string;
};
export const userRepo = {
async findByEmail(email: string): Promise<User | undefined> {
return users.find((u) => u.email === email);
},
async create(data: CreateUserData): Promise<User> {
const user: User = {
id: randomUUID(),
email: data.email,
name: data.name,
passwordHash: data.passwordHash,
role: "user",
provider: "credentials",
isEmailVerified: false,
createdAt: new Date(),
updatedAt: new Date(),
};
users.push(user);
return user;
},
};
// controller.js
async login(req, res) {
try {
const result = await AuthService.login(req.body, req.app.locals.userRepo);
res.json(result);
} catch (err) {
res.status(401).json({ message: err.message });
}
},Benefits
- ✅ Test instantly - In-memory repository works without database setup
- ✅ Switch databases easily - Change MongoDB to PostgreSQL by updating one file
- ✅ Clean architecture - Business logic stays pure
- ✅ Better testing - Mock repositories for unit tests
- ✅ Future-proof - Adapt to any database technology
JWT Authentication Module (Optional)
What's Included
When you select "Yes" for authentication during project creation:
src/modules/auth/
│ ├── auth.controller.ts # Register, login, logout, me endpoints
│ ├── auth.middleware.ts # JWT verification, protected routes
│ ├── auth.service.ts # Business logic for authentication
│ ├── auth.routes.ts # Auth API routes
│ ├── auth.schemas.ts # Auth API Schemas (auto-documented if Swagger enabled!)
│ └── auth.constants.ts # Auth API constantsAvailable Endpoints
POST /api/auth/register # Create new account
POST /api/auth/login # Get JWT token
GET /api/protected/me # Get current user (protected)Golden Rules (Updated for v2.2)
Wrap async handlers with asyncHandler
router.get("/users/:id", asyncHandler(async (req, res) => { ... }))Throw AppError (never use res.status().json())
throw new NotFoundError("User", { id });Validate requests with validateRequest
router.post("/users", validateRequest(schema), handler);Use repositories for database operations
// ❌ Direct database calls const user = await UserModel.findById(id); // ✅ Repository pattern const user = await AuthService.login(req.body, req.app.locals.userRepo);Define schemas once in Zod (if Swagger enabled)
// ✅ Single source of truth const userSchema = z.object({ ... }); // Register in swagger.config.ts setupSwagger(app, { schemas: { userSchema } }); // ❌ Never duplicate in JSDoc
Why Choose Charcole v2.2?
For Startups
- Launch faster - Production-ready API with auto-generated docs in minutes
- Test without DB - In-memory repository for rapid prototyping
- Built-in auth - User management out of the box
- Clean code - Follows best practices from day one
- Free documentation - Swagger UI generated automatically
For Enterprises
- Maintainable - Repository pattern enables easy database migrations
- Scalable - Modular architecture grows with your needs
- Reliable - Battle-tested error handling
- Type-safe - Full TypeScript support reduces bugs
- Always in sync - Documentation can't get outdated
For Developers
- Learn best practices - Production patterns built-in
- Effortless docs - 60-80% less documentation work
- Easy to extend - Add modules, databases, features
- Great DX - Excellent error messages and logging
- Future-proof - Designed for long-term maintenance
🤝 Contributing
We welcome contributions! Please:
- Fork the repository, create new branch and raise a pull request. If it fits with the goals of charcole we'll merge it
- Follow the repository pattern for database operations
- Use TypeScript for new features
- Include tests with in-memory repositories
- Document new modules thoroughly
- Update README.md for significant changes
- If adding Swagger docs, use Zod schemas as single source of truth
📄 License
ISC
