try-catch-cloud
Version:
Advanced error logging for your app with low code integration
293 lines (253 loc) • 11.1 kB
text/typescript
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 { }