mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-12 16:55:37 +02:00
⭐ feat(www): Finish up on the onboarding (#210)
Merging this prematurely to make sure the team is on the same boat... like dang! We need to find a better way to do this. Plus it has become too big
This commit is contained in:
@@ -1,8 +1,145 @@
|
||||
import { z } from "zod"
|
||||
|
||||
/**
|
||||
* Standard error response schema used for OpenAPI documentation
|
||||
*/
|
||||
export const ErrorResponse = z
|
||||
.object({
|
||||
type: z
|
||||
.enum([
|
||||
"validation",
|
||||
"authentication",
|
||||
"forbidden",
|
||||
"not_found",
|
||||
"already_exists",
|
||||
"rate_limit",
|
||||
"internal",
|
||||
])
|
||||
.openapi({
|
||||
description: "The error type category",
|
||||
examples: ["validation", "authentication"],
|
||||
}),
|
||||
code: z.string().openapi({
|
||||
description: "Machine-readable error code identifier",
|
||||
examples: ["invalid_parameter", "missing_required_field", "unauthorized"],
|
||||
}),
|
||||
message: z.string().openapi({
|
||||
description: "Human-readable error message",
|
||||
examples: ["The request was invalid", "Authentication required"],
|
||||
}),
|
||||
param: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
description: "The parameter that caused the error (if applicable)",
|
||||
examples: ["email", "user_id", "team_id"],
|
||||
}),
|
||||
details: z.any().optional().openapi({
|
||||
description: "Additional error context information",
|
||||
}),
|
||||
})
|
||||
.openapi({ ref: "ErrorResponse" });
|
||||
|
||||
export type ErrorResponseType = z.infer<typeof ErrorResponse>;
|
||||
|
||||
/**
|
||||
* Standardized error codes for the API
|
||||
*/
|
||||
export const ErrorCodes = {
|
||||
// Validation errors (400)
|
||||
Validation: {
|
||||
MISSING_REQUIRED_FIELD: "missing_required_field",
|
||||
ALREADY_EXISTS: "resource_already_exists",
|
||||
TEAM_ALREADY_EXISTS: "team_already_exists",
|
||||
INVALID_PARAMETER: "invalid_parameter",
|
||||
INVALID_FORMAT: "invalid_format",
|
||||
INVALID_STATE: "invalid_state",
|
||||
IN_USE: "resource_in_use",
|
||||
},
|
||||
|
||||
// Authentication errors (401)
|
||||
Authentication: {
|
||||
UNAUTHORIZED: "unauthorized",
|
||||
INVALID_TOKEN: "invalid_token",
|
||||
EXPIRED_TOKEN: "expired_token",
|
||||
INVALID_CREDENTIALS: "invalid_credentials",
|
||||
},
|
||||
|
||||
// Permission errors (403)
|
||||
Permission: {
|
||||
FORBIDDEN: "forbidden",
|
||||
INSUFFICIENT_PERMISSIONS: "insufficient_permissions",
|
||||
ACCOUNT_RESTRICTED: "account_restricted",
|
||||
},
|
||||
|
||||
// Resource not found errors (404)
|
||||
NotFound: {
|
||||
RESOURCE_NOT_FOUND: "resource_not_found",
|
||||
},
|
||||
|
||||
// Rate limit errors (429)
|
||||
RateLimit: {
|
||||
TOO_MANY_REQUESTS: "too_many_requests",
|
||||
QUOTA_EXCEEDED: "quota_exceeded",
|
||||
},
|
||||
|
||||
// Server errors (500)
|
||||
Server: {
|
||||
INTERNAL_ERROR: "internal_error",
|
||||
SERVICE_UNAVAILABLE: "service_unavailable",
|
||||
DEPENDENCY_FAILURE: "dependency_failure",
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Standard error that will be exposed to clients through API responses
|
||||
*/
|
||||
export class VisibleError extends Error {
|
||||
constructor(
|
||||
public code: string,
|
||||
public message: string,
|
||||
) {
|
||||
super(message);
|
||||
constructor(
|
||||
public type: ErrorResponseType["type"],
|
||||
public code: string,
|
||||
public message: string,
|
||||
public param?: string,
|
||||
public details?: any,
|
||||
) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this error to an HTTP status code
|
||||
*/
|
||||
public statusCode(): number {
|
||||
switch (this.type) {
|
||||
case "validation":
|
||||
return 400;
|
||||
case "authentication":
|
||||
return 401;
|
||||
case "forbidden":
|
||||
return 403;
|
||||
case "not_found":
|
||||
return 404;
|
||||
case "already_exists":
|
||||
return 409;
|
||||
case "rate_limit":
|
||||
return 429;
|
||||
case "internal":
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this error to a standard response object
|
||||
*/
|
||||
public toResponse(): ErrorResponseType {
|
||||
const response: ErrorResponseType = {
|
||||
type: this.type,
|
||||
code: this.code,
|
||||
message: this.message,
|
||||
};
|
||||
|
||||
if (this.param) response.param = this.param;
|
||||
if (this.details) response.details = this.details;
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user