mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 15:39:40 +02:00
style: auto-format codebase with Prettier
Applied formatting to 1487+ files using pnpm format:write - TypeScript/JavaScript files - Svelte components - Astro pages - JSON configs - Markdown docs 13 files still need manual review (Astro JSX comments)
This commit is contained in:
parent
0241f5554c
commit
d36b321d9d
3952 changed files with 661498 additions and 739751 deletions
|
|
@ -1,26 +1,22 @@
|
|||
import {
|
||||
ErrorCode,
|
||||
ERROR_CODE_TO_HTTP_STATUS,
|
||||
ERROR_CODE_RETRYABLE,
|
||||
} from '../types/error-codes';
|
||||
import { ErrorCode, ERROR_CODE_TO_HTTP_STATUS, ERROR_CODE_RETRYABLE } from '../types/error-codes';
|
||||
|
||||
/**
|
||||
* Additional context that can be attached to errors.
|
||||
*/
|
||||
export interface ErrorContext {
|
||||
[key: string]: unknown;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for creating an AppError.
|
||||
*/
|
||||
export interface AppErrorOptions {
|
||||
code: ErrorCode;
|
||||
message: string;
|
||||
cause?: Error | AppError;
|
||||
context?: ErrorContext;
|
||||
httpStatus?: number;
|
||||
retryable?: boolean;
|
||||
code: ErrorCode;
|
||||
message: string;
|
||||
cause?: Error | AppError;
|
||||
context?: ErrorContext;
|
||||
httpStatus?: number;
|
||||
retryable?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -50,130 +46,126 @@ export interface AppErrorOptions {
|
|||
* ```
|
||||
*/
|
||||
export class AppError extends Error {
|
||||
/** Standardized error code */
|
||||
readonly code: ErrorCode;
|
||||
/** Standardized error code */
|
||||
readonly code: ErrorCode;
|
||||
|
||||
/** HTTP status code for API responses */
|
||||
readonly httpStatus: number;
|
||||
/** HTTP status code for API responses */
|
||||
readonly httpStatus: number;
|
||||
|
||||
/** Whether the operation can be retried */
|
||||
readonly retryable: boolean;
|
||||
/** Whether the operation can be retried */
|
||||
readonly retryable: boolean;
|
||||
|
||||
/** Original error that caused this error (for wrapping) */
|
||||
readonly cause?: Error | AppError;
|
||||
/** Original error that caused this error (for wrapping) */
|
||||
readonly cause?: Error | AppError;
|
||||
|
||||
/** Additional context information */
|
||||
readonly context: ErrorContext;
|
||||
/** Additional context information */
|
||||
readonly context: ErrorContext;
|
||||
|
||||
/** Timestamp when error was created */
|
||||
readonly timestamp: string;
|
||||
/** Timestamp when error was created */
|
||||
readonly timestamp: string;
|
||||
|
||||
constructor(options: AppErrorOptions) {
|
||||
super(options.message);
|
||||
this.name = 'AppError';
|
||||
this.code = options.code;
|
||||
this.cause = options.cause;
|
||||
this.context = options.context ?? {};
|
||||
this.timestamp = new Date().toISOString();
|
||||
constructor(options: AppErrorOptions) {
|
||||
super(options.message);
|
||||
this.name = 'AppError';
|
||||
this.code = options.code;
|
||||
this.cause = options.cause;
|
||||
this.context = options.context ?? {};
|
||||
this.timestamp = new Date().toISOString();
|
||||
|
||||
// Use provided values or defaults from mappings
|
||||
this.httpStatus =
|
||||
options.httpStatus ?? ERROR_CODE_TO_HTTP_STATUS[options.code];
|
||||
this.retryable = options.retryable ?? ERROR_CODE_RETRYABLE[options.code];
|
||||
// Use provided values or defaults from mappings
|
||||
this.httpStatus = options.httpStatus ?? ERROR_CODE_TO_HTTP_STATUS[options.code];
|
||||
this.retryable = options.retryable ?? ERROR_CODE_RETRYABLE[options.code];
|
||||
|
||||
// Capture stack trace
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
// Capture stack trace
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a wrapped error with additional context.
|
||||
* Similar to Go's `fmt.Errorf("context: %w", err)`.
|
||||
*
|
||||
* @param contextMessage - Description of the operation that failed
|
||||
* @param additionalContext - Extra context data to include
|
||||
* @returns A new AppError with the original as its cause
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const wrapped = originalError.wrap('fetching user data');
|
||||
* // Message: "fetching user data: original message"
|
||||
* ```
|
||||
*/
|
||||
wrap(contextMessage: string, additionalContext?: ErrorContext): AppError {
|
||||
return new AppError({
|
||||
code: this.code,
|
||||
message: `${contextMessage}: ${this.message}`,
|
||||
cause: this,
|
||||
context: { ...this.context, ...additionalContext },
|
||||
httpStatus: this.httpStatus,
|
||||
retryable: this.retryable,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Create a wrapped error with additional context.
|
||||
* Similar to Go's `fmt.Errorf("context: %w", err)`.
|
||||
*
|
||||
* @param contextMessage - Description of the operation that failed
|
||||
* @param additionalContext - Extra context data to include
|
||||
* @returns A new AppError with the original as its cause
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const wrapped = originalError.wrap('fetching user data');
|
||||
* // Message: "fetching user data: original message"
|
||||
* ```
|
||||
*/
|
||||
wrap(contextMessage: string, additionalContext?: ErrorContext): AppError {
|
||||
return new AppError({
|
||||
code: this.code,
|
||||
message: `${contextMessage}: ${this.message}`,
|
||||
cause: this,
|
||||
context: { ...this.context, ...additionalContext },
|
||||
httpStatus: this.httpStatus,
|
||||
retryable: this.retryable,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root cause of the error chain.
|
||||
* Traverses the cause chain to find the original error.
|
||||
*/
|
||||
rootCause(): Error {
|
||||
let current: Error = this;
|
||||
while (current instanceof AppError && current.cause) {
|
||||
current = current.cause;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
/**
|
||||
* Get the root cause of the error chain.
|
||||
* Traverses the cause chain to find the original error.
|
||||
*/
|
||||
rootCause(): Error {
|
||||
let current: Error = this;
|
||||
while (current instanceof AppError && current.cause) {
|
||||
current = current.cause;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this error or any in the chain has the given code.
|
||||
* Similar to Go's `errors.Is()`.
|
||||
*
|
||||
* @param code - The error code to check for
|
||||
* @returns true if this error or any cause has the given code
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* if (error.hasCode(ErrorCode.INSUFFICIENT_CREDITS)) {
|
||||
* // Show upgrade prompt
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
hasCode(code: ErrorCode): boolean {
|
||||
let current: Error | undefined = this;
|
||||
while (current) {
|
||||
if (current instanceof AppError && current.code === code) {
|
||||
return true;
|
||||
}
|
||||
current = current instanceof AppError ? current.cause : undefined;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Check if this error or any in the chain has the given code.
|
||||
* Similar to Go's `errors.Is()`.
|
||||
*
|
||||
* @param code - The error code to check for
|
||||
* @returns true if this error or any cause has the given code
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* if (error.hasCode(ErrorCode.INSUFFICIENT_CREDITS)) {
|
||||
* // Show upgrade prompt
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
hasCode(code: ErrorCode): boolean {
|
||||
let current: Error | undefined = this;
|
||||
while (current) {
|
||||
if (current instanceof AppError && current.code === code) {
|
||||
return true;
|
||||
}
|
||||
current = current instanceof AppError ? current.cause : undefined;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to JSON for API responses.
|
||||
* Excludes stack traces and internal details.
|
||||
*/
|
||||
toJSON(): Record<string, unknown> {
|
||||
return {
|
||||
code: this.code,
|
||||
message: this.message,
|
||||
httpStatus: this.httpStatus,
|
||||
retryable: this.retryable,
|
||||
timestamp: this.timestamp,
|
||||
...(Object.keys(this.context).length > 0 && { details: this.context }),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Convert to JSON for API responses.
|
||||
* Excludes stack traces and internal details.
|
||||
*/
|
||||
toJSON(): Record<string, unknown> {
|
||||
return {
|
||||
code: this.code,
|
||||
message: this.message,
|
||||
httpStatus: this.httpStatus,
|
||||
retryable: this.retryable,
|
||||
timestamp: this.timestamp,
|
||||
...(Object.keys(this.context).length > 0 && { details: this.context }),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to full JSON including stack and cause (for logging).
|
||||
* Use this for server-side logging, not client responses.
|
||||
*/
|
||||
toFullJSON(): Record<string, unknown> {
|
||||
return {
|
||||
...this.toJSON(),
|
||||
stack: this.stack,
|
||||
cause:
|
||||
this.cause instanceof AppError
|
||||
? this.cause.toFullJSON()
|
||||
: this.cause?.message,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Convert to full JSON including stack and cause (for logging).
|
||||
* Use this for server-side logging, not client responses.
|
||||
*/
|
||||
toFullJSON(): Record<string, unknown> {
|
||||
return {
|
||||
...this.toJSON(),
|
||||
stack: this.stack,
|
||||
cause: this.cause instanceof AppError ? this.cause.toFullJSON() : this.cause?.message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import { ErrorCode } from '../types/error-codes';
|
|||
import { AppError, type ErrorContext } from './app-error';
|
||||
|
||||
type AuthErrorCode =
|
||||
| ErrorCode.AUTHENTICATION_REQUIRED
|
||||
| ErrorCode.INVALID_TOKEN
|
||||
| ErrorCode.TOKEN_EXPIRED
|
||||
| ErrorCode.PERMISSION_DENIED
|
||||
| ErrorCode.RESOURCE_NOT_OWNED;
|
||||
| ErrorCode.AUTHENTICATION_REQUIRED
|
||||
| ErrorCode.INVALID_TOKEN
|
||||
| ErrorCode.TOKEN_EXPIRED
|
||||
| ErrorCode.PERMISSION_DENIED
|
||||
| ErrorCode.RESOURCE_NOT_OWNED;
|
||||
|
||||
/**
|
||||
* Error for authentication and authorization failures.
|
||||
|
|
@ -25,55 +25,54 @@ type AuthErrorCode =
|
|||
* ```
|
||||
*/
|
||||
export class AuthError extends AppError {
|
||||
constructor(code: AuthErrorCode, message: string, context?: ErrorContext) {
|
||||
super({ code, message, context });
|
||||
this.name = 'AuthError';
|
||||
}
|
||||
constructor(code: AuthErrorCode, message: string, context?: ErrorContext) {
|
||||
super({ code, message, context });
|
||||
this.name = 'AuthError';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error for missing authentication.
|
||||
* HTTP 401 Unauthorized
|
||||
*/
|
||||
static unauthorized(message = 'Authentication required'): AuthError {
|
||||
return new AuthError(ErrorCode.AUTHENTICATION_REQUIRED, message);
|
||||
}
|
||||
/**
|
||||
* Create an error for missing authentication.
|
||||
* HTTP 401 Unauthorized
|
||||
*/
|
||||
static unauthorized(message = 'Authentication required'): AuthError {
|
||||
return new AuthError(ErrorCode.AUTHENTICATION_REQUIRED, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error for an invalid token.
|
||||
* HTTP 401 Unauthorized
|
||||
*/
|
||||
static invalidToken(message = 'Invalid or malformed token'): AuthError {
|
||||
return new AuthError(ErrorCode.INVALID_TOKEN, message);
|
||||
}
|
||||
/**
|
||||
* Create an error for an invalid token.
|
||||
* HTTP 401 Unauthorized
|
||||
*/
|
||||
static invalidToken(message = 'Invalid or malformed token'): AuthError {
|
||||
return new AuthError(ErrorCode.INVALID_TOKEN, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error for an expired token.
|
||||
* HTTP 401 Unauthorized
|
||||
*/
|
||||
static tokenExpired(message = 'Token has expired'): AuthError {
|
||||
return new AuthError(ErrorCode.TOKEN_EXPIRED, message);
|
||||
}
|
||||
/**
|
||||
* Create an error for an expired token.
|
||||
* HTTP 401 Unauthorized
|
||||
*/
|
||||
static tokenExpired(message = 'Token has expired'): AuthError {
|
||||
return new AuthError(ErrorCode.TOKEN_EXPIRED, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error for insufficient permissions.
|
||||
* HTTP 403 Forbidden
|
||||
*/
|
||||
static forbidden(message = 'Permission denied'): AuthError {
|
||||
return new AuthError(ErrorCode.PERMISSION_DENIED, message);
|
||||
}
|
||||
/**
|
||||
* Create an error for insufficient permissions.
|
||||
* HTTP 403 Forbidden
|
||||
*/
|
||||
static forbidden(message = 'Permission denied'): AuthError {
|
||||
return new AuthError(ErrorCode.PERMISSION_DENIED, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error when a user tries to access a resource they don't own.
|
||||
* HTTP 403 Forbidden
|
||||
*
|
||||
* @param resourceType - Type of resource (e.g., 'Story', 'Character')
|
||||
* @param resourceId - ID of the resource
|
||||
*/
|
||||
static notOwned(resourceType: string, resourceId: string): AuthError {
|
||||
return new AuthError(
|
||||
ErrorCode.RESOURCE_NOT_OWNED,
|
||||
`${resourceType} does not belong to you`,
|
||||
{ resourceType, resourceId }
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Create an error when a user tries to access a resource they don't own.
|
||||
* HTTP 403 Forbidden
|
||||
*
|
||||
* @param resourceType - Type of resource (e.g., 'Story', 'Character')
|
||||
* @param resourceId - ID of the resource
|
||||
*/
|
||||
static notOwned(resourceType: string, resourceId: string): AuthError {
|
||||
return new AuthError(ErrorCode.RESOURCE_NOT_OWNED, `${resourceType} does not belong to you`, {
|
||||
resourceType,
|
||||
resourceId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,24 +12,20 @@ import { AppError } from './app-error';
|
|||
* ```
|
||||
*/
|
||||
export class CreditError extends AppError {
|
||||
/** Credits required for the operation */
|
||||
readonly requiredCredits: number;
|
||||
/** Credits required for the operation */
|
||||
readonly requiredCredits: number;
|
||||
|
||||
/** Credits currently available */
|
||||
readonly availableCredits: number;
|
||||
/** Credits currently available */
|
||||
readonly availableCredits: number;
|
||||
|
||||
constructor(
|
||||
requiredCredits: number,
|
||||
availableCredits: number,
|
||||
operation?: string
|
||||
) {
|
||||
super({
|
||||
code: ErrorCode.INSUFFICIENT_CREDITS,
|
||||
message: `Insufficient credits. Required: ${requiredCredits}, Available: ${availableCredits}`,
|
||||
context: { requiredCredits, availableCredits, operation },
|
||||
});
|
||||
this.name = 'CreditError';
|
||||
this.requiredCredits = requiredCredits;
|
||||
this.availableCredits = availableCredits;
|
||||
}
|
||||
constructor(requiredCredits: number, availableCredits: number, operation?: string) {
|
||||
super({
|
||||
code: ErrorCode.INSUFFICIENT_CREDITS,
|
||||
message: `Insufficient credits. Required: ${requiredCredits}, Available: ${availableCredits}`,
|
||||
context: { requiredCredits, availableCredits, operation },
|
||||
});
|
||||
this.name = 'CreditError';
|
||||
this.requiredCredits = requiredCredits;
|
||||
this.availableCredits = availableCredits;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,38 +17,28 @@ type DatabaseErrorCode = ErrorCode.DATABASE_ERROR | ErrorCode.CONSTRAINT_VIOLATI
|
|||
* ```
|
||||
*/
|
||||
export class DatabaseError extends AppError {
|
||||
constructor(
|
||||
code: DatabaseErrorCode,
|
||||
message: string,
|
||||
cause?: Error,
|
||||
context?: ErrorContext
|
||||
) {
|
||||
super({ code, message, cause, context });
|
||||
this.name = 'DatabaseError';
|
||||
}
|
||||
constructor(code: DatabaseErrorCode, message: string, cause?: Error, context?: ErrorContext) {
|
||||
super({ code, message, cause, context });
|
||||
this.name = 'DatabaseError';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a constraint violation error (e.g., unique constraint).
|
||||
*
|
||||
* @param field - The field that violated the constraint
|
||||
* @param message - Description of the violation
|
||||
*/
|
||||
static constraintViolation(field: string, message: string): DatabaseError {
|
||||
return new DatabaseError(
|
||||
ErrorCode.CONSTRAINT_VIOLATION,
|
||||
message,
|
||||
undefined,
|
||||
{ field }
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Create a constraint violation error (e.g., unique constraint).
|
||||
*
|
||||
* @param field - The field that violated the constraint
|
||||
* @param message - Description of the violation
|
||||
*/
|
||||
static constraintViolation(field: string, message: string): DatabaseError {
|
||||
return new DatabaseError(ErrorCode.CONSTRAINT_VIOLATION, message, undefined, { field });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a generic database query error.
|
||||
*
|
||||
* @param message - Description of what went wrong
|
||||
* @param cause - Original error if available
|
||||
*/
|
||||
static queryFailed(message: string, cause?: Error): DatabaseError {
|
||||
return new DatabaseError(ErrorCode.DATABASE_ERROR, message, cause);
|
||||
}
|
||||
/**
|
||||
* Create a generic database query error.
|
||||
*
|
||||
* @param message - Description of what went wrong
|
||||
* @param cause - Original error if available
|
||||
*/
|
||||
static queryFailed(message: string, cause?: Error): DatabaseError {
|
||||
return new DatabaseError(ErrorCode.DATABASE_ERROR, message, cause);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
import { ErrorCode } from '../types/error-codes';
|
||||
import { AppError, type ErrorContext } from './app-error';
|
||||
|
||||
type NetworkErrorCode =
|
||||
| ErrorCode.NETWORK_ERROR
|
||||
| ErrorCode.TIMEOUT
|
||||
| ErrorCode.CONNECTION_REFUSED;
|
||||
type NetworkErrorCode = ErrorCode.NETWORK_ERROR | ErrorCode.TIMEOUT | ErrorCode.CONNECTION_REFUSED;
|
||||
|
||||
/**
|
||||
* Error for network-level failures (timeouts, connection issues, etc.).
|
||||
|
|
@ -23,41 +20,33 @@ type NetworkErrorCode =
|
|||
* ```
|
||||
*/
|
||||
export class NetworkError extends AppError {
|
||||
constructor(
|
||||
code: NetworkErrorCode,
|
||||
message: string,
|
||||
cause?: Error,
|
||||
context?: ErrorContext
|
||||
) {
|
||||
super({ code, message, cause, context });
|
||||
this.name = 'NetworkError';
|
||||
}
|
||||
constructor(code: NetworkErrorCode, message: string, cause?: Error, context?: ErrorContext) {
|
||||
super({ code, message, cause, context });
|
||||
this.name = 'NetworkError';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a timeout error.
|
||||
*
|
||||
* @param operation - Description of the operation that timed out
|
||||
*/
|
||||
static timeout(operation: string): NetworkError {
|
||||
return new NetworkError(
|
||||
ErrorCode.TIMEOUT,
|
||||
`Operation timed out: ${operation}`,
|
||||
undefined,
|
||||
{ operation }
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Create a timeout error.
|
||||
*
|
||||
* @param operation - Description of the operation that timed out
|
||||
*/
|
||||
static timeout(operation: string): NetworkError {
|
||||
return new NetworkError(ErrorCode.TIMEOUT, `Operation timed out: ${operation}`, undefined, {
|
||||
operation,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a connection refused error.
|
||||
*
|
||||
* @param service - Name of the service that refused connection
|
||||
*/
|
||||
static connectionRefused(service: string): NetworkError {
|
||||
return new NetworkError(
|
||||
ErrorCode.CONNECTION_REFUSED,
|
||||
`Connection refused: ${service}`,
|
||||
undefined,
|
||||
{ service }
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Create a connection refused error.
|
||||
*
|
||||
* @param service - Name of the service that refused connection
|
||||
*/
|
||||
static connectionRefused(service: string): NetworkError {
|
||||
return new NetworkError(
|
||||
ErrorCode.CONNECTION_REFUSED,
|
||||
`Connection refused: ${service}`,
|
||||
undefined,
|
||||
{ service }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,30 +16,26 @@ import { AppError, type ErrorContext } from './app-error';
|
|||
* ```
|
||||
*/
|
||||
export class NotFoundError extends AppError {
|
||||
constructor(
|
||||
resourceType: string,
|
||||
identifier: string,
|
||||
context?: ErrorContext
|
||||
) {
|
||||
super({
|
||||
code: ErrorCode.RESOURCE_NOT_FOUND,
|
||||
message: `${resourceType} not found: ${identifier}`,
|
||||
context: { resourceType, identifier, ...context },
|
||||
});
|
||||
this.name = 'NotFoundError';
|
||||
}
|
||||
constructor(resourceType: string, identifier: string, context?: ErrorContext) {
|
||||
super({
|
||||
code: ErrorCode.RESOURCE_NOT_FOUND,
|
||||
message: `${resourceType} not found: ${identifier}`,
|
||||
context: { resourceType, identifier, ...context },
|
||||
});
|
||||
this.name = 'NotFoundError';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a not found error for a user.
|
||||
*/
|
||||
static user(userId: string): NotFoundError {
|
||||
return new NotFoundError('User', userId);
|
||||
}
|
||||
/**
|
||||
* Create a not found error for a user.
|
||||
*/
|
||||
static user(userId: string): NotFoundError {
|
||||
return new NotFoundError('User', userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a not found error for any resource type.
|
||||
*/
|
||||
static resource(resourceType: string, identifier: string): NotFoundError {
|
||||
return new NotFoundError(resourceType, identifier);
|
||||
}
|
||||
/**
|
||||
* Create a not found error for any resource type.
|
||||
*/
|
||||
static resource(resourceType: string, identifier: string): NotFoundError {
|
||||
return new NotFoundError(resourceType, identifier);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,16 +16,16 @@ import { AppError } from './app-error';
|
|||
* ```
|
||||
*/
|
||||
export class RateLimitError extends AppError {
|
||||
/** Seconds to wait before retrying (if known) */
|
||||
readonly retryAfter?: number;
|
||||
/** Seconds to wait before retrying (if known) */
|
||||
readonly retryAfter?: number;
|
||||
|
||||
constructor(message = 'Rate limit exceeded', retryAfter?: number) {
|
||||
super({
|
||||
code: ErrorCode.RATE_LIMIT_EXCEEDED,
|
||||
message,
|
||||
context: retryAfter ? { retryAfter } : {},
|
||||
});
|
||||
this.name = 'RateLimitError';
|
||||
this.retryAfter = retryAfter;
|
||||
}
|
||||
constructor(message = 'Rate limit exceeded', retryAfter?: number) {
|
||||
super({
|
||||
code: ErrorCode.RATE_LIMIT_EXCEEDED,
|
||||
message,
|
||||
context: retryAfter ? { retryAfter } : {},
|
||||
});
|
||||
this.name = 'RateLimitError';
|
||||
this.retryAfter = retryAfter;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import { ErrorCode } from '../types/error-codes';
|
|||
import { AppError, type ErrorContext } from './app-error';
|
||||
|
||||
type ServiceErrorCode =
|
||||
| ErrorCode.INTERNAL_ERROR
|
||||
| ErrorCode.SERVICE_UNAVAILABLE
|
||||
| ErrorCode.GENERATION_FAILED
|
||||
| ErrorCode.EXTERNAL_SERVICE_ERROR;
|
||||
| ErrorCode.INTERNAL_ERROR
|
||||
| ErrorCode.SERVICE_UNAVAILABLE
|
||||
| ErrorCode.GENERATION_FAILED
|
||||
| ErrorCode.EXTERNAL_SERVICE_ERROR;
|
||||
|
||||
/**
|
||||
* Error for service-level failures (internal errors, external API failures, etc.).
|
||||
|
|
@ -27,77 +27,64 @@ type ServiceErrorCode =
|
|||
* ```
|
||||
*/
|
||||
export class ServiceError extends AppError {
|
||||
constructor(
|
||||
code: ServiceErrorCode,
|
||||
message: string,
|
||||
cause?: Error,
|
||||
context?: ErrorContext
|
||||
) {
|
||||
super({ code, message, cause, context });
|
||||
this.name = 'ServiceError';
|
||||
}
|
||||
constructor(code: ServiceErrorCode, message: string, cause?: Error, context?: ErrorContext) {
|
||||
super({ code, message, cause, context });
|
||||
this.name = 'ServiceError';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error for AI/content generation failures.
|
||||
*
|
||||
* @param service - Name of the service (e.g., 'OpenAI', 'Azure OpenAI')
|
||||
* @param reason - Why the generation failed
|
||||
* @param cause - Original error if available
|
||||
*/
|
||||
static generationFailed(
|
||||
service: string,
|
||||
reason: string,
|
||||
cause?: Error
|
||||
): ServiceError {
|
||||
return new ServiceError(
|
||||
ErrorCode.GENERATION_FAILED,
|
||||
`${service} generation failed: ${reason}`,
|
||||
cause,
|
||||
{ service }
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Create an error for AI/content generation failures.
|
||||
*
|
||||
* @param service - Name of the service (e.g., 'OpenAI', 'Azure OpenAI')
|
||||
* @param reason - Why the generation failed
|
||||
* @param cause - Original error if available
|
||||
*/
|
||||
static generationFailed(service: string, reason: string, cause?: Error): ServiceError {
|
||||
return new ServiceError(
|
||||
ErrorCode.GENERATION_FAILED,
|
||||
`${service} generation failed: ${reason}`,
|
||||
cause,
|
||||
{ service }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error for a service that is temporarily unavailable.
|
||||
*
|
||||
* @param service - Name of the unavailable service
|
||||
*/
|
||||
static unavailable(service: string): ServiceError {
|
||||
return new ServiceError(
|
||||
ErrorCode.SERVICE_UNAVAILABLE,
|
||||
`${service} is temporarily unavailable`,
|
||||
undefined,
|
||||
{ service }
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Create an error for a service that is temporarily unavailable.
|
||||
*
|
||||
* @param service - Name of the unavailable service
|
||||
*/
|
||||
static unavailable(service: string): ServiceError {
|
||||
return new ServiceError(
|
||||
ErrorCode.SERVICE_UNAVAILABLE,
|
||||
`${service} is temporarily unavailable`,
|
||||
undefined,
|
||||
{ service }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error for external API failures.
|
||||
*
|
||||
* @param service - Name of the external service
|
||||
* @param message - Error message or description
|
||||
* @param cause - Original error if available
|
||||
*/
|
||||
static externalError(
|
||||
service: string,
|
||||
message: string,
|
||||
cause?: Error
|
||||
): ServiceError {
|
||||
return new ServiceError(
|
||||
ErrorCode.EXTERNAL_SERVICE_ERROR,
|
||||
`${service} error: ${message}`,
|
||||
cause,
|
||||
{ service }
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Create an error for external API failures.
|
||||
*
|
||||
* @param service - Name of the external service
|
||||
* @param message - Error message or description
|
||||
* @param cause - Original error if available
|
||||
*/
|
||||
static externalError(service: string, message: string, cause?: Error): ServiceError {
|
||||
return new ServiceError(
|
||||
ErrorCode.EXTERNAL_SERVICE_ERROR,
|
||||
`${service} error: ${message}`,
|
||||
cause,
|
||||
{ service }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an internal server error.
|
||||
*
|
||||
* @param message - Description of what went wrong
|
||||
* @param cause - Original error if available
|
||||
*/
|
||||
static internal(message: string, cause?: Error): ServiceError {
|
||||
return new ServiceError(ErrorCode.INTERNAL_ERROR, message, cause);
|
||||
}
|
||||
/**
|
||||
* Create an internal server error.
|
||||
*
|
||||
* @param message - Description of what went wrong
|
||||
* @param cause - Original error if available
|
||||
*/
|
||||
static internal(message: string, cause?: Error): ServiceError {
|
||||
return new ServiceError(ErrorCode.INTERNAL_ERROR, message, cause);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,44 +16,44 @@ import { AppError, type ErrorContext } from './app-error';
|
|||
* ```
|
||||
*/
|
||||
export class ValidationError extends AppError {
|
||||
constructor(message: string, context?: ErrorContext) {
|
||||
super({
|
||||
code: ErrorCode.VALIDATION_FAILED,
|
||||
message,
|
||||
context,
|
||||
});
|
||||
this.name = 'ValidationError';
|
||||
}
|
||||
constructor(message: string, context?: ErrorContext) {
|
||||
super({
|
||||
code: ErrorCode.VALIDATION_FAILED,
|
||||
message,
|
||||
context,
|
||||
});
|
||||
this.name = 'ValidationError';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a validation error for an invalid field value.
|
||||
*
|
||||
* @param field - The field name that failed validation
|
||||
* @param reason - Why the validation failed
|
||||
*/
|
||||
static invalidInput(field: string, reason: string): ValidationError {
|
||||
return new ValidationError(`Invalid ${field}: ${reason}`, { field, reason });
|
||||
}
|
||||
/**
|
||||
* Create a validation error for an invalid field value.
|
||||
*
|
||||
* @param field - The field name that failed validation
|
||||
* @param reason - Why the validation failed
|
||||
*/
|
||||
static invalidInput(field: string, reason: string): ValidationError {
|
||||
return new ValidationError(`Invalid ${field}: ${reason}`, { field, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a validation error for a missing required field.
|
||||
*
|
||||
* @param field - The field name that is missing
|
||||
*/
|
||||
static missingField(field: string): ValidationError {
|
||||
return new ValidationError(`Missing required field: ${field}`, { field });
|
||||
}
|
||||
/**
|
||||
* Create a validation error for a missing required field.
|
||||
*
|
||||
* @param field - The field name that is missing
|
||||
*/
|
||||
static missingField(field: string): ValidationError {
|
||||
return new ValidationError(`Missing required field: ${field}`, { field });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a validation error for an invalid format.
|
||||
*
|
||||
* @param field - The field name with invalid format
|
||||
* @param expectedFormat - Description of the expected format
|
||||
*/
|
||||
static invalidFormat(field: string, expectedFormat: string): ValidationError {
|
||||
return new ValidationError(
|
||||
`Invalid format for ${field}: expected ${expectedFormat}`,
|
||||
{ field, expectedFormat }
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Create a validation error for an invalid format.
|
||||
*
|
||||
* @param field - The field name with invalid format
|
||||
* @param expectedFormat - Description of the expected format
|
||||
*/
|
||||
static invalidFormat(field: string, expectedFormat: string): ValidationError {
|
||||
return new ValidationError(`Invalid format for ${field}: expected ${expectedFormat}`, {
|
||||
field,
|
||||
expectedFormat,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue