Procedures in Igniter.js
Procedures are one of the most powerful and flexible features in Igniter.js, providing a sophisticated middleware system that enables you to create reusable, composable, and type-safe request processing logic. This comprehensive guide will take you through everything you need to know about procedures, from basic concepts to advanced patterns.
What Are Procedures?
In Igniter.js, a procedure is a reusable piece of middleware that can be applied to actions or at the builder level. Think of procedures as building blocks that encapsulate common functionality like authentication, logging, rate limiting, input validation, or any custom business logic you need to run before your main handler executes.
Procedures operate within the request lifecycle, executing before your action handlers and having the ability to:
- Validate and transform input data
- Authenticate and authorize requests
- Log request information
- Implement rate limiting
- Add custom context data
- Perform early returns (like redirects or error responses)
- Access the global application context (database connections, services, etc.)
- Chain with other procedures for complex workflows
Core Concepts
Procedure Context
Every procedure receives an IgniterProcedureContext
object that contains all the information about the current request:
Understanding the Procedure Context: A Properties Breakdown
To understand the IgniterProcedureContext
object that every procedure receives, you can expand the section below to see a detailed breakdown of its properties.
The context is the primary way procedures interact with the request lifecycle, providing a clean and type-safe interface for middleware operations.
Creating Your First Procedure
Let's start with a simple example using the igniter.procedure
function. We'll create a request logging procedure:
import { igniter } from '@/igniter';
// Create a simple logging procedure
export const requestLogger = igniter.procedure({
name: 'RequestLogger',
handler: async ({ request, context, response, next }) => {
const startTime = Date.now();
// Use logger from global context if available
const logger = context.logger || console;
logger.log(`[${new Date().toISOString()}] ${request.method} ${request.url}`);
// Continue to the next middleware or handler
const result = await next();
const duration = Date.now() - startTime;
logger.log(`Request completed in ${duration}ms`);
return result;
},
});
This procedure:
- Logs the incoming request with timestamp, method, and URL
- Calls
next()
to continue the middleware chain - Logs the completion time after the request is processed
- Returns the result from the next middleware or handler
Using the Procedure
Once created, you can use this procedure in your controllers:
Action-Level Procedures
export const userController = igniter.controller({
name: 'UserController',
path: '/users',
actions: {
getUser: igniter.query({
path: '/:id',
// Apply the procedure only to this action
use: [requestLogger],
handler: ({ request, response }) => {
return response.success({ user: { id: request.params.id } });
},
}),
},
});
Best Practices
Following established best practices when creating procedures ensures your code remains maintainable, reusable, and type-safe. These guidelines will help you build robust middleware that integrates seamlessly with the Igniter.js ecosystem.
Proper procedure design not only improves code quality but also enhances developer experience by making your APIs more predictable and easier to debug. Each practice below addresses common challenges developers face when building production applications.
Conclusion
Procedures are a fundamental building block of Igniter.js applications, providing a powerful and flexible way to implement cross-cutting concerns in your API using the igniter.procedure
function. By understanding how to create, compose, and use procedures effectively, you can build more maintainable, reusable, and type-safe applications.