Generate Command
Generate modules, tools, guards, and other boilerplate.
The generate command writes boilerplate for NitroStack components, so every new file starts with the same structure. You name what to generate and, for most types, a name for it.
Usage
nitrostack-cli generate <type> [name] [options]Types
TypeScript types
| Type | Creates | Needs a name |
|---|---|---|
types | TypeScript types from your tools | No |
module | A module with its tools, resources, and prompts | Yes |
tools | A tool class | Yes |
resources | A resource class | Yes |
prompts | A prompt class | Yes |
guard | An authentication guard | Yes |
middleware | A middleware class | Yes |
interceptor | An interceptor | Yes |
pipe | A pipe that validates or transforms arguments | Yes |
filter | An exception filter | Yes |
service | An injectable service | Yes |
health | A health check class | Yes |
Python types
The Python CLI generates seven types, and each needs a name. Files are written relative to the folder you run the command in.
| Type | Creates |
|---|---|
tool | {name}_tool.py, plus a widget at widgets/out/{name}.html |
module | {name}_module.py |
guard | guards/<name>.py |
pipe | pipes/<name>.py |
interceptor | interceptors/<name>.py |
filter | filters/<name>.py |
service | services/<name>.py |
Attach the generated pipeline classes with @use_guards, @use_pipes, @use_interceptors, or @use_filters, and register services in a module's providers list.
Options
The TypeScript CLI takes these options, and every one is optional. The Python CLI has no options for generate.
| Option | Description |
|---|---|
--module <name> | The module that tools, resources, and prompts belong to |
--output <path> | Output path, for types |
--force | Overwrite existing files |
--skip-related | When generating a module, skip its tools, resources, and prompts files |
Generate a feature
A feature is a module plus the classes inside it. Generate the module first, then add to it.
Module
nitrostack-cli generate module paymentsThe examples below show the TypeScript output.
This creates the module file and a tools, resources, and prompts file next to it:
src/modules/payments/payments.module.ts
src/modules/payments/payments.tools.ts
src/modules/payments/payments.resources.ts
src/modules/payments/payments.prompts.tsimport { Module } from '@nitrostack/core';
import { PaymentsTools } from './payments.tools.js';
import { PaymentsResources } from './payments.resources.js';
import { PaymentsPrompts } from './payments.prompts.js';
@Module({
name: 'payments',
description: 'Payments module',
controllers: [PaymentsTools, PaymentsResources, PaymentsPrompts]
})
export class PaymentsModule {}Tools
Add a tool class to an existing module. The TypeScript file is written to src/modules/payments/payments.tools.ts. In Python, generate tool creates a single tool and its widget.
nitrostack-cli generate tools payments --module paymentsimport { ToolDecorator as Tool, z, ExecutionContext, Injectable } from '@nitrostack/core';
/**
* payments Tools
*
* TODO: Add description
*/
@Injectable()
export class paymentsTools {
@Tool({
name: 'payments_example',
description: 'TODO: Add description',
inputSchema: z.object({
id: z.string().describe('ID parameter'),
}),
})
async exampleTool(input: { id: string }, context: ExecutionContext) {
// TODO: Implement tool logic
return { id: input.id, result: 'success' };
}
}Resources
TypeScript only. The file is written to src/modules/payments/payments.resources.ts.
nitrostack-cli generate resources payments --module paymentsimport { ResourceDecorator as Resource, ExecutionContext } from '@nitrostack/core';
/**
* payments Resources
*
* TODO: Add description
*/
export class paymentsResources {
@Resource({
uri: 'payments://example',
name: 'Example Resource',
description: 'TODO: Add description',
mimeType: 'application/json',
})
async exampleResource(context: ExecutionContext) {
// TODO: Implement resource logic
return {
type: 'text' as const,
text: JSON.stringify({ example: 'data' }, null, 2),
};
}
}Prompts
TypeScript only. The file is written to src/modules/payments/payments.prompts.ts.
nitrostack-cli generate prompts payments --module paymentsimport { PromptDecorator as Prompt, ExecutionContext } from '@nitrostack/core';
/**
* payments Prompts
*
* TODO: Add description
*/
export class paymentsPrompts {
@Prompt({
name: 'payments-help',
description: 'TODO: Add description',
})
async helpPrompt(args: Record<string, unknown>, context: ExecutionContext) {
return [
{
role: 'user' as const,
content: {
type: 'text' as const,
text: 'TODO: Add prompt content',
},
},
];
}
}Generate supporting components
These types are not tied to a module. Each is written to its own folder, named after what you pass: under src/ in TypeScript, and under the current folder in Python. The code shown is the TypeScript output.
Guard
Written to src/guards/admin.guard.ts, or guards/myguard.py in Python.
nitrostack-cli generate guard adminimport { Guard, ExecutionContext } from '@nitrostack/core';
export class AdminGuard implements Guard {
async canActivate(context: ExecutionContext): Promise<boolean> {
// TODO: Implement admin check
const user = context.auth?.user;
return user?.role === 'admin';
}
}Middleware
Written to src/middleware/logging.middleware.ts. TypeScript only.
nitrostack-cli generate middleware loggingimport { Middleware, MiddlewareInterface, ExecutionContext } from '@nitrostack/core';
@Middleware()
export class LoggingMiddleware implements MiddlewareInterface {
async use(context: ExecutionContext, next: () => Promise<any>) {
const start = Date.now();
console.log(`[${context.toolName}] Started`);
const result = await next();
const duration = Date.now() - start;
console.log(`[${context.toolName}] Completed in ${duration}ms`);
return result;
}
}Interceptor
Written to src/interceptors/transform.interceptor.ts.
nitrostack-cli generate interceptor transformimport { Interceptor, InterceptorInterface, ExecutionContext } from '@nitrostack/core';
@Interceptor()
export class TransformInterceptor implements InterceptorInterface {
async intercept(context: ExecutionContext, next: () => Promise<any>) {
const result = await next();
return {
success: true,
data: result,
timestamp: new Date().toISOString()
};
}
}Pipe
Written to src/pipes/validation.pipe.ts.
nitrostack-cli generate pipe validationimport { Pipe, PipeInterface, ArgumentMetadata } from '@nitrostack/core';
@Pipe()
export class ValidationPipe implements PipeInterface {
transform(value: any, metadata: ArgumentMetadata) {
// TODO: Implement validation
return value;
}
}Filter
Written to src/filters/http-exception.filter.ts.
nitrostack-cli generate filter http-exceptionimport { ExceptionFilter, ExceptionFilterInterface, ExecutionContext } from '@nitrostack/core';
@ExceptionFilter()
export class HttpExceptionFilter implements ExceptionFilterInterface {
catch(exception: any, context: ExecutionContext) {
return {
statusCode: exception.status || 500,
message: exception.message || 'Internal server error',
timestamp: new Date().toISOString(),
tool: context.toolName
};
}
}Service
Written to src/services/email.service.ts.
nitrostack-cli generate service emailimport { Injectable } from '@nitrostack/core';
@Injectable()
export class EmailService {
async send(to: string, subject: string, body: string) {
// TODO: Implement email sending
console.log(`Sending email to ${to}: ${subject}`);
}
}Health check
TypeScript only. Written to src/health/database.ts. The name you pass becomes the class name, and the check is registered under that name without a trailing health.
nitrostack-cli generate health databaseGenerate types
TypeScript only. types reads your tool definitions and writes matching TypeScript types, which is useful for typing widgets. It needs no name.
nitrostack-cli generate typesThe types are written to src/types/generated-tools.ts. Pass --output to write them somewhere else.
export type GetProductInput = {
product_id: string;
};
export type GetProductOutput = {
id: string;
name: string;
price: number;
};
export interface ToolInputs {
'get_product': GetProductInput;
}
export interface ToolOutputs {
'get_product': GetProductOutput;
}nitrostack-cli generate types --output src/types/custom.tsCommon sequences
Add a feature
Generate a module with its tools and a service, then types for your widgets.
nitrostack-cli generate module notificationsnitrostack-cli generate tools notifications --module notificationsnitrostack-cli generate service notificationnitrostack-cli generate types- Import the new module in
app.module.tsand add it to theimportsarray. - Run
nitrostack-cli dev.
Protect tools with a guard
- Run
nitrostack-cli generate guard jwt. - Implement the check in
src/guards/jwt.guard.ts. - Apply the guard to your tools with
@UseGuards(JWTGuard). - Run
nitrostack-cli devand test in Studio.
Move logic into a service
- Run
nitrostack-cli generate service user. - Move the business logic out of your tools and into the service.
- Inject the service into the tools through their constructor.
- Register the service in the module's
providers.
Troubleshooting
File already exists
generate stops rather than overwrite a file. Pass --force to overwrite it, or remove the file first.
nitrostack-cli generate tools users --module users --forceModule not found
If you see Module 'payments' not found, create the module first, then add to it.
nitrostack-cli generate module payments
nitrostack-cli generate tools payments --module paymentsNo tool files found
generate types reads files named *.tools.ts. Check that your tools exist and follow that naming.
ls src/modules/*/*.tools.tsPermission denied
If you see EACCES: permission denied, give yourself write access to the project folder.
chmod +w src/