43 lines
1.1 KiB
TypeScript
43 lines
1.1 KiB
TypeScript
export type FormFeedbackState =
|
|
| 'idle'
|
|
| 'loading'
|
|
| 'success'
|
|
| 'validation'
|
|
| 'network'
|
|
| 'server'
|
|
| 'cancelled';
|
|
|
|
export const formRequestHeader = 'X-KanbanGit-Form-Request';
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return typeof value === 'object' && value !== null;
|
|
}
|
|
|
|
/** Match failures to one submission, without intercepting other forms or polling. */
|
|
export function matchesFormRequest(
|
|
config: unknown,
|
|
requestId: string | null,
|
|
): boolean {
|
|
if (!requestId || !isRecord(config) || !isRecord(config.headers)) {
|
|
return false;
|
|
}
|
|
|
|
return config.headers[formRequestHeader] === requestId;
|
|
}
|
|
|
|
/** Runtime exceptions and cancellations are not network failures. */
|
|
export function isFormNetworkFailure(
|
|
error: unknown,
|
|
requestId: string | null,
|
|
): boolean {
|
|
return (
|
|
isRecord(error) &&
|
|
error.isAxiosError === true &&
|
|
!error.response &&
|
|
['ERR_NETWORK', 'ECONNABORTED', 'ETIMEDOUT'].includes(
|
|
String(error.code),
|
|
) &&
|
|
matchesFormRequest(error.config, requestId)
|
|
);
|
|
}
|