UNPKG

@shopify/cli-kit

Version:

A set of utilities, interfaces, and models that are common across all the platform features

106 lines 4.16 kB
export var ErrorCategory; (function (ErrorCategory) { ErrorCategory["Liquid"] = "LIQUID"; ErrorCategory["ThemeCheck"] = "THEME_CHECK"; ErrorCategory["Network"] = "NETWORK"; ErrorCategory["FileSystem"] = "FILE_SYSTEM"; ErrorCategory["Authentication"] = "AUTHENTICATION"; ErrorCategory["Validation"] = "VALIDATION"; ErrorCategory["Permission"] = "PERMISSION"; ErrorCategory["RateLimit"] = "RATE_LIMIT"; ErrorCategory["Json"] = "JSON"; ErrorCategory["Unknown"] = "UNKNOWN"; })(ErrorCategory || (ErrorCategory = {})); const ERROR_CATEGORY_TERMS = { [ErrorCategory.Liquid]: ['liquid'], [ErrorCategory.Json]: ['json', 'parse response'], [ErrorCategory.ThemeCheck]: ['theme check'], [ErrorCategory.Authentication]: ['unauthorized', 'forbidden', 'auth', 'token', 'credential'], [ErrorCategory.Network]: [ 'eai_again', 'econn', 'enetunreach', 'enotfound', 'epipe', 'etimedout', 'fetch', 'network', 'request', 'socket', 'the operation was aborted', 'timed out', 'timeout', ], [ErrorCategory.FileSystem]: ['enoent', 'eacces', 'file', 'directory', 'path'], [ErrorCategory.Permission]: ['permission', 'denied', 'access', 'insufficient'], [ErrorCategory.RateLimit]: ['rate limit', 'too many requests', 'throttle'], [ErrorCategory.Validation]: ['validation', 'invalid', 'required'], }; export function categorizeError(error) { if (!(error instanceof Error)) return ErrorCategory.Unknown; const message = error.message.toLowerCase(); for (const [category, terms] of Object.entries(ERROR_CATEGORY_TERMS)) { const hasTerm = terms.some((term) => message.includes(term)); if (hasTerm) { return category; } } return ErrorCategory.Unknown; } /** * Formats an error message for analytics tracking, preserving important information * based on the error category while keeping it concise and normalized. */ export function formatErrorMessage(error, category) { const message = error instanceof Error ? error.message : String(error); const formatter = ERROR_FORMATTERS[category] || formatGenericError; return formatter(message); } const ERROR_FORMATTERS = { [ErrorCategory.Network]: formatNetworkError, [ErrorCategory.Authentication]: formatGenericError, [ErrorCategory.FileSystem]: formatGenericError, [ErrorCategory.RateLimit]: formatGenericError, [ErrorCategory.Json]: formatGenericError, [ErrorCategory.Validation]: formatGenericError, [ErrorCategory.Permission]: formatGenericError, [ErrorCategory.Liquid]: formatGenericError, [ErrorCategory.ThemeCheck]: formatGenericError, [ErrorCategory.Unknown]: formatGenericError, }; function formatNetworkError(message) { const httpStatusMatch = message.match(/\b([1-5]\d{2})\b/); const connectionErrorMatch = message.match(/\b(E[A-Z]+)\b/); const graphqlCodeMatch = message.match(/(?:code|error)[:\s]*(\d{3})/i); let normalized = message.toLowerCase().substring(0, 50); if (httpStatusMatch?.[1]) { const statusCode = httpStatusMatch[1]; normalized = `http-${statusCode}-${normalized.replace(/\b\d{3}\b/g, '').trim()}`; } else if (graphqlCodeMatch?.[1]) { const statusCode = graphqlCodeMatch[1]; normalized = `http-${statusCode}-${normalized.replace(/(?:code|error)[:\s]*\d{3}/gi, '').trim()}`; } else if (connectionErrorMatch?.[1]) { const errorCode = connectionErrorMatch[1].toLowerCase(); normalized = `http-000-${errorCode}-${normalized.replace(/\b[eE][A-Z]+\b/g, '').trim()}`; } else { normalized = `http-000-${normalized}`; } return normalized .replace(/[^a-zA-Z0-9-]/g, '-') .replace(/-+/g, '-') .replace(/^-|-$/g, '') .substring(0, 50); } function formatGenericError(message) { return message .toLowerCase() .substring(0, 50) .replace(/[^a-zA-Z0-9]/g, '-') .replace(/-+/g, '-') .replace(/^-|-$/g, ''); } //# sourceMappingURL=error-categorizer.js.map