import * as gracely from "gracely" import * as isoly from "isoly" import { Capture as AuthorizationCapture } from "../../Capture" import { Error } from "../../Error" export type Capture = Fail | Success interface Base { merchant: string number: string date: isoly.DateTime type: "capture" amount: number status: "success" | "fail" currency: isoly.Currency processor?: Record } interface Fail extends Base { status: "fail" reason: Error.Code declinedBy?: "issuer" | "intergiro" error: gracely.Error } interface Success extends Base { status: "success" reference: string } export namespace Capture { function isBase(value: any | Base): value is Base { return ( typeof value == "object" && typeof value.merchant == "string" && typeof value.number == "string" && isoly.DateTime.is(value.date) && value.type == "capture" && typeof value.amount == "number" && (value.processor == undefined || (typeof value.processor == "object" && Object.keys(value.processor).every(v => typeof v == "string"))) && isoly.Currency.is(value.currency) ) } export function isFail(value: any | Fail): value is Fail { return ( typeof value == "object" && value.status == "fail" && Error.Code.is(value.reason) && (value.declinedBy == undefined || value.declinedBy == "issuer" || value.declinedBy == "intergiro") && gracely.Error.is(value.error) && isBase(value) ) } export function isSuccess(value: any | Success): value is Success { return typeof value == "object" && value.status == "success" && typeof value.reference == "string" && isBase(value) } export function is(value: any | Capture): value is Capture { return isFail(value) || isSuccess(value) } export function create( merchant: string, authorization: { number: string; currency: isoly.Currency; processor?: Record }, amount: number, input: gracely.Error | AuthorizationCapture ): Capture { return { merchant, type: "capture", date: isoly.DateTime.now(), number: authorization.number, currency: authorization.currency, processor: authorization.processor, amount, ...(gracely.Error.is(input) ? { status: "fail", reason: Error.Code.is(input.error) ? input.error : "unknown error", error: input, declinedBy: gracely.client.FlawedContent.is(input) && input.error == "rule violation" ? "intergiro" : "issuer", } : { status: "success", reference: input.reference ?? "unknown reference" }), } } }