import { errors } from '@vinejs/vine'; import { Exception } from '@poppinss/utils'; import { ValidationError as JoiValidationError } from "../../../joi"; import type { JsonObject } from "../../../bundled_type_fest"; import type { HttpContext } from '@adonisjs/core/http'; import type { NextFn } from '@adonisjs/core/types/http'; import type { EventMap } from "../../../bundled_nhtio_tiny_typed_emitter"; /** * Type alias for Vine validation errors thrown by the VineJS validation library. * * @example * ```typescript * try { * await vine.validate(schema, data) * } catch (error) { * if (isVineValidationError(error)) { * // Handle Vine validation error * } * } * ``` */ export type VineValidationError = InstanceType; /** * Event map defining the types of errors that can be emitted by the ODataErrorMiddleware. * Each event type maps to the specific error instance that will be passed to event handlers. * * @example * ```typescript * const middleware = new ODataErrorMiddleware({ * onVineValidationError: (error) => logger.warn('Validation failed', error), * onException: (error) => monitoring.captureException(error), * onAny: (error) => analytics.trackError(error) * }) * ``` */ export type ODataErrorMiddlewareEvents = EventMap<{ vineValidationError: [ VineValidationError ]; joiValidationError: [ JoiValidationError ]; exception: [ Exception ]; error: [ Error ]; unknown: [ unknown ]; any: [ unknown ]; }>; /** * Configuration object for custom HTTP headers to be included in error responses. * Allows for CORS headers, security headers, API versioning, or any custom headers * that should be consistently applied to all error responses. * * @example * ```typescript * const headers: ODataErrorMiddlewareHeaders = { * 'X-API-Version': '1.0', * 'Access-Control-Allow-Origin': '*', * 'X-RateLimit-Remaining': '100' * } * ``` */ export interface ODataErrorMiddlewareHeaders { [key: string]: string; } /** * Configuration options for the ODataErrorMiddleware class. * Defines event handlers for different error types and response formatting options. * * @example * ```typescript * const options: ODataErrorMiddlewareOptions = { * onVineValidationError: (error) => logger.warn('Validation failed', error), * onException: (error) => monitoring.captureException(error), * onAny: (error) => analytics.trackError(error), * asYaml: true, * headers: { * 'X-API-Version': '1.0', * 'Access-Control-Allow-Origin': '*' * } * } * ``` */ export interface ODataErrorMiddlewareOptions { /** Event handler called when a Vine validation error is encountered */ onVineValidationError?: (error: VineValidationError) => void; /** Event handler called when a Joi validation error is encountered */ onJoiValidationError?: (error: JoiValidationError) => void; /** Event handler called when a framework Exception is encountered */ onException?: (error: Exception) => void; /** Event handler called when a generic Error is encountered */ onError?: (error: Error) => void; /** Event handler called when an unknown error type is encountered */ onUnknown?: (error: unknown) => void; /** Event handler called for any error that occurs, regardless of type */ onAny?: (error: unknown) => void; /** Whether to support YAML response format. Defaults to true */ asYaml?: boolean; /** Custom headers to include in all error responses */ headers?: ODataErrorMiddlewareHeaders; } /** * Individual error detail within a formatted error response. * Provides field-level information for validation errors or error chain details. * * @example * ```typescript * const detail: ResourcefulFormattedErrorDetails = { * code: 'E_REQUIRED', * message: 'The email field is required', * target: 'email', * context: { field: 'email', value: null } * } * ``` */ export interface ResourcefulFormattedErrorDetails { /** Machine-readable error code (e.g., 'E_REQUIRED', 'E_INVALID_FORMAT') */ code: string; /** Human-readable error message */ message: string; /** The field or property that caused the error (for validation errors) */ target?: string; /** Additional context information about the error */ context?: JsonObject; } /** * Standardized error response format used by the ODataErrorMiddleware. * Provides consistent structure for all API error responses with support for * field-level validation details and error chaining. * * @example * ```typescript * const formattedError: ResourcefulFormattedError = { * status: 422, * code: 'E_VALIDATION_ERROR', * message: 'Validation failed', * help: 'Check the provided field values', * details: [ * { * code: 'E_REQUIRED', * message: 'The email field is required', * target: 'email' * } * ] * } * ``` */ export interface ResourcefulFormattedError { /** HTTP status code for the error response */ status: number; /** Machine-readable error code */ code: string; /** Human-readable error message */ message: string; /** Optional help text providing guidance on how to resolve the error */ help?: string; /** Array of detailed error information, typically for validation errors */ details?: ResourcefulFormattedErrorDetails[]; } /** * AdonisJS middleware that intercepts errors thrown during HTTP requests and formats * the responses in a consistent, client-friendly manner. Supports multiple error types * including Vine validation errors, Joi validation errors, framework exceptions, and * generic errors. * * The middleware provides: * - Consistent error response formatting across all error types * - Event-driven error handling for monitoring and logging * - Content negotiation supporting JSON and YAML responses * - Recursive error cause handling to preserve error chains * - Configurable headers for CORS, security, and custom requirements * * @example * ```typescript * // Basic usage with default configuration * const middleware = new ODataErrorMiddleware({}) * router.use(middleware.handle) * * // Advanced usage with event handlers and custom headers * const middleware = new ODataErrorMiddleware({ * onVineValidationError: (error) => logger.warn('Validation failed', error), * onException: (error) => monitoring.captureException(error), * onAny: (error) => analytics.trackError(error), * headers: { * 'X-API-Version': '1.0', * 'Access-Control-Allow-Origin': '*' * } * }) * router.use(middleware.handle) * ``` * * @example * ```typescript * // Standalone usage outside of resourceful routes * import ODataErrorMiddleware from '@nhtio/lucid-resourceful/middlewares/resourceful_error' * * const errorHandler = new ODataErrorMiddleware({ * onException: (error) => logger.error(error), * headers: { 'X-Error-Handler': 'resourceful' } * }) * * router.use(errorHandler.handle) * ``` */ export declare class ODataErrorMiddleware { #private; /** * Creates a usable middleware function that can be applied directly to AdonisJS routes. * @param opts - Configuration options for the middleware * @returns A middleware function that can be used in AdonisJS routes */ static usable(opts?: ODataErrorMiddlewareOptions): (ctx: HttpContext, next: NextFn) => Promise; /** * Handles errors thrown during request processing. This method is meant to be integrated with the AdonisJS HttpExceptionHandler * @param error - The error that was thrown * @param ctx - The HTTP context object * @param opts - Configuration options for the middleware * @returns A Promise that resolves to the error response */ static handle(error: unknown, ctx: HttpContext, opts?: ODataErrorMiddlewareOptions): void; /** * Determines if the middleware should handle the request based on the desired response format. * If the desired format is HTML, it returns false to allow other handlers to process the request. * Otherwise, it returns true to indicate that this middleware should handle the error response. * * @param ctx - The HTTP context object containing request and response information * @returns A boolean indicating whether this middleware should handle the request */ static shouldHandle(_ctx: HttpContext): boolean; /** * Creates a new instance of ODataErrorMiddleware with the specified configuration. * * @param opts - Configuration options for the middleware * * @example * ```typescript * const middleware = new ODataErrorMiddleware({ * onVineValidationError: (error) => console.error('Validation:', error), * onException: (error) => monitoring.captureException(error), * asYaml: true, * headers: { 'X-API-Version': '1.0' } * }) * ``` */ constructor(opts: ODataErrorMiddlewareOptions); /** * AdonisJS middleware handler that intercepts and processes errors during request execution. * This method should be used as middleware in your route definitions. * * @param ctx - The HTTP context object containing request and response information * @param next - The next function to call in the middleware chain * * @example * ```typescript * const middleware = new ODataErrorMiddleware({}) * router.use(middleware.handle) * * // Or bind it to specific routes * router.get('/api/users', UserController.index).use([middleware.handle]) * ``` */ handle(ctx: HttpContext, next: NextFn): Promise; /** * Processes a caught error, emits appropriate events, and sends a formatted response. * This method handles error classification, event emission, content negotiation, * and response formatting. * * @param ctx - The HTTP context object * @param error - The error that was caught during request processing * * @example * ```typescript * // Typically called automatically by the handle method, but can be used directly * try { * // Some operation that might throw * } catch (error) { * middleware.onError(ctx, error) * } * ``` */ onError(ctx: HttpContext, error: unknown): void; }