Generate TypeScript REST API endpoints with Express.js following the boilerplate patterns. Creates entities, services, controllers, and routes using base class inheritance.
You are an expert TypeScript developer generating REST API code using the boilerplate's base classes and patterns.
ALL TypeScript type definitions MUST be imported from @ai-finance/types package.
Never define types locally. When generating API code:
@ai-finance/types@ai-finance/types/apipackages/shared/types/src/ first// ✅ CORRECT - Import from shared types
import { User, UserRole } from "@ai-finance/types";
import type { ApiResponse, PaginatedResponse } from "@ai-finance/types/api";
// Entity can re-export for backward compatibility
export { UserRole } from "@ai-finance/types";
Use this skill when:
Each API module consists of:
src/modules/{module-name}/
├── {name}.entity.ts # Database entity
├── {name}.service.ts # Business logic
├── {name}.controller.ts # HTTP handlers
├── {name}.router.ts # Express routes
├── {name}.dto.ts # Validation schemas
└── index.ts # Module exports
import { Entity, Column, Index } from "typeorm";
import { BaseEntity } from "@ai-finance/shared-backend/base";
@Entity("{plural_name}")
export class {Name} extends BaseEntity {
@Column()
@Index()
name: string;
@Column({ type: "text", nullable: true })
description?: string;
@Column({ default: true })
isActive: boolean;
}
import { Schema, model, Document } from "mongoose";
import { baseSchemaOptions, baseSchemaFields } from "@ai-finance/shared-backend/base";
export interface I{Name} {
name: string;
description?: string;
isActive: boolean;
}
export interface {Name}Document extends I{Name}, Document {}
const {name}Schema = new Schema<{Name}Document>(
{
...baseSchemaFields,
name: { type: String, required: true, index: true },
description: { type: String },
isActive: { type: Boolean, default: true },
},
baseSchemaOptions
);
export const {Name} = model<{Name}Document>("{Name}", {name}Schema);
import { BaseService } from "@ai-finance/shared-backend/base";
import { {Name} } from "./{name}.entity";
import { Repository } from "typeorm";
export class {Name}Service extends BaseService<{Name}> {
constructor(repository: Repository<{Name}>) {
super(repository);
}
// Add custom methods here
async findByName(name: string): Promise<{Name} | null> {
return this.findOne({ where: { name } });
}
}
import { BaseController } from "@ai-finance/shared-backend/base";
import { {Name} } from "./{name}.entity";
import { {Name}Service } from "./{name}.service";
import { create{Name}Schema, update{Name}Schema } from "./{name}.dto";
export class {Name}Controller extends BaseController<{Name}> {
constructor(service: {Name}Service) {
super(service, {
createSchema: create{Name}Schema,
updateSchema: update{Name}Schema,
});
}
}
import { BaseRouter } from "@ai-finance/shared-backend/base";
import { {Name}Controller } from "./{name}.controller";
import { authMiddleware } from "@/middlewares/auth";
export class {Name}Router extends BaseRouter {
constructor(controller: {Name}Controller) {
super(controller, {
basePath: "/{plural-name}",
middleware: [authMiddleware],
});
}
}
import Joi from "joi";
export const create{Name}Schema = Joi.object({
name: Joi.string().min(2).max(100).required(),
description: Joi.string().max(500).optional(),
isActive: Joi.boolean().default(true),
});
export const update{Name}Schema = Joi.object({
name: Joi.string().min(2).max(100).optional(),
description: Joi.string().max(500).optional().allow(null),
isActive: Joi.boolean().optional(),
});
PascalCase singular (User, Product, Order){Name}Service{Name}Controller{Name}Routersnake_case plural (users, products, orders)kebab-case.ts (user.entity.ts, user.service.ts)All API responses follow this structure:
// Success
{
success: true,
data: T | T[],
meta?: { page, limit, total, totalPages }
}
// Error
{
success: false,
error: {
code: string,
message: string,
details?: object
}
}
.required() for mandatory fields.optional() for optional fields.default(value) for default values.allow(null) to accept null values on updateInput: "Create a Product API with name, price, category, and stock"
Output:
- src/modules/product/product.entity.ts
- src/modules/product/product.service.ts
- src/modules/product/product.controller.ts
- src/modules/product/product.router.ts
- src/modules/product/product.dto.ts
- src/modules/product/index.ts