GuidesAPI Development

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

PropertyTypeDescription
module (m)stringClass-based feature module with @Module, controllers, and providers
controller (c)stringClass-based controller with @Controller, @Get, @Post, @Param, @Body, constructor DI
service (s)stringInjectable service class with @Service decorator and HttpError paths
middleware (mw)stringAsync middleware function with timing pattern
guard (g)stringGuard function with authorization token check pattern
route (r)stringFunctional router (named export) with GET, GET/:id, and POST routes

Examples

Generate a Module

npx nextrush g module todos

Creates src/modules/todos/todos.module.ts:

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 todos

Then register the module in your root module's imports.

Generate a Controller

npx nextrush g controller user

In 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.

src/modules/user/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 user

Creates src/modules/user/user.service.ts in a module project, or src/services/user.service.ts otherwise:

src/modules/user/user.service.ts
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-logger

Creates src/middleware/request-logger.ts:

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 auth

Creates src/guards/auth.guard.ts:

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 product

Creates 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)):

src/routes/product.ts
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

TypeDefault DirectoryModule project (src/modules/ exists)File Suffix
modulesrc/modules/<name>/src/modules/<name>/.module.ts
controllersrc/controllers/src/modules/<name>/.controller.ts
servicesrc/services/src/modules/<name>/.service.ts
middlewaresrc/middleware/src/middleware/.ts
guardsrc/guards/src/guards/.guard.ts
routesrc/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:

InputClass NameFunction Name
userUserControlleruser
user-profileUserProfileControlleruserProfile
authAuthControllerauthGuard

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.

What's Next?

Was this helpful?

On this page