Published on 2025-03-08
App Router
Published on
App Router
The Igniter App Router is a central component that connects your controllers to your HTTP framework. It provides a clean, type-safe way to define your API routes and handle incoming requests.
Setting Up the App Router
The first step is to initialize your router by connecting it to your controllers:
// src/igniter.router.ts
import { igniter } from '@/igniter'
import { userController } from '@/features/user/controllers/user.controller'
import { notesController } from '@/features/notes/controllers/notes.controller'
import { authController } from '@/features/auth/controllers/auth.controller'
/**
* @description Initialize the Igniter Router
* @see https://github.com/felipebarcelospro/igniter-js
*/
export const AppRouter = igniter.router({
baseURL: process.env.IGNITER_APP_URL || 'http://localhost:3000',
basePATH: process.env.IGNITER_APP_BASE_PATH || '/api/v1',
controllers: {
users: userController,
notes: notesController,
auth: authController
}
})
The router configuration includes:
- baseURL: The base URL of your application (e.g., http://localhost:3000)
- basePATH: The base path for your API routes (e.g., /api/v1)
- controllers: An object mapping controller names to their implementations
Integrating with HTTP Frameworks
The Igniter App Router can be integrated with various HTTP frameworks. Here are examples for common frameworks:
Express
// src/server.ts
import express from 'express'
import { AppRouter } from '@/igniter.router'
const app = express()
// Use the Igniter router with Express
app.use(async (req, res) => {
const response = await AppRouter.handler(req)
res.status(response.status).json(response)
})
app.listen(3000, () => {
console.log('Server running on http://localhost:3000')
})
Next.js Route Handlers
// src/app/api/v1/[[...all]]/route.ts
import { AppRouter } from '@/igniter.router'
import { nextRouteHandlerAdapter } from '@igniter-js/core/adapters/next'
export const { GET, POST, PUT, DELETE } = nextRouteHandlerAdapter(AppRouter)
Bun
// src/server.ts
import { AppRouter } from '@/igniter.router'
Bun.serve({
fetch: AppRouter.handler
})
Route Handling
The App Router automatically handles routing based on the path and method defined in your controllers. For example, if you have a controller with the following actions:
const userController = igniter.controller({
path: '/users',
actions: {
list: igniter.query({
path: '/',
handler: async (ctx) => {
// Handle GET /api/v1/users
}
}),
get: igniter.query({
path: '/:id',
handler: async (ctx) => {
// Handle GET /api/v1/users/:id
}
}),
create: igniter.mutation({
path: '/',
method: 'POST',
handler: async (ctx) => {
// Handle POST /api/v1/users
}
})
}
})
The App Router will automatically create the following routes:
- GET /api/v1/users - Handled by the list action
- GET /api/v1/users/:id - Handled by the get action
- POST /api/v1/users - Handled by the create action
Type Safety
One of the key benefits of the Igniter App Router is type safety. The router provides full type inference for your API routes, ensuring that your client code is always in sync with your server code.
// The router type can be used to infer types for your API client
import { AppRouter } from '@/igniter.router'
import { createIgniterClient } from '@igniter-js/core/client'
export const api = createIgniterClient(AppRouter)
// Now your API client has full type inference
const result = await api.users.get.call({ params: { id: '123' } })
// result is fully typed based on the return type of your handler
Error Handling
The App Router includes built-in error handling. If an error occurs in your controller action, the router will automatically catch it and return an appropriate error response.
const errorHandler = igniter.procedure({
handler: async (_, ctx) => {
try {
return await ctx.next()
} catch (error) {
// Log the error
console.error('API Error:', error)
// Return a friendly error response
if (error instanceof ValidationError) {
return ctx.response.badRequest(error.message)
}
if (error instanceof NotFoundError) {
return ctx.response.notFound(error.message)
}
// Default error response
return ctx.response.internalServerError('An unexpected error occurred')
}
}
})
// Use the error handler in your router
export const AppRouter = igniter.router({
baseURL: 'http://localhost:3000',
basePATH: '/api/v1',
controllers: {
users: userController
},
use: [errorHandler()]
})
Advanced Configuration
Middleware
You can add global middleware to your router using the use option:
export const AppRouter = igniter.router({
baseURL: 'http://localhost:3000',
basePATH: '/api/v1',
controllers: {
users: userController
},
use: [
logger(),
rateLimiter(),
cors()
]
})
Custom Response Transformers
You can customize how responses are transformed before they are sent to the client:
export const AppRouter = igniter.router({
baseURL: 'http://localhost:3000',
basePATH: '/api/v1',
controllers: {
users: userController
},
transformResponse: (response) => {
// Add a timestamp to all responses
return {
...response,
timestamp: new Date().toISOString()
}
}
})
Best Practices
-
Organize Controllers by Feature: Group related controllers together based on features or domains.
-
Use Consistent Naming: Use consistent naming conventions for your controllers and actions.
-
Leverage Type Safety: Take advantage of TypeScript's type system to ensure your API is type-safe.
-
Implement Error Handling: Always implement proper error handling to provide meaningful error messages to clients.
-
Use Environment Variables: Store configuration values like baseURL and basePATH in environment variables for flexibility across different environments.
-
Keep the Router Simple: The router should be a thin layer that connects controllers to HTTP frameworks. Complex logic should be in controllers or procedures.
Quick Tip
Always implement proper error handling and reconnection logic in your SSE clients to ensure a robust user experience.