UNPKG

declastruct-stripe-sdk

Version:

declarative control of stripe constructs, via declastruct

114 lines 5.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setInvoiceItem = void 0; const domain_objects_1 = require("domain-objects"); const hash_fns_1 = require("hash-fns"); const helpful_errors_1 = require("helpful-errors"); const type_fns_1 = require("type-fns"); const castToDeclaredStripeInvoiceItem_1 = require("../cast/castToDeclaredStripeInvoiceItem"); const getCustomer_1 = require("../customer/getCustomer"); const setCoupon_1 = require("../discount/coupon/setCoupon"); const getInvoice_1 = require("../invoice/getInvoice"); const getProduct_1 = require("../product/getProduct"); const getInvoiceItem_1 = require("./getInvoiceItem"); /** * .what = sets an invoice item */ const setInvoiceItem = async (input, context) => { // define the desired invoice item state const itemDesired = input.finsert ?? input.upsert ?? helpful_errors_1.UnexpectedCodePathError.throw('expected either finsert or upsert to be defined', { input }); // resolve the invoice ref const invoiceFound = await (0, getInvoice_1.getInvoice)({ by: { ref: itemDesired.invoiceRef, }, }, context); if (!invoiceFound) throw new helpful_errors_1.BadRequestError('can not resolve item.invoiceRef', { input }); // resolve the customer ref const customerFound = await (0, getCustomer_1.getCustomer)({ by: { ref: invoiceFound.customerRef, }, }, context); if (!customerFound) throw new helpful_errors_1.BadRequestError('can not resolve item.invoice.customerRef', { invoiceFound, }); // resolve the product ref const productFound = await (0, getProduct_1.getProduct)({ by: { ref: itemDesired.productRef, }, }, context); if (!productFound) throw new helpful_errors_1.BadRequestError('can not resolve item.productRef', { input }); // lookup the item const itemFound = await (0, getInvoiceItem_1.getInvoiceItem)({ by: { unique: { invoiceRef: invoiceFound, exid: itemDesired.exid, }, }, }, context); // define how to get the desired discounts const getDiscountsDesired = async () => !itemDesired.discounts ? '' // per stripe, "pass an empty string to remove existing discounts" : await Promise.all(itemDesired.discounts.map(async (discountDesired) => { const coupon = await (0, setCoupon_1.setCoupon)({ insert: discountDesired }, // unfortunately, stripe has no unique key for coupons, so we must always insert 🥲 context); return { coupon: coupon.id }; })); // sanity check that if the product exists, their id matches the user's expectations, if any const primaryIdFound = itemFound?.id; const primaryIdExpected = itemDesired.id; if (primaryIdFound && primaryIdExpected && primaryIdExpected !== primaryIdFound) throw new helpful_errors_1.UnexpectedCodePathError('asked to setItem with a desired.primary=id which does not match the found.primary=id', { primaryIdExpected, primaryIdFound, itemFound, }); // if the item was found, then handle that if (itemFound) { // if asked to finsert, then we can return it now if (input.finsert) return itemFound; // if asked to upsert, then we can update it now if (input.upsert) { const invoiceUpdated = await context.stripe.invoiceItems.update(itemFound.id, { description: input.upsert.description ?? undefined, metadata: input.upsert.metadata ?? undefined, discounts: await getDiscountsDesired(), price: (await context.stripe.products.retrieve(productFound.id)).default_price, expand: ['discounts'], }); return (0, castToDeclaredStripeInvoiceItem_1.castToDeclaredStripeInvoiceItem)(invoiceUpdated); } } // otherwise, create the item const itemCreated = await context.stripe.invoiceItems.create({ invoice: invoiceFound.id, customer: customerFound.id, description: itemDesired.description ?? undefined, metadata: { exid: itemDesired.exid, ...(0, type_fns_1.omit)(itemDesired.metadata ?? {}, ['exid']), }, discounts: await getDiscountsDesired(), price: (await context.stripe.products.retrieve(productFound.id)).default_price, expand: ['discounts'], }, { idempotencyKey: (0, hash_fns_1.toHashSha256Sync)([ 'v1.0.0', (0, domain_objects_1.serialize)((0, type_fns_1.pick)(itemDesired, ['invoiceRef', 'exid'])), // make it idempotent on the unique keys; // todo: use domain-objects.getUniqueKeys({ of: DeclaredStripeInvoice }) instead of hardcoding the keys ].join(';')), }); return (0, castToDeclaredStripeInvoiceItem_1.castToDeclaredStripeInvoiceItem)(itemCreated); }; exports.setInvoiceItem = setInvoiceItem; //# sourceMappingURL=setInvoiceItem.js.map