Skip to main content

Quick Start

Get started with Express Base API in 5 minutes! This guide will walk you through creating your first API resource.

Step 1: Create Your First Resource

Let's create a simple "Product" resource with full CRUD operations.

npm run g resource product

This single command generates:

✅ src/types/product.types.ts          # TypeScript interfaces
✅ src/models/product.model.ts # Mongoose model
✅ src/services/app/product.service.ts # Service layer
✅ src/controllers/app/product.controller.ts # Controller
✅ routes/app/product.route.ts # REST routes
✅ utils/validations/product.validation.ts # Joi validation
tip

The CLI generator creates production-ready code following all project conventions!

Step 2: Register the Route

Add your new route to routes.ts:

routes.ts
import { Middleware } from './configs/app.config';

const routes = [
// Existing routes...

{
path: '/product',
middlewares: [
Middleware.xApiKey, // Require API key
Middleware.isLogin, // Require authentication
],
},
];

export default routes;

Step 3: Customize the Model

Edit the generated model to add your fields:

src/models/product.model.ts
import { Model } from 'mongoose';
import { BaseSchema } from '../../../configs/app.config';
import { IProduct } from '../../types';

const productSchema = {
name: {
type: String,
required: true,
index: true,
},
description: {
type: String,
required: false,
},
price: {
type: Number,
required: true,
min: 0,
},
stock: {
type: Number,
required: true,
default: 0,
},
category: {
type: String,
required: true,
},
};

const Product: Model<IProduct> = BaseSchema<IProduct>(
'products',
productSchema
);

export default Product;

Step 4: Update TypeScript Types

Define your interfaces:

src/types/product.types.ts
import { BaseDocument } from './service.types';

export interface IProduct extends BaseDocument {
name: string;
description?: string;
price: number;
stock: number;
category: string;
}

Step 5: Add Custom Validation

Enhance the generated validation:

utils/validations/product.validation.ts
import { validation } from '../../configs/app.config';
import Joi from 'joi';

const productValidation = {
store: validation({
body: Joi.object({
name: Joi.string().min(3).max(100).required(),
description: Joi.string().max(500).optional(),
price: Joi.number().min(0).required(),
stock: Joi.number().integer().min(0).required(),
category: Joi.string().valid('Electronics', 'Clothing', 'Food', 'Other').required(),
}),
}),

update: validation({
body: Joi.object({
name: Joi.string().min(3).max(100).optional(),
description: Joi.string().max(500).optional(),
price: Joi.number().min(0).optional(),
stock: Joi.number().integer().min(0).optional(),
category: Joi.string().valid('Electronics', 'Clothing', 'Food', 'Other').optional(),
}),
params: Joi.object({
id: Joi.string().hex().length(24).required(),
}),
}),

destroy: validation({
params: Joi.object({
id: Joi.string().hex().length(24).required(),
}),
}),
};

export default productValidation;

Step 6: Test Your API

Start the server:

npm run dev

Create a Product

curl -X POST http://localhost:3000/product \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"name": "Laptop",
"description": "High-performance laptop",
"price": 999.99,
"stock": 10,
"category": "Electronics"
}'

Response:

{
"status_code": 201,
"status": "SUCCESS",
"message": "Product created successfully",
"data": {
"_id": "65abc123...",
"name": "Laptop",
"description": "High-performance laptop",
"price": 999.99,
"stock": 10,
"category": "Electronics",
"created_at": "2024-01-15T10:30:00.000Z",
"updated_at": "2024-01-15T10:30:00.000Z"
}
}

List All Products

curl -X GET http://localhost:3000/product \
-H "x-api-key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_TOKEN"

Get a Single Product

curl -X GET http://localhost:3000/product/65abc123... \
-H "x-api-key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_TOKEN"

Update a Product

curl -X PUT http://localhost:3000/product/65abc123... \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"price": 899.99,
"stock": 8
}'

Delete a Product

curl -X DELETE http://localhost:3000/product/65abc123... \
-H "x-api-key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_TOKEN"

Bonus: Add Custom Business Logic

Extend the service with custom methods:

src/services/app/product.service.ts
class ProductService extends BaseService<IProduct> {
// ... generated methods ...

/**
* Get products by category with caching
*/
async getByCategory(category: string) {
return await this.cacheGetOrSet(
`products:category:${category}`,
async () => {
return await this.find(
{ category } as any,
{ sort: { name: 1 } }
);
},
3600 // Cache for 1 hour
);
}

/**
* Update stock after purchase
*/
async updateStock(productId: string, quantity: number) {
const product = await this.findById(productId);

if (product.error || !product.data) {
return { error: true, message: 'Product not found' };
}

if (product.data.stock < quantity) {
return { error: true, message: 'Insufficient stock' };
}

const result = await this.update(
{ _id: productId } as any,
{ stock: product.data.stock - quantity } as any
);

// Invalidate cache
await this.invalidateCache(productId);

return result;
}

/**
* Get low stock products
*/
async getLowStockProducts(threshold: number = 5) {
return await this.find(
{ stock: { $lte: threshold } } as any,
{ sort: { stock: 1 } }
);
}
}

What's Next?

Congratulations! You've created your first API resource. Here's what to explore next:

Learn Core Concepts

Explore Features

Advanced Topics


Need help? Join our community on GitHub or check the full documentation.