Criando uma procedure com o Igniter.js no SaaS Boilerplate
Procedures no Igniter são funções de middleware poderosas que permitem implementar preocupações transversais como autenticação, validação, tratamento de erros e registro de logs. Eles podem ser aplicados a ações individuais do controlador ou globalmente ao seu roteador.
Criando um Procedure
Para criar um Procedure no Igniter, você usa a função igniter.procedure()
. Aqui está um exemplo básico:
// src/procedures/auth.procedure.ts import { igniter } from '@/igniter' import { verifyToken } from '@/utils/jwt' export const auth = igniter.procedure({ handler: async (input, ctx) => { // Get the authorization header const authHeader = ctx.headers.authorization if (!authHeader || !authHeader.startsWith('Bearer ')) { return ctx.response.unauthorized('Missing or invalid authorization token') } const token = authHeader.split(' ')[1] try { // Verify the token const user = await verifyToken(token) // Add the user to the context ctx.user = user // Continue to the next middleware or handler return ctx.next() } catch (error) { return ctx.response.unauthorized('Invalid token') } } })
A configuração do Procedure inclui:
handler
: Uma função que recebe a entrada e o contexto, e retorna uma resposta ou chamactx.next()
para continuar para o próximo middleware ou manipulador
Usando Procedures com Controladores
Procedures podem ser aplicados a ações individuais do controlador:
// src/features/user/controllers/user.controller.ts import { igniter } from '@/igniter' import { auth } from '@/procedures/auth.procedure' export const userController = igniter.controller({ path: '/users', actions: { list: igniter.query({ path: '/', use: [auth()], // Apply the auth procedure handler: async (ctx) => { // This handler will only be called if the auth procedure passes const users = await ctx.providers.database.user.findMany() return ctx.response.ok(users) } }) } })
Usando Procedures com Roteadores (Em Breve)
Nota: Este recurso está atualmente em desenvolvimento e estará disponível em uma versão futura.
No futuro, Procedures poderão ser aplicados globalmente ao seu roteador:
// src/igniter.router.ts import { igniter } from '@/igniter' import { userController } from '@/features/user/controllers/user.controller' import { logger } from '@/procedures/logger.procedure' import { errorHandler } from '@/procedures/error-handler.procedure' export const AppRouter = igniter.router({ baseURL: 'https://localhost:3000', basePATH: '/api/v1', controllers: { users: userController }, use: [ logger(), // Applied to all requests (coming soon) errorHandler() // Applied to all requests (coming soon) ] })
Padrões Comuns de Procedures
Nota: O Igniter.js tem suporte integrado para validação de entrada em mutations e queries. Os exemplos abaixo focam em outros casos de uso comuns para Procedures.
Tratamento de Erros
// src/procedures/error-handler.procedure.ts import { igniter } from '@/igniter' export const errorHandler = igniter.procedure({ handler: async (_, ctx) => { try { // Continua para o próximo middleware ou manipulador return await ctx.next() } catch (error) { // Registra o erro console.error('Erro de API:', error) // Retorna uma resposta de erro apropriada if (error.name === 'ValidationError') { return ctx.response.badRequest(error.message) } if (error.name === 'NotFoundError') { return ctx.response.notFound(error.message) } // Resposta de erro padrão return ctx.response.internalServerError('Ocorreu um erro inesperado') } } })
Registro de Logs
// src/procedures/logger.procedure.ts import { igniter } from '@/igniter' export const logger = igniter.procedure({ handler: async (_, ctx) => { const start = Date.now() // Registra a requisição console.log(`${ctx.method} ${ctx.path} - Requisição recebida`) // Continua para o próximo middleware ou manipulador const response = await ctx.next() // Registra a resposta const duration = Date.now() - start console.log(`${ctx.method} ${ctx.path} - Resposta enviada (${response.status}) em ${duration}ms`) return response } })
Encadeando Procedures
Procedures podem ser encadeados para criar um pipeline de middleware:
export const userController = igniter.controller({ path: '/users', actions: { create: igniter.mutation({ path: '/', method: 'POST', use: [ logger(), // Primeiro Procedure na cadeia auth(), // Segundo Procedure na cadeia ], handler: async (ctx) => { // O manipulador só é chamado se todos os Procedures passarem } }) } })
Melhores Práticas
-
Mantenha os Procedures Focados: Cada Procedure deve se concentrar em uma única preocupação.
-
Use Procedures para Preocupações Transversais: Use Procedures para autenticação, validação, registro de logs e outras preocupações transversais.
-
Encadeie Procedures em uma Ordem Lógica: Ordene seus Procedures logicamente, com Procedures de uso geral (como registro de logs) primeiro e os mais específicos (como validação) depois.
-
Trate Erros com Elegância: Implemente tratamento adequado de erros em seus Procedures para fornecer mensagens de erro significativas aos clientes.
-
Compartilhe Contexto Entre Procedures: Use o objeto de contexto para compartilhar dados entre Procedures e manipuladores.
-
Make Procedures Reusable: Design your procedures to be reusable across different controllers and actions.
Acelere seu desenvolvimento
Construa aplicações SaaS completas em minutos com nosso boilerplate moderno. Autenticação, pagamentos, gerenciamento de usuários e muito mais!
Conheça o SaaS Boilerplate