alchemy 0.24.0 → 0.24.1

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 (163) hide show
  1. package/lib/aws/function.d.ts.map +1 -1
  2. package/lib/aws/function.js +1 -4
  3. package/lib/aws/function.js.map +1 -1
  4. package/lib/cloudflare/bindings.d.ts +3 -3
  5. package/lib/cloudflare/bindings.d.ts.map +1 -1
  6. package/lib/cloudflare/bindings.js.map +1 -1
  7. package/lib/cloudflare/bound.d.ts +3 -3
  8. package/lib/cloudflare/bound.d.ts.map +1 -1
  9. package/lib/cloudflare/do-state-store/index.d.ts +2 -0
  10. package/lib/cloudflare/do-state-store/index.d.ts.map +1 -0
  11. package/lib/cloudflare/do-state-store/index.js +2 -0
  12. package/lib/cloudflare/do-state-store/index.js.map +1 -0
  13. package/lib/cloudflare/do-state-store/internal.d.ts +19 -0
  14. package/lib/cloudflare/do-state-store/internal.d.ts.map +1 -0
  15. package/lib/cloudflare/do-state-store/internal.js +163 -0
  16. package/lib/cloudflare/do-state-store/internal.js.map +1 -0
  17. package/lib/cloudflare/do-state-store/store.d.ts +59 -0
  18. package/lib/cloudflare/do-state-store/store.d.ts.map +1 -0
  19. package/lib/cloudflare/do-state-store/store.js +120 -0
  20. package/lib/cloudflare/do-state-store/store.js.map +1 -0
  21. package/lib/cloudflare/do-state-store/types.d.ts +82 -0
  22. package/lib/cloudflare/do-state-store/types.d.ts.map +1 -0
  23. package/lib/cloudflare/do-state-store/types.js +1 -0
  24. package/lib/cloudflare/do-state-store/types.js.map +1 -0
  25. package/lib/cloudflare/do-state-store/worker.d.ts +27 -0
  26. package/lib/cloudflare/do-state-store/worker.d.ts.map +1 -0
  27. package/lib/cloudflare/do-state-store/worker.js +170 -0
  28. package/lib/cloudflare/do-state-store/worker.js.map +1 -0
  29. package/lib/cloudflare/index.d.ts +1 -0
  30. package/lib/cloudflare/index.d.ts.map +1 -1
  31. package/lib/cloudflare/index.js +1 -0
  32. package/lib/cloudflare/index.js.map +1 -1
  33. package/lib/cloudflare/pipeline.js +1 -1
  34. package/lib/cloudflare/pipeline.js.map +1 -1
  35. package/lib/cloudflare/queue-consumer.d.ts +14 -1
  36. package/lib/cloudflare/queue-consumer.d.ts.map +1 -1
  37. package/lib/cloudflare/queue-consumer.js +17 -0
  38. package/lib/cloudflare/queue-consumer.js.map +1 -1
  39. package/lib/cloudflare/website.d.ts +30 -1
  40. package/lib/cloudflare/website.d.ts.map +1 -1
  41. package/lib/cloudflare/website.js +8 -5
  42. package/lib/cloudflare/website.js.map +1 -1
  43. package/lib/cloudflare/worker-metadata.js +1 -1
  44. package/lib/cloudflare/worker-metadata.js.map +1 -1
  45. package/lib/cloudflare/worker.d.ts +40 -1
  46. package/lib/cloudflare/worker.d.ts.map +1 -1
  47. package/lib/cloudflare/worker.js +40 -38
  48. package/lib/cloudflare/worker.js.map +1 -1
  49. package/lib/cloudflare/wrangler.json.js +1 -1
  50. package/lib/cloudflare/wrangler.json.js.map +1 -1
  51. package/lib/fs/file-system-state-store.d.ts +3 -1
  52. package/lib/fs/file-system-state-store.d.ts.map +1 -1
  53. package/lib/fs/file-system-state-store.js +2 -2
  54. package/lib/fs/file-system-state-store.js.map +1 -1
  55. package/lib/stripe/card.d.ts +171 -0
  56. package/lib/stripe/card.d.ts.map +1 -0
  57. package/lib/stripe/card.js +148 -0
  58. package/lib/stripe/card.js.map +1 -0
  59. package/lib/stripe/client.d.ts +9 -0
  60. package/lib/stripe/client.d.ts.map +1 -0
  61. package/lib/stripe/client.js +94 -0
  62. package/lib/stripe/client.js.map +1 -0
  63. package/lib/stripe/coupon.d.ts +135 -0
  64. package/lib/stripe/coupon.d.ts.map +1 -0
  65. package/lib/stripe/coupon.js +161 -0
  66. package/lib/stripe/coupon.js.map +1 -0
  67. package/lib/stripe/customer.d.ts +269 -0
  68. package/lib/stripe/customer.d.ts.map +1 -0
  69. package/lib/stripe/customer.js +289 -0
  70. package/lib/stripe/customer.js.map +1 -0
  71. package/lib/stripe/entitlements-feature.d.ts +84 -0
  72. package/lib/stripe/entitlements-feature.d.ts.map +1 -0
  73. package/lib/stripe/entitlements-feature.js +102 -0
  74. package/lib/stripe/entitlements-feature.js.map +1 -0
  75. package/lib/stripe/file.d.ts +143 -0
  76. package/lib/stripe/file.d.ts.map +1 -0
  77. package/lib/stripe/file.js +97 -0
  78. package/lib/stripe/file.js.map +1 -0
  79. package/lib/stripe/index.d.ts +11 -0
  80. package/lib/stripe/index.d.ts.map +1 -1
  81. package/lib/stripe/index.js +11 -0
  82. package/lib/stripe/index.js.map +1 -1
  83. package/lib/stripe/meter.d.ts +10 -1
  84. package/lib/stripe/meter.d.ts.map +1 -1
  85. package/lib/stripe/meter.js +13 -7
  86. package/lib/stripe/meter.js.map +1 -1
  87. package/lib/stripe/portal-configuration.d.ts +286 -0
  88. package/lib/stripe/portal-configuration.d.ts.map +1 -0
  89. package/lib/stripe/portal-configuration.js +320 -0
  90. package/lib/stripe/portal-configuration.js.map +1 -0
  91. package/lib/stripe/price.d.ts +10 -1
  92. package/lib/stripe/price.d.ts.map +1 -1
  93. package/lib/stripe/price.js +34 -13
  94. package/lib/stripe/price.js.map +1 -1
  95. package/lib/stripe/product-feature.d.ts +76 -0
  96. package/lib/stripe/product-feature.d.ts.map +1 -0
  97. package/lib/stripe/product-feature.js +74 -0
  98. package/lib/stripe/product-feature.js.map +1 -0
  99. package/lib/stripe/product.d.ts +10 -1
  100. package/lib/stripe/product.d.ts.map +1 -1
  101. package/lib/stripe/product.js +33 -14
  102. package/lib/stripe/product.js.map +1 -1
  103. package/lib/stripe/promotion-code.d.ts +138 -0
  104. package/lib/stripe/promotion-code.d.ts.map +1 -0
  105. package/lib/stripe/promotion-code.js +150 -0
  106. package/lib/stripe/promotion-code.js.map +1 -0
  107. package/lib/stripe/shipping-rate.d.ts +188 -0
  108. package/lib/stripe/shipping-rate.d.ts.map +1 -0
  109. package/lib/stripe/shipping-rate.js +198 -0
  110. package/lib/stripe/shipping-rate.js.map +1 -0
  111. package/lib/stripe/tax-rate.d.ts +130 -0
  112. package/lib/stripe/tax-rate.d.ts.map +1 -0
  113. package/lib/stripe/tax-rate.js +126 -0
  114. package/lib/stripe/tax-rate.js.map +1 -0
  115. package/lib/stripe/webhook.d.ts +10 -1
  116. package/lib/stripe/webhook.d.ts.map +1 -1
  117. package/lib/stripe/webhook.js +59 -14
  118. package/lib/stripe/webhook.js.map +1 -1
  119. package/lib/test/bun.d.ts.map +1 -1
  120. package/lib/test/bun.js +2 -6
  121. package/lib/test/bun.js.map +1 -1
  122. package/lib/test/vitest.d.ts.map +1 -1
  123. package/lib/test/vitest.js +3 -7
  124. package/lib/test/vitest.js.map +1 -1
  125. package/lib/util/retry.d.ts +1 -1
  126. package/lib/util/retry.d.ts.map +1 -1
  127. package/lib/util/retry.js.map +1 -1
  128. package/package.json +2 -1
  129. package/src/aws/function.ts +3 -6
  130. package/src/cloudflare/bindings.ts +3 -2
  131. package/src/cloudflare/bound.ts +3 -3
  132. package/src/cloudflare/do-state-store/index.ts +1 -0
  133. package/src/cloudflare/do-state-store/internal.ts +215 -0
  134. package/src/cloudflare/do-state-store/store.ts +188 -0
  135. package/src/cloudflare/do-state-store/types.ts +74 -0
  136. package/src/cloudflare/do-state-store/worker.ts +199 -0
  137. package/src/cloudflare/index.ts +1 -0
  138. package/src/cloudflare/pipeline.ts +1 -1
  139. package/src/cloudflare/queue-consumer.ts +59 -1
  140. package/src/cloudflare/website.ts +38 -6
  141. package/src/cloudflare/worker-metadata.ts +1 -1
  142. package/src/cloudflare/worker.ts +66 -46
  143. package/src/cloudflare/wrangler.json.ts +1 -1
  144. package/src/fs/file-system-state-store.ts +7 -2
  145. package/src/stripe/card.ts +320 -0
  146. package/src/stripe/client.ts +145 -0
  147. package/src/stripe/coupon.ts +280 -0
  148. package/src/stripe/customer.ts +528 -0
  149. package/src/stripe/entitlements-feature.ts +169 -0
  150. package/src/stripe/file.ts +219 -0
  151. package/src/stripe/index.ts +11 -0
  152. package/src/stripe/meter.ts +23 -7
  153. package/src/stripe/portal-configuration.ts +609 -0
  154. package/src/stripe/price.ts +47 -14
  155. package/src/stripe/product-feature.ts +150 -0
  156. package/src/stripe/product.ts +48 -15
  157. package/src/stripe/promotion-code.ts +268 -0
  158. package/src/stripe/shipping-rate.ts +362 -0
  159. package/src/stripe/tax-rate.ts +218 -0
  160. package/src/stripe/webhook.ts +82 -15
  161. package/src/test/bun.ts +2 -7
  162. package/src/test/vitest.ts +3 -8
  163. package/src/util/retry.ts +1 -1
