@crvouga/mockingbird-service-stripe 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +254 -0
  2. package/dist/account.d.ts +8 -0
  3. package/dist/account.d.ts.map +1 -0
  4. package/dist/account.js +13 -0
  5. package/dist/account.js.map +1 -0
  6. package/dist/charges.d.ts +4 -0
  7. package/dist/charges.d.ts.map +1 -0
  8. package/dist/charges.js +89 -0
  9. package/dist/charges.js.map +1 -0
  10. package/dist/checkout-sessions.d.ts +5 -0
  11. package/dist/checkout-sessions.d.ts.map +1 -0
  12. package/dist/checkout-sessions.js +303 -0
  13. package/dist/checkout-sessions.js.map +1 -0
  14. package/dist/constants.d.ts +3 -0
  15. package/dist/constants.d.ts.map +1 -0
  16. package/dist/constants.js +3 -0
  17. package/dist/constants.js.map +1 -0
  18. package/dist/coupons.d.ts +4 -0
  19. package/dist/coupons.d.ts.map +1 -0
  20. package/dist/coupons.js +158 -0
  21. package/dist/coupons.js.map +1 -0
  22. package/dist/customers.d.ts +4 -0
  23. package/dist/customers.d.ts.map +1 -0
  24. package/dist/customers.js +218 -0
  25. package/dist/customers.js.map +1 -0
  26. package/dist/disputes.d.ts +4 -0
  27. package/dist/disputes.d.ts.map +1 -0
  28. package/dist/disputes.js +36 -0
  29. package/dist/disputes.js.map +1 -0
  30. package/dist/errors.d.ts +29 -0
  31. package/dist/errors.d.ts.map +1 -0
  32. package/dist/errors.js +74 -0
  33. package/dist/errors.js.map +1 -0
  34. package/dist/events.d.ts +4 -0
  35. package/dist/events.d.ts.map +1 -0
  36. package/dist/events.js +76 -0
  37. package/dist/events.js.map +1 -0
  38. package/dist/expand.d.ts +11 -0
  39. package/dist/expand.d.ts.map +1 -0
  40. package/dist/expand.js +45 -0
  41. package/dist/expand.js.map +1 -0
  42. package/dist/fields.d.ts +25 -0
  43. package/dist/fields.d.ts.map +1 -0
  44. package/dist/fields.js +117 -0
  45. package/dist/fields.js.map +1 -0
  46. package/dist/generated/openapi.d.ts +7 -0
  47. package/dist/generated/openapi.d.ts.map +1 -0
  48. package/dist/generated/openapi.js +5 -0
  49. package/dist/generated/openapi.js.map +1 -0
  50. package/dist/index.d.ts +43 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +172 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/internal.d.ts +134 -0
  55. package/dist/internal.d.ts.map +1 -0
  56. package/dist/internal.js +460 -0
  57. package/dist/internal.js.map +1 -0
  58. package/dist/invoice-items.d.ts +4 -0
  59. package/dist/invoice-items.d.ts.map +1 -0
  60. package/dist/invoice-items.js +179 -0
  61. package/dist/invoice-items.js.map +1 -0
  62. package/dist/invoices.d.ts +4 -0
  63. package/dist/invoices.d.ts.map +1 -0
  64. package/dist/invoices.js +312 -0
  65. package/dist/invoices.js.map +1 -0
  66. package/dist/list.d.ts +24 -0
  67. package/dist/list.d.ts.map +1 -0
  68. package/dist/list.js +68 -0
  69. package/dist/list.js.map +1 -0
  70. package/dist/params.d.ts +29 -0
  71. package/dist/params.d.ts.map +1 -0
  72. package/dist/params.js +165 -0
  73. package/dist/params.js.map +1 -0
  74. package/dist/payment-intents.d.ts +4 -0
  75. package/dist/payment-intents.d.ts.map +1 -0
  76. package/dist/payment-intents.js +232 -0
  77. package/dist/payment-intents.js.map +1 -0
  78. package/dist/payment-methods.d.ts +4 -0
  79. package/dist/payment-methods.d.ts.map +1 -0
  80. package/dist/payment-methods.js +99 -0
  81. package/dist/payment-methods.js.map +1 -0
  82. package/dist/prices.d.ts +4 -0
  83. package/dist/prices.d.ts.map +1 -0
  84. package/dist/prices.js +176 -0
  85. package/dist/prices.js.map +1 -0
  86. package/dist/products.d.ts +6 -0
  87. package/dist/products.d.ts.map +1 -0
  88. package/dist/products.js +202 -0
  89. package/dist/products.js.map +1 -0
  90. package/dist/promotion-codes.d.ts +4 -0
  91. package/dist/promotion-codes.d.ts.map +1 -0
  92. package/dist/promotion-codes.js +193 -0
  93. package/dist/promotion-codes.js.map +1 -0
  94. package/dist/qa-corpus.d.ts +26 -0
  95. package/dist/qa-corpus.d.ts.map +1 -0
  96. package/dist/qa-corpus.js +42 -0
  97. package/dist/qa-corpus.js.map +1 -0
  98. package/dist/refunds.d.ts +4 -0
  99. package/dist/refunds.d.ts.map +1 -0
  100. package/dist/refunds.js +125 -0
  101. package/dist/refunds.js.map +1 -0
  102. package/dist/render.d.ts +60 -0
  103. package/dist/render.d.ts.map +1 -0
  104. package/dist/render.js +426 -0
  105. package/dist/render.js.map +1 -0
  106. package/dist/reshape-qa.d.ts +8 -0
  107. package/dist/reshape-qa.d.ts.map +1 -0
  108. package/dist/reshape-qa.js +102 -0
  109. package/dist/reshape-qa.js.map +1 -0
  110. package/dist/search.d.ts +32 -0
  111. package/dist/search.d.ts.map +1 -0
  112. package/dist/search.js +64 -0
  113. package/dist/search.js.map +1 -0
  114. package/dist/setup-intents.d.ts +4 -0
  115. package/dist/setup-intents.d.ts.map +1 -0
  116. package/dist/setup-intents.js +129 -0
  117. package/dist/setup-intents.js.map +1 -0
  118. package/dist/state.d.ts +485 -0
  119. package/dist/state.d.ts.map +1 -0
  120. package/dist/state.js +143 -0
  121. package/dist/state.js.map +1 -0
  122. package/dist/subscription-schedules.d.ts +4 -0
  123. package/dist/subscription-schedules.d.ts.map +1 -0
  124. package/dist/subscription-schedules.js +122 -0
  125. package/dist/subscription-schedules.js.map +1 -0
  126. package/dist/subscriptions.d.ts +23 -0
  127. package/dist/subscriptions.d.ts.map +1 -0
  128. package/dist/subscriptions.js +260 -0
  129. package/dist/subscriptions.js.map +1 -0
  130. package/dist/test-tokens.d.ts +27 -0
  131. package/dist/test-tokens.d.ts.map +1 -0
  132. package/dist/test-tokens.js +61 -0
  133. package/dist/test-tokens.js.map +1 -0
  134. package/dist/url.d.ts +6 -0
  135. package/dist/url.d.ts.map +1 -0
  136. package/dist/url.js +38 -0
  137. package/dist/url.js.map +1 -0
  138. package/dist/version.d.ts +3 -0
  139. package/dist/version.d.ts.map +1 -0
  140. package/dist/version.js +3 -0
  141. package/dist/version.js.map +1 -0
  142. package/package.json +72 -0
