api-forge-dev
v2.0.0
Published
A high-performance framework to forge Node.js API servers, powered by Fastify with built-in authentication, validation, and OpenAPI documentation.
Maintainers
Readme
Api-Forge
Api-Forge is a high-performance micro-framework for Node.js, designed to “forge” robust, secure, and well-documented API servers with minimal effort.
Built on top of Fastify, it provides a powerful declarative development experience with essential features already integrated.
Created by: Fernando Martini (@fmartini23).
✨ Key Features
- 🚀 High Performance – Built on Fastify, one of the fastest web frameworks for Node.js.
- 🔐 Integrated Authentication – Native support for JWT and API Key strategies with minimal configuration.
- 🛡️ Schema Validation – Automatically validate request body, query, and params using Zod schemas.
- 📖 Automatic Documentation – Generate interactive API docs with OpenAPI/Swagger directly from your schemas and routes.
- 🚦 Rate Limiting – Protect your endpoints with per-route rate limiting.
- 📁 File Uploads – Built-in support for multipart/form-data file uploads.
- ⛑️ Security by Default – Pre-configured middlewares like Helmet and CORS.
- ✍️ Declarative & Simple – Define your entire API (routes, authentication, validation) in a single configuration object.
📦 Installation
npm install api-forge zod⚠️
zodis a peer dependency and must be installed separately in your project.
🚀 Quick Start: Create Your First Server
Create a file index.js:
// index.js
const { z } = require('zod');
const ApiForgeServer = require('api-forge');
// 1. Define routes declaratively
const routes = [
{
method: 'POST',
path: '/login',
schema: {
body: z.object({
username: z.string(),
password: z.string(),
}),
response: {
200: z.object({ token: z.string() }),
},
},
handler: async (request, reply) => {
const { username, password } = request.body;
if (username === 'admin' && password === '123456') {
const token = server.generateToken({ id: username, roles: ['admin'] });
return { token };
}
reply.code(401).send({ error: 'Invalid credentials' });
},
},
{
method: 'GET',
path: '/profile',
auth: 'jwt',
handler: async (request) => {
return { user: request.user };
},
},
];
// 2. Configure and instantiate the server
const server = new ApiForgeServer({
port: 3000,
auth: {
jwt: { secretKey: 'your-super-secret-key-here' },
},
docs: {
title: 'My Awesome API',
version: '1.0.0',
routePrefix: '/documentation',
},
routes,
});
// 3. Start the server
server.start();Run your server:
node index.jsYour API will be available at http://localhost:3000.
Interactive documentation will be at http://localhost:3000/documentation.
📚 Configuration API
new ApiForgeServer(config) accepts a configuration object.
| Key | Type | Description |
|----------------|----------------|-------------|
| port | number | Port the server will listen on (default: 3000). |
| host | string | Host the server will bind to (default: '0.0.0.0'). |
| routes | Array<Route> | Array of route objects that define your API. |
| auth | object | Authentication strategies configuration. |
| docs | object | OpenAPI/Swagger documentation settings. |
| corsOptions | object | Options for @fastify/cors. |
| helmetOptions| object | Options for @fastify/helmet. |
Route Object (Route)
| Key | Type | Required | Description |
|---------------|------------|----------|-------------|
| method | string | ✅ | HTTP method (GET, POST, etc.). |
| path | string | ✅ | URL path (e.g. /users/:id). |
| handler | function | ✅ | Async function (request, reply) handling the logic. |
| auth | string | ❌ | Authentication strategy (jwt or apiKey). |
| schema | object | ❌ | Zod schemas for body, query, params, response. |
| rateLimit | object | ❌ | Options for @fastify/rate-limit. |
| preValidation | Array | ❌ | Hooks that run before validation (e.g., file uploads). |
Authentication Configuration
const config = {
auth: {
jwt: {
secretKey: 'my-secret-key',
sign: { expiresIn: '1h' },
},
apiKey: {
header: 'X-Custom-API-Key',
validate: async (key) => key === 'secret-db-key',
},
},
};💡 Advanced Examples
Validation with Zod
const routes = [{
method: 'POST',
path: '/users/:userId/posts',
schema: {
body: z.object({
title: z.string().min(5),
content: z.string(),
}),
params: z.object({
userId: z.string().uuid(),
}),
query: z.object({
published: z.boolean().optional(),
}),
response: {
201: z.object({
id: z.string(),
title: z.string(),
authorId: z.string(),
}),
},
},
handler: async (request, reply) => {
const { userId } = request.params;
const { title, content } = request.body;
reply.code(201).send({ id: 'post-123', title, authorId: userId });
},
}];File Uploads
const { createUploadHook } = require('api-forge/middlewares');
const routes = [{
method: 'POST',
path: '/profile/avatar',
auth: 'jwt',
preValidation: [
createUploadHook({
dest: './uploads',
fields: ['avatar'],
limits: { fileSize: 5 * 1024 * 1024 },
}),
],
handler: async (request) => {
const uploadedFile = request.files.avatar[0];
const userId = request.user.id;
return { message: 'Avatar updated!', filename: uploadedFile.filename, user: userId };
},
}];Rate Limiting
const routes = [{
method: 'POST',
path: '/login',
rateLimit: {
max: 5,
timeWindow: '10 minutes',
},
handler: async (request, reply) => {
// login logic...
},
}];🤝 Contributing
Contributions are welcome!
Feel free to open an issue or submit a pull request.
📜 License
This project is licensed under the MIT License.
See the LICENSE file for details.
