alchemy 0.24.0 → 0.25.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 (184) hide show
  1. package/lib/aws/control/client.js +1 -1
  2. package/lib/aws/control/client.js.map +1 -1
  3. package/lib/aws/control/resource.d.ts.map +1 -1
  4. package/lib/aws/control/resource.js +2 -1
  5. package/lib/aws/control/resource.js.map +1 -1
  6. package/lib/aws/function.d.ts.map +1 -1
  7. package/lib/aws/function.js +1 -4
  8. package/lib/aws/function.js.map +1 -1
  9. package/lib/cloudflare/ai.d.ts +21 -0
  10. package/lib/cloudflare/ai.d.ts.map +1 -1
  11. package/lib/cloudflare/ai.js +21 -0
  12. package/lib/cloudflare/ai.js.map +1 -1
  13. package/lib/cloudflare/bindings.d.ts +3 -3
  14. package/lib/cloudflare/bindings.d.ts.map +1 -1
  15. package/lib/cloudflare/bindings.js.map +1 -1
  16. package/lib/cloudflare/bound.d.ts +3 -3
  17. package/lib/cloudflare/bound.d.ts.map +1 -1
  18. package/lib/cloudflare/do-state-store/index.d.ts +2 -0
  19. package/lib/cloudflare/do-state-store/index.d.ts.map +1 -0
  20. package/lib/cloudflare/do-state-store/index.js +2 -0
  21. package/lib/cloudflare/do-state-store/index.js.map +1 -0
  22. package/lib/cloudflare/do-state-store/internal.d.ts +19 -0
  23. package/lib/cloudflare/do-state-store/internal.d.ts.map +1 -0
  24. package/lib/cloudflare/do-state-store/internal.js +163 -0
  25. package/lib/cloudflare/do-state-store/internal.js.map +1 -0
  26. package/lib/cloudflare/do-state-store/store.d.ts +59 -0
  27. package/lib/cloudflare/do-state-store/store.d.ts.map +1 -0
  28. package/lib/cloudflare/do-state-store/store.js +120 -0
  29. package/lib/cloudflare/do-state-store/store.js.map +1 -0
  30. package/lib/cloudflare/do-state-store/types.d.ts +82 -0
  31. package/lib/cloudflare/do-state-store/types.d.ts.map +1 -0
  32. package/lib/cloudflare/do-state-store/types.js +1 -0
  33. package/lib/cloudflare/do-state-store/types.js.map +1 -0
  34. package/lib/cloudflare/do-state-store/worker.d.ts +27 -0
  35. package/lib/cloudflare/do-state-store/worker.d.ts.map +1 -0
  36. package/lib/cloudflare/do-state-store/worker.js +170 -0
  37. package/lib/cloudflare/do-state-store/worker.js.map +1 -0
  38. package/lib/cloudflare/index.d.ts +1 -0
  39. package/lib/cloudflare/index.d.ts.map +1 -1
  40. package/lib/cloudflare/index.js +1 -0
  41. package/lib/cloudflare/index.js.map +1 -1
  42. package/lib/cloudflare/pipeline.js +1 -1
  43. package/lib/cloudflare/pipeline.js.map +1 -1
  44. package/lib/cloudflare/queue-consumer.d.ts +14 -1
  45. package/lib/cloudflare/queue-consumer.d.ts.map +1 -1
  46. package/lib/cloudflare/queue-consumer.js +17 -0
  47. package/lib/cloudflare/queue-consumer.js.map +1 -1
  48. package/lib/cloudflare/website.d.ts +30 -1
  49. package/lib/cloudflare/website.d.ts.map +1 -1
  50. package/lib/cloudflare/website.js +8 -5
  51. package/lib/cloudflare/website.js.map +1 -1
  52. package/lib/cloudflare/worker-assets.d.ts.map +1 -1
  53. package/lib/cloudflare/worker-assets.js +13 -3
  54. package/lib/cloudflare/worker-assets.js.map +1 -1
  55. package/lib/cloudflare/worker-metadata.js +1 -1
  56. package/lib/cloudflare/worker-metadata.js.map +1 -1
  57. package/lib/cloudflare/worker.d.ts +40 -1
  58. package/lib/cloudflare/worker.d.ts.map +1 -1
  59. package/lib/cloudflare/worker.js +40 -38
  60. package/lib/cloudflare/worker.js.map +1 -1
  61. package/lib/cloudflare/wrangler.json.js +1 -1
  62. package/lib/cloudflare/wrangler.json.js.map +1 -1
  63. package/lib/cloudflare/zone.d.ts +30 -2
  64. package/lib/cloudflare/zone.d.ts.map +1 -1
  65. package/lib/cloudflare/zone.js +53 -0
  66. package/lib/cloudflare/zone.js.map +1 -1
  67. package/lib/fs/file-system-state-store.d.ts +3 -1
  68. package/lib/fs/file-system-state-store.d.ts.map +1 -1
  69. package/lib/fs/file-system-state-store.js +2 -2
  70. package/lib/fs/file-system-state-store.js.map +1 -1
  71. package/lib/stripe/card.d.ts +171 -0
  72. package/lib/stripe/card.d.ts.map +1 -0
  73. package/lib/stripe/card.js +148 -0
  74. package/lib/stripe/card.js.map +1 -0
  75. package/lib/stripe/client.d.ts +9 -0
  76. package/lib/stripe/client.d.ts.map +1 -0
  77. package/lib/stripe/client.js +94 -0
  78. package/lib/stripe/client.js.map +1 -0
  79. package/lib/stripe/coupon.d.ts +135 -0
  80. package/lib/stripe/coupon.d.ts.map +1 -0
  81. package/lib/stripe/coupon.js +161 -0
  82. package/lib/stripe/coupon.js.map +1 -0
  83. package/lib/stripe/customer.d.ts +269 -0
  84. package/lib/stripe/customer.d.ts.map +1 -0
  85. package/lib/stripe/customer.js +289 -0
  86. package/lib/stripe/customer.js.map +1 -0
  87. package/lib/stripe/entitlements-feature.d.ts +84 -0
  88. package/lib/stripe/entitlements-feature.d.ts.map +1 -0
  89. package/lib/stripe/entitlements-feature.js +102 -0
  90. package/lib/stripe/entitlements-feature.js.map +1 -0
  91. package/lib/stripe/file.d.ts +143 -0
  92. package/lib/stripe/file.d.ts.map +1 -0
  93. package/lib/stripe/file.js +97 -0
  94. package/lib/stripe/file.js.map +1 -0
  95. package/lib/stripe/index.d.ts +11 -0
  96. package/lib/stripe/index.d.ts.map +1 -1
  97. package/lib/stripe/index.js +11 -0
  98. package/lib/stripe/index.js.map +1 -1
  99. package/lib/stripe/meter.d.ts +10 -1
  100. package/lib/stripe/meter.d.ts.map +1 -1
  101. package/lib/stripe/meter.js +13 -7
  102. package/lib/stripe/meter.js.map +1 -1
  103. package/lib/stripe/portal-configuration.d.ts +286 -0
  104. package/lib/stripe/portal-configuration.d.ts.map +1 -0
  105. package/lib/stripe/portal-configuration.js +320 -0
  106. package/lib/stripe/portal-configuration.js.map +1 -0
  107. package/lib/stripe/price.d.ts +10 -1
  108. package/lib/stripe/price.d.ts.map +1 -1
  109. package/lib/stripe/price.js +34 -13
  110. package/lib/stripe/price.js.map +1 -1
  111. package/lib/stripe/product-feature.d.ts +76 -0
  112. package/lib/stripe/product-feature.d.ts.map +1 -0
  113. package/lib/stripe/product-feature.js +74 -0
  114. package/lib/stripe/product-feature.js.map +1 -0
  115. package/lib/stripe/product.d.ts +10 -1
  116. package/lib/stripe/product.d.ts.map +1 -1
  117. package/lib/stripe/product.js +33 -14
  118. package/lib/stripe/product.js.map +1 -1
  119. package/lib/stripe/promotion-code.d.ts +138 -0
  120. package/lib/stripe/promotion-code.d.ts.map +1 -0
  121. package/lib/stripe/promotion-code.js +150 -0
  122. package/lib/stripe/promotion-code.js.map +1 -0
  123. package/lib/stripe/shipping-rate.d.ts +188 -0
  124. package/lib/stripe/shipping-rate.d.ts.map +1 -0
  125. package/lib/stripe/shipping-rate.js +198 -0
  126. package/lib/stripe/shipping-rate.js.map +1 -0
  127. package/lib/stripe/tax-rate.d.ts +130 -0
  128. package/lib/stripe/tax-rate.d.ts.map +1 -0
  129. package/lib/stripe/tax-rate.js +126 -0
  130. package/lib/stripe/tax-rate.js.map +1 -0
  131. package/lib/stripe/webhook.d.ts +10 -1
  132. package/lib/stripe/webhook.d.ts.map +1 -1
  133. package/lib/stripe/webhook.js +59 -14
  134. package/lib/stripe/webhook.js.map +1 -1
  135. package/lib/test/bun.d.ts.map +1 -1
  136. package/lib/test/bun.js +2 -6
  137. package/lib/test/bun.js.map +1 -1
  138. package/lib/test/vitest.d.ts.map +1 -1
  139. package/lib/test/vitest.js +3 -7
  140. package/lib/test/vitest.js.map +1 -1
  141. package/lib/util/retry.d.ts +1 -1
  142. package/lib/util/retry.d.ts.map +1 -1
  143. package/lib/util/retry.js.map +1 -1
  144. package/package.json +3 -2
  145. package/src/aws/control/client.ts +1 -1
  146. package/src/aws/control/resource.ts +2 -1
  147. package/src/aws/function.ts +3 -6
  148. package/src/cloudflare/ai.ts +21 -0
  149. package/src/cloudflare/bindings.ts +3 -2
  150. package/src/cloudflare/bound.ts +3 -3
  151. package/src/cloudflare/do-state-store/index.ts +1 -0
  152. package/src/cloudflare/do-state-store/internal.ts +215 -0
  153. package/src/cloudflare/do-state-store/store.ts +188 -0
  154. package/src/cloudflare/do-state-store/types.ts +74 -0
  155. package/src/cloudflare/do-state-store/worker.ts +199 -0
  156. package/src/cloudflare/index.ts +1 -0
  157. package/src/cloudflare/pipeline.ts +1 -1
  158. package/src/cloudflare/queue-consumer.ts +59 -1
  159. package/src/cloudflare/website.ts +38 -6
  160. package/src/cloudflare/worker-assets.ts +15 -3
  161. package/src/cloudflare/worker-metadata.ts +1 -1
  162. package/src/cloudflare/worker.ts +66 -46
  163. package/src/cloudflare/wrangler.json.ts +1 -1
  164. package/src/cloudflare/zone.ts +75 -2
  165. package/src/fs/file-system-state-store.ts +7 -2
  166. package/src/stripe/card.ts +320 -0
  167. package/src/stripe/client.ts +145 -0
  168. package/src/stripe/coupon.ts +280 -0
  169. package/src/stripe/customer.ts +528 -0
  170. package/src/stripe/entitlements-feature.ts +169 -0
  171. package/src/stripe/file.ts +219 -0
  172. package/src/stripe/index.ts +11 -0
  173. package/src/stripe/meter.ts +23 -7
  174. package/src/stripe/portal-configuration.ts +609 -0
  175. package/src/stripe/price.ts +47 -14
  176. package/src/stripe/product-feature.ts +150 -0
  177. package/src/stripe/product.ts +48 -15
  178. package/src/stripe/promotion-code.ts +268 -0
  179. package/src/stripe/shipping-rate.ts +362 -0
  180. package/src/stripe/tax-rate.ts +218 -0
  181. package/src/stripe/webhook.ts +82 -15
  182. package/src/test/bun.ts +2 -7
  183. package/src/test/vitest.ts +3 -8
  184. package/src/util/retry.ts +1 -1
