import { CloseApiError, getCloseApi as getCloseContractApi, } from "@automate.ax/integration-contracts/close" import * as z from "zod" import { parseRetryAfter, retryableActionError, terminalActionError, } from "../../../automation/actions" export const CLOSE_ACCOUNT = "close" export const CLOSE_ID_SCHEMA = z.string().trim().min(1) export const CLOSE_DATE_INPUT_SCHEMA = z.union([ z.date(), z.iso.datetime({ offset: true }).transform((value) => new Date(value)), ]) export const CLOSE_DATE_OR_DAY_INPUT_SCHEMA = z.union([ CLOSE_DATE_INPUT_SCHEMA, z.iso.date(), ]) export const CLOSE_PAGINATION_SCHEMA = { limit: z.number().int().positive().prefault(100), skip: z.number().int().nonnegative().prefault(0), } /** * Creates a Close client whose provider failures carry action disposition. * * @param secret - Resolved Close account secret. */ export function getCloseApi( secret: unknown, ): ReturnType { const api = getCloseContractApi(secret) const request = api.request.bind(api) api.request = async (path, options) => { try { return await request(path, options) } catch (error) { if (error instanceof CloseApiError) { if (error.status === 429) { throw retryableActionError(error, { retryAt: parseRetryAfter(error.retryAfter), }) } if (error.status < 500) throw terminalActionError(error) } throw error } } return api } /** * Requires at least one mutable field in an update action. * * @param input - Parsed update input. * @param identifier - Resource identifier field to exclude. */ export function hasCloseUpdate( input: Record, identifier: string, ) { return Object.entries(input).some( ([key, value]) => key !== identifier && value !== undefined, ) }