@@ -0,0 +1,528 @@
1
+ import type Stripe from "stripe";
2
+ import type { Context } from "../context.ts";
3
+ import { Resource } from "../resource.ts";
4
+ import type { Secret } from "../secret.ts";
5
+ import { createStripeClient, handleStripeDeleteError } from "./client.ts";
6
+
7
+ /**
8
+ * Customer address information
9
+ */
10
+ export interface CustomerAddress {
11
+ /**
12
+ * City, district, suburb, town, or village
13
+ */
14
+ city?: string;
15
+ /**
16
+ * Two-letter country code (ISO 3166-1 alpha-2)
17
+ */
18
+ country?: string;
19
+ /**
20
+ * Address line 1 (e.g., street, PO Box, or company name)
21
+ */
22
+ line1?: string;
23
+ /**
24
+ * Address line 2 (e.g., apartment, suite, unit, or building)
25
+ */
26
+ line2?: string;
27
+ /**
28
+ * ZIP or postal code
29
+ */
30
+ postalCode?: string;
31
+ /**
32
+ * State, county, province, or region
33
+ */
34
+ state?: string;
35
+ }
36
+
37
+ /**
38
+ * Customer shipping information
39
+ */
40
+ export interface CustomerShipping {
41
+ /**
42
+ * Customer's shipping address
43
+ */
44
+ address?: CustomerAddress;
45
+ /**
46
+ * Customer name
47
+ */
48
+ name?: string;
49
+ /**
50
+ * Customer phone number
51
+ */
52
+ phone?: string;
53
+ }
54
+
55
+ /**
56
+ * Customer invoice settings
57
+ */
58
+ export interface CustomerInvoiceSettings {
59
+ /**
60
+ * Default custom fields to be displayed on invoices for this customer
61
+ */
62
+ customFields?: Array<{
63
+ name: string;
64
+ value: string;
65
+ }>;
66
+ /**
67
+ * ID of a payment method that's attached to the customer, to be used as the customer's default payment method for subscriptions and invoices
68
+ */
69
+ defaultPaymentMethod?: string;
70
+ /**
71
+ * Default footer to be displayed on invoices for this customer
72
+ */
73
+ footer?: string;
74
+ /**
75
+ * Default options for invoice PDF rendering for this customer
76
+ */
77
+ renderingOptions?: {
78
+ amountTaxDisplay?: Stripe.CustomerCreateParams.InvoiceSettings.RenderingOptions.AmountTaxDisplay;
79
+ };
80
+ }
81
+
82
+ /**
83
+ * Properties for creating a Stripe customer
84
+ */
85
+ export interface CustomerProps {
86
+ /**
87
+ * The customer's address
88
+ */
89
+ address?: CustomerAddress;
90
+ /**
91
+ * An integer amount in cents that represents the customer's current balance
92
+ */
93
+ balance?: number;
94
+ /**
95
+ * If you provide a coupon code, the customer will have a discount applied on all recurring charges
96
+ */
97
+ coupon?: string;
98
+ /**
99
+ * An arbitrary string attached to the object
100
+ */
101
+ description?: string;
102
+ /**
103
+ * Customer's email address
104
+ */
105
+ email?: string;
106
+ /**
107
+ * The prefix for the customer used to generate unique invoice numbers
108
+ */
109
+ invoicePrefix?: string;
110
+ /**
111
+ * Default invoice settings for this customer
112
+ */
113
+ invoiceSettings?: CustomerInvoiceSettings;
114
+ /**
115
+ * Set of key-value pairs that you can attach to an object
116
+ */
117
+ metadata?: Record<string, string>;
118
+ /**
119
+ * The customer's full name or business name
120
+ */
121
+ name?: string;
122
+ /**
123
+ * The sequence to be used on the customer's next invoice
124
+ */
125
+ nextInvoiceSequence?: number;
126
+ /**
127
+ * The ID of the PaymentMethod to attach to the customer
128
+ */
129
+ paymentMethod?: string;
130
+ /**
131
+ * The customer's phone number
132
+ */
133
+ phone?: string;
134
+ /**
135
+ * Customer's preferred languages, ordered by preference
136
+ */
137
+ preferredLocales?: string[];
138
+ /**
139
+ * The ID of a promotion code to apply to the customer
140
+ */
141
+ promotionCode?: string;
142
+ /**
143
+ * The customer's shipping information
144
+ */
145
+ shipping?: CustomerShipping;
146
+ /**
147
+ * When using a card as a source, you can pass the card information
148
+ */
149
+ source?: string;
150
+ /**
151
+ * The customer's tax exemption status
152
+ */
153
+ taxExempt?: Stripe.CustomerCreateParams.TaxExempt;
154
+ /**
155
+ * ID of the test clock to attach to the customer
156
+ */
157
+ testClock?: string;
158
+
159
+ /**
160
+ * API key to use (overrides environment variable)
161
+ */
162
+ apiKey?: Secret;
163
+
164
+ /**
165
+ * If true, adopt existing resource if creation fails due to conflict
166
+ */
167
+ adopt?: boolean;
168
+ }
169
+
170
+ /**
171
+ * Output from the Stripe customer
172
+ */
173
+ export interface Customer extends Resource<"stripe::Customer">, CustomerProps {
174
+ /**
175
+ * The ID of the customer
176
+ */
177
+ id: string;
178
+ /**
179
+ * String representing the object's type
180
+ */
181
+ object: "customer";
182
+ /**
183
+ * Time at which the object was created
184
+ */
185
+ created: number;
186
+ /**
187
+ * Three-letter ISO code for the currency the customer can be charged in for recurring billing purposes
188
+ */
189
+ currency?: string;
190
+ /**
191
+ * ID of the default payment source for the customer
192
+ */
193
+ defaultSource?: string;
194
+ /**
195
+ * Whether or not the customer is currently delinquent
196
+ */
197
+ delinquent?: boolean;
198
+ /**
199
+ * Describes the current discount active on the customer, if there is one
200
+ */
201
+ discount?: any;
202
+ /**
203
+ * Has the value true if the object exists in live mode or the value false if the object exists in test mode
204
+ */
205
+ livemode: boolean;
206
+ /**
207
+ * The customer's payment sources, if any
208
+ */
209
+ sources?: any;
210
+ /**
211
+ * The customer's current subscriptions, if any
212
+ */
213
+ subscriptions?: any;
214
+ /**
215
+ * The customer's tax IDs, if any
216
+ */
217
+ taxIds?: any;
218
+ }
219
+
220
+ /**
221
+ * Create and manage Stripe customers
222
+ *
223
+ * @example
224
+ * // Create a basic customer
225
+ * const basicCustomer = await Customer("basic-customer", {
226
+ * email: "john@example.com",
227
+ * name: "John Doe",
228
+ * description: "Premium customer",
229
+ * metadata: {
230
+ * tier: "premium",
231
+ * source: "website"
232
+ * }
233
+ * });
234
+ *
235
+ * @example
236
+ * // Create a customer with full address information
237
+ * const customerWithAddress = await Customer("customer-with-address", {
238
+ * email: "jane@example.com",
239
+ * name: "Jane Smith",
240
+ * phone: "+1-555-123-4567",
241
+ * address: {
242
+ * line1: "123 Main St",
243
+ * line2: "Apt 4B",
244
+ * city: "San Francisco",
245
+ * state: "CA",
246
+ * postalCode: "94105",
247
+ * country: "US"
248
+ * },
249
+ * shipping: {
250
+ * name: "Jane Smith",
251
+ * address: {
252
+ * line1: "456 Oak Ave",
253
+ * city: "Oakland",
254
+ * state: "CA",
255
+ * postalCode: "94612",
256
+ * country: "US"
257
+ * }
258
+ * }
259
+ * });
260
+ *
261
+ * @example
262
+ * // Create a business customer with tax exemption
263
+ * const businessCustomer = await Customer("business-customer", {
264
+ * email: "billing@acmecorp.com",
265
+ * name: "Acme Corporation",
266
+ * description: "Enterprise customer",
267
+ * taxExempt: "exempt",
268
+ * invoicePrefix: "ACME",
269
+ * preferredLocales: ["en"],
270
+ * metadata: {
271
+ * type: "business",
272
+ * industry: "technology",
273
+ * employees: "500+"
274
+ * }
275
+ * });
276
+ */
277
+ export const Customer = Resource(
278
+ "stripe::Customer",
279
+ async function (
280
+ this: Context<Customer>,
281
+ _id: string,
282
+ props: CustomerProps,
283
+ ): Promise<Customer> {
284
+ const stripe = createStripeClient({ apiKey: props.apiKey });
285
+
286
+ if (this.phase === "delete") {
287
+ try {
288
+ if (this.output?.id) {
289
+ await stripe.customers.del(this.output.id);
290
+ }
291
+ } catch (error) {
292
+ handleStripeDeleteError(error, "Customer", this.output?.id);
293
+ }
294
+ return this.destroy();
295
+ }
296
+
297
+ try {
298
+ let customer: Stripe.Customer;
299
+
300
+ if (this.phase === "update" && this.output?.id) {
301
+ const updateParams: Stripe.CustomerUpdateParams = {
302
+ address: props.address
303
+ ? {
304
+ city: props.address.city,
305
+ country: props.address.country,
306
+ line1: props.address.line1,
307
+ line2: props.address.line2,
308
+ postal_code: props.address.postalCode,
309
+ state: props.address.state,
310
+ }
311
+ : undefined,
312
+ balance: props.balance,
313
+ coupon: props.coupon,
314
+ description: props.description,
315
+ email: props.email,
316
+ invoice_prefix: props.invoicePrefix,
317
+ metadata: props.metadata,
318
+ name: props.name,
319
+ next_invoice_sequence: props.nextInvoiceSequence,
320
+ phone: props.phone,
321
+ preferred_locales: props.preferredLocales,
322
+ promotion_code: props.promotionCode,
323
+ shipping: props.shipping as any,
324
+ source: props.source,
325
+ tax_exempt: props.taxExempt,
326
+ };
327
+
328
+ if (props.invoiceSettings) {
329
+ updateParams.invoice_settings = {
330
+ custom_fields: props.invoiceSettings.customFields,
331
+ default_payment_method: props.invoiceSettings.defaultPaymentMethod,
332
+ footer: props.invoiceSettings.footer,
333
+ rendering_options: props.invoiceSettings.renderingOptions
334
+ ? {
335
+ amount_tax_display:
336
+ props.invoiceSettings.renderingOptions.amountTaxDisplay,
337
+ }
338
+ : null,
339
+ };
340
+ }
341
+
342
+ customer = await stripe.customers.update(this.output.id, updateParams);
343
+ } else {
344
+ const createParams: Stripe.CustomerCreateParams = {
345
+ address: props.address
346
+ ? {
347
+ city: props.address.city,
348
+ country: props.address.country,
349
+ line1: props.address.line1,
350
+ line2: props.address.line2,
351
+ postal_code: props.address.postalCode,
352
+ state: props.address.state,
353
+ }
354
+ : undefined,
355
+ balance: props.balance,
356
+ coupon: props.coupon,
357
+ description: props.description,
358
+ email: props.email,
359
+ invoice_prefix: props.invoicePrefix,
360
+ metadata: props.metadata,
361
+ name: props.name,
362
+ next_invoice_sequence: props.nextInvoiceSequence,
363
+ payment_method: props.paymentMethod,
364
+ phone: props.phone,
365
+ preferred_locales: props.preferredLocales,
366
+ promotion_code: props.promotionCode,
367
+ shipping: props.shipping as any,
368
+ source: props.source,
369
+ tax_exempt: props.taxExempt,
370
+ test_clock: props.testClock,
371
+ };
372
+
373
+ if (props.invoiceSettings) {
374
+ createParams.invoice_settings = {
375
+ custom_fields: props.invoiceSettings.customFields,
376
+ default_payment_method: props.invoiceSettings.defaultPaymentMethod,
377
+ footer: props.invoiceSettings.footer,
378
+ rendering_options: props.invoiceSettings.renderingOptions
379
+ ? {
380
+ amount_tax_display:
381
+ props.invoiceSettings.renderingOptions.amountTaxDisplay,
382
+ }
383
+ : null,
384
+ };
385
+ }
386
+
387
+ if (props.adopt && props.email) {
388
+ const existingCustomers = await stripe.customers.list({
389
+ email: props.email,
390
+ limit: 1,
391
+ });
392
+ if (existingCustomers.data.length > 0) {
393
+ const existingCustomer = existingCustomers.data[0];
394
+ const adoptUpdateParams: Stripe.CustomerUpdateParams = {
395
+ address: props.address
396
+ ? {
397
+ city: props.address.city,
398
+ country: props.address.country,
399
+ line1: props.address.line1,
400
+ line2: props.address.line2,
401
+ postal_code: props.address.postalCode,
402
+ state: props.address.state,
403
+ }
404
+ : undefined,
405
+ balance: props.balance,
406
+ coupon: props.coupon,
407
+ description: props.description,
408
+ email: props.email,
409
+ invoice_prefix: props.invoicePrefix,
410
+ metadata: props.metadata,
411
+ name: props.name,
412
+ next_invoice_sequence: props.nextInvoiceSequence,
413
+ phone: props.phone,
414
+ preferred_locales: props.preferredLocales,
415
+ promotion_code: props.promotionCode,
416
+ shipping: props.shipping as any,
417
+ source: props.source,
418
+ tax_exempt: props.taxExempt,
419
+ };
420
+
421
+ if (props.invoiceSettings) {
422
+ adoptUpdateParams.invoice_settings = {
423
+ custom_fields: props.invoiceSettings.customFields,
424
+ default_payment_method:
425
+ props.invoiceSettings.defaultPaymentMethod,
426
+ footer: props.invoiceSettings.footer,
427
+ rendering_options: props.invoiceSettings.renderingOptions
428
+ ? {
429
+ amount_tax_display:
430
+ props.invoiceSettings.renderingOptions.amountTaxDisplay,
431
+ }
432
+ : null,
433
+ };
434
+ }
435
+
436
+ customer = await stripe.customers.update(
437
+ existingCustomer.id,
438
+ adoptUpdateParams,
439
+ );
440
+ } else {
441
+ customer = await stripe.customers.create(createParams);
442
+ }
443
+ } else {
444
+ customer = await stripe.customers.create(createParams);
445
+ }
446
+ }
447
+
448
+ return this({
449
+ id: customer.id,
450
+ object: customer.object,
451
+ address: customer.address
452
+ ? {
453
+ city: customer.address.city || undefined,
454
+ country: customer.address.country || undefined,
455
+ line1: customer.address.line1 || undefined,
456
+ line2: customer.address.line2 || undefined,
457
+ postalCode: customer.address.postal_code || undefined,
458
+ state: customer.address.state || undefined,
459
+ }
460
+ : undefined,
461
+ balance: customer.balance || undefined,
462
+ created: customer.created,
463
+ currency: customer.currency || undefined,
464
+ defaultSource:
465
+ typeof customer.default_source === "string"
466
+ ? customer.default_source
467
+ : undefined,
468
+ delinquent: customer.delinquent || undefined,
469
+ description: customer.description || undefined,
470
+ discount: customer.discount || undefined,
471
+ email: customer.email || undefined,
472
+ invoicePrefix: customer.invoice_prefix || undefined,
473
+ invoiceSettings: customer.invoice_settings
474
+ ? {
475
+ customFields:
476
+ customer.invoice_settings.custom_fields?.map((field) => ({
477
+ name: field.name,
478
+ value: field.value,
479
+ })) || undefined,
480
+ defaultPaymentMethod:
481
+ typeof customer.invoice_settings.default_payment_method ===
482
+ "string"
483
+ ? customer.invoice_settings.default_payment_method
484
+ : customer.invoice_settings.default_payment_method?.id ||
485
+ undefined,
486
+ footer: customer.invoice_settings.footer || undefined,
487
+ renderingOptions: customer.invoice_settings.rendering_options
488
+ ? {
489
+ amountTaxDisplay: customer.invoice_settings
490
+ .rendering_options.amount_tax_display as any,
491
+ }
492
+ : undefined,
493
+ }
494
+ : undefined,
495
+ livemode: customer.livemode,
496
+ metadata: customer.metadata || undefined,
497
+ name: customer.name || undefined,
498
+ nextInvoiceSequence: customer.next_invoice_sequence || undefined,
499
+ phone: customer.phone || undefined,
500
+ preferredLocales: customer.preferred_locales || undefined,
501
+ shipping: customer.shipping
502
+ ? {
503
+ address: customer.shipping.address
504
+ ? {
505
+ city: customer.shipping.address.city || undefined,
506
+ country: customer.shipping.address.country || undefined,
507
+ line1: customer.shipping.address.line1 || undefined,
508
+ line2: customer.shipping.address.line2 || undefined,
509
+ postalCode:
510
+ customer.shipping.address.postal_code || undefined,
511
+ state: customer.shipping.address.state || undefined,
512
+ }
513
+ : undefined,
514
+ name: customer.shipping.name || undefined,
515
+ phone: customer.shipping.phone || undefined,
516
+ }
517
+ : undefined,
518
+ sources: customer.sources || undefined,
519
+ subscriptions: customer.subscriptions || undefined,
520
+ taxExempt: customer.tax_exempt || undefined,
521
+ taxIds: customer.tax_ids || undefined,
522
+ });
523
+ } catch (error) {
524
+ console.error("Error creating/updating customer:", error);
525
+ throw error;
526
+ }
527
+ },
528
+ );
@@ -0,0 +1,169 @@
1
+ import type Stripe from "stripe";
2
+ import type { Context } from "../context.ts";
3
+ import { Resource } from "../resource.ts";
4
+ import type { Secret } from "../secret.ts";
5
+ import { createStripeClient, isStripeConflictError } from "./client.ts";
6
+
7
+ /**
8
+ * Properties for creating a Stripe entitlements feature
9
+ */
10
+ export interface EntitlementsFeatureProps {
11
+ /**
12
+ * The feature's name, for your own purpose, not meant to be displayable to the customer
13
+ */
14
+ name: string;
15
+
16
+ /**
17
+ * A unique key you provide as your own system identifier. This may be up to 80 characters
18
+ */
19
+ lookupKey?: string;
20
+
21
+ /**
22
+ * Set of key-value pairs that you can attach to an object
23
+ */
24
+ metadata?: Record<string, string>;
25
+
26
+ /**
27
+ * API key to use (overrides environment variable)
28
+ */
29
+ apiKey?: Secret;
30
+
31
+ /**
32
+ * If true, adopt existing resource if creation fails due to conflict
33
+ */
34
+ adopt?: boolean;
35
+ }
36
+
37
+ /**
38
+ * Output from the Stripe entitlements feature
39
+ */
40
+ export interface EntitlementsFeature
41
+ extends Resource<"stripe::EntitlementsFeature">,
42
+ EntitlementsFeatureProps {
43
+ /**
44
+ * The ID of the feature
45
+ */
46
+ id: string;
47
+
48
+ /**
49
+ * String representing the object's type
50
+ */
51
+ object: "entitlements.feature";
52
+
53
+ /**
54
+ * Has the value true if the object exists in live mode or the value false if the object exists in test mode
55
+ */
56
+ livemode: boolean;
57
+ }
58
+
59
+ /**
60
+ * Create and manage Stripe entitlements features
61
+ *
62
+ * @example
63
+ * // Create a basic feature for API access
64
+ * const apiFeature = await EntitlementsFeature("api-access", {
65
+ * name: "API Access",
66
+ * lookupKey: "api_access_v1",
67
+ * metadata: {
68
+ * tier: "premium",
69
+ * category: "api"
70
+ * }
71
+ * });
72
+ *
73
+ * @example
74
+ * // Create a feature for advanced analytics
75
+ * const analyticsFeature = await EntitlementsFeature("advanced-analytics", {
76
+ * name: "Advanced Analytics",
77
+ * lookupKey: "analytics_advanced",
78
+ * metadata: {
79
+ * tier: "enterprise",
80
+ * category: "analytics"
81
+ * }
82
+ * });
83
+ *
84
+ * @example
85
+ * // Create a feature for custom integrations
86
+ * const integrationsFeature = await EntitlementsFeature("custom-integrations", {
87
+ * name: "Custom Integrations",
88
+ * lookupKey: "integrations_custom",
89
+ * metadata: {
90
+ * tier: "enterprise",
91
+ * category: "integrations",
92
+ * limit: "unlimited"
93
+ * }
94
+ * });
95
+ */
96
+ export const EntitlementsFeature = Resource(
97
+ "stripe::EntitlementsFeature",
98
+ async function (
99
+ this: Context<EntitlementsFeature>,
100
+ _id: string,
101
+ props: EntitlementsFeatureProps,
102
+ ): Promise<EntitlementsFeature> {
103
+ const stripe = createStripeClient({ apiKey: props.apiKey });
104
+
105
+ if (this.phase === "delete") {
106
+ return this.destroy();
107
+ }
108
+
109
+ try {
110
+ let feature: Stripe.Entitlements.Feature;
111
+
112
+ if (this.phase === "update" && this.output?.id) {
113
+ const updateParams: any = {
114
+ name: props.name,
115
+ metadata: props.metadata,
116
+ };
117
+ feature = await stripe.entitlements.features.update(
118
+ this.output.id,
119
+ updateParams,
120
+ );
121
+ } else {
122
+ const createParams: any = {
123
+ name: props.name,
124
+ metadata: props.metadata,
125
+ };
126
+ if (props.lookupKey) {
127
+ createParams.lookup_key = props.lookupKey;
128
+ }
129
+ try {
130
+ feature = await stripe.entitlements.features.create(createParams);
131
+ } catch (error) {
132
+ if (isStripeConflictError(error) && props.adopt) {
133
+ const existingFeatures = await stripe.entitlements.features.list({
134
+ lookup_key: props.lookupKey,
135
+ limit: 1,
136
+ });
137
+ if (existingFeatures.data.length > 0) {
138
+ const existingFeature = existingFeatures.data[0];
139
+ const updateParams: Stripe.Entitlements.FeatureUpdateParams = {
140
+ name: props.name,
141
+ metadata: props.metadata,
142
+ };
143
+ feature = await stripe.entitlements.features.update(
144
+ existingFeature.id,
145
+ updateParams,
146
+ );
147
+ } else {
148
+ throw error;
149
+ }
150
+ } else {
151
+ throw error;
152
+ }
153
+ }
154
+ }
155
+
156
+ return this({
157
+ id: feature.id,
158
+ object: feature.object,
159
+ name: feature.name,
160
+ lookupKey: feature.lookup_key || undefined,
161
+ metadata: feature.metadata || undefined,
162
+ livemode: feature.livemode,
163
+ });
164
+ } catch (error) {
165
+ console.error("Error creating/updating entitlements feature:", error);
166
+ throw error;
167
+ }
168
+ },
169
+ );