Static Files Generation
The tgraph static command generates essential backend infrastructure files including guards, decorators, DTOs, interceptors, and utilities. These files provide foundational functionality for your NestJS API.
Overview
Static files are reusable backend components that support your generated controllers and services. Unlike model-specific files (controllers, services, DTOs), static files are generated once and can be customized for your application’s specific needs.
When to generate static files:
- During initial project setup
- When adding new features that require additional infrastructure
- When you need to regenerate specific components after manual modifications
- As part of the
tgraph apiworkflow (you’ll be prompted)
Available Static Modules
Guards
admin.guard - src/guards/admin.guard.ts
Implements role-based access control for admin-only endpoints. Checks if the authenticated user has admin privileges.
@Injectable()
export class AdminGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const user = request.user;
return user?.role === 'ADMIN';
}
}
feature-flag.guard - src/guards/feature-flag.guard.ts
A stub guard for feature flag checks. Wire it to your feature flag service.
@Injectable()
export class FeatureFlagGuard implements CanActivate {
canActivate(_context: ExecutionContext): boolean {
// TODO: wire to your feature-flag service
return true;
}
}
Decorators
is-admin.decorator - src/decorators/is-admin.decorator.ts
Endpoint-level decorator that marks routes as admin-only. Works in conjunction with guards to enforce admin access.
@Controller('users')
@UseGuards(JwtAuthGuard, AdminGuard)
export class UserController {
@Post()
@IsAdmin() // Explicitly marks this endpoint as admin-only
create(@Body() dto: CreateUserDto) {
// ...
}
}
paginated-search.decorator - src/decorators/paginated-search.decorator.ts
Combines multiple decorators for paginated search endpoints. Automatically applies pagination interceptor and API documentation.
DTOs
paginated-search-query.dto - src/dtos/paginated-search-query.dto.ts
Standard query parameters for paginated and searchable endpoints.
export class PaginatedSearchQueryDto {
@IsOptional()
@IsInt()
@Min(1)
page?: number = 1;
@IsOptional()
@IsInt()
@Min(1)
@Max(100)
limit?: number = 10;
@IsOptional()
@IsString()
search?: string;
@IsOptional()
@IsString()
sortBy?: string;
@IsOptional()
@IsEnum(['asc', 'desc'])
sortOrder?: 'asc' | 'desc' = 'asc';
}
paginated-search-result.dto - src/dtos/paginated-search-result.dto.ts
Standard response structure for paginated results.
export class PaginatedSearchResultDto<T> {
data: T[];
total: number;
page: number;
limit: number;
totalPages: number;
}
api-response.dto - src/dtos/api-response.dto.ts
Wrapper for standardized API responses with success/error status and optional metadata.
export class ApiResponseDto<T> {
success: boolean;
data?: T;
error?: string;
message?: string;
timestamp: string;
}
Interceptors
pagination.interceptor - src/interceptors/pagination.interceptor.ts
Automatically transforms service responses into paginated result format. Apply to search/list endpoints.
@Controller('users')
export class UserController {
@Get()
@UseInterceptors(PaginationInterceptor)
async search(@Query() query: PaginatedSearchQueryDto) {
return this.userService.search(query);
}
}
audit.interceptor - src/interceptors/audit.interceptor.ts
Stub interceptor for audit logging. Wire it to your logging service to track API requests.
@Injectable()
export class AuditInterceptor implements NestInterceptor {
intercept(_context: ExecutionContext, next: CallHandler): Observable<any> {
const started = Date.now();
return next.handle().pipe(
tap(() => {
// TODO: replace with your audit log sink
// console.log('Audit:', { duration: Date.now() - started });
}),
);
}
}
Utilities
paginated-search.util - src/utils/paginated-search.ts
Helper functions for building Prisma queries with pagination, sorting, and searching.
export function buildPaginatedQuery(query: PaginatedSearchQueryDto, searchFields: string[]) {
const { page, limit, search, sortBy, sortOrder } = query;
const skip = (page - 1) * limit;
return {
skip,
take: limit,
where: search ? buildSearchWhere(search, searchFields) : {},
orderBy: sortBy ? { [sortBy]: sortOrder } : {},
};
}
Usage
Interactive Mode (Default)
Prompts you for each module individually:
tgraph static
Output:
Generate admin.guard? (y/n): y
Generate feature-flag.guard? (y/n): n
Generate is-admin.decorator? (y/n): y
...
✅ Static files generation completed
List Available Modules
View all available static modules without generating:
tgraph static --list
Output:
Available static modules:
- admin.guard
- is-admin.decorator
- paginated-search-query.dto
- paginated-search-result.dto
- api-response.dto
- pagination.interceptor
- paginated-search.decorator
- paginated-search.util
- feature-flag.guard
- audit.interceptor
Selective Generation
Generate only specific modules:
# Generate guards only
tgraph static --include admin.guard,feature-flag.guard
# Generate pagination utilities
tgraph static --include paginated-search-query.dto,paginated-search-result.dto,pagination.interceptor
Non-Interactive Mode
Generate all modules without prompts (useful for CI/CD):
tgraph static --yes
Configuration
Static files are generated to directories specified in your tgraph.config.ts:
export const config: Config = {
output: {
backend: {
staticFiles: {
guards: 'src/guards',
decorators: 'src/decorators',
dtos: 'src/dtos',
interceptors: 'src/interceptors',
utils: 'src/utils',
},
},
},
};
Adjust these paths to match your project structure. The generator will create directories if they don’t exist.
Integration with tgraph api
When you run tgraph api, you’ll be prompted to generate static files:
tgraph api
Prompt:
Generate required static files (guards, dtos, utils)? (y/n): y
Generate admin.guard? (y/n): y
Generate is-admin.decorator? (y/n): y
...
Use --yes to auto-confirm in CI environments:
tgraph api --yes
Customization
Static files are generated once and are meant to be customized for your application:
1. Modify Generated Files
After generation, edit the files to fit your needs:
// src/guards/admin.guard.ts
@Injectable()
export class AdminGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const user = request.user;
// Custom logic: check database, cache, etc.
return user?.permissions?.includes('ADMIN_ACCESS');
}
}
2. Regenerate Selectively
If you’ve customized some files but need to regenerate others:
# Only regenerate DTOs, preserve custom guards
tgraph static --include paginated-search-query.dto,api-response.dto
3. Skip Auto-Generation
If you don’t need static files during tgraph api:
# Answer 'n' when prompted, or use custom guards in config
tgraph api
# When prompted: Generate required static files? (y/n): n
Common Workflows
Initial Setup
# Generate all static files
tgraph static --yes
# Or during API generation
tgraph api --yes
Adding New Feature Flags
# Generate the feature flag guard stub
tgraph static --include feature-flag.guard
# Customize it for your feature flag service
vim src/guards/feature-flag.guard.ts
Adding Audit Logging
# Generate the audit interceptor stub
tgraph static --include audit.interceptor
# Wire it to your logging service
vim src/interceptors/audit.interceptor.ts
# Apply globally in main.ts
app.useGlobalInterceptors(new AuditInterceptor());
Pagination Setup
# Generate pagination utilities
tgraph static --include paginated-search-query.dto,paginated-search-result.dto,pagination.interceptor,paginated-search.util
# Use in your service
import { buildPaginatedQuery } from '@/utils/paginated-search';
File Regeneration
Important: Running tgraph static will overwrite existing files for selected modules.
Best practices:
- Version control: Commit files before regenerating
- Selective generation: Use
--includeto regenerate only what’s needed - Custom files: Keep custom implementations in separate files with different names
Example:
# Original generated file
src/guards/admin.guard.ts
# Your custom extension (won't be overwritten)
src/guards/admin-enhanced.guard.ts
Integration with Generated Code
Using Guards in Generated Controllers
Configure guards in your tgraph.config.ts:
api: {
authentication: {
enabled: true,
requireAdmin: true,
guards: [
{ name: 'JwtAuthGuard', importPath: '@/guards/jwt-auth.guard' },
],
adminGuards: [
{ name: 'AdminGuard', importPath: '@/guards/admin.guard' },
],
},
}
Generated controllers will automatically import and apply these guards:
@Controller('users')
@UseGuards(JwtAuthGuard, AdminGuard)
export class UserAdminController {
// ...
}
Using DTOs in Generated Services
Generated services can leverage pagination DTOs:
async search(query: PaginatedSearchQueryDto) {
const { skip, take, where, orderBy } = buildPaginatedQuery(
query,
this.searchFields,
);
const [data, total] = await Promise.all([
this.prisma.user.findMany({ skip, take, where, orderBy }),
this.prisma.user.count({ where }),
]);
return { data, total, page: query.page, limit: query.limit };
}
Troubleshooting
Files Not Generated
Problem: tgraph static completes but files are missing.
Solutions:
-
Check config paths exist:
ls -la src/guards src/decorators src/dtos -
Verify permissions:
chmod -R u+w src/ -
Use
--includeto target specific modules:tgraph static --include admin.guard
Import Errors After Generation
Problem: TypeScript errors about missing imports.
Solutions:
-
Ensure path aliases are configured in
tsconfig.json:{ "compilerOptions": { "paths": { "@/*": ["src/*"] } } } -
Run TypeScript compiler:
npx tsc --noEmit -
Install missing dependencies:
npm install
Customizations Overwritten
Problem: Regeneration overwrote custom changes.
Solutions:
-
Use version control to restore:
git checkout -- src/guards/admin.guard.ts -
Use selective generation:
# Only regenerate what's needed tgraph static --include pagination.interceptor -
Keep customizations in separate files:
// src/guards/admin-custom.guard.ts (won't be overwritten)
Next Steps
- Authentication Guards Guide - Configure and customize authentication
- API Reference - Generator implementation details
- CLI Reference - Full command documentation