Code Generators
Scaffold modules, controllers, services, middleware, guards, and routes from the command line
The nextrush generate command (alias nextrush g) creates new files from templates with the correct structure, imports, and naming conventions — matching the layouts the create-nextrush scaffolds emit.
Usage
The nextrush CLI ships with the @nextrush/dev toolkit, which create-nextrush adds to every
scaffolded project as a devDependency. Invoke it through your package manager so the local
binary resolves:
# npm
npx nextrush generate <type> <name>
npx nextrush g <type> <name>
# pnpm
pnpm exec nextrush generate <type> <name>
pnpm exec nextrush g <type> <name>If you installed @nextrush/dev globally, you can call the bare command instead:
nextrush g <type> <name>Generator Types
Available generators
| Property | Type | Description |
|---|---|---|
module (m) | string | Class-based feature module with @Module, controllers, and providers |
controller (c) | string | Class-based controller with @Controller, @Get, @Post, @Param, @Body, constructor DI |
service (s) | string | Injectable service class with @Service decorator and HttpError paths |
middleware (mw) | string | Async middleware function with timing pattern |
guard (g) | string | Guard function with authorization token check pattern |
route (r) | string | Functional router (named export) with GET, GET/:id, and POST routes |
Examples
Generate a Module
npx nextrush g module todosCreates src/modules/todos/todos.module.ts:
import { Module } from 'nextrush/class';
import { TodosController } from './todos.controller.js';
import { TodosService } from './todos.service.js';
@Module({
controllers: [TodosController],
providers: [TodosService],
})
export class TodosModule {}A feature module composes its controller and service. Generate all three for a complete feature:
npx nextrush g m todos
npx nextrush g controller todos
npx nextrush g service todosThen register the module in your root module's imports.
Generate a Controller
npx nextrush g controller userIn a class-based project (one with a src/modules/ directory) the controller is placed
inside its feature module: src/modules/user/user.controller.ts. In a module-less project
it lands at src/controllers/user.controller.ts.
import { Body, Controller, Get, Param, Post } from 'nextrush/class';
import { UserService } from './user.service.js';
@Controller('/user')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get()
findAll() {
return this.userService.findAll();
}
@Get('/:id')
findOne(@Param('id') id: string) {
return this.userService.findOne(id);
}
@Post()
create(@Body() data: unknown) {
return this.userService.create(data);
}
}Generate a Service
npx nextrush g service userCreates src/modules/user/user.service.ts in a module project, or
src/services/user.service.ts otherwise:
import { HttpError } from 'nextrush';
import { Service } from 'nextrush/class';
@Service()
export class UserService {
findAll() {
return [];
}
findOne(id: string) {
if (!id) throw new HttpError(404, 'Not found');
return { id };
}
create(data: unknown) {
if (!data || typeof data !== 'object') throw new HttpError(400, 'Invalid input');
return data;
}
}Generate Middleware
npx nextrush g middleware request-loggerCreates src/middleware/request-logger.ts:
import type { Middleware } from 'nextrush';
export const requestLogger: Middleware = async (ctx) => {
const start = Date.now();
await ctx.next();
const duration = Date.now() - start;
console.log(`${ctx.method} ${ctx.path} ${ctx.status} ${duration}ms`);
};Generate a Guard
npx nextrush g guard authCreates src/guards/auth.guard.ts:
import type { GuardFn } from 'nextrush/class';
export const authGuard: GuardFn = async (ctx) => {
const token = ctx.get('authorization');
if (!token) return false;
// TODO: Validate token
return true;
};Generate a Route
npx nextrush g route productCreates src/routes/product.ts — a named-export router, matching the functional
template's mounting idiom (import { productRouter } from './routes/product.js' +
app.route('/product', productRouter)):
import { createRouter } from 'nextrush';
export const productRouter = createRouter();
productRouter.get('/', (ctx) => {
ctx.json([]);
});
productRouter.get('/:id', (ctx) => {
ctx.json({ id: ctx.params.id });
});
productRouter.post('/', (ctx) => {
ctx.status = 201;
ctx.json(ctx.body);
});Output Directories
| Type | Default Directory | Module project (src/modules/ exists) | File Suffix |
|---|---|---|---|
| module | src/modules/<name>/ | src/modules/<name>/ | .module.ts |
| controller | src/controllers/ | src/modules/<name>/ | .controller.ts |
| service | src/services/ | src/modules/<name>/ | .service.ts |
| middleware | src/middleware/ | src/middleware/ | .ts |
| guard | src/guards/ | src/guards/ | .guard.ts |
| route | src/routes/ | src/routes/ | .ts |
In a class-based project (one with a src/modules/ directory), controllers and services
co-locate inside their feature module so the module, controller, service, and tests live
together. In module-less (functional/full) projects they use the flat directories above.
Directories are created automatically if they don't exist.
Naming Convention
Names must be lowercase with optional hyphens. The generator converts them to PascalCase for class names and camelCase for function names:
| Input | Class Name | Function Name |
|---|---|---|
user | UserController | user |
user-profile | UserProfileController | userProfile |
auth | AuthController | authGuard |
Wiring generated files
Generators create files; they do not edit existing source. Add generated modules to
your root module's imports, mount generated routes with app.route(...), and register
guards/middleware where they apply.
Existing Files
The generator will not overwrite existing files. If the target file already exists, the command exits with an error.