@@ -0,0 +1,179 @@
1
+ import { jsonResponse } from "@crvouga/mockingbird-service";
2
+ import { parameterMissing, resourceMissing } from "./errors.js";
3
+ import { applyExpand } from "./expand.js";
4
+ import { optionalString } from "./fields.js";
5
+ import { invoiceLineFromItem, mergeRecordMetadata, priceAmount, recomputeInvoice, requestScope, requireInvoice, requireLiveCustomer, requirePrice, } from "./internal.js";
6
+ import { matchesCreated, paginate } from "./list.js";
7
+ import { bodyParams, queryParams } from "./params.js";
8
+ import { renderCustomer, renderDeletedInvoiceItem, renderInvoice, renderInvoiceItem, renderPrice, } from "./render.js";
9
+ import { seconds } from "./state.js";
10
+ const stringOf = (params, key) => {
11
+ const value = params[key];
12
+ return typeof value === "string" && value !== "" ? value : null;
13
+ };
14
+ const intOf = (value) => {
15
+ if (value === undefined || value === "")
16
+ return undefined;
17
+ const parsed = Number(value);
18
+ return Number.isFinite(parsed) ? Math.trunc(parsed) : undefined;
19
+ };
20
+ export const invoiceItemHandlers = (services) => {
21
+ /**
22
+ * Both spellings of every path: the list operations expand `data.price` on the envelope, the
23
+ * single-object operations expand `price` on the record.
24
+ */
25
+ const expanders = (scope) => {
26
+ const customer = (id) => {
27
+ const entry = scope.account.customers.get(id);
28
+ return entry?.kind === "live" ? renderCustomer(entry.customer) : undefined;
29
+ };
30
+ const price = (id) => {
31
+ const record = scope.account.prices.get(id);
32
+ return record ? renderPrice(record) : undefined;
33
+ };
34
+ const invoice = (id) => {
35
+ const record = scope.account.invoices.get(id);
36
+ return record ? renderInvoice(record, scope.account) : undefined;
37
+ };
38
+ return {
39
+ customer,
40
+ invoice,
41
+ price,
42
+ "data.customer": customer,
43
+ "data.invoice": invoice,
44
+ "data.price": price,
45
+ };
46
+ };
47
+ /** The rendered item carries its price id so `expand[]=price` has something to replace. */
48
+ const renderItem = (item) => {
49
+ const rendered = renderInvoiceItem(item);
50
+ return item.price === null ? rendered : { ...rendered, price: item.price };
51
+ };
52
+ /** Draft invoices derive their money fields from lines, so any change re-derives both. */
53
+ const syncDraftInvoice = (scope, item) => {
54
+ if (item.invoice === null)
55
+ return;
56
+ const invoice = scope.account.invoices.get(item.invoice);
57
+ if (invoice?.status !== "draft")
58
+ return;
59
+ const line = invoiceLineFromItem(scope, {
60
+ id: item.id,
61
+ amount: item.amount,
62
+ currency: item.currency,
63
+ description: item.description,
64
+ quantity: item.quantity,
65
+ metadata: item.metadata,
66
+ price: item.price,
67
+ });
68
+ const lines = invoice.lines.some((existing) => existing.invoice_item === item.id)
69
+ ? invoice.lines.map((existing) => existing.invoice_item === item.id
70
+ ? {
71
+ ...existing,
72
+ amount: item.amount,
73
+ description: item.description,
74
+ metadata: item.metadata,
75
+ price: item.price,
76
+ quantity: item.quantity,
77
+ subtotal: item.amount,
78
+ }
79
+ : existing)
80
+ : [...invoice.lines, line];
81
+ scope.account.invoices.update(invoice.id, recomputeInvoice({ ...invoice, lines }));
82
+ };
83
+ const requireItem = (scope, id) => {
84
+ const item = scope.account.invoiceItems.get(id);
85
+ if (!item)
86
+ throw resourceMissing("invoiceitem", id, "invoiceitem");
87
+ return item;
88
+ };
89
+ return {
90
+ PostInvoiceitems: async (context) => {
91
+ const scope = requestScope(services, context);
92
+ const params = bodyParams(context);
93
+ const customer = requireLiveCustomer(scope, stringOf(params, "customer") ?? "", "customer");
94
+ const priceId = stringOf(params, "price");
95
+ const price = priceId === null ? undefined : requirePrice(scope, priceId, "price");
96
+ const invoiceId = stringOf(params, "invoice");
97
+ const invoice = invoiceId === null ? undefined : requireInvoice(scope, invoiceId, "invoice");
98
+ const quantity = intOf(params.quantity) ?? 1;
99
+ const derived = price === undefined ? undefined : priceAmount(price, quantity);
100
+ const amount = intOf(params.amount) ?? derived;
101
+ if (amount === undefined)
102
+ throw parameterMissing("amount");
103
+ const id = scope.ids.next("ii_");
104
+ const now = seconds(scope.now);
105
+ const item = {
106
+ id,
107
+ amount,
108
+ created: now,
109
+ currency: stringOf(params, "currency") ?? "usd",
110
+ customer: customer.id,
111
+ date: now,
112
+ description: stringOf(params, "description"),
113
+ discountable: params.discountable !== false,
114
+ invoice: invoice?.id ?? null,
115
+ metadata: params.metadata ?? {},
116
+ period: { start: now, end: now },
117
+ price: price?.id ?? null,
118
+ proration: false,
119
+ quantity,
120
+ unit_amount: price === undefined ? null : Number(price.unit_amount_decimal),
121
+ };
122
+ scope.account.invoiceItems.insert(id, item);
123
+ syncDraftInvoice(scope, item);
124
+ return jsonResponse(200, applyExpand(renderItem(item), params.expand, expanders(scope)));
125
+ },
126
+ GetInvoiceitems: async (context) => {
127
+ const scope = requestScope(services, context);
128
+ const params = queryParams(context);
129
+ const customer = stringOf(params, "customer");
130
+ const invoice = stringOf(params, "invoice");
131
+ const page = await paginate(scope.account.invoiceItems, params, {
132
+ url: "/v1/invoiceitems",
133
+ kind: "invoiceitem",
134
+ where: (item) => matchesCreated(item.created, params.created) &&
135
+ (customer === null || item.customer === customer) &&
136
+ (invoice === null || item.invoice === invoice),
137
+ render: renderItem,
138
+ });
139
+ return jsonResponse(200, applyExpand(page, params.expand, expanders(scope)));
140
+ },
141
+ GetInvoiceitemsInvoiceitem: async (context) => {
142
+ const scope = requestScope(services, context);
143
+ const params = queryParams(context);
144
+ const item = requireItem(scope, context.params.invoiceitem ?? "");
145
+ return jsonResponse(200, applyExpand(renderItem(item), params.expand, expanders(scope)));
146
+ },
147
+ PostInvoiceitemsInvoiceitem: async (context) => {
148
+ const scope = requestScope(services, context);
149
+ const params = bodyParams(context);
150
+ const current = requireItem(scope, context.params.invoiceitem ?? "");
151
+ const next = {
152
+ ...current,
153
+ amount: intOf(params.amount) ?? current.amount,
154
+ description: optionalString(params, "description", current.description),
155
+ metadata: mergeRecordMetadata(current.metadata, params.metadata),
156
+ quantity: intOf(params.quantity) ?? current.quantity,
157
+ };
158
+ scope.account.invoiceItems.update(next.id, next);
159
+ syncDraftInvoice(scope, next);
160
+ return jsonResponse(200, applyExpand(renderItem(next), params.expand, expanders(scope)));
161
+ },
162
+ DeleteInvoiceitemsInvoiceitem: async (context) => {
163
+ const scope = requestScope(services, context);
164
+ const id = context.params.invoiceitem ?? "";
165
+ const item = requireItem(scope, id);
166
+ if (item.invoice !== null) {
167
+ const invoice = scope.account.invoices.get(item.invoice);
168
+ if (invoice && invoice.status === "draft") {
169
+ const lines = invoice.lines.filter((line) => line.invoice_item !== item.id);
170
+ if (lines.length !== invoice.lines.length)
171
+ scope.account.invoices.update(invoice.id, recomputeInvoice({ ...invoice, lines }));
172
+ }
173
+ }
174
+ scope.account.invoiceItems.delete(id);
175
+ return jsonResponse(200, renderDeletedInvoiceItem(id));
176
+ },
177
+ };
178
+ };
179
+ //# sourceMappingURL=invoice-items.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoice-items.js","sourceRoot":"","sources":["../src/invoice-items.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type OperationHandler } from "@crvouga/mockingbird-service";
2
+ import { type Services } from "./internal.js";
3
+ export declare const invoiceHandlers: (services: Services) => Record<string, OperationHandler>;
4
+ //# sourceMappingURL=invoices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoices.d.ts","sourceRoot":"","sources":["../src/invoices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAGlF,OAAO,EAgBL,KAAK,QAAQ,EACd,MAAM,eAAe,CAAA;AA2BtB,eAAO,MAAM,eAAe,GAAI,UAAU,QAAQ,KAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAkUnF,CAAA"}
@@ -0,0 +1,312 @@
1
+ import { jsonResponse } from "@crvouga/mockingbird-service";
2
+ import { invalidRequest, parameterMissing } from "./errors.js";
3
+ import { applyExpand } from "./expand.js";
4
+ import { clientSecretFor, confirmPaymentIntent, createCharge, customerEmail, customerName, invoiceLineFromItem, invoiceLineFromPrice, mergeRecordMetadata, openInvoice, recomputeInvoice, requestScope, requireInvoice, requirePrice, requireSubscription, } from "./internal.js";
5
+ import { matchesCreated, paginate } from "./list.js";
6
+ import { bodyParams, queryParams } from "./params.js";
7
+ import { renderCharge, renderCustomer, renderDeletedInvoice, renderInvoice, renderPaymentIntent, renderPromotionCode, renderSubscription, } from "./render.js";
8
+ import { seconds } from "./state.js";
9
+ const stringOf = (params, key) => {
10
+ const value = params[key];
11
+ return typeof value === "string" && value !== "" ? value : null;
12
+ };
13
+ const intOf = (value) => {
14
+ if (value === undefined || value === "")
15
+ return undefined;
16
+ const parsed = Number(value);
17
+ return Number.isFinite(parsed) ? Math.trunc(parsed) : undefined;
18
+ };
19
+ export const invoiceHandlers = (services) => {
20
+ const expanders = (scope) => ({
21
+ charge: (id) => {
22
+ const charge = scope.account.charges.get(id);
23
+ return charge ? renderCharge(charge) : undefined;
24
+ },
25
+ payment_intent: (id) => {
26
+ const intent = scope.account.paymentIntents.get(id);
27
+ return intent ? renderPaymentIntent(intent) : undefined;
28
+ },
29
+ subscription: (id) => {
30
+ const subscription = scope.account.subscriptions.get(id);
31
+ return subscription ? renderSubscription(subscription, scope.account) : undefined;
32
+ },
33
+ customer: (id) => {
34
+ const entry = scope.account.customers.get(id);
35
+ return entry?.kind === "live" ? renderCustomer(entry.customer) : undefined;
36
+ },
37
+ default_payment_method: (id) => scope.account.paymentMethods.get(id),
38
+ "discounts.coupon": (id) => scope.account.coupons.get(id),
39
+ "discounts.promotion_code": (id) => {
40
+ const promotion = scope.account.promotionCodes.get(id);
41
+ return promotion ? renderPromotionCode(promotion) : undefined;
42
+ },
43
+ "discount.coupon": (id) => scope.account.coupons.get(id),
44
+ "discount.promotion_code": (id) => {
45
+ const promotion = scope.account.promotionCodes.get(id);
46
+ return promotion ? renderPromotionCode(promotion) : undefined;
47
+ },
48
+ });
49
+ const render = (scope, record, params) => applyExpand(renderInvoice(record, scope.account), params.expand, expanders(scope));
50
+ /** Lines of a preview invoice describe the subscription's current items. */
51
+ const subscriptionLines = (scope, subscriptionId) => {
52
+ const subscription = requireSubscription(scope, subscriptionId);
53
+ return subscription.item_ids
54
+ .map((id) => scope.account.subscriptionItems.get(id))
55
+ .filter((item) => item !== undefined)
56
+ .map((item) => invoiceLineFromPrice(scope, requirePrice(scope, item.price), item.quantity ?? 1));
57
+ };
58
+ return {
59
+ GetInvoices: async (context) => {
60
+ const scope = requestScope(services, context);
61
+ const params = queryParams(context);
62
+ const customer = stringOf(params, "customer");
63
+ const subscription = stringOf(params, "subscription");
64
+ const status = stringOf(params, "status");
65
+ const billingReason = stringOf(params, "billing_reason");
66
+ return jsonResponse(200, await paginate(scope.account.invoices, params, {
67
+ url: "/v1/invoices",
68
+ kind: "invoice",
69
+ where: (record) => matchesCreated(record.created, params.created) &&
70
+ (customer === null || record.customer === customer) &&
71
+ (subscription === null || record.subscription === subscription) &&
72
+ (status === null || record.status === status) &&
73
+ (billingReason === null || record.billing_reason === billingReason),
74
+ render: (record) => render(scope, record, params),
75
+ }));
76
+ },
77
+ PostInvoices: async (context) => {
78
+ const scope = requestScope(services, context);
79
+ const params = bodyParams(context);
80
+ const customer = stringOf(params, "customer");
81
+ if (customer === null)
82
+ throw parameterMissing("customer");
83
+ const entry = scope.account.customers.get(customer);
84
+ if (!entry || entry.kind === "deleted")
85
+ throw invalidRequest(`No such customer: '${customer}'`, "customer", "resource_missing");
86
+ const subscription = stringOf(params, "subscription");
87
+ if (subscription !== null)
88
+ requireSubscription(scope, subscription);
89
+ const pending = scope.account.invoiceItems
90
+ .list({ order: "oldest" })
91
+ .map((item) => item.value)
92
+ .filter((item) => item.customer === customer && item.invoice === null);
93
+ const opened = openInvoice(scope, {
94
+ billingReason: "manual",
95
+ customer,
96
+ lines: pending.map((item) => invoiceLineFromItem(scope, item)),
97
+ metadata: params.metadata ?? {},
98
+ subscription,
99
+ });
100
+ const draft = {
101
+ ...opened,
102
+ auto_advance: params.auto_advance !== undefined && params.auto_advance !== "false",
103
+ collection_method: stringOf(params, "collection_method") === "send_invoice"
104
+ ? "send_invoice"
105
+ : "charge_automatically",
106
+ description: stringOf(params, "description"),
107
+ status: "draft",
108
+ status_transitions: { ...opened.status_transitions, finalized_at: null },
109
+ };
110
+ scope.account.invoices.update(draft.id, draft);
111
+ for (const item of pending)
112
+ scope.account.invoiceItems.update(item.id, { ...item, invoice: draft.id });
113
+ return jsonResponse(200, render(scope, draft, params));
114
+ },
115
+ GetInvoicesInvoice: async (context) => {
116
+ const scope = requestScope(services, context);
117
+ const params = queryParams(context);
118
+ return jsonResponse(200, render(scope, requireInvoice(scope, context.params.invoice ?? ""), params));
119
+ },
120
+ PostInvoicesInvoice: async (context) => {
121
+ const scope = requestScope(services, context);
122
+ const params = bodyParams(context);
123
+ const current = requireInvoice(scope, context.params.invoice ?? "");
124
+ const next = {
125
+ ...current,
126
+ auto_advance: params.auto_advance === undefined
127
+ ? current.auto_advance
128
+ : params.auto_advance === true || params.auto_advance === "true",
129
+ collection_method: stringOf(params, "collection_method") === "send_invoice"
130
+ ? "send_invoice"
131
+ : current.collection_method,
132
+ description: stringOf(params, "description") ?? current.description,
133
+ due_date: intOf(params.due_date) ?? current.due_date,
134
+ metadata: mergeRecordMetadata(current.metadata, params.metadata),
135
+ };
136
+ scope.account.invoices.update(next.id, next);
137
+ return jsonResponse(200, render(scope, next, params));
138
+ },
139
+ DeleteInvoicesInvoice: async (context) => {
140
+ const scope = requestScope(services, context);
141
+ const id = context.params.invoice ?? "";
142
+ const current = requireInvoice(scope, id);
143
+ if (current.status !== "draft")
144
+ throw invalidRequest(`Only draft invoices can be deleted; this invoice has a status of ${current.status}.`, undefined, "invoice_not_draft");
145
+ scope.account.invoices.delete(id);
146
+ return jsonResponse(200, renderDeletedInvoice(id));
147
+ },
148
+ PostInvoicesInvoiceFinalize: async (context) => {
149
+ const scope = requestScope(services, context);
150
+ const params = bodyParams(context);
151
+ const current = requireInvoice(scope, context.params.invoice ?? "");
152
+ if (current.status !== "draft")
153
+ throw invalidRequest(`Only draft invoices can be finalized; this invoice has a status of ${current.status}.`, undefined, "invoice_not_draft");
154
+ const next = {
155
+ ...current,
156
+ status: "open",
157
+ status_transitions: { ...current.status_transitions, finalized_at: seconds(scope.now) },
158
+ };
159
+ scope.account.invoices.update(next.id, next);
160
+ return jsonResponse(200, render(scope, next, params));
161
+ },
162
+ PostInvoicesInvoicePay: async (context) => {
163
+ const scope = requestScope(services, context);
164
+ const params = bodyParams(context);
165
+ const current = requireInvoice(scope, context.params.invoice ?? "");
166
+ if (current.status === "paid")
167
+ return jsonResponse(200, render(scope, current, params));
168
+ if (current.status === "void" || current.status === "uncollectible")
169
+ throw invalidRequest(`This invoice cannot be paid because it has a status of ${current.status}.`, undefined, "invoice_not_payable");
170
+ const subscription = current.subscription === null
171
+ ? undefined
172
+ : scope.account.subscriptions.get(current.subscription);
173
+ const paymentMethod = stringOf(params, "payment_method") ?? subscription?.default_payment_method ?? null;
174
+ const payable = recomputeInvoice(current);
175
+ const intentId = scope.ids.next("pi_");
176
+ scope.account.paymentIntents.insert(intentId, {
177
+ id: intentId,
178
+ amount: payable.amount_due,
179
+ amount_capturable: 0,
180
+ amount_received: 0,
181
+ capture_method: "automatic",
182
+ charge_ids: [],
183
+ client_secret: clientSecretFor(intentId),
184
+ confirmation_method: "automatic",
185
+ created: seconds(scope.now),
186
+ currency: payable.currency,
187
+ customer: payable.customer,
188
+ description: null,
189
+ invoice: payable.id,
190
+ last_payment_error: null,
191
+ latest_charge: null,
192
+ metadata: {},
193
+ payment_method: paymentMethod,
194
+ payment_method_types: ["card"],
195
+ receipt_email: null,
196
+ setup_future_usage: null,
197
+ status: "requires_payment_method",
198
+ canceled_at: null,
199
+ cancellation_reason: null,
200
+ });
201
+ const intent = scope.account.paymentIntents.get(intentId);
202
+ const settled = intent !== undefined && paymentMethod !== null
203
+ ? confirmPaymentIntent(scope, intent, paymentMethod)
204
+ : intent;
205
+ const chargeId = settled?.latest_charge ??
206
+ createCharge(scope, {
207
+ amount: payable.amount_due,
208
+ currency: payable.currency,
209
+ customer: payable.customer,
210
+ invoice: payable.id,
211
+ payment_intent: intentId,
212
+ payment_method: paymentMethod,
213
+ }).id;
214
+ const paidAt = seconds(scope.now);
215
+ const next = {
216
+ ...payable,
217
+ amount_paid: payable.amount_due,
218
+ amount_remaining: 0,
219
+ attempt_count: 1,
220
+ attempted: true,
221
+ charge: chargeId,
222
+ paid: true,
223
+ payment_intent: intentId,
224
+ status: "paid",
225
+ status_transitions: {
226
+ ...payable.status_transitions,
227
+ finalized_at: payable.status_transitions.finalized_at ?? paidAt,
228
+ paid_at: paidAt,
229
+ },
230
+ };
231
+ scope.account.invoices.update(next.id, next);
232
+ scope.emit("invoice.paid", renderInvoice(next, scope.account));
233
+ return jsonResponse(200, render(scope, next, params));
234
+ },
235
+ GetInvoicesInvoiceLines: async (context) => {
236
+ const scope = requestScope(services, context);
237
+ const params = queryParams(context);
238
+ const invoice = requireInvoice(scope, context.params.invoice ?? "");
239
+ const limit = Math.min(100, Math.max(1, intOf(params.limit) ?? 10));
240
+ const rendered = render(scope, invoice, params);
241
+ const data = (rendered.lines ?? { data: [] }).data;
242
+ const cursor = stringOf(params, "starting_after");
243
+ const found = cursor === null ? 0 : data.findIndex((line) => line.id === cursor) + 1;
244
+ const from = Math.max(0, found);
245
+ const window = data.slice(from, from + limit);
246
+ return jsonResponse(200, {
247
+ object: "list",
248
+ data: window,
249
+ has_more: from + window.length < data.length,
250
+ url: `/v1/invoices/${invoice.id}/lines`,
251
+ });
252
+ },
253
+ GetInvoicesUpcoming: async (context) => {
254
+ const scope = requestScope(services, context);
255
+ const params = queryParams(context);
256
+ const subscriptionId = stringOf(params, "subscription");
257
+ const subscription = subscriptionId === null ? undefined : scope.account.subscriptions.get(subscriptionId);
258
+ const customer = stringOf(params, "customer") ?? subscription?.customer ?? null;
259
+ if (customer !== null) {
260
+ const entry = scope.account.customers.get(customer);
261
+ if (!entry || entry.kind === "deleted")
262
+ throw invalidRequest(`No such customer: '${customer}'`, "customer", "resource_missing");
263
+ }
264
+ const lines = subscriptionId === null ? [] : subscriptionLines(scope, subscriptionId);
265
+ const now = seconds(scope.now);
266
+ const subtotal = lines.reduce((total, line) => total + line.amount, 0);
267
+ const preview = {
268
+ id: `upcoming_in_${now}`,
269
+ amount_due: subtotal,
270
+ amount_paid: 0,
271
+ amount_remaining: subtotal,
272
+ attempt_count: 0,
273
+ attempted: false,
274
+ auto_advance: true,
275
+ billing_reason: "upcoming",
276
+ charge: null,
277
+ collection_method: "charge_automatically",
278
+ created: now,
279
+ currency: lines[0]?.currency ?? "usd",
280
+ customer,
281
+ customer_email: customerEmail(scope, customer),
282
+ customer_name: customerName(scope, customer),
283
+ description: null,
284
+ discount_ids: [],
285
+ due_date: null,
286
+ ending_balance: 0,
287
+ hosted_invoice_url: null,
288
+ invoice_pdf: null,
289
+ lines,
290
+ metadata: {},
291
+ next_payment_attempt: null,
292
+ number: null,
293
+ paid: false,
294
+ payment_intent: null,
295
+ period_end: now,
296
+ period_start: now,
297
+ status: "draft",
298
+ status_transitions: {
299
+ finalized_at: null,
300
+ marked_uncollectible_at: null,
301
+ paid_at: null,
302
+ voided_at: null,
303
+ },
304
+ subscription: subscriptionId,
305
+ subtotal,
306
+ total: subtotal,
307
+ };
308
+ return jsonResponse(200, render(scope, preview, params));
309
+ },
310
+ };
311
+ };
312
+ //# sourceMappingURL=invoices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoices.js","sourceRoot":"","sources":["../src/invoices.ts"],"names":[],"mappings":"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"}
package/dist/list.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type { Collection } from "@crvouga/mockingbird-service";
2
+ import type { Params } from "./params.js";
3
+ /** Stripe clamps `limit` into 1..100 instead of rejecting it. */
4
+ export declare const clampLimit: (limit: unknown) => number;
5
+ export declare const matchesCreated: (created: number, filter: unknown) => boolean;
6
+ export type Page<T> = {
7
+ object: "list";
8
+ data: T[];
9
+ has_more: boolean;
10
+ url: string;
11
+ };
12
+ /**
13
+ * Cursor pagination over records sorted newest first. `starting_after` continues past a record,
14
+ * `ending_before` yields the records immediately newer than one, both in newest-first order.
15
+ */
16
+ export declare const paginate: <T>(collection: Collection<T>, params: Params, options: {
17
+ url: string;
18
+ kind: string;
19
+ where: (record: T) => boolean;
20
+ /** Existence check for cursors; deleted tombstones count as missing. */
21
+ exists?: (record: T) => boolean;
22
+ render: (record: T) => unknown;
23
+ }) => Promise<Page<unknown>>;
24
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../src/list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAU,MAAM,8BAA8B,CAAA;AAEtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAKzC,iEAAiE;AACjE,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,WAGxC,CAAA;AAID,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,EAAE,QAAQ,OAAO,YAS9D,CAAA;AAED,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAEnF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAU,CAAC,EAC9B,YAAY,UAAU,CAAC,CAAC,CAAC,EACzB,QAAQ,MAAM,EACd,SAAS;IACP,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAA;IAC7B,wEAAwE;IACxE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAA;IAC/B,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAA;CAC/B,KACA,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CA0CvB,CAAA"}
package/dist/list.js ADDED
@@ -0,0 +1,68 @@
1
+ import { invalidRequest, resourceMissing } from "./errors.js";
2
+ const DEFAULT_LIMIT = 10;
3
+ const MAX_LIMIT = 100;
4
+ /** Stripe clamps `limit` into 1..100 instead of rejecting it. */
5
+ export const clampLimit = (limit) => {
6
+ if (typeof limit !== "number")
7
+ return DEFAULT_LIMIT;
8
+ return Math.min(MAX_LIMIT, Math.max(1, limit));
9
+ };
10
+ export const matchesCreated = (created, filter) => {
11
+ if (filter === undefined)
12
+ return true;
13
+ const spec = filter;
14
+ if (typeof spec === "number")
15
+ return created === spec;
16
+ if (spec.gt !== undefined && !(created > spec.gt))
17
+ return false;
18
+ if (spec.gte !== undefined && !(created >= spec.gte))
19
+ return false;
20
+ if (spec.lt !== undefined && !(created < spec.lt))
21
+ return false;
22
+ if (spec.lte !== undefined && !(created <= spec.lte))
23
+ return false;
24
+ return true;
25
+ };
26
+ /**
27
+ * Cursor pagination over records sorted newest first. `starting_after` continues past a record,
28
+ * `ending_before` yields the records immediately newer than one, both in newest-first order.
29
+ */
30
+ export const paginate = async (collection, params, options) => {
31
+ const startingAfter = params.starting_after;
32
+ const endingBefore = params.ending_before;
33
+ if (typeof startingAfter === "string" &&
34
+ startingAfter !== "" &&
35
+ typeof endingBefore === "string" &&
36
+ endingBefore !== "") {
37
+ throw invalidRequest("Received both starting_after and ending_before parameters. Please pass in only one.");
38
+ }
39
+ const limit = clampLimit(params.limit);
40
+ const all = await collection.list({ order: "newest" });
41
+ const exists = options.exists ?? (() => true);
42
+ const cursorIndex = (id, param) => {
43
+ const index = all.findIndex((entry) => entry.id === id && exists(entry.value));
44
+ if (index === -1)
45
+ throw resourceMissing(options.kind, id, param, 400);
46
+ return index;
47
+ };
48
+ const matching = (entries) => entries.filter((entry) => options.where(entry.value));
49
+ let data;
50
+ let hasMore;
51
+ if (typeof startingAfter === "string" && startingAfter !== "") {
52
+ const rest = matching(all.slice(cursorIndex(startingAfter, "starting_after") + 1));
53
+ data = rest.slice(0, limit).map((e) => e.value);
54
+ hasMore = rest.length > limit;
55
+ }
56
+ else if (typeof endingBefore === "string" && endingBefore !== "") {
57
+ const before = matching(all.slice(0, cursorIndex(endingBefore, "ending_before")));
58
+ data = before.slice(Math.max(0, before.length - limit)).map((e) => e.value);
59
+ hasMore = before.length > limit;
60
+ }
61
+ else {
62
+ const rows = matching(all);
63
+ data = rows.slice(0, limit).map((e) => e.value);
64
+ hasMore = rows.length > limit;
65
+ }
66
+ return { object: "list", data: data.map(options.render), has_more: hasMore, url: options.url };
67
+ };
68
+ //# sourceMappingURL=list.js.map