- v2: auth/signup, auth/login (+ code step, rate limited), PATCH /me; check-in look-up and scan returning an outcome for every normal result. Campus rule as v1. - Sign up/login/2FA/profile moved to src/services/auth.ts; scan preview and scan to src/services/checkin.ts. v1 answers unchanged (ServiceError v1Status). - Login, 2FA step, sign up and profile/password pages use v2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ls1vMdg2GYqbnKZmPaX1ot
27 lines
1.1 KiB
TypeScript
27 lines
1.1 KiB
TypeScript
/**
|
|
* An error from a service (src/services/*) with the HTTP status it means. v2 turns it into its
|
|
* error shape by the status (v2/errors.ts); v1 controllers keep answering as they always did —
|
|
* `v1Status` when v1 used a different status for it (e.g. 400 for a wrong password).
|
|
*/
|
|
export class ServiceError extends Error {
|
|
readonly statusCode: number;
|
|
/** Extra, e.g. a code the caller can switch on. */
|
|
readonly code?: string;
|
|
readonly v1Status?: number;
|
|
|
|
constructor(statusCode: number, message: string, code?: string, opts: { v1Status?: number } = {}) {
|
|
super(message);
|
|
this.statusCode = statusCode;
|
|
this.code = code;
|
|
this.v1Status = opts.v1Status;
|
|
}
|
|
}
|
|
|
|
export const fail = (statusCode: number, message: string, code?: string, opts?: { v1Status?: number }): never => {
|
|
throw new ServiceError(statusCode, message, code, opts);
|
|
};
|
|
|
|
/** The status a v1 controller answers for an error (its old one where it differs). */
|
|
export const v1StatusOf = (error: { v1Status?: number; statusCode?: number } | null | undefined, fallback: number): number =>
|
|
error?.v1Status || error?.statusCode || fallback;
|