visual-journal / src /lib /api-error-guidance.ts
misonL's picture
Deploy Next.js Docker Space
c7d34c1 verified
Raw
History Blame
2.77 kB
export const superApiReferralUrl = 'https://superapi.buzz/register?aff=W0rz';
type Translate = (key: string, values?: Record<string, string | number>) => string;
export type ApiErrorSummary = {
message: string;
status?: number;
};
export type ApiErrorNotice = {
message: string;
links: Array<{
label: string;
url: string;
}>;
};
export function buildUserFacingApiErrorMessage(options: ApiErrorSummary & { t: Translate }): string {
const advice = buildApiErrorAdvice(options.status, options.t);
if (!advice) return options.message;
return options.t('error.apiFailedWithAdvice', {
message: options.message,
advice
});
}
export function buildBatchPartialFailureMessage(options: {
failed: number;
total: number;
errors: ApiErrorSummary[];
t: Translate;
}): string {
const reasons = options.errors
.map((error, index) =>
`${index + 1}. ${buildUserFacingApiErrorMessage({
message: error.message,
status: error.status,
t: options.t
})}`
)
.join(' ');
return options.t('error.batchPartialFailureDetailed', {
failed: options.failed,
total: options.total,
reasons
});
}
export function buildApiErrorNotice(message: string, superApiLabel: string): ApiErrorNotice {
if (!message.includes(superApiReferralUrl)) {
return { message, links: [] };
}
return {
message: message.replace(
new RegExp(`(SuperAPI)?(:|:\\s*)?${escapeRegExp(superApiReferralUrl)}`, 'g'),
(_match, existingLabel: string | undefined, punctuation: string | undefined) => {
if (existingLabel) return 'SuperAPI';
if (!punctuation) return 'SuperAPI';
return `${punctuation.startsWith(':') ? ': ' : ':'}SuperAPI`;
}
),
links: [
{
label: superApiLabel,
url: superApiReferralUrl
}
]
};
}
function escapeRegExp(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function buildApiErrorAdvice(status: number | undefined, t: Translate): string | null {
if (status === 401 || status === 403) return t('error.adviceAuth');
if (status === 429) return t('error.adviceRateLimit');
if (status === 524) return t('error.adviceCloudflare', { url: superApiReferralUrl });
if (isUpstreamStatus(status)) return t('error.adviceUpstream');
return null;
}
function isUpstreamStatus(status: number | undefined): boolean {
return status === 500 || status === 502 || status === 503 || status === 504 || status === 520 || status === 522 || status === 523;
}