@jimmy-nitron/fastify-kick-start
v1.1.3
Published
A comprehensive, reusable Fastify library with decorators, plugins, and Swagger integration
Maintainers
Readme
Fastify Kick-Start
A comprehensive, reusable Fastify library with decorators, plugins, and Swagger integration. Build production-ready REST APIs quickly with TypeScript-first design and extensive customization options.
Features
- 🎯 Decorator-based Controllers - Clean, annotation-driven API development
- 📚 Auto-generated Documentation - Swagger/OpenAPI 3.0 with interactive UI
- 🔧 Smart Dependency Injection - Multi-container support (Awilix, InversifyJS, TSyringe, custom)
- 🛡️ Security Middleware - Rate limiting, CORS, security headers, and more
- 🔧 Highly Configurable - Flexible server builder with sensible defaults
- 📦 Plugin Architecture - Extensible with custom plugins
- 🚀 Production Ready - Error handling, logging, and performance optimizations
- 📖 TypeScript First - Full type safety with TypeBox schema validation
Quick Start
Installation
npm install @jimmy-nitron/fastify-kick-start
# or
yarn add @jimmy-nitron/fastify-kick-startBasic Example
import { Controller, Get, createQuickServer } from '@jimmy-nitron/fastify-kick-start';
import { Type } from '@sinclair/typebox';
@Controller('/api/users')
class UserController {
@Get('/')
async getUsers() {
return { users: [] };
}
@Get('/:id')
async getUserById(req: any, reply: any) {
const { id } = req.params;
return { id, name: 'John Doe' };
}
}
// Create and start server
const app = await createQuickServer([UserController]);
await app.listen({ port: 3000 });With Dependency Injection (Awilix)
import { createContainer, asClass } from 'awilix';
import { Controller, Get, createServer } from '@jimmy-nitron/fastify-kick-start';
// Services
class UserService {
async getUsers() {
return [{ id: 1, name: 'John Doe' }];
}
}
// Controller with DI
@Controller('/api/users')
class UserController {
constructor(private readonly cradle: { userService: UserService }) {}
@Get('/')
async getUsers() {
return await this.cradle.userService.getUsers();
}
}
// Setup with Awilix
const container = createContainer();
container.register({
userService: asClass(UserService).singleton(),
});
const app = await createServer()
.withAwilix(container, { enableRequestScoping: true })
.withControllers([UserController])
.build();
await app.listen({ port: 3000 });Core Decorators
@Controller
Mark a class as a controller and optionally set a route prefix:
@Controller('/api/users')
class UserController {
// Routes will be prefixed with /api/users
}HTTP Method Decorators
@Controller('/api/users')
class UserController {
@Get('/') // GET /api/users
@Post('/') // POST /api/users
@Put('/:id') // PUT /api/users/:id
@Patch('/:id') // PATCH /api/users/:id
@Delete('/:id') // DELETE /api/users/:id
async handleRequest() {}
}@Opts - Route Configuration
Add Fastify route options including schema validation:
@Get('/:id')
@Opts({
schema: {
tags: ['Users'],
summary: 'Get user by ID',
params: Type.Object({
id: Type.Number()
}),
response: {
200: UserSchema,
404: ErrorSchema
}
}
})
async getUserById(req: any, reply: any) {}@Prefix - Route Prefixes
Add prefixes to controllers (can be stacked):
@Prefix('/api')
@Prefix('/v1')
@Controller('/users')
class UserController {
// Routes will be prefixed with /api/v1/users
}@Middleware - Custom Middleware
Apply middleware to controllers or routes:
@Middleware([loggingMiddleware, rateLimitMiddleware])
@Controller('/api')
class ApiController {
@Get('/data')
@Middleware(cacheMiddleware)
async getData() {}
}Server Builder
Quick Server
For rapid development with sensible defaults:
import { createQuickServer } from '@jimmy-nitron/fastify-kick-start';
const app = await createQuickServer([UserController, ProductController], {
swagger: {
info: {
title: 'My API',
version: '1.0.0',
},
},
});Advanced Configuration
For full control over server configuration:
import { createServer } from '@jimmy-nitron/fastify-kick-start';
const app = await createServer()
.withLogging({
enabled: true,
level: 'info',
prettyPrint: true,
})
.withSwagger({
enabled: true,
info: {
title: 'Advanced API',
description: 'Full-featured REST API',
version: '2.0.0',
},
components: {
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
},
},
},
})
.withSwaggerUI({
enabled: true,
routePrefix: '/docs',
})
.withCors({
enabled: true,
options: {
origin: ['http://localhost:3000'],
credentials: true,
},
})
.withControllers([UserController, ProductController])
.build();Middleware
Built-in Middleware
import {
corsMiddleware,
loggingMiddleware,
rateLimitMiddleware,
securityHeadersMiddleware,
validationMiddleware,
} from '@jimmy-nitron/fastify-kick-start';
@Middleware([
corsMiddleware({ origin: 'https://example.com' }),
loggingMiddleware({ level: 'info' }),
rateLimitMiddleware({ maxRequests: 100, windowMs: 60000 }),
securityHeadersMiddleware(),
validationMiddleware({
validateBody: body => body.name?.length > 0 || 'Name is required',
}),
])
@Controller('/api')
class ApiController {}Custom Middleware
const customMiddleware: MiddlewareFunction = async (req, reply) => {
// Custom logic
req.customData = 'some value';
};
@Middleware(customMiddleware)
@Controller('/custom')
class CustomController {}Schema Validation
Using TypeBox for type-safe schema validation:
import { Type } from '@sinclair/typebox';
const UserSchema = Type.Object({
id: Type.Number(),
name: Type.String({ minLength: 1 }),
email: Type.String({ format: 'email' }),
age: Type.Optional(Type.Number({ minimum: 0, maximum: 150 }))
});
@Post('/users')
@Opts({
schema: {
body: UserSchema,
response: {
201: UserSchema,
400: Type.Object({
statusCode: Type.Number(),
error: Type.String(),
message: Type.String()
})
}
}
})
async createUser(req: any, reply: any) {
// req.body is automatically validated against UserSchema
return reply.code(201).send(req.body);
}Error Handling
Default Error Handler
The library includes a comprehensive error handler:
const app = await createServer()
.withErrorHandler({
enabled: true,
handler: (error, req, reply) => {
req.log.error(error);
const statusCode = error.statusCode || 500;
reply.code(statusCode).send({
statusCode,
error: 'Something went wrong',
message: error.message,
});
},
})
.build();Custom Error Classes
class ValidationError extends Error {
statusCode = 400;
constructor(message: string) {
super(message);
this.name = 'ValidationError';
}
}
// Throw in controllers
throw new ValidationError('Invalid input data');Examples
Check out the examples/ directory for complete working examples:
basic-server.ts- Simple REST APIadvanced-server.ts- Full-featured API with auth, middleware, and advanced routing
API Reference
Decorators
@Controller(prefix?)- Mark class as controller@Get(path?),@Post(path?),@Put(path?),@Patch(path?),@Delete(path?)- HTTP methods@Prefix(prefix)- Add route prefix@Opts(options)- Fastify route options@Middleware(middleware)- Custom middleware
Server Builder
createQuickServer(controllers, options?)- Quick server creationcreateServer()- Advanced server builder.withLogging(options).withSwagger(options).withSwaggerUI(options).withCors(options).withErrorHandler(options).withControllers(controllers).withPlugin(plugin, options?).build()
Middleware
corsMiddleware(options)loggingMiddleware(options)rateLimitMiddleware(options)securityHeadersMiddleware(options)validationMiddleware(options)
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see the LICENSE file for details.
