Initial boilerplate scaffold for continuum-common
Adds ts-core (logger, Supabase JWT verification, Elysia error transformers) and rust-core (thiserror error type, tracing init, G-code checksum/header parsing) packages.
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
export abstract class HttpError extends Error {
|
||||
abstract readonly status: number;
|
||||
abstract readonly code: string;
|
||||
|
||||
constructor(message: string, readonly details?: unknown) {
|
||||
super(message);
|
||||
this.name = new.target.name;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
error: {
|
||||
code: this.code,
|
||||
message: this.message,
|
||||
details: this.details,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class BadRequestError extends HttpError {
|
||||
readonly status = 400;
|
||||
readonly code = "BAD_REQUEST";
|
||||
}
|
||||
|
||||
export class UnauthorizedError extends HttpError {
|
||||
readonly status = 401;
|
||||
readonly code = "UNAUTHORIZED";
|
||||
}
|
||||
|
||||
export class ForbiddenError extends HttpError {
|
||||
readonly status = 403;
|
||||
readonly code = "FORBIDDEN";
|
||||
}
|
||||
|
||||
export class NotFoundError extends HttpError {
|
||||
readonly status = 404;
|
||||
readonly code = "NOT_FOUND";
|
||||
}
|
||||
|
||||
export class ConflictError extends HttpError {
|
||||
readonly status = 409;
|
||||
readonly code = "CONFLICT";
|
||||
}
|
||||
|
||||
export class InternalError extends HttpError {
|
||||
readonly status = 500;
|
||||
readonly code = "INTERNAL_ERROR";
|
||||
}
|
||||
|
||||
interface ElysiaErrorContext {
|
||||
code: string | number;
|
||||
error: unknown;
|
||||
set: { status?: number | string };
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop-in handler for Elysia's `.onError()`. Maps our HttpError hierarchy,
|
||||
* Elysia's built-in error codes, and anything unrecognized to a consistent
|
||||
* `{ error: { code, message, details? } }` JSON body.
|
||||
*/
|
||||
export function toErrorResponse({ code, error, set }: ElysiaErrorContext) {
|
||||
if (error instanceof HttpError) {
|
||||
set.status = error.status;
|
||||
return error.toJSON();
|
||||
}
|
||||
|
||||
if (code === "VALIDATION") {
|
||||
set.status = 422;
|
||||
return {
|
||||
error: {
|
||||
code: "VALIDATION",
|
||||
message: error instanceof Error ? error.message : "validation failed",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (code === "NOT_FOUND") {
|
||||
set.status = 404;
|
||||
return { error: { code: "NOT_FOUND", message: "not found" } };
|
||||
}
|
||||
|
||||
set.status = 500;
|
||||
return {
|
||||
error: {
|
||||
code: "INTERNAL_ERROR",
|
||||
message: error instanceof Error ? error.message : "internal server error",
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user