UNPKG

try-catch-cloud

Version:

Advanced error logging for your app with low code integration

293 lines (253 loc) 11.1 kB
import type { APIGatewayEvent } from 'aws-lambda'; import type { AxiosError } from 'axios'; import type { ErrorRequestHandler } from 'express'; import type { HonoRequest } from 'hono'; import type { MiddlewareHandler } from 'hono'; import type { MiddlewareObj } from '@middy/core'; import type { Request as Request_2 } from 'express'; import type { RequestHandler } from 'express'; /** * Adds context details to try-catch-cloud error. * If you call it multiple times, it collects all details, * but details with the same name will be overwritten with the latest value. * * @example * addContext(req, { username: 'hugo_reyes8' }); // Context: { username: 'hugo_reyes8' } * addContext(req, { age: 29 }); // Context: { username: 'hugo_reyes8', age: 29 } * addContext(req, { age: 32 }); // Context: { username: 'hugo_reyes8', age: 32 } * * @param req - Express request * @param details - Context details */ export declare const addContext: (req: Request_2, details: Record<string, unknown>) => void; export declare function addContext_alias_1(ctx: ErrorContext_alias_1): void; export declare type APIGatewayEventCommon = Partial<Pick<APIGatewayEvent, "httpMethod" | "path" | "queryStringParameters" | "body" | "headers">>; export declare type AxiosErrorRequest = ErrorRequest<{ url: string | null; query: Record<string, string | string[] | undefined> | null; params: unknown | null; method: string | null; statusCode: number; requestBody: unknown | null; responseBody: unknown | null; }>; export declare abstract class BaseErrorUtility<TRequest> implements ErrorUtilityMethods<TRequest> { protected readonly projectName: string; protected readonly apiKey: string; protected readonly debug?: boolean | undefined; constructor(projectName: string, apiKey: string, debug?: boolean | undefined); protected abstract mapRequest(request: TRequest): Promise<MappedHttpRequest> | MappedHttpRequest; sendError(error: Error | unknown, userContext?: Record<string, unknown>): Promise<{ id: string; } | undefined>; /** * Sends error and request details to try-catch-cloud service. * You can manually map details from your route to request object. * * ``` * errorTrack.sendErrorFromEndpoint( * error, * { * url: req.originalUrl.split("?")[0], * method: req.method, * headers: req.headers, * query: req.query, * body, * }, * { ...context } * ); * ``` */ sendErrorFromEndPoint(error: Error | unknown, request: TRequest, userContext?: Record<string, unknown>): Promise<{ id: string; } | undefined>; protected send(payload: ErrorRequest): Promise<{ id: string; }>; /** * It has to return Promise to be compatible with different implementations * e.g. Hono returns Promise when accessing req.json() */ protected mapErrorRequestPayload(error: Error | unknown, request?: TRequest, context?: Record<string, unknown>): Promise<ErrorRequest>; protected mapAxiosRequestBody(error: AxiosError): any; protected mapAxiosError(error: AxiosError, request?: TRequest, context?: ErrorRequestContext): Promise<AxiosErrorRequest>; protected sanitizeValue(value: unknown, level?: number): unknown; } declare type BaseHandlerContext<TErrorUtility extends ExpressErrorUtility> = { instance: TErrorUtility; }; export declare interface BasicMiddlewareOptions { projectName: string; apiKey: string; } declare class CloudflareErrorUtility extends BaseErrorUtility<HttpRequest> { protected mapRequest(req: HttpRequest): Promise<MappedHttpRequest>; } export { CloudflareErrorUtility } export { CloudflareErrorUtility as CloudflareErrorUtility_alias_1 } export declare type ErrorContext = Record<string, unknown>; export declare type ErrorContext_alias_1 = Record<string, unknown>; export declare type ErrorDetails<T extends Record<string, unknown> = Record<string, unknown>> = { name: string; message: string; } & T; export declare interface ErrorRequest<TDetails extends Record<string, unknown> = Record<string, unknown>> { errorName: string; errorDetails: ErrorDetails<TDetails>; stack: string | null; context: ErrorRequestContext; user: string; projectName: string; } export declare type ErrorRequestContext = Record<string, unknown> | null; /** * Implements universal request mapping, you can map details from your request object manually. * See `sendErrorFromEndPoint` method. */ declare class ErrorUtility extends BaseErrorUtility<HttpRequest> { protected mapRequest<TRequest extends HttpRequest = HttpRequest>(req: TRequest): MappedHttpRequest; sendErrorFromEndPoint(error: unknown, request: HttpRequest, userContext?: Record<string, unknown> | undefined): Promise<SendErrorResponse>; } export { ErrorUtility } export { ErrorUtility as ErrorUtility_alias_1 } export { ErrorUtility as ErrorUtility_alias_2 } export declare interface ErrorUtilityMethods<TRequest> { sendError(error: Error | unknown, userContext?: Record<string, unknown>): Promise<SendErrorResponse>; sendErrorFromEndPoint(error: Error | unknown, request: TRequest, userContext?: Record<string, unknown>): Promise<SendErrorResponse>; } export declare namespace express { export { ExpressErrorUtility, setupTryCatch, addContext } } /** * Implements request mapping for Express. * See `sendErrorFromEndPoint` method. */ declare class ExpressErrorUtility extends BaseErrorUtility<Request_2> { protected mapRequest(req: Request_2): MappedHttpRequest; /** * Sends error and Express request details to try-catch-cloud service. * ``` * app.use((error, req, res, next) => { * errorUtility.sendErrorFromEndPoint(error, req) * .catch((e) => { ... }); * * res.status(500).json({ message: "Internal server error" }); * }); * ``` */ sendErrorFromEndPoint(error: unknown, request: Request_2, userContext?: Record<string, unknown> | undefined): Promise<SendErrorResponse>; } export { ExpressErrorUtility } export { ExpressErrorUtility as ExpressErrorUtility_alias_1 } export declare type ExpressMiddlewareSetup<TMiddlewareOptions extends BasicMiddlewareOptions> = (opts: TMiddlewareOptions) => { initialize: RequestHandler; onError: ErrorRequestHandler; }; export declare type ExtendedRequest = Request_2 & { tryCatchContext: Record<string, unknown>; }; declare interface FactoryContext<TInstance extends HonoErrorUtility> { instance: TInstance; } export declare namespace hono { export { HonoErrorUtility, tryCatch } } /** * Implements request mapping for Hono. * See `sendErrorFromEndPoint` method. */ declare class HonoErrorUtility extends BaseErrorUtility<HonoRequest> { protected mapRequest<TRequest extends HonoRequest = HonoRequest>(req: TRequest): Promise<MappedHttpRequest>; /** * Sends error and Hono request details to try-catch-cloud service. * ``` * app.onError(async (err, ctx) => { * errorUtility.sendErrorFromEndPoint(err, ctx.req, { ...errorContext }) * .catch((e) => { ... }); * * return ctx.json({ message: 'Internal server error' }, 500); * }); * ``` */ sendErrorFromEndPoint(error: unknown, request: HonoRequest, userContext?: Record<string, unknown> | undefined): Promise<SendErrorResponse>; } export { HonoErrorUtility } export { HonoErrorUtility as HonoErrorUtility_alias_1 } export declare type HonoMiddlewareSetup<TMiddlewareOptions extends MiddlewareOptions = MiddlewareOptions> = (options: TMiddlewareOptions) => MiddlewareHandler; export declare interface HttpRequest { url?: string; method?: string; path?: string; body?: unknown; query?: Record<string, unknown>; headers?: Record<string, unknown>; } export declare function isAxiosError(e: unknown): e is AxiosError; export declare namespace lambda { export { tryCatch_alias_1 as tryCatch, addContext_alias_1 as addContext, LambdaErrorUtility } } declare class LambdaErrorUtility extends BaseErrorUtility<APIGatewayEventCommon> { protected mapRequest(request: APIGatewayEventCommon): MappedHttpRequest | Promise<MappedHttpRequest>; sendErrorFromEndPoint: (error: unknown, request: APIGatewayEventCommon, userContext?: Record<string, unknown> | undefined) => Promise<SendErrorResponse>; } export { LambdaErrorUtility } export { LambdaErrorUtility as LambdaErrorUtility_alias_1 } export declare interface MappedHttpRequest { method: string | null; url: string | null; requestBody: unknown | null; query: Record<string, unknown> | null; headers: Record<string, unknown> | null; } export declare interface MiddlewareOptions { projectName: string; apiKey: string; debug?: boolean; } export declare interface MiddlewareOptions_alias_1 { projectName: string; apiKey: string; } export declare type SendErrorResponse = { id: string; } | undefined; /** * It returns two handlers - `initialize` and `onError`. * Add `initialize` to your app using `app.use` before all route handlers. * Add `onError` after all route handlers and before other error handlers. * * @param MiddlewareOptions - pass project name and your API key here. */ export declare const setupTryCatch: ExpressMiddlewareSetup<BasicMiddlewareOptions>; export declare const setupTryCatchFactory: <TErrorUtility extends ExpressErrorUtility, THandlerContext extends BaseHandlerContext<TErrorUtility>, TMiddlewareOptions extends BasicMiddlewareOptions = BasicMiddlewareOptions>(factoryOptions: { createContext: (options: TMiddlewareOptions) => THandlerContext; handlers: { initialize: (context: THandlerContext) => RequestHandler; onError: (context: THandlerContext) => ErrorRequestHandler; }; }) => ExpressMiddlewareSetup<TMiddlewareOptions>; export declare const tryCatch: HonoMiddlewareSetup<MiddlewareOptions>; export declare function tryCatch_alias_1({ projectName, apiKey, }: MiddlewareOptions_alias_1): MiddlewareObj<APIGatewayEventCommon>; export declare interface TryCatchContext { addContext: (errorContext: ErrorContext) => void; } export declare const tryCatchFactory: <TInstance extends HonoErrorUtility, TFactoryContext extends FactoryContext<TInstance>>(factoryOptions: { createContext: (options: MiddlewareOptions) => TFactoryContext; handler: (context: TFactoryContext) => MiddlewareHandler; }) => HonoMiddlewareSetup; export declare class WrappedError extends Error { readonly value: unknown; constructor(message: string, value: unknown); } export { }