Getting Started with HazelJS CLI
A step-by-step guide to using the HazelJS CLI for scaffolding and managing your projects.
Introduction
The HazelJS CLI is a powerful command-line tool that accelerates your development workflow by generating boilerplate code, scaffolding new applications, and creating components with best practices built-in. Say goodbye to repetitive typing and hello to faster development!
Installation
Install the CLI globally to use it from anywhere:
# Install globally
npm install -g @hazeljs/cli
# Or install locally in your project
npm install -D @hazeljs/cli
# Verify installation
hazel --versionCreating a New Application
Start a new HazelJS project with a single command. The CLI scaffolds a complete application structure with TypeScript, testing setup, and all necessary configurations.
# Create a new application
hazel new my-app
# This creates:
# - TypeScript configuration
# - Jest testing setup
# - Example module, controller, and service
# - Package.json with all dependencies
# - README with getting started instructionsGenerating Components
The CLI provides a comprehensive set of generators for all HazelJS components. Use the generate command (or its alias g) to create components:
Core Components
1. Controllers
Generate a new controller with CRUD operations:
hazel g controller user
# or
hazel generate controller userThis generates a complete controller with all CRUD endpoints:
import { Controller, Get, Post, Body, Param, Delete, Put } from '@hazeljs/core';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@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(CreateUserDto) createUserDto: CreateUserDto) {
return this.userService.create(createUserDto);
}
@Put(':id')
update(@Param('id') id: string, @Body(UpdateUserDto) updateUserDto: UpdateUserDto) {
return this.userService.update(id, updateUserDto);
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.userService.remove(id);
}
}2. Services
Generate a service with dependency injection:
hazel g service auth
# or with custom path
hazel g service auth -p src/authimport { Injectable } from '@hazeljs/core';
@Injectable()
export class AuthService {
// Your service logic here
}3. Modules
Generate a new module with controllers and providers:
hazel g module productsimport { HazelModule } from '@hazeljs/core';
import { ProductsController } from './products.controller';
import { ProductsService } from './products.service';
@HazelModule({
controllers: [ProductsController],
providers: [ProductsService],
})
export class ProductsModule {}4. DTOs (Data Transfer Objects)
Generate create and update DTOs with validation decorators:
hazel g dto productThis creates both create-product.dto.ts and update-product.dto.ts:
// create-product.dto.ts
import { IsString, IsNumber, IsOptional } from 'class-validator';
export class CreateProductDto {
@IsString()
name: string;
@IsNumber()
price: number;
@IsOptional()
@IsString()
description?: string;
}
// update-product.dto.ts
import { PartialType } from '@hazeljs/core';
import { CreateProductDto } from './create-product.dto';
export class UpdateProductDto extends PartialType(CreateProductDto) {}5. Guards
Generate authentication or authorization guards:
hazel g guard auth
# or
hazel g g authimport { Injectable, CanActivate, ExecutionContext } from '@hazeljs/core';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.getRequest();
// Your guard logic here
return true;
}
}6. Interceptors
Generate interceptors for request/response transformation:
hazel g interceptor logging
# or
hazel g i loggingimport { Injectable, Interceptor, ExecutionContext, CallHandler } from '@hazeljs/core';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptor implements Interceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before...');
const now = Date.now();
return next.handle().pipe(
tap(() => console.log(`After... ${Date.now() - now}ms`))
);
}
}Advanced Features
7. WebSocket Gateways
Generate WebSocket gateways for real-time communication:
hazel g gateway notifications
# or
hazel g ws notificationsimport { WebSocketGateway, OnConnect, OnDisconnect, OnMessage } from '@hazeljs/websocket';
import { WebSocketClient, Data } from '@hazeljs/websocket';
@WebSocketGateway({ path: '/notifications' })
export class NotificationsGateway {
@OnConnect()
handleConnection(client: WebSocketClient) {
console.log('Client connected:', client.id);
}
@OnDisconnect()
handleDisconnect(client: WebSocketClient) {
console.log('Client disconnected:', client.id);
}
@OnMessage('message')
handleMessage(client: WebSocketClient, @Data() data: any) {
// Handle message
}
}8. Exception Filters
Generate exception filters for centralized error handling:
hazel g filter http-exception
# or
hazel g f http-exceptionimport { ExceptionFilter, Catch, ArgumentsHost } from '@hazeljs/core';
import { HttpException } from '@hazeljs/core';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.getContext();
const response = ctx.getResponse();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
timestamp: new Date().toISOString(),
message: exception.getMessage(),
});
}
}9. Pipes
Generate transformation pipes for data validation and transformation:
hazel g pipe validation
# or
hazel g p validationimport { PipeTransform, Injectable, ArgumentMetadata } from '@hazeljs/core';
@Injectable()
export class ValidationPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
// Your transformation logic
return value;
}
}10. Prisma Repositories
Generate Prisma repositories with base CRUD operations:
hazel g repository user
# or
hazel g repo userimport { PrismaService, BaseRepository } from '@hazeljs/prisma';
import { Injectable } from '@hazeljs/core';
@Injectable()
export class UserRepository extends BaseRepository {
constructor(prisma: PrismaService) {
super(prisma, 'user');
}
// Add custom methods here
async findByEmail(email: string) {
return this.prisma.user.findUnique({ where: { email } });
}
}11. AI Services
Generate AI services with decorators for OpenAI, Anthropic, and other providers:
hazel g ai-service chat
# or
hazel g ai chatimport { Injectable } from '@hazeljs/core';
import { AIService } from '@hazeljs/ai';
import { AIFunction, AIPrompt } from '@hazeljs/ai';
@Injectable()
export class ChatAIService {
constructor(private readonly aiService: AIService) {}
@AIFunction({
provider: 'openai',
model: 'gpt-4',
streaming: false,
})
async chatTask(@AIPrompt() prompt: string): Promise<unknown> {
const result = await this.aiService.complete({
provider: 'openai',
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
});
return result;
}
}12. Serverless Handlers
Generate serverless handlers for AWS Lambda or Google Cloud Functions:
# AWS Lambda
hazel g serverless handler --platform lambda
# or
hazel g sls handler
# Google Cloud Functions
hazel g serverless handler --platform cloud-function// lambda-handler.ts
import { createLambdaHandler } from '@hazeljs/serverless';
import { AppModule } from './app.module';
export const handler = createLambdaHandler(AppModule);
// cloud-function-handler.ts
import { createCloudFunctionHandler } from '@hazeljs/serverless';
import { AppModule } from './app.module';
export const cloudFunction = createCloudFunctionHandler(AppModule);Command Options
All generate commands support the following options:
-p, --path <path>: Specify the path where the component should be generated (default: 'src')--platform <platform>: For serverless, specify platform:lambdaorcloud-function(default: 'lambda')
Complete Workflow Example
Here's a complete example of building a feature using the CLI:
# 1. Create a new application
hazel new blog-api
cd blog-api
# 2. Generate a module
hazel g module posts
# 3. Generate DTOs
hazel g dto post
# 4. Generate service
hazel g service post -p src/posts
# 5. Generate controller
hazel g controller post -p src/posts
# 6. Generate Prisma repository
hazel g repository post
# 7. Generate exception filter
hazel g filter http-exception
# 8. Generate WebSocket gateway for real-time updates
hazel g gateway post-updatesInteractive Mode
The CLI includes an interactive mode that prompts you for missing information. If you don't specify a path, the CLI will ask you where to generate the component:
$ hazel g controller user
? Where should the controller be generated? (src)
> src/users
✓ Generated controller at src/users/user.controller.tsBest Practices
- Organize by Feature: Use the
-poption to organize components by feature (e.g.,src/users,src/products) - Generate DTOs First: Generate DTOs before controllers to ensure proper typing
- Use Aliases: Save time with short aliases (
ginstead ofgenerate,cinstead ofcontroller) - Customize Templates: The generated code follows HazelJS best practices but can be customized to fit your needs
What Gets Generated?
The CLI generates production-ready code with:
- ✅ Proper TypeScript types and imports
- ✅ Decorators configured correctly
- ✅ Dependency injection setup
- ✅ Validation decorators (for DTOs)
- ✅ Best practice patterns
- ✅ Ready-to-use CRUD operations (for controllers)
Conclusion
The HazelJS CLI is your productivity multiplier. It eliminates boilerplate code, enforces best practices, and helps you build features faster. Whether you're creating a new application or adding components to an existing one, the CLI has you covered.
Start using the CLI today and experience the difference it makes in your development workflow!