Quando Usar
Use este skill ao implementar validação de requisições, verificações de autorização, mapeamento de respostas, logging, tratamento de erros ou rastreamento de desempenho em métodos de ferramentas NitroStack.
1. Guards (Guard e @UseGuards)
Guards determinam se uma requisição deve ser processada por um manipulador de ferramenta com base em autenticação, autorização ou outras condições.
Interface:
import { Guard, ExecutionContext } from '@nitrostack/core';
export interface Guard {
canActivate(context: ExecutionContext): boolean | Promise<boolean>;
}
Exemplo:
import { Guard, ExecutionContext, Injectable } from '@nitrostack/core';
@Injectable()
export class RolesGuard implements Guard {
async canActivate(context: ExecutionContext): Promise<boolean> {
const userRoles = context.clientMetadata?.roles || [];
return userRoles.includes('admin');
}
}
Aplique o guard usando @UseGuards(...):
import { Tool, UseGuards, z } from '@nitrostack/core';
import { RolesGuard } from './roles.guard.js';
export class AdminTools {
@Tool({
name: 'delete_system_logs',
description: 'Deletar todos os logs do sistema do servidor.',
inputSchema: z.object({}),
})
@UseGuards(RolesGuard)
async deleteLogs() {
return { success: true };
}
}
2. Interceptors (InterceptorInterface e @UseInterceptors)
Interceptors podem transformar/interceptar argumentos de entrada ou a saída mapeada da execução de um método de ferramenta.
Interface:
import { ExecutionContext } from '@nitrostack/core';
export interface InterceptorInterface {
intercept(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown>;
}
Exemplo:
import { InterceptorInterface, ExecutionContext, Injectable } from '@nitrostack/core';
@Injectable()
export class TimingInterceptor implements InterceptorInterface {
async intercept(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown> {
const start = Date.now();
const result = await next();
const duration = Date.now() - start;
context.logger.info(`Execução levou ${duration}ms`);
return {
...result,
_meta: { durationMs: duration }
};
}
}
3. Exception Filters (ExceptionFilterInterface e @UseFilters)
Exception Filters capturam quaisquer erros lançados dentro de guards, interceptors ou os próprios manipuladores de ferramenta, mapeando-os em payloads JSON amigáveis ao usuário.
Interface:
import { ExecutionContext } from '@nitrostack/core';
export interface ExceptionFilterInterface {
catch(exception: unknown, context: ExecutionContext): unknown | Promise<unknown>;
}
Exemplo:
import { ExceptionFilterInterface, ExecutionContext, Injectable } from '@nitrostack/core';
@Injectable()
export class CustomExceptionFilter implements ExceptionFilterInterface {
catch(exception: unknown, context: ExecutionContext) {
const message = exception instanceof Error ? exception.message : 'Erro desconhecido';
return {
error: true,
message,
timestamp: new Date().toISOString()
};
}
}
Aplique o filtro usando @UseFilters(...) em um método de ferramenta:
import { Tool, UseFilters, z } from '@nitrostack/core';
import { CustomExceptionFilter } from './custom-exception.filter.js';
export class LoggingTools {
@Tool({
name: 'generate_report',
description: 'Gera relatórios de uso do sistema.',
inputSchema: z.object({}),
})
@UseFilters(CustomExceptionFilter)
async generateReport() {
throw new Error('A geração de relatório ainda não foi implementada.');
}
}
4. Middleware (MiddlewareInterface, @Middleware e @UseMiddleware)
Middleware executa antes da requisição chegar ao manipulador da ferramenta e pode envolver a execução do manipulador invocando next().
Interface:
import { ExecutionContext } from '@nitrostack/core';
export interface MiddlewareInterface {
use(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown>;
}
Exemplo:
import { Middleware, MiddlewareInterface, ExecutionContext } from '@nitrostack/core';
@Middleware()
export class LoggingMiddleware implements MiddlewareInterface {
async use(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown> {
context.logger.info(`Entrando na ferramenta: ${context.toolName}`);
try {
const result = await next();
context.logger.info(`Saindo da ferramenta: ${context.toolName}`);
return result;
} catch (error) {
context.logger.error(`Erro na ferramenta: ${error}`);
throw error;
}
}
}
Aplique o middleware usando @UseMiddleware(...) em um método de ferramenta:
import { Tool, UseMiddleware, z } from '@nitrostack/core';
import { LoggingMiddleware } from './logging.middleware.js';
export class StationTools {
@Tool({
name: 'fetch_logs',
description: 'Buscar logs de operações da estação.',
inputSchema: z.object({}),
})
@UseMiddleware(LoggingMiddleware)
async fetchLogs() {
return { status: 'operational' };
}
}
5. Pipes (PipeInterface, @Pipe e @UsePipes)
Pipes são usados para transformar ou validar argumentos de entrada antes que eles cheguem ao método manipulador da ferramenta.
Interface:
import { ArgumentMetadata } from '@nitrostack/core';
export interface PipeInterface<T = unknown, R = unknown> {
transform(value: T, metadata: ArgumentMetadata): R | Promise<R>;
}
Exemplo:
import { Pipe, PipeInterface, ArgumentMetadata } from '@nitrostack/core';
@Pipe()
export class TrimPipe implements PipeInterface<Record<string, unknown>, Record<string, unknown>> {
transform(value: Record<string, unknown>, metadata: ArgumentMetadata) {
const trimmed: Record<string, unknown> = {};
for (const [key, val] of Object.entries(value)) {
trimmed[key] = typeof val === 'string' ? val.trim() : val;
}
return trimmed;
}
}
Aplique o pipe usando @UsePipes(...) em um método de ferramenta:
import { Tool, UsePipes, z } from '@nitrostack/core';
import { TrimPipe } from './trim.pipe.js';
export class MessagingTools {
@Tool({
name: 'send_message',
description: 'Enviar uma mensagem para outras estações.',
inputSchema: z.object({ text: z.string() }),
})
@UsePipes(TrimPipe)
async sendMessage(input: { text: string }) {
return { sentText: input.text };
}
}