april-gen
v0.0.13
Published
Generate CRUD APIs Using UI & JSON code
Readme
🌱 april-gen
april-gen is a powerful NestJS module developed by the team at April Innovations. It enables developers to dynamically generate fully functional CRUD modules at runtime via both a user interface and API routes.
Perfect for rapidly scaffolding resources in large-scale NestJS applications, april-gen significantly reduces development time and helps maintain consistency across your codebase.
✨ Features
✅ Auto-generate CRUD modules in seconds
🧠 Smart creation of:
Controller
Service
Module
DTOs
Schema
Swagger API Docs
🧩 Dynamic Form UI at /generate/form
⚙️ Seamless integration into NestJS projects
📄 Auto-generates .http files for API testing
📦 Installation
npm install april-genNote: Your project must have the following peer dependencies installed:
@nestjs/common
@nestjs/core
@nestjs/platform-express.⚙️ Setup Instructions
- Modify main.ts
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { ValidationPipe } from '@nestjs/common';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { join, dirname } from 'path';
import { registerAppPort } from 'april-gen';
import { AppModule } from './app.module';}
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
const PORT = 3001; // (Your port number)
registerAppPort(PORT); // Register port for internal routing
const libPath = dirname(require.resolve('april-gen/package.json'));
const viewsPath = join(libPath, 'dist', 'generateController', 'views');
app.setBaseViewsDir(viewsPath);
app.setViewEngine('hbs');
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
transform: true,
transformOptions: { enableImplicitConversion: true },
forbidNonWhitelisted: true,
}),
);
const config = new DocumentBuilder()
.setTitle('NestJS API Document')
.setDescription('Use the base API URL as http://localhost:{PORT}')
.setTermsOfService(`http://localhost:${PORT}/terms-of-service`)
.setLicense('MIT License', '')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
await app.listen(PORT);
}
bootstrap();- Modify app.module.ts
import { Module } from '@nestjs/common';
import { GenerateModule } from 'april-gen';
@Module({
imports: [GenerateModule],
})
export class AppModule {}📬 Usage
UI Form (No Code Required)
Visit:
GET http://localhost:{PORT}/generate/formYou’ll see a UI to input the module name and fields, and generate code instantly.
🔸 API Route
Send a POST request to generate a new CRUD module dynamically.
POST http://localhost:{PORT}/generate
Request Body
{
"entityName": "productData",
"fields": [
{
"name": "fullName",
"type": "String",
"required": true,
"description": "Product name",
"example": "Tata Nexon",
"enumValues": ["Tata Nexon"]
},
{
"name": "price",
"type": "Number",
"required": true,
"description": "Price of the product",
"example": 1500000
},
{
"name": "testObject",
"type": "Object",
"required": false,
"description": "Testing object",
"example": {}
},
{
"name": "isActive",
"type": "Boolean",
"required": false,
"default": true,
"description": "Product active status",
"example": true
},
{
"name": "createdAt",
"type": "Date",
"required": false,
"default": "new Date()",
"description": "Product creation date",
"example": "2024-01-01T00:00:00.000Z"
},
{
"name": "images",
"type": "Array",
"arrayType": "String",
"required": true,
"description": "List of product image URLs",
"example": ["image url 1", "image url 2"]
},
{
"name": "serviceCenter",
"type": "Array",
"arrayType": "ServiceCenter",
"required": false,
"description": "List of associated service centers",
"example": [
{
"name": "Prabhat Tata center",
"location": "Thane",
"area": "Mumbai"
}
],
"innerFields": [
{
"name": "name",
"type": "String",
"required": true,
"description": "Name of the service center",
"example": "XYZ Tata center"
},
{
"name": "location",
"type": "String",
"required": true,
"description": "Location (city/town)",
"example": "Thane"
},
{
"name": "area",
"type": "String",
"required": true,
"description": "Area (region/district)",
"example": "Mumbai"
}
]
},
{
"name": "specifications",
"type": "Object",
"objectType": "specifications",
"required": false,
"description": "Detailed product specifications",
"example": {
"engineType": "Petrol Engine",
"isSuv": true,
"groundClearance": 155
},
"innerFields": [
{
"name": "engineType",
"type": "String",
"required": true,
"description": "Type of engine",
"example": "Petrol Engine"
},
{
"name": "isSuv",
"type": "Boolean",
"required": false,
"description": "Is the vehicle an SUV?",
"example": true
},
{
"name": "groundClearance",
"type": "Number",
"required": false,
"description": "Ground clearance in mm",
"example": 155
}
]
}
]
}
This will generate a fully structured module named post with all the necessary files.
🗂️ Output Structure (Example)
src/
└── post/
├── dtos/
│ └── post.dto.ts
├── http/
│ ├── post.create.http
│ ├── post.delete.http
│ ├── post.fetchById.http
│ ├── post.getAll.http
│ ├── post.getAllByUserId.http
│ ├── post.update.http
│ └── post.updateByUser.http
│ └── post.search.http
├── post.controller.ts
├── post.module.ts
├── post.schema.ts
└── post.service.ts
🔍 Search API Guide
Route - POST //search
This API endpoint allows powerful querying using flexible filters, pagination, sorting, and lookup (join) operations.
📥 Example Body
In the below example, we are filtering the state collection where:
- The state
nameequals Maharashtra - The state is related to the
countriescollection viacountryId
{
"filters": [
{
"field": "name",
"operator": "eq",
"value": "Maharashtra",
"type": "string"
},
{
"field": "countryId",
"operator": "in",
"value": [],
"type": "objectId",
"innerFilter": {
"modelName": "countries",
"projection": ["name"]
}
}
],
"page": 1,
"limit": 10,
"sort": {
"createdAt": "desc"
},
"projection": ["name"]
}🧩 Filter Object Structure
Use this to define your search conditions. Each filter object contains the following keys:
| Key | Type | Description |
|---------------|-------------------|-----------------------------------------------------------------------------|
| `field` | `string` | The field name in the model you want to filter. |
| `operator` | `string` | The condition to apply (`eq`, `regex`, `in`, `lt`, `lte`,`gt`,`gte`, etc.). |
| `value` | `any` | The value(s) to match against. |
| `type` | `string` | The data type of the field (`string`, `objectId`, `number`, etc.). |
| `innerFilter` | `object` _(optional)_ | Used for lookups (joins). Contains `modelName` and `projection`. |
📤 Example Response
[
{
"_id": "6836f135c86a2cfd6b87f9f8",
"name": "Maharashtra",
"countryId_lookup": {
"name": "India"
}
}
]
To check swagger documentation
GET http://localhost:{PORT}/api#/📝 License
MIT © 2025
👨💻 Developer:
Website: https://aprilinnovations.com/
Email: [email protected]
Name: Avinash Shirale
Demo



