@swoft/gtd-domain
Version:
Getting Things Done (GTD) productivity system - consolidated domain implementation
312 lines (309 loc) • 8.82 kB
JavaScript
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