metatron-open-seo/src/server/lib/serverFnErrorBoundary.ts
2026-02-27 14:09:33 -05:00

52 lines
1.4 KiB
TypeScript

export class PublicServerError extends Error {
constructor(message: string) {
super(message);
this.name = "PublicServerError";
}
}
interface ErrorBoundaryOptions<TArgs> {
fallbackMessage?: string;
passThroughMessages?: string[];
getLogContext?: (args: TArgs) => Record<string, unknown>;
}
export function withServerFnErrorBoundary<TArgs, TResult>(
operation: string,
handler: (args: TArgs) => Promise<TResult>,
options: ErrorBoundaryOptions<TArgs> = {},
) {
const passThroughMessages = new Set(options.passThroughMessages ?? []);
return async (args: TArgs): Promise<TResult> => {
try {
return await handler(args);
} catch (error) {
if (error instanceof PublicServerError) {
throw error;
}
if (error instanceof Error && passThroughMessages.has(error.message)) {
throw error;
}
const message = error instanceof Error ? error.message : String(error);
const cause =
error instanceof Error && "cause" in error
? (error as { cause?: unknown }).cause
: undefined;
const logContext = options.getLogContext?.(args);
console.error(`${operation} failed`, {
message,
cause,
stack: error instanceof Error ? error.stack : undefined,
...logContext,
});
throw new PublicServerError(
options.fallbackMessage ?? "Something went wrong. Please try again.",
);
}
};
}