UNPKG

@swoft/gtd-domain

Version:

Getting Things Done (GTD) productivity system - consolidated domain implementation

312 lines (309 loc) 8.82 kB
import { __name } from "./chunk-PAWJFY3S.mjs"; // src/contracts/api/backend-response-types.ts import { z } from "zod"; var BackendInboxItemSchema = z.object({ id: z.string(), content: z.string(), text: z.string().optional(), title: z.string().optional(), status: z.enum([ "unprocessed", "processed", "clarified" ]), capturedAt: z.string(), createdAt: z.string(), capturedBy: z.string(), capturedByPerson: z.string().nullable().optional(), clarification: z.string().nullable().optional(), description: z.string().nullable().optional(), isActionable: z.boolean().nullable().optional(), tags: z.array(z.string()) }); var BackendProjectSchema = z.object({ id: z.string(), name: z.string().optional(), title: z.string().optional(), description: z.string(), status: z.enum([ "active", "completed", "someday", "cancelled" ]), createdAt: z.string(), ownerId: z.string().optional(), createdBy: z.string().optional(), priority: z.enum([ "low", "medium", "high" ]).optional(), progress: z.object({ totalActions: z.number(), completedActions: z.number(), completionPercentage: z.number() }) }); var BackendSuccessResponseSchema = /* @__PURE__ */ __name((dataSchema) => z.object({ success: z.literal(true), data: dataSchema }), "BackendSuccessResponseSchema"); var BackendErrorResponseSchema = z.object({ success: z.literal(false), error: z.object({ message: z.string(), code: z.string().optional(), details: z.record(z.any()).optional() }) }); var BackendInboxListResponseSchema = z.union([ BackendSuccessResponseSchema(z.object({ items: z.array(BackendInboxItemSchema), total: z.number() })), BackendErrorResponseSchema ]); var BackendProjectsListResponseSchema = z.union([ BackendSuccessResponseSchema(z.object({ projects: z.array(BackendProjectSchema), total: z.number().optional() })), BackendErrorResponseSchema ]); function isBackendSuccessResponse(response) { return response.success === true; } __name(isBackendSuccessResponse, "isBackendSuccessResponse"); function isBackendErrorResponse(response) { return response.success === false; } __name(isBackendErrorResponse, "isBackendErrorResponse"); var BackendApiError = class _BackendApiError extends Error { static { __name(this, "BackendApiError"); } code; details; constructor(code, message, details) { super(message), this.code = code, this.details = details; this.name = "BackendApiError"; } static fromBackendError(errorResponse) { return new _BackendApiError(errorResponse.error.code || "UNKNOWN_ERROR", errorResponse.error.message, errorResponse.error.details); } }; var ApiValidationError = class extends Error { static { __name(this, "ApiValidationError"); } validationErrors; constructor(message, validationErrors) { super(message), this.validationErrors = validationErrors; this.name = "ApiValidationError"; } }; // src/contracts/api/error-handling.ts var ErrorType = /* @__PURE__ */ function(ErrorType2) { ErrorType2["NETWORK_ERROR"] = "NETWORK_ERROR"; ErrorType2["API_ERROR"] = "API_ERROR"; ErrorType2["VALIDATION_ERROR"] = "VALIDATION_ERROR"; ErrorType2["AUTHENTICATION_ERROR"] = "AUTHENTICATION_ERROR"; ErrorType2["AUTHORIZATION_ERROR"] = "AUTHORIZATION_ERROR"; ErrorType2["NOT_FOUND_ERROR"] = "NOT_FOUND_ERROR"; ErrorType2["SERVER_ERROR"] = "SERVER_ERROR"; ErrorType2["TIMEOUT_ERROR"] = "TIMEOUT_ERROR"; ErrorType2["UNKNOWN_ERROR"] = "UNKNOWN_ERROR"; return ErrorType2; }({}); function classifyError(error) { if (error instanceof TypeError && error.message.includes("fetch")) { return { type: "NETWORK_ERROR", message: "Network connection failed. Please check your internet connection.", originalError: error }; } if (error instanceof BackendApiError) { return { type: getErrorTypeFromCode(error.code), message: error.message, code: error.code, details: error.details, originalError: error }; } if (error instanceof ApiValidationError) { return { type: "VALIDATION_ERROR", message: error.message, details: error.validationErrors, originalError: error }; } if (error.status) { return classifyHttpError(error.status, error.message || "HTTP Error"); } return { type: "UNKNOWN_ERROR", message: error.message || "An unexpected error occurred", originalError: error }; } __name(classifyError, "classifyError"); function getErrorTypeFromCode(code) { switch (code) { case "UNAUTHORIZED": case "INVALID_TOKEN": return "AUTHENTICATION_ERROR"; case "FORBIDDEN": case "INSUFFICIENT_PERMISSIONS": return "AUTHORIZATION_ERROR"; case "NOT_FOUND": case "RESOURCE_NOT_FOUND": return "NOT_FOUND_ERROR"; case "VALIDATION_FAILED": case "INVALID_REQUEST": return "VALIDATION_ERROR"; case "SERVER_ERROR": case "INTERNAL_ERROR": return "SERVER_ERROR"; case "TIMEOUT": return "TIMEOUT_ERROR"; default: return "API_ERROR"; } } __name(getErrorTypeFromCode, "getErrorTypeFromCode"); function classifyHttpError(status, message) { if (status === 401) { return { type: "AUTHENTICATION_ERROR", message: "Authentication required. Please log in.", code: "UNAUTHORIZED" }; } if (status === 403) { return { type: "AUTHORIZATION_ERROR", message: "You do not have permission to perform this action.", code: "FORBIDDEN" }; } if (status === 404) { return { type: "NOT_FOUND_ERROR", message: "The requested resource was not found.", code: "NOT_FOUND" }; } if (status >= 400 && status < 500) { return { type: "VALIDATION_ERROR", message: message || "Invalid request", code: `HTTP_${status}` }; } if (status >= 500) { return { type: "SERVER_ERROR", message: "Server error occurred. Please try again later.", code: `HTTP_${status}` }; } return { type: "UNKNOWN_ERROR", message: message || `HTTP error ${status}`, code: `HTTP_${status}` }; } __name(classifyHttpError, "classifyHttpError"); function getUserFriendlyMessage(error) { switch (error.type) { case "NETWORK_ERROR": return "Unable to connect to the server. Please check your internet connection and try again."; case "AUTHENTICATION_ERROR": return "Please log in to continue."; case "AUTHORIZATION_ERROR": return "You do not have permission to perform this action."; case "NOT_FOUND_ERROR": return "The requested item was not found."; case "VALIDATION_ERROR": return error.message || "Please check your input and try again."; case "SERVER_ERROR": return "A server error occurred. Please try again in a moment."; case "TIMEOUT_ERROR": return "The request timed out. Please try again."; default: return error.message || "An unexpected error occurred. Please try again."; } } __name(getUserFriendlyMessage, "getUserFriendlyMessage"); var DEFAULT_RETRY_CONFIG = { maxRetries: 3, retryDelay: 1e3, retryableErrors: [ "NETWORK_ERROR", "TIMEOUT_ERROR", "SERVER_ERROR" ] }; function shouldRetry(error, config = DEFAULT_RETRY_CONFIG) { return config.retryableErrors.includes(error.type); } __name(shouldRetry, "shouldRetry"); async function withRetry(operation, config = DEFAULT_RETRY_CONFIG) { let lastError; for (let attempt = 0; attempt <= config.maxRetries; attempt++) { try { return await operation(); } catch (error) { lastError = classifyError(error); if (attempt === config.maxRetries || !shouldRetry(lastError, config)) { throw lastError; } await new Promise((resolve) => setTimeout(resolve, config.retryDelay * Math.pow(2, attempt))); } } throw lastError; } __name(withRetry, "withRetry"); var ConsoleErrorLogger = class { static { __name(this, "ConsoleErrorLogger"); } logError(error, context) { console.error("API Error:", { type: error.type, message: error.message, code: error.code, details: error.details, context, stack: error.originalError?.stack }); } }; var defaultErrorLogger = new ConsoleErrorLogger(); export { BackendInboxItemSchema, BackendProjectSchema, BackendSuccessResponseSchema, BackendErrorResponseSchema, BackendInboxListResponseSchema, BackendProjectsListResponseSchema, isBackendSuccessResponse, isBackendErrorResponse, BackendApiError, ApiValidationError, ErrorType, classifyError, getUserFriendlyMessage, DEFAULT_RETRY_CONFIG, shouldRetry, withRetry, ConsoleErrorLogger, defaultErrorLogger }; //# sourceMappingURL=chunk-GQ5XH56W.mjs.map