@@ -0,0 +1,362 @@
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 {
6
+ createStripeClient,
7
+ handleStripeDeleteError,
8
+ isStripeConflictError,
9
+ } from "./client.ts";
10
+
11
+ /**
12
+ * Delivery estimate for shipping rate
13
+ */
14
+ export interface ShippingRateDeliveryEstimate {
15
+ /**
16
+ * The lower bound of the estimated range
17
+ */
18
+ minimum?: {
19
+ /**
20
+ * A unit of time
21
+ */
22
+ unit: Stripe.ShippingRateCreateParams.DeliveryEstimate.Minimum.Unit;
23
+ /**
24
+ * Must be greater than 0
25
+ */
26
+ value: number;
27
+ };
28
+ /**
29
+ * The upper bound of the estimated range
30
+ */
31
+ maximum?: {
32
+ /**
33
+ * A unit of time
34
+ */
35
+ unit: Stripe.ShippingRateCreateParams.DeliveryEstimate.Maximum.Unit;
36
+ /**
37
+ * Must be greater than 0
38
+ */
39
+ value: number;
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Fixed amount configuration for shipping rate
45
+ */
46
+ export interface ShippingRateFixedAmount {
47
+ /**
48
+ * A non-negative integer in cents representing how much to charge
49
+ */
50
+ amount: number;
51
+ /**
52
+ * Three-letter ISO currency code, in lowercase
53
+ */
54
+ currency: string;
55
+ /**
56
+ * Shipping rates defined in each available currency option
57
+ */
58
+ currencyOptions?: Record<
59
+ string,
60
+ {
61
+ /**
62
+ * A non-negative integer in cents representing how much to charge
63
+ */
64
+ amount: number;
65
+ /**
66
+ * Specifies whether the rate is considered inclusive or exclusive of taxes
67
+ */
68
+ taxBehavior?: Stripe.ShippingRateCreateParams.FixedAmount.CurrencyOptions.TaxBehavior;
69
+ }
70
+ >;
71
+ }
72
+
73
+ /**
74
+ * Properties for creating a Stripe shipping rate
75
+ */
76
+ export interface ShippingRateProps {
77
+ /**
78
+ * The name of the shipping rate, meant to be displayable to the customer
79
+ */
80
+ displayName: string;
81
+ /**
82
+ * Describes a fixed amount to charge for shipping
83
+ */
84
+ fixedAmount?: ShippingRateFixedAmount;
85
+ /**
86
+ * The estimated range for how long shipping will take
87
+ */
88
+ deliveryEstimate?: ShippingRateDeliveryEstimate;
89
+ /**
90
+ * Set of key-value pairs that you can attach to an object
91
+ */
92
+ metadata?: Record<string, string>;
93
+ /**
94
+ * Whether the shipping rate can be used for new purchases
95
+ */
96
+ active?: boolean;
97
+ /**
98
+ * Specifies whether the rate is considered inclusive or exclusive of taxes
99
+ */
100
+ taxBehavior?: Stripe.ShippingRateCreateParams.TaxBehavior;
101
+ /**
102
+ * A tax code ID
103
+ */
104
+ taxCode?: string;
105
+ /**
106
+ * The type of calculation to use on the shipping rate
107
+ */
108
+ type?: "fixed_amount";
109
+
110
+ /**
111
+ * API key to use (overrides environment variable)
112
+ */
113
+ apiKey?: Secret;
114
+
115
+ /**
116
+ * If true, adopt existing resource if creation fails due to conflict
117
+ */
118
+ adopt?: boolean;
119
+ }
120
+
121
+ /**
122
+ * Output from the Stripe shipping rate
123
+ */
124
+ export interface ShippingRate
125
+ extends Resource<"stripe::ShippingRate">,
126
+ ShippingRateProps {
127
+ /**
128
+ * The ID of the shipping rate
129
+ */
130
+ id: string;
131
+ /**
132
+ * String representing the object's type
133
+ */
134
+ object: "shipping_rate";
135
+ /**
136
+ * Time at which the object was created
137
+ */
138
+ created: number;
139
+ /**
140
+ * Has the value true if the object exists in live mode or the value false if the object exists in test mode
141
+ */
142
+ livemode: boolean;
143
+ }
144
+
145
+ /**
146
+ * Create and manage Stripe shipping rates
147
+ *
148
+ * @example
149
+ * // Create a standard shipping rate
150
+ * const standardShipping = await ShippingRate("standard-shipping", {
151
+ * displayName: "Standard Shipping",
152
+ * type: "fixed_amount",
153
+ * fixedAmount: {
154
+ * amount: 500,
155
+ * currency: "usd"
156
+ * },
157
+ * deliveryEstimate: {
158
+ * minimum: { unit: "business_day", value: 5 },
159
+ * maximum: { unit: "business_day", value: 7 }
160
+ * },
161
+ * taxBehavior: "exclusive"
162
+ * });
163
+ *
164
+ * @example
165
+ * // Create an express shipping rate
166
+ * const expressShipping = await ShippingRate("express-shipping", {
167
+ * displayName: "Express Shipping",
168
+ * type: "fixed_amount",
169
+ * fixedAmount: {
170
+ * amount: 1500,
171
+ * currency: "usd"
172
+ * },
173
+ * deliveryEstimate: {
174
+ * minimum: { unit: "business_day", value: 1 },
175
+ * maximum: { unit: "business_day", value: 2 }
176
+ * },
177
+ * taxBehavior: "exclusive",
178
+ * metadata: {
179
+ * priority: "high",
180
+ * service_level: "express"
181
+ * }
182
+ * });
183
+ *
184
+ * @example
185
+ * // Create a free shipping rate
186
+ * const freeShipping = await ShippingRate("free-shipping", {
187
+ * displayName: "Free Shipping",
188
+ * type: "fixed_amount",
189
+ * fixedAmount: {
190
+ * amount: 0,
191
+ * currency: "usd"
192
+ * },
193
+ * deliveryEstimate: {
194
+ * minimum: { unit: "business_day", value: 7 },
195
+ * maximum: { unit: "business_day", value: 10 }
196
+ * },
197
+ * taxBehavior: "unspecified",
198
+ * metadata: {
199
+ * promotion: "free_shipping_over_50",
200
+ * cost_center: "marketing"
201
+ * }
202
+ * });
203
+ */
204
+ export const ShippingRate = Resource(
205
+ "stripe::ShippingRate",
206
+ async function (
207
+ this: Context<ShippingRate>,
208
+ _id: string,
209
+ props: ShippingRateProps,
210
+ ): Promise<ShippingRate> {
211
+ const stripe = createStripeClient({ apiKey: props.apiKey });
212
+
213
+ if (this.phase === "delete") {
214
+ try {
215
+ if (this.output?.id) {
216
+ await stripe.shippingRates.update(this.output.id, { active: false });
217
+ }
218
+ } catch (error) {
219
+ handleStripeDeleteError(error, "ShippingRate", this.output?.id);
220
+ }
221
+ return this.destroy();
222
+ }
223
+
224
+ try {
225
+ let shippingRate: Stripe.ShippingRate;
226
+
227
+ if (this.phase === "update" && this.output?.id) {
228
+ const updateParams: any = {
229
+ metadata: props.metadata,
230
+ tax_behavior: props.taxBehavior,
231
+ };
232
+ if (props.active !== undefined) updateParams.active = props.active;
233
+ shippingRate = await stripe.shippingRates.update(
234
+ this.output.id,
235
+ updateParams,
236
+ );
237
+ } else {
238
+ const createParams: Stripe.ShippingRateCreateParams = {
239
+ display_name: props.displayName,
240
+ metadata: props.metadata,
241
+
242
+ tax_behavior: props.taxBehavior,
243
+ tax_code: props.taxCode,
244
+ type: props.type,
245
+ };
246
+
247
+ if (props.fixedAmount) {
248
+ createParams.fixed_amount = {
249
+ amount: props.fixedAmount.amount,
250
+ currency: props.fixedAmount.currency,
251
+ currency_options: props.fixedAmount.currencyOptions
252
+ ? Object.fromEntries(
253
+ Object.entries(props.fixedAmount.currencyOptions).map(
254
+ ([key, value]) => [
255
+ key,
256
+ {
257
+ amount: value.amount,
258
+ tax_behavior: value.taxBehavior,
259
+ },
260
+ ],
261
+ ),
262
+ )
263
+ : undefined,
264
+ };
265
+ }
266
+
267
+ if (props.deliveryEstimate) {
268
+ createParams.delivery_estimate = {
269
+ minimum: props.deliveryEstimate.minimum
270
+ ? {
271
+ unit: props.deliveryEstimate.minimum.unit,
272
+ value: props.deliveryEstimate.minimum.value,
273
+ }
274
+ : undefined,
275
+ maximum: props.deliveryEstimate.maximum
276
+ ? {
277
+ unit: props.deliveryEstimate.maximum.unit,
278
+ value: props.deliveryEstimate.maximum.value,
279
+ }
280
+ : undefined,
281
+ };
282
+ }
283
+
284
+ try {
285
+ try {
286
+ shippingRate = await stripe.shippingRates.create(createParams);
287
+ } catch (error) {
288
+ if (isStripeConflictError(error) && props.adopt) {
289
+ throw new Error(
290
+ "ShippingRate adoption is not supported - shipping rates cannot be uniquely identified for adoption",
291
+ );
292
+ } else {
293
+ throw error;
294
+ }
295
+ }
296
+ } catch (error) {
297
+ if (isStripeConflictError(error) && props.adopt) {
298
+ throw new Error(
299
+ "ShippingRate adoption is not supported - shipping rates cannot be uniquely identified for adoption",
300
+ );
301
+ } else {
302
+ throw error;
303
+ }
304
+ }
305
+ }
306
+
307
+ return this({
308
+ id: shippingRate.id,
309
+ object: shippingRate.object,
310
+ displayName: shippingRate.display_name || "",
311
+ fixedAmount: shippingRate.fixed_amount
312
+ ? {
313
+ amount: shippingRate.fixed_amount.amount,
314
+ currency: shippingRate.fixed_amount.currency,
315
+ currencyOptions: shippingRate.fixed_amount.currency_options
316
+ ? Object.fromEntries(
317
+ Object.entries(
318
+ shippingRate.fixed_amount.currency_options,
319
+ ).map(([key, value]) => [
320
+ key,
321
+ {
322
+ amount: value.amount,
323
+ taxBehavior: value.tax_behavior,
324
+ },
325
+ ]),
326
+ )
327
+ : undefined,
328
+ }
329
+ : undefined,
330
+ deliveryEstimate: shippingRate.delivery_estimate
331
+ ? {
332
+ minimum: shippingRate.delivery_estimate.minimum
333
+ ? {
334
+ unit: shippingRate.delivery_estimate.minimum.unit,
335
+ value: shippingRate.delivery_estimate.minimum.value,
336
+ }
337
+ : undefined,
338
+ maximum: shippingRate.delivery_estimate.maximum
339
+ ? {
340
+ unit: shippingRate.delivery_estimate.maximum.unit,
341
+ value: shippingRate.delivery_estimate.maximum.value,
342
+ }
343
+ : undefined,
344
+ }
345
+ : undefined,
346
+ metadata: shippingRate.metadata || undefined,
347
+ active: shippingRate.active,
348
+ taxBehavior: shippingRate.tax_behavior || undefined,
349
+ taxCode:
350
+ typeof shippingRate.tax_code === "string"
351
+ ? shippingRate.tax_code
352
+ : undefined,
353
+ type: shippingRate.type || undefined,
354
+ created: shippingRate.created,
355
+ livemode: shippingRate.livemode,
356
+ });
357
+ } catch (error) {
358
+ console.error("Error creating/updating shipping rate:", error);
359
+ throw error;
360
+ }
361
+ },
362
+ );
@@ -0,0 +1,218 @@
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 {
6
+ createStripeClient,
7
+ handleStripeDeleteError,
8
+ isStripeConflictError,
9
+ } from "./client.ts";
10
+
11
+ /**
12
+ * Properties for creating a Stripe tax rate
13
+ */
14
+ export interface TaxRateProps {
15
+ /**
16
+ * The display name of the tax rate, which will be shown to users
17
+ */
18
+ displayName: string;
19
+ /**
20
+ * This represents the tax rate percent out of 100
21
+ */
22
+ percentage: number;
23
+ /**
24
+ * This specifies if the tax rate is inclusive or exclusive
25
+ */
26
+ inclusive: boolean;
27
+ /**
28
+ * Flag determining whether the tax rate is active or inactive
29
+ */
30
+ active?: boolean;
31
+ /**
32
+ * Two-letter country code (ISO 3166-1 alpha-2)
33
+ */
34
+ country?: string;
35
+ /**
36
+ * An arbitrary string attached to the tax rate for your internal use only
37
+ */
38
+ description?: string;
39
+ /**
40
+ * The jurisdiction for the tax rate
41
+ */
42
+ jurisdiction?: string;
43
+ /**
44
+ * Set of key-value pairs that you can attach to an object
45
+ */
46
+ metadata?: Record<string, string>;
47
+ /**
48
+ * ISO 3166-2 subdivision code, without country prefix
49
+ */
50
+ state?: string;
51
+ /**
52
+ * The high-level tax type, such as vat or sales_tax
53
+ */
54
+ taxType?: Stripe.TaxRateCreateParams.TaxType;
55
+ /**
56
+ * API key to use (overrides environment variable)
57
+ */
58
+ apiKey?: Secret;
59
+
60
+ /**
61
+ * If true, adopt existing resource if creation fails due to conflict
62
+ */
63
+ adopt?: boolean;
64
+ }
65
+
66
+ /**
67
+ * Output from the Stripe tax rate
68
+ */
69
+ export interface TaxRate extends Resource<"stripe::TaxRate">, TaxRateProps {
70
+ /**
71
+ * The ID of the tax rate
72
+ */
73
+ id: string;
74
+ /**
75
+ * String representing the object's type
76
+ */
77
+ object: "tax_rate";
78
+ /**
79
+ * Time at which the object was created
80
+ */
81
+ created: number;
82
+ /**
83
+ * Has the value true if the object exists in live mode or the value false if the object exists in test mode
84
+ */
85
+ livemode: boolean;
86
+ }
87
+
88
+ /**
89
+ * Create and manage Stripe tax rates
90
+ *
91
+ * @example
92
+ * // Create a basic sales tax rate
93
+ * const salesTax = await TaxRate("ca-sales-tax", {
94
+ * displayName: "CA Sales Tax",
95
+ * percentage: 8.5,
96
+ * inclusive: false,
97
+ * active: true,
98
+ * country: "US",
99
+ * state: "CA",
100
+ * description: "California sales tax",
101
+ * taxType: "sales_tax"
102
+ * });
103
+ *
104
+ * @example
105
+ * // Create a VAT tax rate
106
+ * const vatTax = await TaxRate("uk-vat", {
107
+ * displayName: "UK VAT",
108
+ * percentage: 20.0,
109
+ * inclusive: true,
110
+ * active: true,
111
+ * country: "GB",
112
+ * description: "United Kingdom Value Added Tax",
113
+ * taxType: "vat",
114
+ * metadata: {
115
+ * region: "europe",
116
+ * tax_authority: "hmrc"
117
+ * }
118
+ * });
119
+ *
120
+ * @example
121
+ * // Create a city tax rate
122
+ * const cityTax = await TaxRate("nyc-tax", {
123
+ * displayName: "NYC Local Tax",
124
+ * percentage: 4.5,
125
+ * inclusive: false,
126
+ * active: true,
127
+ * country: "US",
128
+ * state: "NY",
129
+ * jurisdiction: "New York City",
130
+ * description: "New York City local sales tax",
131
+ * taxType: "sales_tax",
132
+ * metadata: {
133
+ * locality: "nyc",
134
+ * tax_level: "city"
135
+ * }
136
+ * });
137
+ */
138
+ export const TaxRate = Resource(
139
+ "stripe::TaxRate",
140
+ async function (
141
+ this: Context<TaxRate>,
142
+ _id: string,
143
+ props: TaxRateProps,
144
+ ): Promise<TaxRate> {
145
+ const stripe = createStripeClient({ apiKey: props.apiKey });
146
+
147
+ if (this.phase === "delete") {
148
+ try {
149
+ if (this.output?.id) {
150
+ await stripe.taxRates.update(this.output.id, { active: false });
151
+ }
152
+ } catch (error) {
153
+ handleStripeDeleteError(error, "TaxRate", this.output?.id);
154
+ }
155
+ return this.destroy();
156
+ }
157
+
158
+ try {
159
+ let taxRate: Stripe.TaxRate;
160
+
161
+ if (this.phase === "update" && this.output?.id) {
162
+ taxRate = await stripe.taxRates.update(this.output.id, {
163
+ active: props.active,
164
+ country: props.country,
165
+ description: props.description,
166
+ display_name: props.displayName,
167
+ jurisdiction: props.jurisdiction,
168
+ metadata: props.metadata,
169
+ state: props.state,
170
+ tax_type: props.taxType,
171
+ });
172
+ } else {
173
+ try {
174
+ taxRate = await stripe.taxRates.create({
175
+ display_name: props.displayName,
176
+ percentage: props.percentage,
177
+ inclusive: props.inclusive,
178
+ active: props.active,
179
+ country: props.country,
180
+ description: props.description,
181
+ jurisdiction: props.jurisdiction,
182
+ metadata: props.metadata,
183
+ state: props.state,
184
+ tax_type: props.taxType,
185
+ });
186
+ } catch (error) {
187
+ if (isStripeConflictError(error) && props.adopt) {
188
+ throw new Error(
189
+ "TaxRate adoption is not supported - tax rates cannot be uniquely identified for adoption",
190
+ );
191
+ } else {
192
+ throw error;
193
+ }
194
+ }
195
+ }
196
+
197
+ return this({
198
+ id: taxRate.id,
199
+ object: taxRate.object,
200
+ displayName: taxRate.display_name,
201
+ percentage: taxRate.percentage,
202
+ inclusive: taxRate.inclusive,
203
+ active: taxRate.active,
204
+ country: taxRate.country || undefined,
205
+ description: taxRate.description || undefined,
206
+ jurisdiction: taxRate.jurisdiction || undefined,
207
+ metadata: taxRate.metadata || undefined,
208
+ state: taxRate.state || undefined,
209
+ taxType: taxRate.tax_type || undefined,
210
+ created: taxRate.created,
211
+ livemode: taxRate.livemode,
212
+ });
213
+ } catch (error) {
214
+ console.error("Error creating/updating tax rate:", error);
215
+ throw error;
216
+ }
217
+ },
218
+ );
@@ -1,6 +1,12 @@
1
- import Stripe from "stripe";
1
+ import type Stripe from "stripe";
2
2
  import type { Context } from "../context.ts";
3
3
  import { Resource } from "../resource.ts";
4
+ import type { Secret } from "../secret.ts";
5
+ import {
6
+ createStripeClient,
7
+ handleStripeDeleteError,
8
+ isStripeConflictError,
9
+ } from "./client.ts";
4
10
 
5
11
  export type EnabledEvent = Stripe.WebhookEndpointUpdateParams.EnabledEvent;
6
12
 
@@ -42,6 +48,16 @@ export interface WebhookEndpointProps {
42
48
  * Webhook endpoint metadata
43
49
  */
44
50
  metadata?: Record<string, string>;
51
+
52
+ /**
53
+ * API key to use (overrides environment variable)
54
+ */
55
+ apiKey?: Secret;
56
+
57
+ /**
58
+ * If true, adopt existing resource if creation fails due to conflict
59
+ */
60
+ adopt?: boolean;
45
61
  }
46
62
 
47
63
  /**
@@ -138,14 +154,7 @@ export const WebhookEndpoint = Resource(
138
154
  _id: string,
139
155
  props: WebhookEndpointProps,
140
156
  ) {
141
- // Get Stripe API key from context or environment
142
- const apiKey = process.env.STRIPE_API_KEY;
143
- if (!apiKey) {
144
- throw new Error("STRIPE_API_KEY environment variable is required");
145
- }
146
-
147
- // Initialize Stripe client
148
- const stripe = new Stripe(apiKey);
157
+ const stripe = createStripeClient({ apiKey: props.apiKey });
149
158
 
150
159
  if (this.phase === "delete") {
151
160
  try {
@@ -154,8 +163,7 @@ export const WebhookEndpoint = Resource(
154
163
  await stripe.webhookEndpoints.del(this.output.id);
155
164
  }
156
165
  } catch (error) {
157
- // Ignore if the webhook doesn't exist
158
- console.error("Error deleting webhook:", error);
166
+ handleStripeDeleteError(error, "WebhookEndpoint", this.output?.id);
159
167
  }
160
168
 
161
169
  return this.destroy();
@@ -165,21 +173,80 @@ export const WebhookEndpoint = Resource(
165
173
 
166
174
  if (this.phase === "update" && this.output?.id) {
167
175
  // Update existing webhook
168
- webhook = await stripe.webhookEndpoints.update(this.output.id, {
176
+ const updateParams = {
169
177
  url: props.url,
170
178
  enabled_events: props.enabledEvents,
171
179
  description: props.description,
172
180
  disabled: props.active === false,
173
181
  metadata: props.metadata,
174
- });
182
+ };
183
+ webhook = await stripe.webhookEndpoints.update(
184
+ this.output.id,
185
+ updateParams,
186
+ );
175
187
  } else {
176
188
  // Create new webhook
177
- webhook = await stripe.webhookEndpoints.create({
189
+ const createParams = {
178
190
  url: props.url,
179
191
  enabled_events: props.enabledEvents,
180
192
  description: props.description,
181
193
  metadata: props.metadata,
182
- });
194
+ };
195
+ try {
196
+ try {
197
+ webhook = await stripe.webhookEndpoints.create(createParams);
198
+ } catch (error) {
199
+ if (isStripeConflictError(error) && props.adopt) {
200
+ const existingWebhooks = await stripe.webhookEndpoints.list({
201
+ limit: 100,
202
+ });
203
+ const existingWebhook = existingWebhooks.data.find(
204
+ (w) => w.url === props.url,
205
+ );
206
+ if (existingWebhook) {
207
+ const updateParams: Stripe.WebhookEndpointUpdateParams = {
208
+ url: props.url,
209
+ enabled_events: props.enabledEvents as any,
210
+ description: props.description,
211
+ metadata: props.metadata,
212
+ };
213
+ webhook = await stripe.webhookEndpoints.update(
214
+ existingWebhook.id,
215
+ updateParams,
216
+ );
217
+ } else {
218
+ throw error;
219
+ }
220
+ } else {
221
+ throw error;
222
+ }
223
+ }
224
+ } catch (error) {
225
+ if (isStripeConflictError(error) && props.adopt) {
226
+ const existingWebhooks = await stripe.webhookEndpoints.list({
227
+ limit: 100,
228
+ });
229
+ const existingWebhook = existingWebhooks.data.find(
230
+ (w) => w.url === props.url,
231
+ );
232
+ if (existingWebhook) {
233
+ const updateParams: Stripe.WebhookEndpointUpdateParams = {
234
+ url: props.url,
235
+ enabled_events: props.enabledEvents as any,
236
+ description: props.description,
237
+ metadata: props.metadata,
238
+ };
239
+ webhook = await stripe.webhookEndpoints.update(
240
+ existingWebhook.id,
241
+ updateParams,
242
+ );
243
+ } else {
244
+ throw error;
245
+ }
246
+ } else {
247
+ throw error;
248
+ }
249
+ }
183
250
 
184
251
  // For connect parameter, need to handle it separately if it exists
185
252
  if (props.connect !== undefined) {