every-plugin
Version:
211 lines (209 loc) • 8.46 kB
JavaScript
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
let _orpc_contract = require("@orpc/contract");
let effect = require("effect");
//#region src/runtime/errors.ts
var PluginRuntimeError = class extends effect.Data.TaggedError("PluginRuntimeError") {};
var ModuleFederationError = class extends effect.Data.TaggedError("ModuleFederationError") {};
var ValidationError = class extends effect.Data.TaggedError("ValidationError") {};
const extractErrorMessage = (error) => {
if (!error) return "Unknown error";
if (error instanceof Error) {
if (error.message) return error.message;
if (error.cause instanceof Error) return extractErrorMessage(error.cause);
}
if (error instanceof AggregateError && error.errors?.length) return error.errors.map((e) => extractErrorMessage(e)).join("; ");
if (typeof error === "object" && "message" in error) return String(error.message);
return String(error);
};
const formatValidationIssue = (issue, index, maxDisplay) => {
if (index >= maxDisplay) return "";
const path = Array.isArray(issue.path) && issue.path.length > 0 ? issue.path.join(".") : issue.path || "root";
const message = issue.message || "Validation failed";
return `│ ${index + 1}. ${path}: ${message}`;
};
const formatDataPreview = (data, maxLength = 100) => {
if (!data) return "undefined";
try {
const str = JSON.stringify(data);
if (str.length <= maxLength) return str;
if (typeof data === "object" && data !== null) {
if (Array.isArray(data)) return `Array(${data.length}) [...]`;
const keys = Object.keys(data);
return `{ ${keys.slice(0, 3).join(", ")}${keys.length > 3 ? ", ..." : ""} }`;
}
return `${str.slice(0, maxLength)}...`;
} catch {
return String(data).slice(0, maxLength);
}
};
const formatORPCValidationError = (error) => {
const cause = error?.cause || error;
if (!cause?.issues || !Array.isArray(cause.issues) || cause.issues.length === 0) return null;
const lines = [];
const errorType = error?.message || cause?.message || "Validation failed";
lines.push(`\n╭─ oRPC Validation Error ${"─".repeat(30)}`);
lines.push(`│ ${errorType}`);
lines.push(`│`);
const maxDisplay = 10;
const totalIssues = cause.issues.length;
lines.push(`│ Issues (${totalIssues}):`);
cause.issues.slice(0, maxDisplay).forEach((issue, idx) => {
const formatted = formatValidationIssue(issue, idx, maxDisplay);
if (formatted) lines.push(formatted);
});
if (totalIssues > maxDisplay) lines.push(`│ ... and ${totalIssues - maxDisplay} more`);
if (cause.data !== void 0) {
lines.push(`│`);
lines.push(`│ Data preview: ${formatDataPreview(cause.data, 80)}`);
}
lines.push(`╰${"─".repeat(50)}\n`);
return lines;
};
const formatORPCError = (error) => {
if (!(error instanceof _orpc_contract.ORPCError)) return;
const validationLines = formatORPCValidationError(error);
if (validationLines) {
console.error(validationLines.join("\n"));
return;
}
const lines = [];
const code = error.code || "UNKNOWN";
const status = error.status || 500;
const message = error.message || "An error occurred";
lines.push(`\n╭─ oRPC Error ${"─".repeat(40)}`);
lines.push(`│ ${message}`);
lines.push(`│ Code: ${code} (${status})`);
lines.push(`│`);
if (error.data) {
if (typeof error.data === "object" && error.data !== null) {
if ("retryAfter" in error.data) lines.push(`│ Retry after: ${error.data.retryAfter} seconds`);
if ("remainingRequests" in error.data) lines.push(`│ Remaining: ${error.data.remainingRequests} requests`);
if ("host" in error.data) lines.push(`│ Host: ${error.data.host}`);
if ("port" in error.data) lines.push(`│ Port: ${error.data.port}`);
if ("suggestion" in error.data) lines.push(`│ → ${error.data.suggestion}`);
if ("resource" in error.data) lines.push(`│ Resource: ${error.data.resource}`);
if ("resourceId" in error.data) lines.push(`│ ID: ${error.data.resourceId}`);
}
}
switch (code) {
case "UNAUTHORIZED":
lines.push(`│ → Check your API key or credentials`);
break;
case "TOO_MANY_REQUESTS":
lines.push(`│ → Wait before retrying`);
break;
case "SERVICE_UNAVAILABLE":
case "BAD_GATEWAY":
case "GATEWAY_TIMEOUT":
lines.push(`│ → The service may be temporarily unavailable`);
break;
case "TIMEOUT":
lines.push(`│ → The operation took too long`);
break;
}
lines.push(`╰${"─".repeat(50)}\n`);
console.error(lines.join("\n"));
};
const formatPluginError = (pluginId, operation, message) => {
const lines = [];
lines.push(`\n╭─ Plugin Error ${"─".repeat(40)}`);
if (pluginId) lines.push(`│ Plugin: ${pluginId}`);
if (operation) lines.push(`│ During: ${operation}`);
lines.push(`│`);
if (message.includes("ECONNREFUSED")) {
lines.push(`│ ❌ Connection refused`);
lines.push(`│ `);
lines.push(`│ A required service is not running.`);
lines.push(`│ → Run: docker compose up -d`);
} else if (message.includes("ENOTFOUND")) {
lines.push(`│ ❌ Host not found`);
lines.push(`│ `);
lines.push(`│ Check your connection URL or network settings.`);
} else if (message.includes("ETIMEDOUT") || message.includes("timeout")) {
lines.push(`│ ❌ Connection timeout`);
lines.push(`│ `);
lines.push(`│ The service took too long to respond.`);
} else if (message.includes("EACCES") || message.includes("permission")) {
lines.push(`│ ❌ Permission denied`);
lines.push(`│ `);
lines.push(`│ Check credentials or access permissions.`);
} else if (message.includes("401") || message.includes("unauthorized")) {
lines.push(`│ ❌ Authentication failed`);
lines.push(`│ `);
lines.push(`│ Check your API key or credentials.`);
} else lines.push(`│ ❌ ${message}`);
lines.push(`╰${"─".repeat(50)}\n`);
console.error(lines.join("\n"));
};
const isRetryableError = (message) => {
return [
"ETIMEDOUT",
"ECONNRESET",
"timeout",
"503",
"429"
].some((p) => message.toLowerCase().includes(p.toLowerCase()));
};
const isRetryableORPCCode = (code) => {
switch (code) {
case "TOO_MANY_REQUESTS":
case "SERVICE_UNAVAILABLE":
case "BAD_GATEWAY":
case "GATEWAY_TIMEOUT":
case "TIMEOUT": return true;
default: return false;
}
};
const wrapORPCError = (orpcError, pluginId, procedureName, operation) => {
const validationLines = formatORPCValidationError(orpcError);
if (validationLines) console.error(validationLines.join("\n"));
return new PluginRuntimeError({
pluginId,
operation,
procedureName,
retryable: isRetryableORPCCode(orpcError.code),
cause: orpcError
});
};
/**
* Extracts the underlying error from Effect's FiberFailure wrapper.
* When Effect.runPromise rejects, errors are wrapped in FiberFailure.
* This extracts the original error so oRPC can handle it properly.
*/
const extractFromFiberFailure = (error) => {
if (!error || typeof error !== "object") return error;
if ("cause" in error) {
const cause = error.cause;
if (cause && typeof cause === "object" && "_tag" in cause) try {
const squashed = effect.Cause.squash(cause);
if (squashed instanceof _orpc_contract.ORPCError) return squashed;
return squashed;
} catch {}
if (cause instanceof _orpc_contract.ORPCError) return cause;
}
return error;
};
const toPluginRuntimeError = (error, pluginId, procedureName, operation, defaultRetryable = false) => {
if (error instanceof _orpc_contract.ORPCError) return wrapORPCError(error, pluginId, procedureName, operation);
if (error instanceof PluginRuntimeError) return error;
const validationLines = formatORPCValidationError(error);
if (validationLines) console.error(validationLines.join("\n"));
else formatPluginError(pluginId, operation, extractErrorMessage(error));
return new PluginRuntimeError({
pluginId,
operation,
procedureName,
retryable: defaultRetryable || isRetryableError(extractErrorMessage(error)),
cause: error instanceof Error ? error : new Error(extractErrorMessage(error))
});
};
//#endregion
exports.ModuleFederationError = ModuleFederationError;
exports.PluginRuntimeError = PluginRuntimeError;
exports.ValidationError = ValidationError;
exports.extractFromFiberFailure = extractFromFiberFailure;
exports.formatORPCError = formatORPCError;
exports.isRetryableORPCCode = isRetryableORPCCode;
exports.toPluginRuntimeError = toPluginRuntimeError;
exports.wrapORPCError = wrapORPCError;
//# sourceMappingURL=errors.cjs.map