UNPKG

@swoft/gtd-domain

Version:

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

1 lines 20 kB
{"version":3,"sources":["../src/contracts/api/backend-response-types.ts","../src/contracts/api/error-handling.ts"],"sourcesContent":["/**\n * Backend API Response Contracts\n * \n * These types define the ACTUAL format returned by the backend APIs\n * This prevents runtime surprises and enables compile-time validation\n */\n\nimport { z } from 'zod';\n\n// =============================================================================\n// Base Backend Response Format\n// =============================================================================\n\n/**\n * Standard backend success response wrapper\n */\nexport interface BackendSuccessResponse<T> {\n success: true;\n data: T;\n}\n\n/**\n * Standard backend error response\n */\nexport interface BackendErrorResponse {\n success: false;\n error: {\n message: string;\n code?: string;\n details?: Record<string, any>;\n };\n}\n\n/**\n * Union type for all backend responses\n */\nexport type BackendResponse<T> = BackendSuccessResponse<T> | BackendErrorResponse;\n\n// =============================================================================\n// GTD-Specific Backend Response Types\n// =============================================================================\n\n/**\n * Raw inbox item as returned by backend\n */\nexport interface BackendInboxItem {\n id: string;\n content: string;\n text?: string;\n title?: string;\n status: 'unprocessed' | 'processed' | 'clarified';\n capturedAt: string;\n createdAt: string;\n capturedBy: string;\n capturedByPerson?: string | null;\n clarification?: string | null;\n description?: string | null;\n isActionable?: boolean | null;\n tags: string[];\n}\n\n/**\n * Backend inbox list response data\n */\nexport interface BackendInboxListData {\n items: BackendInboxItem[];\n total: number;\n}\n\n/**\n * Complete backend inbox list response\n */\nexport type BackendInboxListResponse = BackendResponse<BackendInboxListData>;\n\n/**\n * Raw project as returned by backend\n */\nexport interface BackendProject {\n id: string;\n name?: string;\n title?: string;\n description: string;\n status: 'active' | 'completed' | 'someday' | 'cancelled';\n createdAt: string;\n ownerId?: string;\n createdBy?: string;\n priority?: 'low' | 'medium' | 'high';\n progress: {\n totalActions: number;\n completedActions: number;\n completionPercentage: number;\n };\n}\n\n/**\n * Backend projects list response data\n */\nexport interface BackendProjectsListData {\n projects: BackendProject[]; // Note: 'projects' not 'items'!\n total?: number;\n}\n\n/**\n * Complete backend projects list response\n */\nexport type BackendProjectsListResponse = BackendResponse<BackendProjectsListData>;\n\n/**\n * Backend inbox item creation request\n */\nexport interface BackendCreateInboxItemRequest {\n content: string;\n capturedBy: string;\n}\n\n/**\n * Backend inbox item creation response data\n */\nexport interface BackendCreateInboxItemData {\n item: BackendInboxItem;\n}\n\n/**\n * Complete backend inbox creation response\n */\nexport type BackendCreateInboxItemResponse = BackendResponse<BackendCreateInboxItemData>;\n\n// =============================================================================\n// Zod Schemas for Runtime Validation\n// =============================================================================\n\nexport const BackendInboxItemSchema = z.object({\n id: z.string(),\n content: z.string(),\n text: z.string().optional(),\n title: z.string().optional(),\n status: z.enum(['unprocessed', 'processed', 'clarified']),\n capturedAt: z.string(),\n createdAt: z.string(),\n capturedBy: z.string(),\n capturedByPerson: z.string().nullable().optional(),\n clarification: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n isActionable: z.boolean().nullable().optional(),\n tags: z.array(z.string()),\n});\n\nexport const BackendProjectSchema = z.object({\n id: z.string(),\n name: z.string().optional(),\n title: z.string().optional(), \n description: z.string(),\n status: z.enum(['active', 'completed', 'someday', 'cancelled']),\n createdAt: z.string(),\n ownerId: z.string().optional(),\n createdBy: z.string().optional(),\n priority: z.enum(['low', 'medium', 'high']).optional(),\n progress: z.object({\n totalActions: z.number(),\n completedActions: z.number(),\n completionPercentage: z.number(),\n }),\n});\n\nexport const BackendSuccessResponseSchema = <T extends z.ZodType>(dataSchema: T) =>\n z.object({\n success: z.literal(true),\n data: dataSchema,\n });\n\nexport const BackendErrorResponseSchema = z.object({\n success: z.literal(false),\n error: z.object({\n message: z.string(),\n code: z.string().optional(),\n details: z.record(z.any()).optional(),\n }),\n});\n\nexport const BackendInboxListResponseSchema = z.union([\n BackendSuccessResponseSchema(z.object({\n items: z.array(BackendInboxItemSchema),\n total: z.number(),\n })),\n BackendErrorResponseSchema,\n]);\n\nexport const BackendProjectsListResponseSchema = z.union([\n BackendSuccessResponseSchema(z.object({\n projects: z.array(BackendProjectSchema),\n total: z.number().optional(),\n })),\n BackendErrorResponseSchema,\n]);\n\n// =============================================================================\n// Type Guards for Runtime Checking\n// =============================================================================\n\nexport function isBackendSuccessResponse<T>(\n response: BackendResponse<T>\n): response is BackendSuccessResponse<T> {\n return response.success === true;\n}\n\nexport function isBackendErrorResponse<T>(\n response: BackendResponse<T>\n): response is BackendErrorResponse {\n return response.success === false;\n}\n\n// =============================================================================\n// Error Classes\n// =============================================================================\n\nexport class BackendApiError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n public readonly details?: Record<string, any>\n ) {\n super(message);\n this.name = 'BackendApiError';\n }\n \n static fromBackendError(errorResponse: BackendErrorResponse): BackendApiError {\n return new BackendApiError(\n errorResponse.error.code || 'UNKNOWN_ERROR',\n errorResponse.error.message,\n errorResponse.error.details\n );\n }\n}\n\nexport class ApiValidationError extends Error {\n constructor(message: string, public readonly validationErrors: any) {\n super(message);\n this.name = 'ApiValidationError';\n }\n}","/**\n * Standardized Error Handling System\n * \n * Provides consistent error handling across all platforms\n */\n\nimport { BackendApiError, ApiValidationError } from './backend-response-types';\n\n// =============================================================================\n// Standard Error Types\n// =============================================================================\n\nexport enum ErrorType {\n NETWORK_ERROR = 'NETWORK_ERROR',\n API_ERROR = 'API_ERROR', \n VALIDATION_ERROR = 'VALIDATION_ERROR',\n AUTHENTICATION_ERROR = 'AUTHENTICATION_ERROR',\n AUTHORIZATION_ERROR = 'AUTHORIZATION_ERROR',\n NOT_FOUND_ERROR = 'NOT_FOUND_ERROR',\n SERVER_ERROR = 'SERVER_ERROR',\n TIMEOUT_ERROR = 'TIMEOUT_ERROR',\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n}\n\nexport interface StandardError {\n type: ErrorType;\n message: string;\n code?: string;\n details?: Record<string, any>;\n originalError?: Error;\n}\n\n// =============================================================================\n// Error Classification\n// =============================================================================\n\nexport function classifyError(error: any): StandardError {\n // Network errors\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return {\n type: ErrorType.NETWORK_ERROR,\n message: 'Network connection failed. Please check your internet connection.',\n originalError: error,\n };\n }\n \n // Backend API errors\n if (error instanceof BackendApiError) {\n return {\n type: getErrorTypeFromCode(error.code),\n message: error.message,\n code: error.code,\n details: error.details,\n originalError: error,\n };\n }\n \n // Validation errors\n if (error instanceof ApiValidationError) {\n return {\n type: ErrorType.VALIDATION_ERROR,\n message: error.message,\n details: error.validationErrors,\n originalError: error,\n };\n }\n \n // HTTP errors\n if (error.status) {\n return classifyHttpError(error.status, error.message || 'HTTP Error');\n }\n \n // Default fallback\n return {\n type: ErrorType.UNKNOWN_ERROR,\n message: error.message || 'An unexpected error occurred',\n originalError: error,\n };\n}\n\nfunction getErrorTypeFromCode(code: string): ErrorType {\n switch (code) {\n case 'UNAUTHORIZED':\n case 'INVALID_TOKEN':\n return ErrorType.AUTHENTICATION_ERROR;\n \n case 'FORBIDDEN':\n case 'INSUFFICIENT_PERMISSIONS':\n return ErrorType.AUTHORIZATION_ERROR;\n \n case 'NOT_FOUND':\n case 'RESOURCE_NOT_FOUND':\n return ErrorType.NOT_FOUND_ERROR;\n \n case 'VALIDATION_FAILED':\n case 'INVALID_REQUEST':\n return ErrorType.VALIDATION_ERROR;\n \n case 'SERVER_ERROR':\n case 'INTERNAL_ERROR':\n return ErrorType.SERVER_ERROR;\n \n case 'TIMEOUT':\n return ErrorType.TIMEOUT_ERROR;\n \n default:\n return ErrorType.API_ERROR;\n }\n}\n\nfunction classifyHttpError(status: number, message: string): StandardError {\n if (status === 401) {\n return {\n type: ErrorType.AUTHENTICATION_ERROR,\n message: 'Authentication required. Please log in.',\n code: 'UNAUTHORIZED',\n };\n }\n \n if (status === 403) {\n return {\n type: ErrorType.AUTHORIZATION_ERROR,\n message: 'You do not have permission to perform this action.',\n code: 'FORBIDDEN',\n };\n }\n \n if (status === 404) {\n return {\n type: ErrorType.NOT_FOUND_ERROR,\n message: 'The requested resource was not found.',\n code: 'NOT_FOUND',\n };\n }\n \n if (status >= 400 && status < 500) {\n return {\n type: ErrorType.VALIDATION_ERROR,\n message: message || 'Invalid request',\n code: `HTTP_${status}`,\n };\n }\n \n if (status >= 500) {\n return {\n type: ErrorType.SERVER_ERROR,\n message: 'Server error occurred. Please try again later.',\n code: `HTTP_${status}`,\n };\n }\n \n return {\n type: ErrorType.UNKNOWN_ERROR,\n message: message || `HTTP error ${status}`,\n code: `HTTP_${status}`,\n };\n}\n\n// =============================================================================\n// User-Friendly Error Messages\n// =============================================================================\n\nexport function getUserFriendlyMessage(error: StandardError): string {\n switch (error.type) {\n case ErrorType.NETWORK_ERROR:\n return 'Unable to connect to the server. Please check your internet connection and try again.';\n \n case ErrorType.AUTHENTICATION_ERROR:\n return 'Please log in to continue.';\n \n case ErrorType.AUTHORIZATION_ERROR:\n return 'You do not have permission to perform this action.';\n \n case ErrorType.NOT_FOUND_ERROR:\n return 'The requested item was not found.';\n \n case ErrorType.VALIDATION_ERROR:\n return error.message || 'Please check your input and try again.';\n \n case ErrorType.SERVER_ERROR:\n return 'A server error occurred. Please try again in a moment.';\n \n case ErrorType.TIMEOUT_ERROR:\n return 'The request timed out. Please try again.';\n \n default:\n return error.message || 'An unexpected error occurred. Please try again.';\n }\n}\n\n// =============================================================================\n// Retry Logic\n// =============================================================================\n\nexport interface RetryConfig {\n maxRetries: number;\n retryDelay: number;\n retryableErrors: ErrorType[];\n}\n\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n retryDelay: 1000,\n retryableErrors: [\n ErrorType.NETWORK_ERROR,\n ErrorType.TIMEOUT_ERROR,\n ErrorType.SERVER_ERROR,\n ],\n};\n\nexport function shouldRetry(error: StandardError, config = DEFAULT_RETRY_CONFIG): boolean {\n return config.retryableErrors.includes(error.type);\n}\n\nexport async function withRetry<T>(\n operation: () => Promise<T>,\n config = DEFAULT_RETRY_CONFIG\n): Promise<T> {\n let lastError: StandardError;\n \n for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = classifyError(error);\n \n if (attempt === config.maxRetries || !shouldRetry(lastError, config)) {\n throw lastError;\n }\n \n await new Promise(resolve => \n setTimeout(resolve, config.retryDelay * Math.pow(2, attempt))\n );\n }\n }\n \n throw lastError!;\n}\n\n// =============================================================================\n// Logging Integration\n// =============================================================================\n\nexport interface ErrorLogger {\n logError(error: StandardError, context?: Record<string, any>): void;\n}\n\nexport class ConsoleErrorLogger implements ErrorLogger {\n logError(error: StandardError, context?: Record<string, any>): void {\n console.error('API Error:', {\n type: error.type,\n message: error.message,\n code: error.code,\n details: error.details,\n context,\n stack: error.originalError?.stack,\n });\n }\n}\n\nexport const defaultErrorLogger = new ConsoleErrorLogger();"],"mappings":"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","names":["z","BackendInboxItemSchema","z","object","id","string","content","text","optional","title","status","enum","capturedAt","createdAt","capturedBy","capturedByPerson","nullable","clarification","description","isActionable","boolean","tags","array","BackendProjectSchema","name","ownerId","createdBy","priority","progress","totalActions","number","completedActions","completionPercentage","BackendSuccessResponseSchema","dataSchema","success","literal","data","BackendErrorResponseSchema","error","message","code","details","record","any","BackendInboxListResponseSchema","union","items","total","BackendProjectsListResponseSchema","projects","isBackendSuccessResponse","response","isBackendErrorResponse","BackendApiError","Error","fromBackendError","errorResponse","ApiValidationError","validationErrors","ErrorType","classifyError","error","TypeError","message","includes","type","originalError","BackendApiError","getErrorTypeFromCode","code","details","ApiValidationError","validationErrors","status","classifyHttpError","getUserFriendlyMessage","DEFAULT_RETRY_CONFIG","maxRetries","retryDelay","retryableErrors","shouldRetry","config","withRetry","operation","lastError","attempt","Promise","resolve","setTimeout","Math","pow","ConsoleErrorLogger","logError","context","console","stack","defaultErrorLogger"]}