@autumnsgrove/groveengine 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 (219) hide show
  1. package/README.md +163 -0
  2. package/dist/auth/jwt.d.ts +14 -0
  3. package/dist/auth/jwt.js +109 -0
  4. package/dist/auth/session.d.ts +42 -0
  5. package/dist/auth/session.js +105 -0
  6. package/dist/components/admin/GutterManager.svelte +910 -0
  7. package/dist/components/admin/GutterManager.svelte.d.ts +15 -0
  8. package/dist/components/admin/MarkdownEditor.svelte +3114 -0
  9. package/dist/components/admin/MarkdownEditor.svelte.d.ts +43 -0
  10. package/dist/components/custom/CollapsibleSection.svelte +74 -0
  11. package/dist/components/custom/CollapsibleSection.svelte.d.ts +15 -0
  12. package/dist/components/custom/ContentWithGutter.svelte +646 -0
  13. package/dist/components/custom/ContentWithGutter.svelte.d.ts +19 -0
  14. package/dist/components/custom/GutterItem.svelte +201 -0
  15. package/dist/components/custom/GutterItem.svelte.d.ts +11 -0
  16. package/dist/components/custom/LeftGutter.svelte +271 -0
  17. package/dist/components/custom/LeftGutter.svelte.d.ts +17 -0
  18. package/dist/components/custom/MobileTOC.svelte +273 -0
  19. package/dist/components/custom/MobileTOC.svelte.d.ts +11 -0
  20. package/dist/components/custom/TableOfContents.svelte +163 -0
  21. package/dist/components/custom/TableOfContents.svelte.d.ts +11 -0
  22. package/dist/components/gallery/ImageGallery.svelte +681 -0
  23. package/dist/components/gallery/ImageGallery.svelte.d.ts +11 -0
  24. package/dist/components/gallery/Lightbox.svelte +107 -0
  25. package/dist/components/gallery/Lightbox.svelte.d.ts +19 -0
  26. package/dist/components/gallery/LightboxCaption.svelte +25 -0
  27. package/dist/components/gallery/LightboxCaption.svelte.d.ts +11 -0
  28. package/dist/components/gallery/ZoomableImage.svelte +163 -0
  29. package/dist/components/gallery/ZoomableImage.svelte.d.ts +17 -0
  30. package/dist/components/ui/Accordion.svelte +74 -0
  31. package/dist/components/ui/Accordion.svelte.d.ts +42 -0
  32. package/dist/components/ui/Badge.svelte +48 -0
  33. package/dist/components/ui/Badge.svelte.d.ts +26 -0
  34. package/dist/components/ui/Button.svelte +74 -0
  35. package/dist/components/ui/Button.svelte.d.ts +34 -0
  36. package/dist/components/ui/Card.svelte +102 -0
  37. package/dist/components/ui/Card.svelte.d.ts +46 -0
  38. package/dist/components/ui/Dialog.svelte +91 -0
  39. package/dist/components/ui/Dialog.svelte.d.ts +43 -0
  40. package/dist/components/ui/Input.svelte +81 -0
  41. package/dist/components/ui/Input.svelte.d.ts +35 -0
  42. package/dist/components/ui/Select.svelte +69 -0
  43. package/dist/components/ui/Select.svelte.d.ts +36 -0
  44. package/dist/components/ui/Sheet.svelte +98 -0
  45. package/dist/components/ui/Sheet.svelte.d.ts +45 -0
  46. package/dist/components/ui/Skeleton.svelte +31 -0
  47. package/dist/components/ui/Skeleton.svelte.d.ts +26 -0
  48. package/dist/components/ui/Table.svelte +59 -0
  49. package/dist/components/ui/Table.svelte.d.ts +44 -0
  50. package/dist/components/ui/Tabs.svelte +76 -0
  51. package/dist/components/ui/Tabs.svelte.d.ts +41 -0
  52. package/dist/components/ui/Textarea.svelte +81 -0
  53. package/dist/components/ui/Textarea.svelte.d.ts +35 -0
  54. package/dist/components/ui/Toast.svelte +18 -0
  55. package/dist/components/ui/Toast.svelte.d.ts +7 -0
  56. package/dist/components/ui/accordion/accordion-content.svelte +24 -0
  57. package/dist/components/ui/accordion/accordion-content.svelte.d.ts +4 -0
  58. package/dist/components/ui/accordion/accordion-item.svelte +12 -0
  59. package/dist/components/ui/accordion/accordion-item.svelte.d.ts +4 -0
  60. package/dist/components/ui/accordion/accordion-trigger.svelte +29 -0
  61. package/dist/components/ui/accordion/accordion-trigger.svelte.d.ts +7 -0
  62. package/dist/components/ui/accordion/index.d.ts +6 -0
  63. package/dist/components/ui/accordion/index.js +8 -0
  64. package/dist/components/ui/badge/badge.svelte +50 -0
  65. package/dist/components/ui/badge/badge.svelte.d.ts +60 -0
  66. package/dist/components/ui/badge/index.d.ts +2 -0
  67. package/dist/components/ui/badge/index.js +2 -0
  68. package/dist/components/ui/button/button.svelte +82 -0
  69. package/dist/components/ui/button/button.svelte.d.ts +132 -0
  70. package/dist/components/ui/button/index.d.ts +2 -0
  71. package/dist/components/ui/button/index.js +4 -0
  72. package/dist/components/ui/card/card-content.svelte +16 -0
  73. package/dist/components/ui/card/card-content.svelte.d.ts +5 -0
  74. package/dist/components/ui/card/card-description.svelte +16 -0
  75. package/dist/components/ui/card/card-description.svelte.d.ts +5 -0
  76. package/dist/components/ui/card/card-footer.svelte +16 -0
  77. package/dist/components/ui/card/card-footer.svelte.d.ts +5 -0
  78. package/dist/components/ui/card/card-header.svelte +16 -0
  79. package/dist/components/ui/card/card-header.svelte.d.ts +5 -0
  80. package/dist/components/ui/card/card-title.svelte +25 -0
  81. package/dist/components/ui/card/card-title.svelte.d.ts +8 -0
  82. package/dist/components/ui/card/card.svelte +20 -0
  83. package/dist/components/ui/card/card.svelte.d.ts +5 -0
  84. package/dist/components/ui/card/index.d.ts +7 -0
  85. package/dist/components/ui/card/index.js +9 -0
  86. package/dist/components/ui/dialog/dialog-content.svelte +38 -0
  87. package/dist/components/ui/dialog/dialog-content.svelte.d.ts +9 -0
  88. package/dist/components/ui/dialog/dialog-description.svelte +16 -0
  89. package/dist/components/ui/dialog/dialog-description.svelte.d.ts +4 -0
  90. package/dist/components/ui/dialog/dialog-footer.svelte +20 -0
  91. package/dist/components/ui/dialog/dialog-footer.svelte.d.ts +5 -0
  92. package/dist/components/ui/dialog/dialog-header.svelte +20 -0
  93. package/dist/components/ui/dialog/dialog-header.svelte.d.ts +5 -0
  94. package/dist/components/ui/dialog/dialog-overlay.svelte +19 -0
  95. package/dist/components/ui/dialog/dialog-overlay.svelte.d.ts +4 -0
  96. package/dist/components/ui/dialog/dialog-title.svelte +16 -0
  97. package/dist/components/ui/dialog/dialog-title.svelte.d.ts +4 -0
  98. package/dist/components/ui/dialog/index.d.ts +12 -0
  99. package/dist/components/ui/dialog/index.js +14 -0
  100. package/dist/components/ui/index.d.ts +26 -0
  101. package/dist/components/ui/index.js +29 -0
  102. package/dist/components/ui/input/index.d.ts +2 -0
  103. package/dist/components/ui/input/index.js +4 -0
  104. package/dist/components/ui/input/input.svelte +46 -0
  105. package/dist/components/ui/input/input.svelte.d.ts +13 -0
  106. package/dist/components/ui/select/index.d.ts +11 -0
  107. package/dist/components/ui/select/index.js +13 -0
  108. package/dist/components/ui/select/select-content.svelte +39 -0
  109. package/dist/components/ui/select/select-content.svelte.d.ts +7 -0
  110. package/dist/components/ui/select/select-group-heading.svelte +16 -0
  111. package/dist/components/ui/select/select-group-heading.svelte.d.ts +4 -0
  112. package/dist/components/ui/select/select-item.svelte +37 -0
  113. package/dist/components/ui/select/select-item.svelte.d.ts +4 -0
  114. package/dist/components/ui/select/select-scroll-down-button.svelte +19 -0
  115. package/dist/components/ui/select/select-scroll-down-button.svelte.d.ts +4 -0
  116. package/dist/components/ui/select/select-scroll-up-button.svelte +19 -0
  117. package/dist/components/ui/select/select-scroll-up-button.svelte.d.ts +4 -0
  118. package/dist/components/ui/select/select-separator.svelte +13 -0
  119. package/dist/components/ui/select/select-separator.svelte.d.ts +4 -0
  120. package/dist/components/ui/select/select-trigger.svelte +24 -0
  121. package/dist/components/ui/select/select-trigger.svelte.d.ts +4 -0
  122. package/dist/components/ui/separator/index.d.ts +2 -0
  123. package/dist/components/ui/separator/index.js +4 -0
  124. package/dist/components/ui/separator/separator.svelte +22 -0
  125. package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
  126. package/dist/components/ui/sheet/index.d.ts +12 -0
  127. package/dist/components/ui/sheet/index.js +14 -0
  128. package/dist/components/ui/sheet/sheet-content.svelte +53 -0
  129. package/dist/components/ui/sheet/sheet-content.svelte.d.ts +62 -0
  130. package/dist/components/ui/sheet/sheet-description.svelte +16 -0
  131. package/dist/components/ui/sheet/sheet-description.svelte.d.ts +4 -0
  132. package/dist/components/ui/sheet/sheet-footer.svelte +20 -0
  133. package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +5 -0
  134. package/dist/components/ui/sheet/sheet-header.svelte +20 -0
  135. package/dist/components/ui/sheet/sheet-header.svelte.d.ts +5 -0
  136. package/dist/components/ui/sheet/sheet-overlay.svelte +21 -0
  137. package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +6 -0
  138. package/dist/components/ui/sheet/sheet-title.svelte +16 -0
  139. package/dist/components/ui/sheet/sheet-title.svelte.d.ts +4 -0
  140. package/dist/components/ui/skeleton/index.d.ts +2 -0
  141. package/dist/components/ui/skeleton/index.js +4 -0
  142. package/dist/components/ui/skeleton/skeleton.svelte +17 -0
  143. package/dist/components/ui/skeleton/skeleton.svelte.d.ts +5 -0
  144. package/dist/components/ui/table/index.d.ts +9 -0
  145. package/dist/components/ui/table/index.js +11 -0
  146. package/dist/components/ui/table/table-body.svelte +16 -0
  147. package/dist/components/ui/table/table-body.svelte.d.ts +5 -0
  148. package/dist/components/ui/table/table-caption.svelte +16 -0
  149. package/dist/components/ui/table/table-caption.svelte.d.ts +5 -0
  150. package/dist/components/ui/table/table-cell.svelte +20 -0
  151. package/dist/components/ui/table/table-cell.svelte.d.ts +5 -0
  152. package/dist/components/ui/table/table-footer.svelte +16 -0
  153. package/dist/components/ui/table/table-footer.svelte.d.ts +5 -0
  154. package/dist/components/ui/table/table-head.svelte +23 -0
  155. package/dist/components/ui/table/table-head.svelte.d.ts +5 -0
  156. package/dist/components/ui/table/table-header.svelte +16 -0
  157. package/dist/components/ui/table/table-header.svelte.d.ts +5 -0
  158. package/dist/components/ui/table/table-row.svelte +23 -0
  159. package/dist/components/ui/table/table-row.svelte.d.ts +5 -0
  160. package/dist/components/ui/table/table.svelte +18 -0
  161. package/dist/components/ui/table/table.svelte.d.ts +5 -0
  162. package/dist/components/ui/tabs/index.d.ts +6 -0
  163. package/dist/components/ui/tabs/index.js +8 -0
  164. package/dist/components/ui/tabs/tabs-content.svelte +19 -0
  165. package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
  166. package/dist/components/ui/tabs/tabs-list.svelte +19 -0
  167. package/dist/components/ui/tabs/tabs-list.svelte.d.ts +4 -0
  168. package/dist/components/ui/tabs/tabs-trigger.svelte +19 -0
  169. package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
  170. package/dist/components/ui/textarea/index.d.ts +2 -0
  171. package/dist/components/ui/textarea/index.js +4 -0
  172. package/dist/components/ui/textarea/textarea.svelte +24 -0
  173. package/dist/components/ui/textarea/textarea.svelte.d.ts +6 -0
  174. package/dist/components/ui/toast.d.ts +86 -0
  175. package/dist/components/ui/toast.js +99 -0
  176. package/dist/db/schema.sql +238 -0
  177. package/dist/index.d.ts +14 -0
  178. package/dist/index.js +20 -0
  179. package/dist/payments/index.d.ts +33 -0
  180. package/dist/payments/index.js +47 -0
  181. package/dist/payments/shop.d.ts +165 -0
  182. package/dist/payments/shop.js +588 -0
  183. package/dist/payments/stripe/client.d.ts +231 -0
  184. package/dist/payments/stripe/client.js +198 -0
  185. package/dist/payments/stripe/index.d.ts +18 -0
  186. package/dist/payments/stripe/index.js +17 -0
  187. package/dist/payments/stripe/provider.d.ts +50 -0
  188. package/dist/payments/stripe/provider.js +530 -0
  189. package/dist/payments/types.d.ts +355 -0
  190. package/dist/payments/types.js +7 -0
  191. package/dist/server/logger.d.ts +53 -0
  192. package/dist/server/logger.js +252 -0
  193. package/dist/styles/content.css +514 -0
  194. package/dist/styles/tokens.css +175 -0
  195. package/dist/utils/api.d.ts +20 -0
  196. package/dist/utils/api.js +109 -0
  197. package/dist/utils/cn.d.ts +15 -0
  198. package/dist/utils/cn.js +18 -0
  199. package/dist/utils/csrf.d.ts +22 -0
  200. package/dist/utils/csrf.js +72 -0
  201. package/dist/utils/debounce.d.ts +7 -0
  202. package/dist/utils/debounce.js +14 -0
  203. package/dist/utils/gallery.d.ts +66 -0
  204. package/dist/utils/gallery.js +181 -0
  205. package/dist/utils/gutter.d.ts +54 -0
  206. package/dist/utils/gutter.js +169 -0
  207. package/dist/utils/imageProcessor.d.ts +58 -0
  208. package/dist/utils/imageProcessor.js +205 -0
  209. package/dist/utils/json.d.ts +17 -0
  210. package/dist/utils/json.js +26 -0
  211. package/dist/utils/markdown.d.ts +101 -0
  212. package/dist/utils/markdown.js +947 -0
  213. package/dist/utils/sanitize.d.ts +25 -0
  214. package/dist/utils/sanitize.js +127 -0
  215. package/dist/utils/validation.d.ts +46 -0
  216. package/dist/utils/validation.js +169 -0
  217. package/dist/utils.d.ts +5 -0
  218. package/dist/utils.js +5 -0
  219. package/package.json +129 -0
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Stripe API Client for Cloudflare Workers
3
+ *
4
+ * A lightweight, fetch-based Stripe client that works in edge environments.
5
+ * Does not depend on the Node.js Stripe SDK.
6
+ */
7
+ export interface StripeClientConfig {
8
+ secretKey: string;
9
+ apiVersion?: string;
10
+ }
11
+ export interface StripeRequestOptions {
12
+ method?: 'GET' | 'POST' | 'DELETE';
13
+ params?: Record<string, unknown>;
14
+ idempotencyKey?: string;
15
+ stripeAccount?: string;
16
+ }
17
+ export interface StripeError {
18
+ type: string;
19
+ code?: string;
20
+ message: string;
21
+ param?: string;
22
+ decline_code?: string;
23
+ }
24
+ export declare class StripeAPIError extends Error {
25
+ readonly type: string;
26
+ readonly code?: string;
27
+ readonly param?: string;
28
+ readonly statusCode: number;
29
+ constructor(error: StripeError, statusCode: number);
30
+ }
31
+ /**
32
+ * Stripe API Client
33
+ *
34
+ * Usage:
35
+ * ```ts
36
+ * const stripe = new StripeClient({ secretKey: 'sk_test_...' });
37
+ * const session = await stripe.request('checkout/sessions', {
38
+ * method: 'POST',
39
+ * params: { mode: 'payment', ... }
40
+ * });
41
+ * ```
42
+ */
43
+ export declare class StripeClient {
44
+ private readonly secretKey;
45
+ private readonly apiVersion;
46
+ constructor(config: StripeClientConfig);
47
+ /**
48
+ * Make a request to the Stripe API
49
+ */
50
+ request<T>(endpoint: string, options?: StripeRequestOptions): Promise<T>;
51
+ /**
52
+ * Encode parameters for application/x-www-form-urlencoded
53
+ * Handles nested objects and arrays
54
+ */
55
+ private encodeParams;
56
+ /**
57
+ * Append params to URLSearchParams for GET requests
58
+ */
59
+ private appendSearchParams;
60
+ /**
61
+ * Verify a webhook signature
62
+ *
63
+ * @param payload - Raw request body as string
64
+ * @param signature - Stripe-Signature header value
65
+ * @param secret - Webhook signing secret
66
+ * @param tolerance - Max age of event in seconds (default 300)
67
+ */
68
+ verifyWebhookSignature(payload: string, signature: string, secret: string, tolerance?: number): Promise<{
69
+ valid: boolean;
70
+ event?: unknown;
71
+ error?: string;
72
+ }>;
73
+ /**
74
+ * Constant-time string comparison to prevent timing attacks
75
+ */
76
+ private secureCompare;
77
+ }
78
+ export interface StripeProduct {
79
+ id: string;
80
+ object: 'product';
81
+ active: boolean;
82
+ name: string;
83
+ description?: string;
84
+ images: string[];
85
+ metadata: Record<string, string>;
86
+ default_price?: string;
87
+ created: number;
88
+ updated: number;
89
+ }
90
+ export interface StripePrice {
91
+ id: string;
92
+ object: 'price';
93
+ active: boolean;
94
+ product: string;
95
+ currency: string;
96
+ unit_amount: number;
97
+ type: 'one_time' | 'recurring';
98
+ recurring?: {
99
+ interval: 'day' | 'week' | 'month' | 'year';
100
+ interval_count: number;
101
+ };
102
+ metadata: Record<string, string>;
103
+ created: number;
104
+ }
105
+ export interface StripeCheckoutSession {
106
+ id: string;
107
+ object: 'checkout.session';
108
+ url: string;
109
+ status: 'open' | 'complete' | 'expired';
110
+ mode: 'payment' | 'subscription' | 'setup';
111
+ customer?: string;
112
+ customer_email?: string;
113
+ amount_total: number;
114
+ currency: string;
115
+ payment_status: 'unpaid' | 'paid' | 'no_payment_required';
116
+ payment_intent?: string;
117
+ subscription?: string;
118
+ metadata: Record<string, string>;
119
+ expires_at: number;
120
+ client_reference_id?: string;
121
+ }
122
+ export interface StripeCustomer {
123
+ id: string;
124
+ object: 'customer';
125
+ email?: string;
126
+ name?: string;
127
+ phone?: string;
128
+ address?: StripeAddress;
129
+ metadata: Record<string, string>;
130
+ created: number;
131
+ }
132
+ export interface StripeAddress {
133
+ line1?: string;
134
+ line2?: string;
135
+ city?: string;
136
+ state?: string;
137
+ postal_code?: string;
138
+ country?: string;
139
+ }
140
+ export interface StripePaymentIntent {
141
+ id: string;
142
+ object: 'payment_intent';
143
+ amount: number;
144
+ currency: string;
145
+ status: 'requires_payment_method' | 'requires_confirmation' | 'requires_action' | 'processing' | 'requires_capture' | 'canceled' | 'succeeded';
146
+ customer?: string;
147
+ metadata: Record<string, string>;
148
+ latest_charge?: string;
149
+ created: number;
150
+ }
151
+ export interface StripeSubscription {
152
+ id: string;
153
+ object: 'subscription';
154
+ status: 'incomplete' | 'incomplete_expired' | 'trialing' | 'active' | 'past_due' | 'canceled' | 'unpaid' | 'paused';
155
+ customer: string;
156
+ items: {
157
+ data: Array<{
158
+ id: string;
159
+ price: StripePrice;
160
+ quantity: number;
161
+ }>;
162
+ };
163
+ current_period_start: number;
164
+ current_period_end: number;
165
+ cancel_at_period_end: boolean;
166
+ canceled_at?: number;
167
+ trial_start?: number;
168
+ trial_end?: number;
169
+ metadata: Record<string, string>;
170
+ created: number;
171
+ }
172
+ export interface StripeRefund {
173
+ id: string;
174
+ object: 'refund';
175
+ amount: number;
176
+ currency: string;
177
+ status: 'pending' | 'succeeded' | 'failed' | 'canceled';
178
+ payment_intent?: string;
179
+ reason?: 'duplicate' | 'fraudulent' | 'requested_by_customer';
180
+ metadata: Record<string, string>;
181
+ created: number;
182
+ }
183
+ export interface StripeAccount {
184
+ id: string;
185
+ object: 'account';
186
+ type: 'standard' | 'express' | 'custom';
187
+ email?: string;
188
+ country?: string;
189
+ default_currency?: string;
190
+ charges_enabled: boolean;
191
+ payouts_enabled: boolean;
192
+ details_submitted: boolean;
193
+ capabilities?: Record<string, 'active' | 'inactive' | 'pending'>;
194
+ requirements?: {
195
+ currently_due: string[];
196
+ eventually_due: string[];
197
+ past_due: string[];
198
+ };
199
+ created: number;
200
+ }
201
+ export interface StripeAccountLink {
202
+ object: 'account_link';
203
+ url: string;
204
+ expires_at: number;
205
+ created: number;
206
+ }
207
+ export interface StripeLoginLink {
208
+ object: 'login_link';
209
+ url: string;
210
+ created: number;
211
+ }
212
+ export interface StripeBillingPortalSession {
213
+ id: string;
214
+ object: 'billing_portal.session';
215
+ url: string;
216
+ customer: string;
217
+ return_url: string;
218
+ created: number;
219
+ }
220
+ export interface StripeEvent {
221
+ id: string;
222
+ object: 'event';
223
+ type: string;
224
+ data: {
225
+ object: unknown;
226
+ previous_attributes?: Record<string, unknown>;
227
+ };
228
+ account?: string;
229
+ created: number;
230
+ livemode: boolean;
231
+ }
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Stripe API Client for Cloudflare Workers
3
+ *
4
+ * A lightweight, fetch-based Stripe client that works in edge environments.
5
+ * Does not depend on the Node.js Stripe SDK.
6
+ */
7
+ const STRIPE_API_VERSION = '2024-11-20.acacia';
8
+ const STRIPE_API_BASE = 'https://api.stripe.com/v1';
9
+ export class StripeAPIError extends Error {
10
+ type;
11
+ code;
12
+ param;
13
+ statusCode;
14
+ constructor(error, statusCode) {
15
+ super(error.message);
16
+ this.name = 'StripeAPIError';
17
+ this.type = error.type;
18
+ this.code = error.code;
19
+ this.param = error.param;
20
+ this.statusCode = statusCode;
21
+ }
22
+ }
23
+ /**
24
+ * Stripe API Client
25
+ *
26
+ * Usage:
27
+ * ```ts
28
+ * const stripe = new StripeClient({ secretKey: 'sk_test_...' });
29
+ * const session = await stripe.request('checkout/sessions', {
30
+ * method: 'POST',
31
+ * params: { mode: 'payment', ... }
32
+ * });
33
+ * ```
34
+ */
35
+ export class StripeClient {
36
+ secretKey;
37
+ apiVersion;
38
+ constructor(config) {
39
+ this.secretKey = config.secretKey;
40
+ this.apiVersion = config.apiVersion || STRIPE_API_VERSION;
41
+ }
42
+ /**
43
+ * Make a request to the Stripe API
44
+ */
45
+ async request(endpoint, options = {}) {
46
+ const { method = 'GET', params, idempotencyKey, stripeAccount } = options;
47
+ const url = new URL(`${STRIPE_API_BASE}/${endpoint}`);
48
+ // For GET requests, append params as query string
49
+ if (method === 'GET' && params) {
50
+ this.appendSearchParams(url.searchParams, params);
51
+ }
52
+ const headers = {
53
+ 'Authorization': `Bearer ${this.secretKey}`,
54
+ 'Stripe-Version': this.apiVersion,
55
+ };
56
+ // For POST requests, encode params as form data
57
+ let body;
58
+ if (method === 'POST' && params) {
59
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
60
+ body = this.encodeParams(params);
61
+ }
62
+ // Idempotency key for POST requests
63
+ if (idempotencyKey) {
64
+ headers['Idempotency-Key'] = idempotencyKey;
65
+ }
66
+ // Stripe Connect: make request on behalf of connected account
67
+ if (stripeAccount) {
68
+ headers['Stripe-Account'] = stripeAccount;
69
+ }
70
+ const response = await fetch(url.toString(), {
71
+ method,
72
+ headers,
73
+ body,
74
+ });
75
+ const data = await response.json();
76
+ if (!response.ok) {
77
+ throw new StripeAPIError(data.error || { type: 'api_error', message: 'Unknown error' }, response.status);
78
+ }
79
+ return data;
80
+ }
81
+ /**
82
+ * Encode parameters for application/x-www-form-urlencoded
83
+ * Handles nested objects and arrays
84
+ */
85
+ encodeParams(params, prefix = '') {
86
+ const parts = [];
87
+ for (const [key, value] of Object.entries(params)) {
88
+ if (value === undefined || value === null)
89
+ continue;
90
+ const fullKey = prefix ? `${prefix}[${key}]` : key;
91
+ if (Array.isArray(value)) {
92
+ value.forEach((item, index) => {
93
+ if (typeof item === 'object' && item !== null) {
94
+ parts.push(this.encodeParams(item, `${fullKey}[${index}]`));
95
+ }
96
+ else {
97
+ parts.push(`${encodeURIComponent(`${fullKey}[${index}]`)}=${encodeURIComponent(String(item))}`);
98
+ }
99
+ });
100
+ }
101
+ else if (typeof value === 'object') {
102
+ parts.push(this.encodeParams(value, fullKey));
103
+ }
104
+ else {
105
+ parts.push(`${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`);
106
+ }
107
+ }
108
+ return parts.filter(Boolean).join('&');
109
+ }
110
+ /**
111
+ * Append params to URLSearchParams for GET requests
112
+ */
113
+ appendSearchParams(searchParams, params, prefix = '') {
114
+ for (const [key, value] of Object.entries(params)) {
115
+ if (value === undefined || value === null)
116
+ continue;
117
+ const fullKey = prefix ? `${prefix}[${key}]` : key;
118
+ if (Array.isArray(value)) {
119
+ value.forEach((item, index) => {
120
+ if (typeof item === 'object' && item !== null) {
121
+ this.appendSearchParams(searchParams, item, `${fullKey}[${index}]`);
122
+ }
123
+ else {
124
+ searchParams.append(`${fullKey}[${index}]`, String(item));
125
+ }
126
+ });
127
+ }
128
+ else if (typeof value === 'object') {
129
+ this.appendSearchParams(searchParams, value, fullKey);
130
+ }
131
+ else {
132
+ searchParams.append(fullKey, String(value));
133
+ }
134
+ }
135
+ }
136
+ /**
137
+ * Verify a webhook signature
138
+ *
139
+ * @param payload - Raw request body as string
140
+ * @param signature - Stripe-Signature header value
141
+ * @param secret - Webhook signing secret
142
+ * @param tolerance - Max age of event in seconds (default 300)
143
+ */
144
+ async verifyWebhookSignature(payload, signature, secret, tolerance = 300) {
145
+ try {
146
+ // Parse the signature header
147
+ const parts = signature.split(',').reduce((acc, part) => {
148
+ const [key, value] = part.split('=');
149
+ if (key && value) {
150
+ acc[key] = value;
151
+ }
152
+ return acc;
153
+ }, {});
154
+ const timestamp = parts['t'];
155
+ const v1Signature = parts['v1'];
156
+ if (!timestamp || !v1Signature) {
157
+ return { valid: false, error: 'Invalid signature format' };
158
+ }
159
+ // Check timestamp tolerance
160
+ const timestampSeconds = parseInt(timestamp, 10);
161
+ const now = Math.floor(Date.now() / 1000);
162
+ if (now - timestampSeconds > tolerance) {
163
+ return { valid: false, error: 'Webhook timestamp too old' };
164
+ }
165
+ // Compute expected signature
166
+ const signedPayload = `${timestamp}.${payload}`;
167
+ const encoder = new TextEncoder();
168
+ const key = await crypto.subtle.importKey('raw', encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
169
+ const signatureBytes = await crypto.subtle.sign('HMAC', key, encoder.encode(signedPayload));
170
+ const expectedSignature = Array.from(new Uint8Array(signatureBytes))
171
+ .map(b => b.toString(16).padStart(2, '0'))
172
+ .join('');
173
+ // Constant-time comparison
174
+ if (!this.secureCompare(expectedSignature, v1Signature)) {
175
+ return { valid: false, error: 'Signature mismatch' };
176
+ }
177
+ // Parse and return the event
178
+ const event = JSON.parse(payload);
179
+ return { valid: true, event };
180
+ }
181
+ catch (err) {
182
+ return { valid: false, error: `Verification failed: ${err}` };
183
+ }
184
+ }
185
+ /**
186
+ * Constant-time string comparison to prevent timing attacks
187
+ */
188
+ secureCompare(a, b) {
189
+ if (a.length !== b.length) {
190
+ return false;
191
+ }
192
+ let result = 0;
193
+ for (let i = 0; i < a.length; i++) {
194
+ result |= a.charCodeAt(i) ^ b.charCodeAt(i);
195
+ }
196
+ return result === 0;
197
+ }
198
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Stripe Payment Provider
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { createStripeProvider } from './';
7
+ *
8
+ * const stripe = createStripeProvider({
9
+ * secretKey: platform.env.STRIPE_SECRET_KEY,
10
+ * webhookSecret: platform.env.STRIPE_WEBHOOK_SECRET,
11
+ * });
12
+ *
13
+ * const session = await stripe.createCheckoutSession(items, options, resolveVariant);
14
+ * ```
15
+ */
16
+ export { StripeClient, StripeAPIError } from './client.js';
17
+ export { StripeProvider, createStripeProvider } from './provider.js';
18
+ export type { StripeClientConfig, StripeRequestOptions, StripeError, StripeProduct, StripePrice, StripeCheckoutSession, StripeCustomer, StripeAddress, StripePaymentIntent, StripeSubscription, StripeRefund, StripeAccount, StripeAccountLink, StripeLoginLink, StripeBillingPortalSession, StripeEvent, } from './client.js';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Stripe Payment Provider
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { createStripeProvider } from './';
7
+ *
8
+ * const stripe = createStripeProvider({
9
+ * secretKey: platform.env.STRIPE_SECRET_KEY,
10
+ * webhookSecret: platform.env.STRIPE_WEBHOOK_SECRET,
11
+ * });
12
+ *
13
+ * const session = await stripe.createCheckoutSession(items, options, resolveVariant);
14
+ * ```
15
+ */
16
+ export { StripeClient, StripeAPIError } from './client.js';
17
+ export { StripeProvider, createStripeProvider } from './provider.js';
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Stripe Payment Provider Implementation
3
+ *
4
+ * Implements the PaymentProvider interface using Stripe's API.
5
+ * Supports Stripe Connect for marketplace functionality.
6
+ */
7
+ import type { PaymentProvider, PaymentProviderConfig, ProductBase, ProductVariant, CartItem, CheckoutOptions, CheckoutSession, PaymentStatus, RefundRequest, RefundResult, Subscription, Customer, WebhookResult, ConnectAccount, ConnectOnboardingOptions, ConnectOnboardingResult } from '../types.js';
8
+ export declare class StripeProvider implements PaymentProvider {
9
+ readonly name = "stripe";
10
+ private readonly client;
11
+ private readonly webhookSecret?;
12
+ private readonly connectWebhookSecret?;
13
+ constructor(config: PaymentProviderConfig);
14
+ syncProduct(product: ProductBase): Promise<{
15
+ providerProductId: string;
16
+ }>;
17
+ syncPrice(variant: ProductVariant, providerProductId: string): Promise<{
18
+ providerPriceId: string;
19
+ }>;
20
+ archiveProduct(providerProductId: string): Promise<void>;
21
+ createCheckoutSession(items: CartItem[], options: CheckoutOptions, resolveVariant: (variantId: string) => Promise<ProductVariant | null>): Promise<CheckoutSession>;
22
+ getCheckoutSession(sessionId: string): Promise<CheckoutSession | null>;
23
+ private mapCheckoutSession;
24
+ getPaymentStatus(providerPaymentId: string): Promise<PaymentStatus>;
25
+ refund(request: RefundRequest, providerPaymentId: string): Promise<RefundResult>;
26
+ getSubscription(providerSubscriptionId: string): Promise<Subscription | null>;
27
+ cancelSubscription(providerSubscriptionId: string, cancelImmediately?: boolean): Promise<void>;
28
+ resumeSubscription(providerSubscriptionId: string): Promise<void>;
29
+ private mapSubscription;
30
+ syncCustomer(customer: Partial<Customer>): Promise<{
31
+ providerCustomerId: string;
32
+ }>;
33
+ getCustomer(providerCustomerId: string): Promise<Customer | null>;
34
+ createBillingPortalSession(providerCustomerId: string, returnUrl: string): Promise<{
35
+ url: string;
36
+ }>;
37
+ handleWebhook(request: Request): Promise<WebhookResult>;
38
+ private mapEventType;
39
+ createConnectAccount(options: ConnectOnboardingOptions): Promise<ConnectOnboardingResult>;
40
+ getConnectAccount(providerAccountId: string): Promise<ConnectAccount | null>;
41
+ createConnectAccountLink(providerAccountId: string, options: Pick<ConnectOnboardingOptions, 'returnUrl' | 'refreshUrl'>): Promise<{
42
+ url: string;
43
+ expiresAt?: Date;
44
+ }>;
45
+ createConnectLoginLink(providerAccountId: string): Promise<{
46
+ url: string;
47
+ }>;
48
+ private mapConnectAccount;
49
+ }
50
+ export declare function createStripeProvider(config: PaymentProviderConfig): StripeProvider;