@runapi.ai/core
Advanced tools
| // src/constants.ts | ||
| var TIMEOUTS = { | ||
| /** | ||
| * Default HTTP request timeout (15 minutes). | ||
| * AI generation APIs can take significant time to complete. | ||
| */ | ||
| HTTP_REQUEST: 9e5, | ||
| /** | ||
| * Default polling timeout (15 minutes). | ||
| * Matches HTTP_REQUEST to allow long-running tasks to complete. | ||
| */ | ||
| POLLING_MAX_WAIT: 9e5, | ||
| /** | ||
| * Default polling interval (2 seconds). | ||
| * How often to check task status during polling. | ||
| */ | ||
| POLLING_INTERVAL: 2e3 | ||
| }; | ||
| var RETRY_CONFIG = { | ||
| /** | ||
| * Maximum number of retry attempts. | ||
| */ | ||
| MAX_RETRIES: 2, | ||
| /** | ||
| * Base delay between retries (500ms). | ||
| * Actual delay uses exponential backoff. | ||
| */ | ||
| BASE_DELAY: 500, | ||
| /** | ||
| * Maximum delay between retries (5 seconds). | ||
| * Caps the exponential backoff. | ||
| */ | ||
| MAX_DELAY: 5e3 | ||
| }; | ||
| var DEFAULT_BASE_URL = "https://runapi.ai"; | ||
| var SDK_USER_AGENT = "runapi-sdk-js"; | ||
| // src/retry.ts | ||
| function getRetryDelayMs(attempt, baseDelayMs, maxDelayMs) { | ||
| const exponential = baseDelayMs * Math.pow(2, attempt); | ||
| const capped = Math.min(exponential, maxDelayMs); | ||
| const jitter = Math.random() * capped * 0.5; | ||
| return Math.min(maxDelayMs, capped + jitter); | ||
| } | ||
| function isRetryableStatus(status) { | ||
| return status === 429 || status >= 500; | ||
| } | ||
| function isIdempotentMethod(method) { | ||
| return ["GET", "HEAD", "PUT", "DELETE", "OPTIONS"].includes(method); | ||
| } | ||
| function parseRetryAfterMs(response) { | ||
| const retryAfter = response.headers.get("retry-after"); | ||
| if (!retryAfter) { | ||
| return void 0; | ||
| } | ||
| const numeric = Number(retryAfter); | ||
| if (!Number.isNaN(numeric)) { | ||
| return numeric * 1e3; | ||
| } | ||
| const dateMs = Date.parse(retryAfter); | ||
| if (!Number.isNaN(dateMs)) { | ||
| return Math.max(0, dateMs - Date.now()); | ||
| } | ||
| return void 0; | ||
| } | ||
| // src/errors.ts | ||
| var RunApiError = class extends Error { | ||
| /** Explicit machine-readable reason when one was provided. */ | ||
| code; | ||
| /** HTTP status code if available. */ | ||
| status; | ||
| /** Request ID from response headers. */ | ||
| requestId; | ||
| /** Parsed response body or error details. */ | ||
| details; | ||
| constructor(message, options = {}) { | ||
| super(message, options); | ||
| this.name = "RunApiError"; | ||
| this.code = options.code; | ||
| this.status = options.status; | ||
| this.requestId = options.requestId; | ||
| this.details = options.details; | ||
| } | ||
| }; | ||
| var AuthenticationError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "authentication", ...options }); | ||
| this.name = "AuthenticationError"; | ||
| } | ||
| }; | ||
| var RateLimitError = class extends RunApiError { | ||
| /** Suggested retry delay in milliseconds from `Retry-After` header. */ | ||
| retryAfterMs; | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "rate_limit", ...options }); | ||
| this.name = "RateLimitError"; | ||
| this.retryAfterMs = options.retryAfterMs; | ||
| } | ||
| }; | ||
| var InsufficientCreditsError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "insufficient_credits", ...options }); | ||
| this.name = "InsufficientCreditsError"; | ||
| } | ||
| }; | ||
| var NotFoundError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "not_found", ...options }); | ||
| this.name = "NotFoundError"; | ||
| } | ||
| }; | ||
| var ValidationError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "validation", ...options }); | ||
| this.name = "ValidationError"; | ||
| } | ||
| }; | ||
| var ConflictError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "conflict", ...options }); | ||
| this.name = "ConflictError"; | ||
| } | ||
| }; | ||
| var ServiceUnavailableError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "service_unavailable", ...options }); | ||
| this.name = "ServiceUnavailableError"; | ||
| } | ||
| }; | ||
| var NetworkError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "network", ...options }); | ||
| this.name = "NetworkError"; | ||
| } | ||
| }; | ||
| var TimeoutError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "timeout", ...options }); | ||
| this.name = "TimeoutError"; | ||
| } | ||
| }; | ||
| var TaskTimeoutError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "task_timeout", ...options }); | ||
| this.name = "TaskTimeoutError"; | ||
| } | ||
| }; | ||
| var TaskFailedError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "task_failed", ...options }); | ||
| this.name = "TaskFailedError"; | ||
| } | ||
| }; | ||
| var DEFAULT_ERROR_MESSAGE = "Request failed"; | ||
| var HTML_MARKER = /<!doctype|<html/i; | ||
| function extractMessageFromUnknown(value) { | ||
| if (typeof value === "string" && value.trim()) { | ||
| return value.trim(); | ||
| } | ||
| if (value && typeof value === "object") { | ||
| const maybeMessage = value.message; | ||
| if (typeof maybeMessage === "string" && maybeMessage.trim()) { | ||
| return maybeMessage.trim(); | ||
| } | ||
| const maybeDetail = value.detail; | ||
| if (typeof maybeDetail === "string" && maybeDetail.trim()) { | ||
| return maybeDetail.trim(); | ||
| } | ||
| } | ||
| return void 0; | ||
| } | ||
| function extractErrorMessage(body) { | ||
| if (typeof body === "string") { | ||
| if (!body.trim()) { | ||
| return void 0; | ||
| } | ||
| if (HTML_MARKER.test(body)) { | ||
| return void 0; | ||
| } | ||
| return body.trim(); | ||
| } | ||
| if (!body || typeof body !== "object") { | ||
| return void 0; | ||
| } | ||
| const maybeError = body.error; | ||
| const errorMessage = extractMessageFromUnknown(maybeError); | ||
| if (errorMessage) { | ||
| return errorMessage; | ||
| } | ||
| const maybeMessage = body.message; | ||
| if (typeof maybeMessage === "string" && maybeMessage.trim()) { | ||
| return maybeMessage.trim(); | ||
| } | ||
| const maybeDetail = body.detail; | ||
| if (typeof maybeDetail === "string" && maybeDetail.trim()) { | ||
| return maybeDetail.trim(); | ||
| } | ||
| const maybeErrorMessage = body.errorMessage; | ||
| if (typeof maybeErrorMessage === "string" && maybeErrorMessage.trim()) { | ||
| return maybeErrorMessage.trim(); | ||
| } | ||
| const maybeMsg = body.msg; | ||
| if (typeof maybeMsg === "string" && maybeMsg.trim()) { | ||
| return maybeMsg.trim(); | ||
| } | ||
| return void 0; | ||
| } | ||
| function extractErrorCode(body) { | ||
| if (!body || typeof body !== "object") { | ||
| return void 0; | ||
| } | ||
| const error = body.error; | ||
| if (!error || typeof error !== "object") { | ||
| return void 0; | ||
| } | ||
| const code = error.code; | ||
| return typeof code === "string" && code.trim() ? code : void 0; | ||
| } | ||
| function defaultMessageForStatus(status) { | ||
| switch (status) { | ||
| case 400: | ||
| return "Bad request"; | ||
| case 401: | ||
| return "Unauthorized"; | ||
| case 402: | ||
| return "Insufficient credits"; | ||
| case 404: | ||
| return "Not found"; | ||
| case 409: | ||
| return "Conflict"; | ||
| case 408: | ||
| return "Request timeout"; | ||
| case 413: | ||
| return "Payload too large"; | ||
| case 415: | ||
| return "Unsupported media type"; | ||
| case 422: | ||
| return "Validation failed"; | ||
| case 429: | ||
| return "Too many requests"; | ||
| case 503: | ||
| return "Service unavailable"; | ||
| default: | ||
| if (status >= 500) { | ||
| return "Server error"; | ||
| } | ||
| return DEFAULT_ERROR_MESSAGE; | ||
| } | ||
| } | ||
| function errorFromResponse(response, bodyText, bodyJson) { | ||
| const status = response.status; | ||
| const requestId = response.headers.get("x-request-id") || void 0; | ||
| const messageFromBody = bodyJson === void 0 ? extractErrorMessage(bodyText) : extractErrorMessage(bodyJson); | ||
| const message = messageFromBody || defaultMessageForStatus(status); | ||
| const details = bodyJson ?? bodyText ?? void 0; | ||
| const code = extractErrorCode(bodyJson); | ||
| if (status === 401) { | ||
| return new AuthenticationError(message, { code, status, requestId, details }); | ||
| } | ||
| if (status === 402) { | ||
| return new InsufficientCreditsError(message, { code, status, requestId, details }); | ||
| } | ||
| if (status === 404) { | ||
| return new NotFoundError(message, { code, status, requestId, details }); | ||
| } | ||
| if (status === 422 || status === 400) { | ||
| return new ValidationError(message, { code, status, requestId, details }); | ||
| } | ||
| if (status === 409) { | ||
| return new ConflictError(message, { code, status, requestId, details }); | ||
| } | ||
| if (status === 429) { | ||
| return new RateLimitError(message, { | ||
| status, | ||
| code, | ||
| requestId, | ||
| details, | ||
| retryAfterMs: parseRetryAfterMs(response) | ||
| }); | ||
| } | ||
| if (status === 503) { | ||
| return new ServiceUnavailableError(message, { code, status, requestId, details }); | ||
| } | ||
| return new RunApiError(message, { code, status, requestId, details }); | ||
| } | ||
| export { | ||
| TIMEOUTS, | ||
| RETRY_CONFIG, | ||
| DEFAULT_BASE_URL, | ||
| SDK_USER_AGENT, | ||
| getRetryDelayMs, | ||
| isRetryableStatus, | ||
| isIdempotentMethod, | ||
| parseRetryAfterMs, | ||
| RunApiError, | ||
| AuthenticationError, | ||
| RateLimitError, | ||
| InsufficientCreditsError, | ||
| NotFoundError, | ||
| ValidationError, | ||
| ServiceUnavailableError, | ||
| NetworkError, | ||
| TimeoutError, | ||
| TaskTimeoutError, | ||
| TaskFailedError, | ||
| errorFromResponse | ||
| }; | ||
| //# sourceMappingURL=chunk-V4WM5LRA.mjs.map |
| {"version":3,"sources":["../src/constants.ts","../src/retry.ts","../src/errors.ts"],"sourcesContent":["/**\n * Default timeout constants for SDK operations.\n * All values are in milliseconds.\n */\nexport const TIMEOUTS = {\n /**\n * Default HTTP request timeout (15 minutes).\n * AI generation APIs can take significant time to complete.\n */\n HTTP_REQUEST: 900000,\n\n /**\n * Default polling timeout (15 minutes).\n * Matches HTTP_REQUEST to allow long-running tasks to complete.\n */\n POLLING_MAX_WAIT: 900000,\n\n /**\n * Default polling interval (2 seconds).\n * How often to check task status during polling.\n */\n POLLING_INTERVAL: 2000,\n} as const;\n\n/**\n * Default retry configuration for HTTP requests.\n */\nexport const RETRY_CONFIG = {\n /**\n * Maximum number of retry attempts.\n */\n MAX_RETRIES: 2,\n\n /**\n * Base delay between retries (500ms).\n * Actual delay uses exponential backoff.\n */\n BASE_DELAY: 500,\n\n /**\n * Maximum delay between retries (5 seconds).\n * Caps the exponential backoff.\n */\n MAX_DELAY: 5000,\n} as const;\n\n/**\n * Default base URL for RunAPI services.\n */\nexport const DEFAULT_BASE_URL = 'https://runapi.ai';\n\n/**\n * SDK user agent string.\n */\nexport const SDK_USER_AGENT = 'runapi-sdk-js';\n","export interface RetryOptions {\n maxRetries: number;\n baseDelayMs: number;\n maxDelayMs: number;\n}\n\nexport function getRetryDelayMs(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number\n): number {\n const exponential = baseDelayMs * Math.pow(2, attempt);\n const capped = Math.min(exponential, maxDelayMs);\n const jitter = Math.random() * capped * 0.5;\n return Math.min(maxDelayMs, capped + jitter);\n}\n\nexport function isRetryableStatus(status: number): boolean {\n return status === 429 || status >= 500;\n}\n\nexport function isIdempotentMethod(method: string): boolean {\n return ['GET', 'HEAD', 'PUT', 'DELETE', 'OPTIONS'].includes(method);\n}\n\nexport function parseRetryAfterMs(response: Response): number | undefined {\n const retryAfter = response.headers.get('retry-after');\n if (!retryAfter) {\n return undefined;\n }\n\n const numeric = Number(retryAfter);\n if (!Number.isNaN(numeric)) {\n return numeric * 1000;\n }\n\n const dateMs = Date.parse(retryAfter);\n if (!Number.isNaN(dateMs)) {\n return Math.max(0, dateMs - Date.now());\n }\n\n return undefined;\n}\n","import { parseRetryAfterMs } from './retry';\n\n/** Options for constructing RunApiError instances. */\nexport interface RunApiErrorOptions extends ErrorOptions {\n /** Explicit machine-readable reason. */\n code?: string;\n /** HTTP status code. */\n status?: number;\n /** Request ID from `X-Request-ID` header. */\n requestId?: string;\n /** Additional error details from response body. */\n details?: unknown;\n}\n\n/**\n * Base error class for all RunAPI SDK errors.\n * Includes HTTP status, request ID, and response details.\n */\nexport class RunApiError extends Error {\n /** Explicit machine-readable reason when one was provided. */\n code?: string;\n /** HTTP status code if available. */\n status?: number;\n /** Request ID from response headers. */\n requestId?: string;\n /** Parsed response body or error details. */\n details?: unknown;\n\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, options);\n this.name = 'RunApiError';\n this.code = options.code;\n this.status = options.status;\n this.requestId = options.requestId;\n this.details = options.details;\n }\n}\n\n/** Thrown when API key is missing or invalid (HTTP 401). */\nexport class AuthenticationError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'authentication', ...options });\n this.name = 'AuthenticationError';\n }\n}\n\n/** Thrown when rate limit is exceeded (HTTP 429). Includes retry-after delay. */\nexport class RateLimitError extends RunApiError {\n /** Suggested retry delay in milliseconds from `Retry-After` header. */\n retryAfterMs?: number;\n\n constructor(\n message: string,\n options: RunApiErrorOptions & { retryAfterMs?: number } = {}\n ) {\n super(message, { code: 'rate_limit', ...options });\n this.name = 'RateLimitError';\n this.retryAfterMs = options.retryAfterMs;\n }\n}\n\n/** Thrown when account has insufficient credits (HTTP 402). */\nexport class InsufficientCreditsError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'insufficient_credits', ...options });\n this.name = 'InsufficientCreditsError';\n }\n}\n\n/** Thrown when requested resource does not exist (HTTP 404). */\nexport class NotFoundError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'not_found', ...options });\n this.name = 'NotFoundError';\n }\n}\n\n/** Thrown when request validation fails (HTTP 400, 422). */\nexport class ValidationError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'validation', ...options });\n this.name = 'ValidationError';\n }\n}\n\n/** Thrown when a request conflicts with current resource state (HTTP 409). */\nexport class ConflictError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'conflict', ...options });\n this.name = 'ConflictError';\n }\n}\n\n/** Thrown when service is temporarily unavailable (HTTP 503). */\nexport class ServiceUnavailableError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'service_unavailable', ...options });\n this.name = 'ServiceUnavailableError';\n }\n}\n\n/** Thrown when network connection fails or request cannot be sent. */\nexport class NetworkError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'network', ...options });\n this.name = 'NetworkError';\n }\n}\n\n/** Thrown when HTTP request exceeds configured timeout. */\nexport class TimeoutError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'timeout', ...options });\n this.name = 'TimeoutError';\n }\n}\n\n/** Thrown when polling for task completion exceeds maximum wait time. */\nexport class TaskTimeoutError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'task_timeout', ...options });\n this.name = 'TaskTimeoutError';\n }\n}\n\n/** Thrown when async task fails during processing. */\nexport class TaskFailedError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'task_failed', ...options });\n this.name = 'TaskFailedError';\n }\n}\n\nconst DEFAULT_ERROR_MESSAGE = 'Request failed';\n\n// Detect HTML error pages from proxies/gateways to avoid leaking raw markup as message.\nconst HTML_MARKER = /<!doctype|<html/i;\n\nfunction extractMessageFromUnknown(value: unknown): string | undefined {\n if (typeof value === 'string' && value.trim()) {\n return value.trim();\n }\n\n if (value && typeof value === 'object') {\n const maybeMessage = (value as { message?: unknown }).message;\n if (typeof maybeMessage === 'string' && maybeMessage.trim()) {\n return maybeMessage.trim();\n }\n const maybeDetail = (value as { detail?: unknown }).detail;\n if (typeof maybeDetail === 'string' && maybeDetail.trim()) {\n return maybeDetail.trim();\n }\n }\n\n return undefined;\n}\n\nfunction extractErrorMessage(body: unknown): string | undefined {\n if (typeof body === 'string') {\n if (!body.trim()) {\n return undefined;\n }\n if (HTML_MARKER.test(body)) {\n return undefined;\n }\n return body.trim();\n }\n\n if (!body || typeof body !== 'object') {\n return undefined;\n }\n\n const maybeError = (body as { error?: unknown }).error;\n const errorMessage = extractMessageFromUnknown(maybeError);\n if (errorMessage) {\n return errorMessage;\n }\n\n const maybeMessage = (body as { message?: unknown }).message;\n if (typeof maybeMessage === 'string' && maybeMessage.trim()) {\n return maybeMessage.trim();\n }\n\n const maybeDetail = (body as { detail?: unknown }).detail;\n if (typeof maybeDetail === 'string' && maybeDetail.trim()) {\n return maybeDetail.trim();\n }\n\n const maybeErrorMessage = (body as { errorMessage?: unknown }).errorMessage;\n if (typeof maybeErrorMessage === 'string' && maybeErrorMessage.trim()) {\n return maybeErrorMessage.trim();\n }\n\n const maybeMsg = (body as { msg?: unknown }).msg;\n if (typeof maybeMsg === 'string' && maybeMsg.trim()) {\n return maybeMsg.trim();\n }\n\n return undefined;\n}\n\nfunction extractErrorCode(body: unknown): string | undefined {\n if (!body || typeof body !== 'object') {\n return undefined;\n }\n\n const error = (body as { error?: unknown }).error;\n if (!error || typeof error !== 'object') {\n return undefined;\n }\n\n const code = (error as { code?: unknown }).code;\n return typeof code === 'string' && code.trim() ? code : undefined;\n}\n\nfunction defaultMessageForStatus(status: number): string {\n switch (status) {\n case 400:\n return 'Bad request';\n case 401:\n return 'Unauthorized';\n case 402:\n return 'Insufficient credits';\n case 404:\n return 'Not found';\n case 409:\n return 'Conflict';\n case 408:\n return 'Request timeout';\n case 413:\n return 'Payload too large';\n case 415:\n return 'Unsupported media type';\n case 422:\n return 'Validation failed';\n case 429:\n return 'Too many requests';\n case 503:\n return 'Service unavailable';\n default:\n if (status >= 500) {\n return 'Server error';\n }\n return DEFAULT_ERROR_MESSAGE;\n }\n}\n\n/**\n * Constructs appropriate error class from HTTP response.\n * Maps status codes to specific error types and extracts error messages.\n *\n * @param response - HTTP Response object\n * @param bodyText - Response body as text\n * @param bodyJson - Parsed JSON body if available\n * @returns Specific error instance based on status code\n */\nexport function errorFromResponse(\n response: Response,\n bodyText: string | null,\n bodyJson?: unknown\n): RunApiError {\n const status = response.status;\n const requestId = response.headers.get('x-request-id') || undefined;\n const messageFromBody =\n bodyJson === undefined\n ? extractErrorMessage(bodyText)\n : extractErrorMessage(bodyJson);\n const message = messageFromBody || defaultMessageForStatus(status);\n const details = bodyJson ?? bodyText ?? undefined;\n const code = extractErrorCode(bodyJson);\n\n if (status === 401) {\n return new AuthenticationError(message, { code, status, requestId, details });\n }\n if (status === 402) {\n return new InsufficientCreditsError(message, { code, status, requestId, details });\n }\n if (status === 404) {\n return new NotFoundError(message, { code, status, requestId, details });\n }\n if (status === 422 || status === 400) {\n return new ValidationError(message, { code, status, requestId, details });\n }\n if (status === 409) {\n return new ConflictError(message, { code, status, requestId, details });\n }\n if (status === 429) {\n return new RateLimitError(message, {\n status,\n code,\n requestId,\n details,\n retryAfterMs: parseRetryAfterMs(response),\n });\n }\n if (status === 503) {\n return new ServiceUnavailableError(message, { code, status, requestId, details });\n }\n\n return new RunApiError(message, { code, status, requestId, details });\n}\n"],"mappings":"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","names":[]} |
+1
-15
@@ -247,16 +247,2 @@ "use strict"; | ||
| } | ||
| const maybeErrors = body.errors; | ||
| if (Array.isArray(maybeErrors) && maybeErrors.length > 0) { | ||
| const firstString = maybeErrors.find((item) => typeof item === "string"); | ||
| if (typeof firstString === "string") { | ||
| return firstString; | ||
| } | ||
| const firstObject = maybeErrors.find( | ||
| (item) => item && typeof item === "object" | ||
| ); | ||
| const objectMessage = extractMessageFromUnknown(firstObject); | ||
| if (objectMessage) { | ||
| return objectMessage; | ||
| } | ||
| } | ||
| const maybeMessage = body.message; | ||
@@ -325,3 +311,3 @@ if (typeof maybeMessage === "string" && maybeMessage.trim()) { | ||
| const requestId = response.headers.get("x-request-id") || void 0; | ||
| const messageFromBody = extractErrorMessage(bodyJson) || extractErrorMessage(bodyText); | ||
| const messageFromBody = bodyJson === void 0 ? extractErrorMessage(bodyText) : extractErrorMessage(bodyJson); | ||
| const message = messageFromBody || defaultMessageForStatus(status); | ||
@@ -328,0 +314,0 @@ const details = bodyJson ?? bodyText ?? void 0; |
+1
-1
@@ -22,3 +22,3 @@ import { | ||
| parseRetryAfterMs | ||
| } from "./chunk-QT7BMRE5.mjs"; | ||
| } from "./chunk-V4WM5LRA.mjs"; | ||
@@ -25,0 +25,0 @@ // src/auth.ts |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/polling.ts","../src/errors.ts","../src/constants.ts"],"sourcesContent":["import { TaskFailedError, TaskTimeoutError } from './errors';\nimport type { PollingOptions, TaskResponse, TaskStatus } from './types';\nimport { TIMEOUTS } from './constants';\n\nconst SUCCESS_STATUSES = new Set(['completed']);\nconst FAILED_STATUSES = new Set(['failed']);\nconst PENDING_STATUSES = new Set(['pending', 'processing']);\n\nfunction normalizeStatus(\n status: TaskStatus | string\n): 'completed' | 'failed' | 'processing' {\n const value = String(status).toLowerCase();\n if (SUCCESS_STATUSES.has(value)) {\n return 'completed';\n }\n if (FAILED_STATUSES.has(value)) {\n return 'failed';\n }\n if (PENDING_STATUSES.has(value)) {\n return 'processing';\n }\n return 'processing';\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function pollUntilComplete<T extends TaskResponse>(\n fetcher: () => Promise<T>,\n options: PollingOptions = {}\n): Promise<T> {\n const pollIntervalMs = options.pollIntervalMs ?? TIMEOUTS.POLLING_INTERVAL;\n const maxWaitMs = options.maxWaitMs ?? TIMEOUTS.POLLING_MAX_WAIT;\n const start = Date.now();\n\n while (true) {\n const response = await fetcher();\n const normalizedStatus = normalizeStatus(response.status);\n\n if (normalizedStatus === 'completed') {\n return response;\n }\n\n if (normalizedStatus === 'failed') {\n throw new TaskFailedError(response.error || 'Task failed', {\n details: response,\n });\n }\n\n if (Date.now() - start >= maxWaitMs) {\n throw new TaskTimeoutError('Task polling timed out', {\n details: response,\n });\n }\n\n await sleep(pollIntervalMs);\n }\n}\n","import { parseRetryAfterMs } from './retry';\n\n/** Options for constructing RunApiError instances. */\nexport interface RunApiErrorOptions extends ErrorOptions {\n /** Explicit machine-readable reason. */\n code?: string;\n /** HTTP status code. */\n status?: number;\n /** Request ID from `X-Request-ID` header. */\n requestId?: string;\n /** Additional error details from response body. */\n details?: unknown;\n}\n\n/**\n * Base error class for all RunAPI SDK errors.\n * Includes HTTP status, request ID, and response details.\n */\nexport class RunApiError extends Error {\n /** Explicit machine-readable reason when one was provided. */\n code?: string;\n /** HTTP status code if available. */\n status?: number;\n /** Request ID from response headers. */\n requestId?: string;\n /** Parsed response body or error details. */\n details?: unknown;\n\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, options);\n this.name = 'RunApiError';\n this.code = options.code;\n this.status = options.status;\n this.requestId = options.requestId;\n this.details = options.details;\n }\n}\n\n/** Thrown when API key is missing or invalid (HTTP 401). */\nexport class AuthenticationError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'authentication', ...options });\n this.name = 'AuthenticationError';\n }\n}\n\n/** Thrown when rate limit is exceeded (HTTP 429). Includes retry-after delay. */\nexport class RateLimitError extends RunApiError {\n /** Suggested retry delay in milliseconds from `Retry-After` header. */\n retryAfterMs?: number;\n\n constructor(\n message: string,\n options: RunApiErrorOptions & { retryAfterMs?: number } = {}\n ) {\n super(message, { code: 'rate_limit', ...options });\n this.name = 'RateLimitError';\n this.retryAfterMs = options.retryAfterMs;\n }\n}\n\n/** Thrown when account has insufficient credits (HTTP 402). */\nexport class InsufficientCreditsError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'insufficient_credits', ...options });\n this.name = 'InsufficientCreditsError';\n }\n}\n\n/** Thrown when requested resource does not exist (HTTP 404). */\nexport class NotFoundError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'not_found', ...options });\n this.name = 'NotFoundError';\n }\n}\n\n/** Thrown when request validation fails (HTTP 400, 422). */\nexport class ValidationError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'validation', ...options });\n this.name = 'ValidationError';\n }\n}\n\n/** Thrown when a request conflicts with current resource state (HTTP 409). */\nexport class ConflictError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'conflict', ...options });\n this.name = 'ConflictError';\n }\n}\n\n/** Thrown when service is temporarily unavailable (HTTP 503). */\nexport class ServiceUnavailableError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'service_unavailable', ...options });\n this.name = 'ServiceUnavailableError';\n }\n}\n\n/** Thrown when network connection fails or request cannot be sent. */\nexport class NetworkError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'network', ...options });\n this.name = 'NetworkError';\n }\n}\n\n/** Thrown when HTTP request exceeds configured timeout. */\nexport class TimeoutError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'timeout', ...options });\n this.name = 'TimeoutError';\n }\n}\n\n/** Thrown when polling for task completion exceeds maximum wait time. */\nexport class TaskTimeoutError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'task_timeout', ...options });\n this.name = 'TaskTimeoutError';\n }\n}\n\n/** Thrown when async task fails during processing. */\nexport class TaskFailedError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'task_failed', ...options });\n this.name = 'TaskFailedError';\n }\n}\n\nconst DEFAULT_ERROR_MESSAGE = 'Request failed';\n\n// Detect HTML error pages from proxies/gateways to avoid leaking raw markup as message.\nconst HTML_MARKER = /<!doctype|<html/i;\n\nfunction extractMessageFromUnknown(value: unknown): string | undefined {\n if (typeof value === 'string' && value.trim()) {\n return value.trim();\n }\n\n if (value && typeof value === 'object') {\n const maybeMessage = (value as { message?: unknown }).message;\n if (typeof maybeMessage === 'string' && maybeMessage.trim()) {\n return maybeMessage.trim();\n }\n const maybeDetail = (value as { detail?: unknown }).detail;\n if (typeof maybeDetail === 'string' && maybeDetail.trim()) {\n return maybeDetail.trim();\n }\n }\n\n return undefined;\n}\n\nfunction extractErrorMessage(body: unknown): string | undefined {\n if (typeof body === 'string') {\n if (!body.trim()) {\n return undefined;\n }\n if (HTML_MARKER.test(body)) {\n return undefined;\n }\n return body.trim();\n }\n\n if (!body || typeof body !== 'object') {\n return undefined;\n }\n\n const maybeError = (body as { error?: unknown }).error;\n const errorMessage = extractMessageFromUnknown(maybeError);\n if (errorMessage) {\n return errorMessage;\n }\n\n const maybeErrors = (body as { errors?: unknown }).errors;\n if (Array.isArray(maybeErrors) && maybeErrors.length > 0) {\n const firstString = maybeErrors.find((item) => typeof item === 'string');\n if (typeof firstString === 'string') {\n return firstString;\n }\n const firstObject = maybeErrors.find(\n (item) => item && typeof item === 'object'\n );\n const objectMessage = extractMessageFromUnknown(firstObject);\n if (objectMessage) {\n return objectMessage;\n }\n }\n\n const maybeMessage = (body as { message?: unknown }).message;\n if (typeof maybeMessage === 'string' && maybeMessage.trim()) {\n return maybeMessage.trim();\n }\n\n const maybeDetail = (body as { detail?: unknown }).detail;\n if (typeof maybeDetail === 'string' && maybeDetail.trim()) {\n return maybeDetail.trim();\n }\n\n const maybeErrorMessage = (body as { errorMessage?: unknown }).errorMessage;\n if (typeof maybeErrorMessage === 'string' && maybeErrorMessage.trim()) {\n return maybeErrorMessage.trim();\n }\n\n const maybeMsg = (body as { msg?: unknown }).msg;\n if (typeof maybeMsg === 'string' && maybeMsg.trim()) {\n return maybeMsg.trim();\n }\n\n return undefined;\n}\n\nfunction extractErrorCode(body: unknown): string | undefined {\n if (!body || typeof body !== 'object') {\n return undefined;\n }\n\n const error = (body as { error?: unknown }).error;\n if (!error || typeof error !== 'object') {\n return undefined;\n }\n\n const code = (error as { code?: unknown }).code;\n return typeof code === 'string' && code.trim() ? code : undefined;\n}\n\nfunction defaultMessageForStatus(status: number): string {\n switch (status) {\n case 400:\n return 'Bad request';\n case 401:\n return 'Unauthorized';\n case 402:\n return 'Insufficient credits';\n case 404:\n return 'Not found';\n case 409:\n return 'Conflict';\n case 408:\n return 'Request timeout';\n case 413:\n return 'Payload too large';\n case 415:\n return 'Unsupported media type';\n case 422:\n return 'Validation failed';\n case 429:\n return 'Too many requests';\n case 503:\n return 'Service unavailable';\n default:\n if (status >= 500) {\n return 'Server error';\n }\n return DEFAULT_ERROR_MESSAGE;\n }\n}\n\n/**\n * Constructs appropriate error class from HTTP response.\n * Maps status codes to specific error types and extracts error messages.\n *\n * @param response - HTTP Response object\n * @param bodyText - Response body as text\n * @param bodyJson - Parsed JSON body if available\n * @returns Specific error instance based on status code\n */\nexport function errorFromResponse(\n response: Response,\n bodyText: string | null,\n bodyJson?: unknown\n): RunApiError {\n const status = response.status;\n const requestId = response.headers.get('x-request-id') || undefined;\n const messageFromBody =\n extractErrorMessage(bodyJson) || extractErrorMessage(bodyText);\n const message = messageFromBody || defaultMessageForStatus(status);\n const details = bodyJson ?? bodyText ?? undefined;\n const code = extractErrorCode(bodyJson);\n\n if (status === 401) {\n return new AuthenticationError(message, { code, status, requestId, details });\n }\n if (status === 402) {\n return new InsufficientCreditsError(message, { code, status, requestId, details });\n }\n if (status === 404) {\n return new NotFoundError(message, { code, status, requestId, details });\n }\n if (status === 422 || status === 400) {\n return new ValidationError(message, { code, status, requestId, details });\n }\n if (status === 409) {\n return new ConflictError(message, { code, status, requestId, details });\n }\n if (status === 429) {\n return new RateLimitError(message, {\n status,\n code,\n requestId,\n details,\n retryAfterMs: parseRetryAfterMs(response),\n });\n }\n if (status === 503) {\n return new ServiceUnavailableError(message, { code, status, requestId, details });\n }\n\n return new RunApiError(message, { code, status, requestId, details });\n}\n","/**\n * Default timeout constants for SDK operations.\n * All values are in milliseconds.\n */\nexport const TIMEOUTS = {\n /**\n * Default HTTP request timeout (15 minutes).\n * AI generation APIs can take significant time to complete.\n */\n HTTP_REQUEST: 900000,\n\n /**\n * Default polling timeout (15 minutes).\n * Matches HTTP_REQUEST to allow long-running tasks to complete.\n */\n POLLING_MAX_WAIT: 900000,\n\n /**\n * Default polling interval (2 seconds).\n * How often to check task status during polling.\n */\n POLLING_INTERVAL: 2000,\n} as const;\n\n/**\n * Default retry configuration for HTTP requests.\n */\nexport const RETRY_CONFIG = {\n /**\n * Maximum number of retry attempts.\n */\n MAX_RETRIES: 2,\n\n /**\n * Base delay between retries (500ms).\n * Actual delay uses exponential backoff.\n */\n BASE_DELAY: 500,\n\n /**\n * Maximum delay between retries (5 seconds).\n * Caps the exponential backoff.\n */\n MAX_DELAY: 5000,\n} as const;\n\n/**\n * Default base URL for RunAPI services.\n */\nexport const DEFAULT_BASE_URL = 'https://runapi.ai';\n\n/**\n * SDK user agent string.\n */\nexport const SDK_USER_AGENT = 'runapi-sdk-js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACkBO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA,EAErC;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAEA,YAAY,SAAiB,UAA8B,CAAC,GAAG;AAC7D,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AACZ,SAAK,OAAO,QAAQ;AACpB,SAAK,SAAS,QAAQ;AACtB,SAAK,YAAY,QAAQ;AACzB,SAAK,UAAU,QAAQ;AAAA,EACzB;AACF;AAkFO,IAAM,mBAAN,cAA+B,YAAY;AAAA,EAChD,YAAY,SAAiB,UAA8B,CAAC,GAAG;AAC7D,UAAM,SAAS,EAAE,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AACnD,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,kBAAN,cAA8B,YAAY;AAAA,EAC/C,YAAY,SAAiB,UAA8B,CAAC,GAAG;AAC7D,UAAM,SAAS,EAAE,MAAM,eAAe,GAAG,QAAQ,CAAC;AAClD,SAAK,OAAO;AAAA,EACd;AACF;;;AC/HO,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAKtB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,EAMd,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlB,kBAAkB;AACpB;;;AFlBA,IAAM,mBAAmB,oBAAI,IAAI,CAAC,WAAW,CAAC;AAC9C,IAAM,kBAAkB,oBAAI,IAAI,CAAC,QAAQ,CAAC;AAC1C,IAAM,mBAAmB,oBAAI,IAAI,CAAC,WAAW,YAAY,CAAC;AAE1D,SAAS,gBACP,QACuC;AACvC,QAAM,QAAQ,OAAO,MAAM,EAAE,YAAY;AACzC,MAAI,iBAAiB,IAAI,KAAK,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,gBAAgB,IAAI,KAAK,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,MAAI,iBAAiB,IAAI,KAAK,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAEA,eAAsB,kBACpB,SACA,UAA0B,CAAC,GACf;AACZ,QAAM,iBAAiB,QAAQ,kBAAkB,SAAS;AAC1D,QAAM,YAAY,QAAQ,aAAa,SAAS;AAChD,QAAM,QAAQ,KAAK,IAAI;AAEvB,SAAO,MAAM;AACX,UAAM,WAAW,MAAM,QAAQ;AAC/B,UAAM,mBAAmB,gBAAgB,SAAS,MAAM;AAExD,QAAI,qBAAqB,aAAa;AACpC,aAAO;AAAA,IACT;AAEA,QAAI,qBAAqB,UAAU;AACjC,YAAM,IAAI,gBAAgB,SAAS,SAAS,eAAe;AAAA,QACzD,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,IAAI,IAAI,SAAS,WAAW;AACnC,YAAM,IAAI,iBAAiB,0BAA0B;AAAA,QACnD,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,MAAM,cAAc;AAAA,EAC5B;AACF;","names":[]} | ||
| {"version":3,"sources":["../src/polling.ts","../src/errors.ts","../src/constants.ts"],"sourcesContent":["import { TaskFailedError, TaskTimeoutError } from './errors';\nimport type { PollingOptions, TaskResponse, TaskStatus } from './types';\nimport { TIMEOUTS } from './constants';\n\nconst SUCCESS_STATUSES = new Set(['completed']);\nconst FAILED_STATUSES = new Set(['failed']);\nconst PENDING_STATUSES = new Set(['pending', 'processing']);\n\nfunction normalizeStatus(\n status: TaskStatus | string\n): 'completed' | 'failed' | 'processing' {\n const value = String(status).toLowerCase();\n if (SUCCESS_STATUSES.has(value)) {\n return 'completed';\n }\n if (FAILED_STATUSES.has(value)) {\n return 'failed';\n }\n if (PENDING_STATUSES.has(value)) {\n return 'processing';\n }\n return 'processing';\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function pollUntilComplete<T extends TaskResponse>(\n fetcher: () => Promise<T>,\n options: PollingOptions = {}\n): Promise<T> {\n const pollIntervalMs = options.pollIntervalMs ?? TIMEOUTS.POLLING_INTERVAL;\n const maxWaitMs = options.maxWaitMs ?? TIMEOUTS.POLLING_MAX_WAIT;\n const start = Date.now();\n\n while (true) {\n const response = await fetcher();\n const normalizedStatus = normalizeStatus(response.status);\n\n if (normalizedStatus === 'completed') {\n return response;\n }\n\n if (normalizedStatus === 'failed') {\n throw new TaskFailedError(response.error || 'Task failed', {\n details: response,\n });\n }\n\n if (Date.now() - start >= maxWaitMs) {\n throw new TaskTimeoutError('Task polling timed out', {\n details: response,\n });\n }\n\n await sleep(pollIntervalMs);\n }\n}\n","import { parseRetryAfterMs } from './retry';\n\n/** Options for constructing RunApiError instances. */\nexport interface RunApiErrorOptions extends ErrorOptions {\n /** Explicit machine-readable reason. */\n code?: string;\n /** HTTP status code. */\n status?: number;\n /** Request ID from `X-Request-ID` header. */\n requestId?: string;\n /** Additional error details from response body. */\n details?: unknown;\n}\n\n/**\n * Base error class for all RunAPI SDK errors.\n * Includes HTTP status, request ID, and response details.\n */\nexport class RunApiError extends Error {\n /** Explicit machine-readable reason when one was provided. */\n code?: string;\n /** HTTP status code if available. */\n status?: number;\n /** Request ID from response headers. */\n requestId?: string;\n /** Parsed response body or error details. */\n details?: unknown;\n\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, options);\n this.name = 'RunApiError';\n this.code = options.code;\n this.status = options.status;\n this.requestId = options.requestId;\n this.details = options.details;\n }\n}\n\n/** Thrown when API key is missing or invalid (HTTP 401). */\nexport class AuthenticationError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'authentication', ...options });\n this.name = 'AuthenticationError';\n }\n}\n\n/** Thrown when rate limit is exceeded (HTTP 429). Includes retry-after delay. */\nexport class RateLimitError extends RunApiError {\n /** Suggested retry delay in milliseconds from `Retry-After` header. */\n retryAfterMs?: number;\n\n constructor(\n message: string,\n options: RunApiErrorOptions & { retryAfterMs?: number } = {}\n ) {\n super(message, { code: 'rate_limit', ...options });\n this.name = 'RateLimitError';\n this.retryAfterMs = options.retryAfterMs;\n }\n}\n\n/** Thrown when account has insufficient credits (HTTP 402). */\nexport class InsufficientCreditsError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'insufficient_credits', ...options });\n this.name = 'InsufficientCreditsError';\n }\n}\n\n/** Thrown when requested resource does not exist (HTTP 404). */\nexport class NotFoundError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'not_found', ...options });\n this.name = 'NotFoundError';\n }\n}\n\n/** Thrown when request validation fails (HTTP 400, 422). */\nexport class ValidationError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'validation', ...options });\n this.name = 'ValidationError';\n }\n}\n\n/** Thrown when a request conflicts with current resource state (HTTP 409). */\nexport class ConflictError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'conflict', ...options });\n this.name = 'ConflictError';\n }\n}\n\n/** Thrown when service is temporarily unavailable (HTTP 503). */\nexport class ServiceUnavailableError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'service_unavailable', ...options });\n this.name = 'ServiceUnavailableError';\n }\n}\n\n/** Thrown when network connection fails or request cannot be sent. */\nexport class NetworkError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'network', ...options });\n this.name = 'NetworkError';\n }\n}\n\n/** Thrown when HTTP request exceeds configured timeout. */\nexport class TimeoutError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'timeout', ...options });\n this.name = 'TimeoutError';\n }\n}\n\n/** Thrown when polling for task completion exceeds maximum wait time. */\nexport class TaskTimeoutError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'task_timeout', ...options });\n this.name = 'TaskTimeoutError';\n }\n}\n\n/** Thrown when async task fails during processing. */\nexport class TaskFailedError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'task_failed', ...options });\n this.name = 'TaskFailedError';\n }\n}\n\nconst DEFAULT_ERROR_MESSAGE = 'Request failed';\n\n// Detect HTML error pages from proxies/gateways to avoid leaking raw markup as message.\nconst HTML_MARKER = /<!doctype|<html/i;\n\nfunction extractMessageFromUnknown(value: unknown): string | undefined {\n if (typeof value === 'string' && value.trim()) {\n return value.trim();\n }\n\n if (value && typeof value === 'object') {\n const maybeMessage = (value as { message?: unknown }).message;\n if (typeof maybeMessage === 'string' && maybeMessage.trim()) {\n return maybeMessage.trim();\n }\n const maybeDetail = (value as { detail?: unknown }).detail;\n if (typeof maybeDetail === 'string' && maybeDetail.trim()) {\n return maybeDetail.trim();\n }\n }\n\n return undefined;\n}\n\nfunction extractErrorMessage(body: unknown): string | undefined {\n if (typeof body === 'string') {\n if (!body.trim()) {\n return undefined;\n }\n if (HTML_MARKER.test(body)) {\n return undefined;\n }\n return body.trim();\n }\n\n if (!body || typeof body !== 'object') {\n return undefined;\n }\n\n const maybeError = (body as { error?: unknown }).error;\n const errorMessage = extractMessageFromUnknown(maybeError);\n if (errorMessage) {\n return errorMessage;\n }\n\n const maybeMessage = (body as { message?: unknown }).message;\n if (typeof maybeMessage === 'string' && maybeMessage.trim()) {\n return maybeMessage.trim();\n }\n\n const maybeDetail = (body as { detail?: unknown }).detail;\n if (typeof maybeDetail === 'string' && maybeDetail.trim()) {\n return maybeDetail.trim();\n }\n\n const maybeErrorMessage = (body as { errorMessage?: unknown }).errorMessage;\n if (typeof maybeErrorMessage === 'string' && maybeErrorMessage.trim()) {\n return maybeErrorMessage.trim();\n }\n\n const maybeMsg = (body as { msg?: unknown }).msg;\n if (typeof maybeMsg === 'string' && maybeMsg.trim()) {\n return maybeMsg.trim();\n }\n\n return undefined;\n}\n\nfunction extractErrorCode(body: unknown): string | undefined {\n if (!body || typeof body !== 'object') {\n return undefined;\n }\n\n const error = (body as { error?: unknown }).error;\n if (!error || typeof error !== 'object') {\n return undefined;\n }\n\n const code = (error as { code?: unknown }).code;\n return typeof code === 'string' && code.trim() ? code : undefined;\n}\n\nfunction defaultMessageForStatus(status: number): string {\n switch (status) {\n case 400:\n return 'Bad request';\n case 401:\n return 'Unauthorized';\n case 402:\n return 'Insufficient credits';\n case 404:\n return 'Not found';\n case 409:\n return 'Conflict';\n case 408:\n return 'Request timeout';\n case 413:\n return 'Payload too large';\n case 415:\n return 'Unsupported media type';\n case 422:\n return 'Validation failed';\n case 429:\n return 'Too many requests';\n case 503:\n return 'Service unavailable';\n default:\n if (status >= 500) {\n return 'Server error';\n }\n return DEFAULT_ERROR_MESSAGE;\n }\n}\n\n/**\n * Constructs appropriate error class from HTTP response.\n * Maps status codes to specific error types and extracts error messages.\n *\n * @param response - HTTP Response object\n * @param bodyText - Response body as text\n * @param bodyJson - Parsed JSON body if available\n * @returns Specific error instance based on status code\n */\nexport function errorFromResponse(\n response: Response,\n bodyText: string | null,\n bodyJson?: unknown\n): RunApiError {\n const status = response.status;\n const requestId = response.headers.get('x-request-id') || undefined;\n const messageFromBody =\n bodyJson === undefined\n ? extractErrorMessage(bodyText)\n : extractErrorMessage(bodyJson);\n const message = messageFromBody || defaultMessageForStatus(status);\n const details = bodyJson ?? bodyText ?? undefined;\n const code = extractErrorCode(bodyJson);\n\n if (status === 401) {\n return new AuthenticationError(message, { code, status, requestId, details });\n }\n if (status === 402) {\n return new InsufficientCreditsError(message, { code, status, requestId, details });\n }\n if (status === 404) {\n return new NotFoundError(message, { code, status, requestId, details });\n }\n if (status === 422 || status === 400) {\n return new ValidationError(message, { code, status, requestId, details });\n }\n if (status === 409) {\n return new ConflictError(message, { code, status, requestId, details });\n }\n if (status === 429) {\n return new RateLimitError(message, {\n status,\n code,\n requestId,\n details,\n retryAfterMs: parseRetryAfterMs(response),\n });\n }\n if (status === 503) {\n return new ServiceUnavailableError(message, { code, status, requestId, details });\n }\n\n return new RunApiError(message, { code, status, requestId, details });\n}\n","/**\n * Default timeout constants for SDK operations.\n * All values are in milliseconds.\n */\nexport const TIMEOUTS = {\n /**\n * Default HTTP request timeout (15 minutes).\n * AI generation APIs can take significant time to complete.\n */\n HTTP_REQUEST: 900000,\n\n /**\n * Default polling timeout (15 minutes).\n * Matches HTTP_REQUEST to allow long-running tasks to complete.\n */\n POLLING_MAX_WAIT: 900000,\n\n /**\n * Default polling interval (2 seconds).\n * How often to check task status during polling.\n */\n POLLING_INTERVAL: 2000,\n} as const;\n\n/**\n * Default retry configuration for HTTP requests.\n */\nexport const RETRY_CONFIG = {\n /**\n * Maximum number of retry attempts.\n */\n MAX_RETRIES: 2,\n\n /**\n * Base delay between retries (500ms).\n * Actual delay uses exponential backoff.\n */\n BASE_DELAY: 500,\n\n /**\n * Maximum delay between retries (5 seconds).\n * Caps the exponential backoff.\n */\n MAX_DELAY: 5000,\n} as const;\n\n/**\n * Default base URL for RunAPI services.\n */\nexport const DEFAULT_BASE_URL = 'https://runapi.ai';\n\n/**\n * SDK user agent string.\n */\nexport const SDK_USER_AGENT = 'runapi-sdk-js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACkBO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA,EAErC;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAEA,YAAY,SAAiB,UAA8B,CAAC,GAAG;AAC7D,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AACZ,SAAK,OAAO,QAAQ;AACpB,SAAK,SAAS,QAAQ;AACtB,SAAK,YAAY,QAAQ;AACzB,SAAK,UAAU,QAAQ;AAAA,EACzB;AACF;AAkFO,IAAM,mBAAN,cAA+B,YAAY;AAAA,EAChD,YAAY,SAAiB,UAA8B,CAAC,GAAG;AAC7D,UAAM,SAAS,EAAE,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AACnD,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,kBAAN,cAA8B,YAAY;AAAA,EAC/C,YAAY,SAAiB,UAA8B,CAAC,GAAG;AAC7D,UAAM,SAAS,EAAE,MAAM,eAAe,GAAG,QAAQ,CAAC;AAClD,SAAK,OAAO;AAAA,EACd;AACF;;;AC/HO,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAKtB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,EAMd,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlB,kBAAkB;AACpB;;;AFlBA,IAAM,mBAAmB,oBAAI,IAAI,CAAC,WAAW,CAAC;AAC9C,IAAM,kBAAkB,oBAAI,IAAI,CAAC,QAAQ,CAAC;AAC1C,IAAM,mBAAmB,oBAAI,IAAI,CAAC,WAAW,YAAY,CAAC;AAE1D,SAAS,gBACP,QACuC;AACvC,QAAM,QAAQ,OAAO,MAAM,EAAE,YAAY;AACzC,MAAI,iBAAiB,IAAI,KAAK,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,gBAAgB,IAAI,KAAK,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,MAAI,iBAAiB,IAAI,KAAK,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAEA,eAAsB,kBACpB,SACA,UAA0B,CAAC,GACf;AACZ,QAAM,iBAAiB,QAAQ,kBAAkB,SAAS;AAC1D,QAAM,YAAY,QAAQ,aAAa,SAAS;AAChD,QAAM,QAAQ,KAAK,IAAI;AAEvB,SAAO,MAAM;AACX,UAAM,WAAW,MAAM,QAAQ;AAC/B,UAAM,mBAAmB,gBAAgB,SAAS,MAAM;AAExD,QAAI,qBAAqB,aAAa;AACpC,aAAO;AAAA,IACT;AAEA,QAAI,qBAAqB,UAAU;AACjC,YAAM,IAAI,gBAAgB,SAAS,SAAS,eAAe;AAAA,QACzD,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,IAAI,IAAI,SAAS,WAAW;AACnC,YAAM,IAAI,iBAAiB,0BAA0B;AAAA,QACnD,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,MAAM,cAAc;AAAA,EAC5B;AACF;","names":[]} |
+1
-1
@@ -5,3 +5,3 @@ import { | ||
| TaskTimeoutError | ||
| } from "./chunk-QT7BMRE5.mjs"; | ||
| } from "./chunk-V4WM5LRA.mjs"; | ||
@@ -8,0 +8,0 @@ // src/polling.ts |
+1
-1
@@ -6,3 +6,3 @@ { | ||
| }, | ||
| "version": "0.3.4", | ||
| "version": "0.3.5", | ||
| "description": "RunAPI core SDK for JavaScript, Python, Ruby, Go, Java, and PHP", | ||
@@ -9,0 +9,0 @@ "main": "./dist/index.js", |
| // src/constants.ts | ||
| var TIMEOUTS = { | ||
| /** | ||
| * Default HTTP request timeout (15 minutes). | ||
| * AI generation APIs can take significant time to complete. | ||
| */ | ||
| HTTP_REQUEST: 9e5, | ||
| /** | ||
| * Default polling timeout (15 minutes). | ||
| * Matches HTTP_REQUEST to allow long-running tasks to complete. | ||
| */ | ||
| POLLING_MAX_WAIT: 9e5, | ||
| /** | ||
| * Default polling interval (2 seconds). | ||
| * How often to check task status during polling. | ||
| */ | ||
| POLLING_INTERVAL: 2e3 | ||
| }; | ||
| var RETRY_CONFIG = { | ||
| /** | ||
| * Maximum number of retry attempts. | ||
| */ | ||
| MAX_RETRIES: 2, | ||
| /** | ||
| * Base delay between retries (500ms). | ||
| * Actual delay uses exponential backoff. | ||
| */ | ||
| BASE_DELAY: 500, | ||
| /** | ||
| * Maximum delay between retries (5 seconds). | ||
| * Caps the exponential backoff. | ||
| */ | ||
| MAX_DELAY: 5e3 | ||
| }; | ||
| var DEFAULT_BASE_URL = "https://runapi.ai"; | ||
| var SDK_USER_AGENT = "runapi-sdk-js"; | ||
| // src/retry.ts | ||
| function getRetryDelayMs(attempt, baseDelayMs, maxDelayMs) { | ||
| const exponential = baseDelayMs * Math.pow(2, attempt); | ||
| const capped = Math.min(exponential, maxDelayMs); | ||
| const jitter = Math.random() * capped * 0.5; | ||
| return Math.min(maxDelayMs, capped + jitter); | ||
| } | ||
| function isRetryableStatus(status) { | ||
| return status === 429 || status >= 500; | ||
| } | ||
| function isIdempotentMethod(method) { | ||
| return ["GET", "HEAD", "PUT", "DELETE", "OPTIONS"].includes(method); | ||
| } | ||
| function parseRetryAfterMs(response) { | ||
| const retryAfter = response.headers.get("retry-after"); | ||
| if (!retryAfter) { | ||
| return void 0; | ||
| } | ||
| const numeric = Number(retryAfter); | ||
| if (!Number.isNaN(numeric)) { | ||
| return numeric * 1e3; | ||
| } | ||
| const dateMs = Date.parse(retryAfter); | ||
| if (!Number.isNaN(dateMs)) { | ||
| return Math.max(0, dateMs - Date.now()); | ||
| } | ||
| return void 0; | ||
| } | ||
| // src/errors.ts | ||
| var RunApiError = class extends Error { | ||
| /** Explicit machine-readable reason when one was provided. */ | ||
| code; | ||
| /** HTTP status code if available. */ | ||
| status; | ||
| /** Request ID from response headers. */ | ||
| requestId; | ||
| /** Parsed response body or error details. */ | ||
| details; | ||
| constructor(message, options = {}) { | ||
| super(message, options); | ||
| this.name = "RunApiError"; | ||
| this.code = options.code; | ||
| this.status = options.status; | ||
| this.requestId = options.requestId; | ||
| this.details = options.details; | ||
| } | ||
| }; | ||
| var AuthenticationError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "authentication", ...options }); | ||
| this.name = "AuthenticationError"; | ||
| } | ||
| }; | ||
| var RateLimitError = class extends RunApiError { | ||
| /** Suggested retry delay in milliseconds from `Retry-After` header. */ | ||
| retryAfterMs; | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "rate_limit", ...options }); | ||
| this.name = "RateLimitError"; | ||
| this.retryAfterMs = options.retryAfterMs; | ||
| } | ||
| }; | ||
| var InsufficientCreditsError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "insufficient_credits", ...options }); | ||
| this.name = "InsufficientCreditsError"; | ||
| } | ||
| }; | ||
| var NotFoundError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "not_found", ...options }); | ||
| this.name = "NotFoundError"; | ||
| } | ||
| }; | ||
| var ValidationError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "validation", ...options }); | ||
| this.name = "ValidationError"; | ||
| } | ||
| }; | ||
| var ConflictError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "conflict", ...options }); | ||
| this.name = "ConflictError"; | ||
| } | ||
| }; | ||
| var ServiceUnavailableError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "service_unavailable", ...options }); | ||
| this.name = "ServiceUnavailableError"; | ||
| } | ||
| }; | ||
| var NetworkError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "network", ...options }); | ||
| this.name = "NetworkError"; | ||
| } | ||
| }; | ||
| var TimeoutError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "timeout", ...options }); | ||
| this.name = "TimeoutError"; | ||
| } | ||
| }; | ||
| var TaskTimeoutError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "task_timeout", ...options }); | ||
| this.name = "TaskTimeoutError"; | ||
| } | ||
| }; | ||
| var TaskFailedError = class extends RunApiError { | ||
| constructor(message, options = {}) { | ||
| super(message, { code: "task_failed", ...options }); | ||
| this.name = "TaskFailedError"; | ||
| } | ||
| }; | ||
| var DEFAULT_ERROR_MESSAGE = "Request failed"; | ||
| var HTML_MARKER = /<!doctype|<html/i; | ||
| function extractMessageFromUnknown(value) { | ||
| if (typeof value === "string" && value.trim()) { | ||
| return value.trim(); | ||
| } | ||
| if (value && typeof value === "object") { | ||
| const maybeMessage = value.message; | ||
| if (typeof maybeMessage === "string" && maybeMessage.trim()) { | ||
| return maybeMessage.trim(); | ||
| } | ||
| const maybeDetail = value.detail; | ||
| if (typeof maybeDetail === "string" && maybeDetail.trim()) { | ||
| return maybeDetail.trim(); | ||
| } | ||
| } | ||
| return void 0; | ||
| } | ||
| function extractErrorMessage(body) { | ||
| if (typeof body === "string") { | ||
| if (!body.trim()) { | ||
| return void 0; | ||
| } | ||
| if (HTML_MARKER.test(body)) { | ||
| return void 0; | ||
| } | ||
| return body.trim(); | ||
| } | ||
| if (!body || typeof body !== "object") { | ||
| return void 0; | ||
| } | ||
| const maybeError = body.error; | ||
| const errorMessage = extractMessageFromUnknown(maybeError); | ||
| if (errorMessage) { | ||
| return errorMessage; | ||
| } | ||
| const maybeErrors = body.errors; | ||
| if (Array.isArray(maybeErrors) && maybeErrors.length > 0) { | ||
| const firstString = maybeErrors.find((item) => typeof item === "string"); | ||
| if (typeof firstString === "string") { | ||
| return firstString; | ||
| } | ||
| const firstObject = maybeErrors.find( | ||
| (item) => item && typeof item === "object" | ||
| ); | ||
| const objectMessage = extractMessageFromUnknown(firstObject); | ||
| if (objectMessage) { | ||
| return objectMessage; | ||
| } | ||
| } | ||
| const maybeMessage = body.message; | ||
| if (typeof maybeMessage === "string" && maybeMessage.trim()) { | ||
| return maybeMessage.trim(); | ||
| } | ||
| const maybeDetail = body.detail; | ||
| if (typeof maybeDetail === "string" && maybeDetail.trim()) { | ||
| return maybeDetail.trim(); | ||
| } | ||
| const maybeErrorMessage = body.errorMessage; | ||
| if (typeof maybeErrorMessage === "string" && maybeErrorMessage.trim()) { | ||
| return maybeErrorMessage.trim(); | ||
| } | ||
| const maybeMsg = body.msg; | ||
| if (typeof maybeMsg === "string" && maybeMsg.trim()) { | ||
| return maybeMsg.trim(); | ||
| } | ||
| return void 0; | ||
| } | ||
| function extractErrorCode(body) { | ||
| if (!body || typeof body !== "object") { | ||
| return void 0; | ||
| } | ||
| const error = body.error; | ||
| if (!error || typeof error !== "object") { | ||
| return void 0; | ||
| } | ||
| const code = error.code; | ||
| return typeof code === "string" && code.trim() ? code : void 0; | ||
| } | ||
| function defaultMessageForStatus(status) { | ||
| switch (status) { | ||
| case 400: | ||
| return "Bad request"; | ||
| case 401: | ||
| return "Unauthorized"; | ||
| case 402: | ||
| return "Insufficient credits"; | ||
| case 404: | ||
| return "Not found"; | ||
| case 409: | ||
| return "Conflict"; | ||
| case 408: | ||
| return "Request timeout"; | ||
| case 413: | ||
| return "Payload too large"; | ||
| case 415: | ||
| return "Unsupported media type"; | ||
| case 422: | ||
| return "Validation failed"; | ||
| case 429: | ||
| return "Too many requests"; | ||
| case 503: | ||
| return "Service unavailable"; | ||
| default: | ||
| if (status >= 500) { | ||
| return "Server error"; | ||
| } | ||
| return DEFAULT_ERROR_MESSAGE; | ||
| } | ||
| } | ||
| function errorFromResponse(response, bodyText, bodyJson) { | ||
| const status = response.status; | ||
| const requestId = response.headers.get("x-request-id") || void 0; | ||
| const messageFromBody = extractErrorMessage(bodyJson) || extractErrorMessage(bodyText); | ||
| const message = messageFromBody || defaultMessageForStatus(status); | ||
| const details = bodyJson ?? bodyText ?? void 0; | ||
| const code = extractErrorCode(bodyJson); | ||
| if (status === 401) { | ||
| return new AuthenticationError(message, { code, status, requestId, details }); | ||
| } | ||
| if (status === 402) { | ||
| return new InsufficientCreditsError(message, { code, status, requestId, details }); | ||
| } | ||
| if (status === 404) { | ||
| return new NotFoundError(message, { code, status, requestId, details }); | ||
| } | ||
| if (status === 422 || status === 400) { | ||
| return new ValidationError(message, { code, status, requestId, details }); | ||
| } | ||
| if (status === 409) { | ||
| return new ConflictError(message, { code, status, requestId, details }); | ||
| } | ||
| if (status === 429) { | ||
| return new RateLimitError(message, { | ||
| status, | ||
| code, | ||
| requestId, | ||
| details, | ||
| retryAfterMs: parseRetryAfterMs(response) | ||
| }); | ||
| } | ||
| if (status === 503) { | ||
| return new ServiceUnavailableError(message, { code, status, requestId, details }); | ||
| } | ||
| return new RunApiError(message, { code, status, requestId, details }); | ||
| } | ||
| export { | ||
| TIMEOUTS, | ||
| RETRY_CONFIG, | ||
| DEFAULT_BASE_URL, | ||
| SDK_USER_AGENT, | ||
| getRetryDelayMs, | ||
| isRetryableStatus, | ||
| isIdempotentMethod, | ||
| parseRetryAfterMs, | ||
| RunApiError, | ||
| AuthenticationError, | ||
| RateLimitError, | ||
| InsufficientCreditsError, | ||
| NotFoundError, | ||
| ValidationError, | ||
| ServiceUnavailableError, | ||
| NetworkError, | ||
| TimeoutError, | ||
| TaskTimeoutError, | ||
| TaskFailedError, | ||
| errorFromResponse | ||
| }; | ||
| //# sourceMappingURL=chunk-QT7BMRE5.mjs.map |
| {"version":3,"sources":["../src/constants.ts","../src/retry.ts","../src/errors.ts"],"sourcesContent":["/**\n * Default timeout constants for SDK operations.\n * All values are in milliseconds.\n */\nexport const TIMEOUTS = {\n /**\n * Default HTTP request timeout (15 minutes).\n * AI generation APIs can take significant time to complete.\n */\n HTTP_REQUEST: 900000,\n\n /**\n * Default polling timeout (15 minutes).\n * Matches HTTP_REQUEST to allow long-running tasks to complete.\n */\n POLLING_MAX_WAIT: 900000,\n\n /**\n * Default polling interval (2 seconds).\n * How often to check task status during polling.\n */\n POLLING_INTERVAL: 2000,\n} as const;\n\n/**\n * Default retry configuration for HTTP requests.\n */\nexport const RETRY_CONFIG = {\n /**\n * Maximum number of retry attempts.\n */\n MAX_RETRIES: 2,\n\n /**\n * Base delay between retries (500ms).\n * Actual delay uses exponential backoff.\n */\n BASE_DELAY: 500,\n\n /**\n * Maximum delay between retries (5 seconds).\n * Caps the exponential backoff.\n */\n MAX_DELAY: 5000,\n} as const;\n\n/**\n * Default base URL for RunAPI services.\n */\nexport const DEFAULT_BASE_URL = 'https://runapi.ai';\n\n/**\n * SDK user agent string.\n */\nexport const SDK_USER_AGENT = 'runapi-sdk-js';\n","export interface RetryOptions {\n maxRetries: number;\n baseDelayMs: number;\n maxDelayMs: number;\n}\n\nexport function getRetryDelayMs(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number\n): number {\n const exponential = baseDelayMs * Math.pow(2, attempt);\n const capped = Math.min(exponential, maxDelayMs);\n const jitter = Math.random() * capped * 0.5;\n return Math.min(maxDelayMs, capped + jitter);\n}\n\nexport function isRetryableStatus(status: number): boolean {\n return status === 429 || status >= 500;\n}\n\nexport function isIdempotentMethod(method: string): boolean {\n return ['GET', 'HEAD', 'PUT', 'DELETE', 'OPTIONS'].includes(method);\n}\n\nexport function parseRetryAfterMs(response: Response): number | undefined {\n const retryAfter = response.headers.get('retry-after');\n if (!retryAfter) {\n return undefined;\n }\n\n const numeric = Number(retryAfter);\n if (!Number.isNaN(numeric)) {\n return numeric * 1000;\n }\n\n const dateMs = Date.parse(retryAfter);\n if (!Number.isNaN(dateMs)) {\n return Math.max(0, dateMs - Date.now());\n }\n\n return undefined;\n}\n","import { parseRetryAfterMs } from './retry';\n\n/** Options for constructing RunApiError instances. */\nexport interface RunApiErrorOptions extends ErrorOptions {\n /** Explicit machine-readable reason. */\n code?: string;\n /** HTTP status code. */\n status?: number;\n /** Request ID from `X-Request-ID` header. */\n requestId?: string;\n /** Additional error details from response body. */\n details?: unknown;\n}\n\n/**\n * Base error class for all RunAPI SDK errors.\n * Includes HTTP status, request ID, and response details.\n */\nexport class RunApiError extends Error {\n /** Explicit machine-readable reason when one was provided. */\n code?: string;\n /** HTTP status code if available. */\n status?: number;\n /** Request ID from response headers. */\n requestId?: string;\n /** Parsed response body or error details. */\n details?: unknown;\n\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, options);\n this.name = 'RunApiError';\n this.code = options.code;\n this.status = options.status;\n this.requestId = options.requestId;\n this.details = options.details;\n }\n}\n\n/** Thrown when API key is missing or invalid (HTTP 401). */\nexport class AuthenticationError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'authentication', ...options });\n this.name = 'AuthenticationError';\n }\n}\n\n/** Thrown when rate limit is exceeded (HTTP 429). Includes retry-after delay. */\nexport class RateLimitError extends RunApiError {\n /** Suggested retry delay in milliseconds from `Retry-After` header. */\n retryAfterMs?: number;\n\n constructor(\n message: string,\n options: RunApiErrorOptions & { retryAfterMs?: number } = {}\n ) {\n super(message, { code: 'rate_limit', ...options });\n this.name = 'RateLimitError';\n this.retryAfterMs = options.retryAfterMs;\n }\n}\n\n/** Thrown when account has insufficient credits (HTTP 402). */\nexport class InsufficientCreditsError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'insufficient_credits', ...options });\n this.name = 'InsufficientCreditsError';\n }\n}\n\n/** Thrown when requested resource does not exist (HTTP 404). */\nexport class NotFoundError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'not_found', ...options });\n this.name = 'NotFoundError';\n }\n}\n\n/** Thrown when request validation fails (HTTP 400, 422). */\nexport class ValidationError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'validation', ...options });\n this.name = 'ValidationError';\n }\n}\n\n/** Thrown when a request conflicts with current resource state (HTTP 409). */\nexport class ConflictError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'conflict', ...options });\n this.name = 'ConflictError';\n }\n}\n\n/** Thrown when service is temporarily unavailable (HTTP 503). */\nexport class ServiceUnavailableError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'service_unavailable', ...options });\n this.name = 'ServiceUnavailableError';\n }\n}\n\n/** Thrown when network connection fails or request cannot be sent. */\nexport class NetworkError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'network', ...options });\n this.name = 'NetworkError';\n }\n}\n\n/** Thrown when HTTP request exceeds configured timeout. */\nexport class TimeoutError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'timeout', ...options });\n this.name = 'TimeoutError';\n }\n}\n\n/** Thrown when polling for task completion exceeds maximum wait time. */\nexport class TaskTimeoutError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'task_timeout', ...options });\n this.name = 'TaskTimeoutError';\n }\n}\n\n/** Thrown when async task fails during processing. */\nexport class TaskFailedError extends RunApiError {\n constructor(message: string, options: RunApiErrorOptions = {}) {\n super(message, { code: 'task_failed', ...options });\n this.name = 'TaskFailedError';\n }\n}\n\nconst DEFAULT_ERROR_MESSAGE = 'Request failed';\n\n// Detect HTML error pages from proxies/gateways to avoid leaking raw markup as message.\nconst HTML_MARKER = /<!doctype|<html/i;\n\nfunction extractMessageFromUnknown(value: unknown): string | undefined {\n if (typeof value === 'string' && value.trim()) {\n return value.trim();\n }\n\n if (value && typeof value === 'object') {\n const maybeMessage = (value as { message?: unknown }).message;\n if (typeof maybeMessage === 'string' && maybeMessage.trim()) {\n return maybeMessage.trim();\n }\n const maybeDetail = (value as { detail?: unknown }).detail;\n if (typeof maybeDetail === 'string' && maybeDetail.trim()) {\n return maybeDetail.trim();\n }\n }\n\n return undefined;\n}\n\nfunction extractErrorMessage(body: unknown): string | undefined {\n if (typeof body === 'string') {\n if (!body.trim()) {\n return undefined;\n }\n if (HTML_MARKER.test(body)) {\n return undefined;\n }\n return body.trim();\n }\n\n if (!body || typeof body !== 'object') {\n return undefined;\n }\n\n const maybeError = (body as { error?: unknown }).error;\n const errorMessage = extractMessageFromUnknown(maybeError);\n if (errorMessage) {\n return errorMessage;\n }\n\n const maybeErrors = (body as { errors?: unknown }).errors;\n if (Array.isArray(maybeErrors) && maybeErrors.length > 0) {\n const firstString = maybeErrors.find((item) => typeof item === 'string');\n if (typeof firstString === 'string') {\n return firstString;\n }\n const firstObject = maybeErrors.find(\n (item) => item && typeof item === 'object'\n );\n const objectMessage = extractMessageFromUnknown(firstObject);\n if (objectMessage) {\n return objectMessage;\n }\n }\n\n const maybeMessage = (body as { message?: unknown }).message;\n if (typeof maybeMessage === 'string' && maybeMessage.trim()) {\n return maybeMessage.trim();\n }\n\n const maybeDetail = (body as { detail?: unknown }).detail;\n if (typeof maybeDetail === 'string' && maybeDetail.trim()) {\n return maybeDetail.trim();\n }\n\n const maybeErrorMessage = (body as { errorMessage?: unknown }).errorMessage;\n if (typeof maybeErrorMessage === 'string' && maybeErrorMessage.trim()) {\n return maybeErrorMessage.trim();\n }\n\n const maybeMsg = (body as { msg?: unknown }).msg;\n if (typeof maybeMsg === 'string' && maybeMsg.trim()) {\n return maybeMsg.trim();\n }\n\n return undefined;\n}\n\nfunction extractErrorCode(body: unknown): string | undefined {\n if (!body || typeof body !== 'object') {\n return undefined;\n }\n\n const error = (body as { error?: unknown }).error;\n if (!error || typeof error !== 'object') {\n return undefined;\n }\n\n const code = (error as { code?: unknown }).code;\n return typeof code === 'string' && code.trim() ? code : undefined;\n}\n\nfunction defaultMessageForStatus(status: number): string {\n switch (status) {\n case 400:\n return 'Bad request';\n case 401:\n return 'Unauthorized';\n case 402:\n return 'Insufficient credits';\n case 404:\n return 'Not found';\n case 409:\n return 'Conflict';\n case 408:\n return 'Request timeout';\n case 413:\n return 'Payload too large';\n case 415:\n return 'Unsupported media type';\n case 422:\n return 'Validation failed';\n case 429:\n return 'Too many requests';\n case 503:\n return 'Service unavailable';\n default:\n if (status >= 500) {\n return 'Server error';\n }\n return DEFAULT_ERROR_MESSAGE;\n }\n}\n\n/**\n * Constructs appropriate error class from HTTP response.\n * Maps status codes to specific error types and extracts error messages.\n *\n * @param response - HTTP Response object\n * @param bodyText - Response body as text\n * @param bodyJson - Parsed JSON body if available\n * @returns Specific error instance based on status code\n */\nexport function errorFromResponse(\n response: Response,\n bodyText: string | null,\n bodyJson?: unknown\n): RunApiError {\n const status = response.status;\n const requestId = response.headers.get('x-request-id') || undefined;\n const messageFromBody =\n extractErrorMessage(bodyJson) || extractErrorMessage(bodyText);\n const message = messageFromBody || defaultMessageForStatus(status);\n const details = bodyJson ?? bodyText ?? undefined;\n const code = extractErrorCode(bodyJson);\n\n if (status === 401) {\n return new AuthenticationError(message, { code, status, requestId, details });\n }\n if (status === 402) {\n return new InsufficientCreditsError(message, { code, status, requestId, details });\n }\n if (status === 404) {\n return new NotFoundError(message, { code, status, requestId, details });\n }\n if (status === 422 || status === 400) {\n return new ValidationError(message, { code, status, requestId, details });\n }\n if (status === 409) {\n return new ConflictError(message, { code, status, requestId, details });\n }\n if (status === 429) {\n return new RateLimitError(message, {\n status,\n code,\n requestId,\n details,\n retryAfterMs: parseRetryAfterMs(response),\n });\n }\n if (status === 503) {\n return new ServiceUnavailableError(message, { code, status, requestId, details });\n }\n\n return new RunApiError(message, { code, status, requestId, details });\n}\n"],"mappings":"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","names":[]} |
Sorry, the diff of this file is too big to display
272596
-1.07%2776
-1%