@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,355 @@
1
+ /**
2
+ * Abstract Payment Provider Types
3
+ *
4
+ * Provider-agnostic interfaces for payment processing.
5
+ * Designed for easy switching between Stripe, Paddle, LemonSqueezy, etc.
6
+ */
7
+ export interface Money {
8
+ amount: number;
9
+ currency: string;
10
+ }
11
+ export type PricingType = 'one_time' | 'recurring';
12
+ export type BillingInterval = 'day' | 'week' | 'month' | 'year';
13
+ export interface RecurringConfig {
14
+ interval: BillingInterval;
15
+ intervalCount: number;
16
+ }
17
+ export type ProductType = 'physical' | 'digital' | 'subscription' | 'service';
18
+ export type ProductStatus = 'draft' | 'active' | 'archived';
19
+ export interface ProductBase {
20
+ id: string;
21
+ tenantId: string;
22
+ name: string;
23
+ description?: string;
24
+ type: ProductType;
25
+ status: ProductStatus;
26
+ images: string[];
27
+ metadata?: Record<string, string>;
28
+ createdAt: Date;
29
+ updatedAt: Date;
30
+ }
31
+ export interface ProductVariant {
32
+ id: string;
33
+ productId: string;
34
+ name: string;
35
+ sku?: string;
36
+ price: Money;
37
+ compareAtPrice?: Money;
38
+ pricingType: PricingType;
39
+ recurring?: RecurringConfig;
40
+ inventoryQuantity?: number;
41
+ inventoryPolicy?: 'deny' | 'continue';
42
+ downloadUrl?: string;
43
+ downloadLimit?: number;
44
+ providerPriceId?: string;
45
+ isDefault: boolean;
46
+ position: number;
47
+ createdAt: Date;
48
+ updatedAt: Date;
49
+ }
50
+ export interface Product extends ProductBase {
51
+ variants: ProductVariant[];
52
+ defaultVariantId?: string;
53
+ }
54
+ export interface CartItem {
55
+ variantId: string;
56
+ quantity: number;
57
+ metadata?: Record<string, string>;
58
+ }
59
+ export interface LineItem {
60
+ id: string;
61
+ variantId: string;
62
+ productId: string;
63
+ productName: string;
64
+ variantName: string;
65
+ quantity: number;
66
+ unitPrice: Money;
67
+ totalPrice: Money;
68
+ taxAmount?: Money;
69
+ metadata?: Record<string, string>;
70
+ }
71
+ export type CheckoutMode = 'payment' | 'subscription' | 'setup';
72
+ export interface CheckoutOptions {
73
+ mode: CheckoutMode;
74
+ successUrl: string;
75
+ cancelUrl: string;
76
+ customerEmail?: string;
77
+ customerId?: string;
78
+ metadata?: Record<string, string>;
79
+ connectedAccountId?: string;
80
+ applicationFeeAmount?: number;
81
+ automaticTax?: boolean;
82
+ taxIdCollection?: boolean;
83
+ shippingAddressCollection?: {
84
+ allowedCountries: string[];
85
+ };
86
+ billingAddressCollection?: 'auto' | 'required';
87
+ trialPeriodDays?: number;
88
+ allowPromotionCodes?: boolean;
89
+ }
90
+ export interface CheckoutSession {
91
+ id: string;
92
+ url: string;
93
+ status: 'open' | 'complete' | 'expired';
94
+ mode: CheckoutMode;
95
+ customerId?: string;
96
+ customerEmail?: string;
97
+ amountTotal?: Money;
98
+ paymentStatus: 'unpaid' | 'paid' | 'no_payment_required';
99
+ metadata?: Record<string, string>;
100
+ expiresAt: Date;
101
+ }
102
+ export type PaymentStatus = 'pending' | 'processing' | 'succeeded' | 'failed' | 'canceled' | 'refunded' | 'partially_refunded';
103
+ export type OrderStatus = 'pending' | 'paid' | 'processing' | 'shipped' | 'completed' | 'canceled' | 'refunded';
104
+ export interface Order {
105
+ id: string;
106
+ tenantId: string;
107
+ customerId?: string;
108
+ customerEmail: string;
109
+ lineItems: LineItem[];
110
+ subtotal: Money;
111
+ taxTotal: Money;
112
+ shippingTotal: Money;
113
+ discountTotal: Money;
114
+ total: Money;
115
+ status: OrderStatus;
116
+ paymentStatus: PaymentStatus;
117
+ providerOrderId?: string;
118
+ providerSessionId?: string;
119
+ shippingAddress?: Address;
120
+ billingAddress?: Address;
121
+ fulfilledAt?: Date;
122
+ shippedAt?: Date;
123
+ trackingNumber?: string;
124
+ trackingUrl?: string;
125
+ notes?: string;
126
+ createdAt: Date;
127
+ updatedAt: Date;
128
+ }
129
+ export interface Address {
130
+ name?: string;
131
+ line1: string;
132
+ line2?: string;
133
+ city: string;
134
+ state?: string;
135
+ postalCode: string;
136
+ country: string;
137
+ phone?: string;
138
+ }
139
+ export type RefundReason = 'duplicate' | 'fraudulent' | 'requested_by_customer' | 'other';
140
+ export interface RefundRequest {
141
+ orderId: string;
142
+ amount?: number;
143
+ reason?: RefundReason;
144
+ notes?: string;
145
+ }
146
+ export interface RefundResult {
147
+ id: string;
148
+ orderId: string;
149
+ amount: Money;
150
+ status: 'pending' | 'succeeded' | 'failed' | 'canceled';
151
+ reason?: RefundReason;
152
+ providerRefundId?: string;
153
+ createdAt: Date;
154
+ }
155
+ export type SubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'paused' | 'canceled' | 'unpaid';
156
+ export interface Subscription {
157
+ id: string;
158
+ tenantId: string;
159
+ customerId: string;
160
+ customerEmail: string;
161
+ productId: string;
162
+ variantId: string;
163
+ quantity: number;
164
+ status: SubscriptionStatus;
165
+ currentPeriodStart: Date;
166
+ currentPeriodEnd: Date;
167
+ cancelAtPeriodEnd: boolean;
168
+ canceledAt?: Date;
169
+ trialStart?: Date;
170
+ trialEnd?: Date;
171
+ providerSubscriptionId?: string;
172
+ createdAt: Date;
173
+ updatedAt: Date;
174
+ }
175
+ export interface Customer {
176
+ id: string;
177
+ tenantId: string;
178
+ email: string;
179
+ name?: string;
180
+ phone?: string;
181
+ defaultShippingAddress?: Address;
182
+ defaultBillingAddress?: Address;
183
+ providerCustomerId?: string;
184
+ metadata?: Record<string, string>;
185
+ createdAt: Date;
186
+ updatedAt: Date;
187
+ }
188
+ export type WebhookEventType = 'checkout.session.completed' | 'checkout.session.expired' | 'payment.succeeded' | 'payment.failed' | 'subscription.created' | 'subscription.updated' | 'subscription.canceled' | 'subscription.trial_will_end' | 'invoice.paid' | 'invoice.payment_failed' | 'refund.created' | 'refund.updated' | 'account.updated' | 'payout.paid';
189
+ export interface WebhookEvent {
190
+ id: string;
191
+ type: WebhookEventType;
192
+ data: unknown;
193
+ createdAt: Date;
194
+ providerEventId?: string;
195
+ }
196
+ export interface WebhookResult {
197
+ received: boolean;
198
+ event?: WebhookEvent;
199
+ error?: string;
200
+ }
201
+ export type ConnectAccountStatus = 'pending' | 'enabled' | 'restricted' | 'disabled';
202
+ export interface ConnectAccount {
203
+ id: string;
204
+ tenantId: string;
205
+ providerAccountId: string;
206
+ status: ConnectAccountStatus;
207
+ chargesEnabled: boolean;
208
+ payoutsEnabled: boolean;
209
+ detailsSubmitted: boolean;
210
+ email?: string;
211
+ country?: string;
212
+ defaultCurrency?: string;
213
+ createdAt: Date;
214
+ updatedAt: Date;
215
+ }
216
+ export interface ConnectOnboardingOptions {
217
+ tenantId: string;
218
+ returnUrl: string;
219
+ refreshUrl: string;
220
+ type?: 'standard' | 'express' | 'custom';
221
+ country?: string;
222
+ email?: string;
223
+ businessType?: 'individual' | 'company' | 'non_profit';
224
+ }
225
+ export interface ConnectOnboardingResult {
226
+ accountId: string;
227
+ onboardingUrl: string;
228
+ expiresAt?: Date;
229
+ }
230
+ export type PlanTier = 'starter' | 'professional' | 'business';
231
+ export interface PlatformPlan {
232
+ tier: PlanTier;
233
+ name: string;
234
+ price: Money;
235
+ interval: BillingInterval;
236
+ features: string[];
237
+ limits: {
238
+ posts?: number;
239
+ storage?: number;
240
+ customDomain?: boolean;
241
+ analytics?: boolean;
242
+ shop?: boolean;
243
+ };
244
+ providerPriceId?: string;
245
+ }
246
+ export interface TenantBilling {
247
+ tenantId: string;
248
+ plan: PlanTier;
249
+ status: SubscriptionStatus;
250
+ customerId?: string;
251
+ subscriptionId?: string;
252
+ currentPeriodEnd?: Date;
253
+ cancelAtPeriodEnd?: boolean;
254
+ }
255
+ export interface PaymentProviderConfig {
256
+ secretKey: string;
257
+ publishableKey?: string;
258
+ webhookSecret?: string;
259
+ connectClientId?: string;
260
+ platformAccountId?: string;
261
+ }
262
+ /**
263
+ * Abstract Payment Provider Interface
264
+ *
265
+ * Implement this interface for each payment provider (Stripe, Paddle, etc.)
266
+ */
267
+ export interface PaymentProvider {
268
+ readonly name: string;
269
+ /**
270
+ * Sync a product to the payment provider
271
+ * Creates/updates product in Stripe/Paddle/etc.
272
+ */
273
+ syncProduct(product: ProductBase): Promise<{
274
+ providerProductId: string;
275
+ }>;
276
+ /**
277
+ * Sync a price/variant to the payment provider
278
+ */
279
+ syncPrice(variant: ProductVariant, providerProductId: string): Promise<{
280
+ providerPriceId: string;
281
+ }>;
282
+ /**
283
+ * Archive a product in the provider
284
+ */
285
+ archiveProduct(providerProductId: string): Promise<void>;
286
+ /**
287
+ * Create a checkout session for purchasing items
288
+ */
289
+ createCheckoutSession(items: CartItem[], options: CheckoutOptions, resolveVariant: (variantId: string) => Promise<ProductVariant | null>): Promise<CheckoutSession>;
290
+ /**
291
+ * Retrieve a checkout session by ID
292
+ */
293
+ getCheckoutSession(sessionId: string): Promise<CheckoutSession | null>;
294
+ /**
295
+ * Get payment status for an order
296
+ */
297
+ getPaymentStatus(providerPaymentId: string): Promise<PaymentStatus>;
298
+ /**
299
+ * Process a refund
300
+ */
301
+ refund(request: RefundRequest, providerPaymentId: string): Promise<RefundResult>;
302
+ /**
303
+ * Get subscription details
304
+ */
305
+ getSubscription(providerSubscriptionId: string): Promise<Subscription | null>;
306
+ /**
307
+ * Cancel a subscription
308
+ */
309
+ cancelSubscription(providerSubscriptionId: string, cancelImmediately?: boolean): Promise<void>;
310
+ /**
311
+ * Resume a canceled subscription (if not yet ended)
312
+ */
313
+ resumeSubscription(providerSubscriptionId: string): Promise<void>;
314
+ /**
315
+ * Create or update a customer in the provider
316
+ */
317
+ syncCustomer(customer: Partial<Customer>): Promise<{
318
+ providerCustomerId: string;
319
+ }>;
320
+ /**
321
+ * Get customer by provider ID
322
+ */
323
+ getCustomer(providerCustomerId: string): Promise<Customer | null>;
324
+ /**
325
+ * Create a billing portal session for customer self-service
326
+ */
327
+ createBillingPortalSession(providerCustomerId: string, returnUrl: string): Promise<{
328
+ url: string;
329
+ }>;
330
+ /**
331
+ * Verify and parse a webhook payload
332
+ */
333
+ handleWebhook(request: Request): Promise<WebhookResult>;
334
+ /**
335
+ * Create a Connect account for a tenant
336
+ */
337
+ createConnectAccount?(options: ConnectOnboardingOptions): Promise<ConnectOnboardingResult>;
338
+ /**
339
+ * Get Connect account status
340
+ */
341
+ getConnectAccount?(providerAccountId: string): Promise<ConnectAccount | null>;
342
+ /**
343
+ * Create an account link for onboarding/updating
344
+ */
345
+ createConnectAccountLink?(providerAccountId: string, options: Pick<ConnectOnboardingOptions, 'returnUrl' | 'refreshUrl'>): Promise<{
346
+ url: string;
347
+ expiresAt?: Date;
348
+ }>;
349
+ /**
350
+ * Create a login link for the Connect dashboard
351
+ */
352
+ createConnectLoginLink?(providerAccountId: string): Promise<{
353
+ url: string;
354
+ }>;
355
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Abstract Payment Provider Types
3
+ *
4
+ * Provider-agnostic interfaces for payment processing.
5
+ * Designed for easy switching between Stripe, Paddle, LemonSqueezy, etc.
6
+ */
7
+ export {};
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Log API activity (requests, responses, timing)
3
+ */
4
+ export function logAPI(endpoint: any, method: any, status: any, metadata?: {}): void;
5
+ /**
6
+ * Log GitHub API operations (rate limits, queries, errors)
7
+ */
8
+ export function logGitHub(operation: any, metadata?: {}): void;
9
+ /**
10
+ * Log errors (exceptions, failed operations, validation errors)
11
+ */
12
+ export function logError(message: any, error?: null, metadata?: {}): void;
13
+ /**
14
+ * Log cache operations (KV get/set, hits/misses)
15
+ */
16
+ export function logCache(operation: any, key: any, metadata?: {}): void;
17
+ /**
18
+ * Get logs from a specific category
19
+ */
20
+ export function getLogs(category: any, since?: null): any;
21
+ /**
22
+ * Get all logs across all categories
23
+ */
24
+ export function getAllLogs(since?: null): any[];
25
+ /**
26
+ * Get log statistics
27
+ */
28
+ export function getLogStats(): {
29
+ api: {
30
+ total: number;
31
+ recent: number;
32
+ };
33
+ github: {
34
+ total: number;
35
+ recent: number;
36
+ };
37
+ errors: {
38
+ total: number;
39
+ recent: number;
40
+ };
41
+ cache: {
42
+ total: number;
43
+ recent: number;
44
+ };
45
+ };
46
+ /**
47
+ * Subscribe to log events (for SSE streaming)
48
+ */
49
+ export function subscribe(callback: any): () => boolean;
50
+ /**
51
+ * Clear logs for a specific category or all categories
52
+ */
53
+ export function clearLogs(category?: null): void;
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Server-side logging utility with in-memory circular buffers
3
+ * Supports real-time log streaming to admin console
4
+ */
5
+
6
+ // Circular buffer implementation
7
+ class CircularBuffer {
8
+ constructor(maxSize = 1000) {
9
+ this.maxSize = maxSize;
10
+ this.buffer = [];
11
+ }
12
+
13
+ push(item) {
14
+ this.buffer.push(item);
15
+ if (this.buffer.length > this.maxSize) {
16
+ this.buffer.shift(); // Remove oldest item
17
+ }
18
+ }
19
+
20
+ getAll() {
21
+ return [...this.buffer]; // Return copy to prevent external mutations
22
+ }
23
+
24
+ getSince(timestamp) {
25
+ return this.buffer.filter(
26
+ (log) => new Date(log.timestamp) > new Date(timestamp),
27
+ );
28
+ }
29
+
30
+ clear() {
31
+ this.buffer = [];
32
+ }
33
+
34
+ get length() {
35
+ return this.buffer.length;
36
+ }
37
+ }
38
+
39
+ // Log buffers for each category (module-level, persists across requests in same worker)
40
+ const logBuffers = {
41
+ api: new CircularBuffer(1000),
42
+ github: new CircularBuffer(500),
43
+ errors: new CircularBuffer(500),
44
+ cache: new CircularBuffer(1000),
45
+ };
46
+
47
+ // Subscribers for SSE streaming
48
+ const subscribers = new Set();
49
+
50
+ /**
51
+ * Create a log entry with consistent format
52
+ */
53
+ function createLogEntry(level, category, message, metadata = {}) {
54
+ return {
55
+ id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
56
+ timestamp: new Date().toISOString(),
57
+ level, // 'info' | 'warn' | 'error' | 'success'
58
+ category, // 'api' | 'github' | 'errors' | 'cache'
59
+ message,
60
+ metadata,
61
+ };
62
+ }
63
+
64
+ /**
65
+ * Broadcast log to all SSE subscribers
66
+ */
67
+ function broadcast(log) {
68
+ subscribers.forEach((subscriber) => {
69
+ try {
70
+ subscriber(log);
71
+ } catch (error) {
72
+ console.error("[Logger] Failed to broadcast to subscriber:", error);
73
+ }
74
+ });
75
+ }
76
+
77
+ /**
78
+ * Log API activity (requests, responses, timing)
79
+ */
80
+ export function logAPI(endpoint, method, status, metadata = {}) {
81
+ const level =
82
+ status >= 500
83
+ ? "error"
84
+ : status >= 400
85
+ ? "warn"
86
+ : status >= 200
87
+ ? "success"
88
+ : "info";
89
+ const log = createLogEntry(
90
+ level,
91
+ "api",
92
+ `${method} ${endpoint} → ${status}`,
93
+ {
94
+ endpoint,
95
+ method,
96
+ status,
97
+ ...metadata,
98
+ },
99
+ );
100
+
101
+ logBuffers.api.push(log);
102
+ broadcast(log);
103
+
104
+ // Also log to console in development
105
+ if (metadata.duration) {
106
+ console.log(
107
+ `[API] ${method} ${endpoint} ${status} (${metadata.duration}ms)`,
108
+ );
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Log GitHub API operations (rate limits, queries, errors)
114
+ */
115
+ export function logGitHub(operation, metadata = {}) {
116
+ const level = metadata.error ? "error" : metadata.warning ? "warn" : "info";
117
+ const log = createLogEntry(level, "github", operation, metadata);
118
+
119
+ logBuffers.github.push(log);
120
+ broadcast(log);
121
+
122
+ console.log(
123
+ `[GitHub] ${operation}`,
124
+ metadata.rateLimit
125
+ ? `(${metadata.rateLimit.remaining}/${metadata.rateLimit.limit} remaining)`
126
+ : "",
127
+ );
128
+ }
129
+
130
+ /**
131
+ * Log errors (exceptions, failed operations, validation errors)
132
+ */
133
+ export function logError(message, error = null, metadata = {}) {
134
+ const log = createLogEntry("error", "errors", message, {
135
+ error: error
136
+ ? {
137
+ message: error.message,
138
+ stack: error.stack,
139
+ name: error.name,
140
+ }
141
+ : null,
142
+ ...metadata,
143
+ });
144
+
145
+ logBuffers.errors.push(log);
146
+ broadcast(log);
147
+
148
+ console.error(`[Error] ${message}`, error || "");
149
+ }
150
+
151
+ /**
152
+ * Log cache operations (KV get/set, hits/misses)
153
+ */
154
+ export function logCache(operation, key, metadata = {}) {
155
+ const level = metadata.error ? "error" : "info";
156
+ const log = createLogEntry(
157
+ level,
158
+ "cache",
159
+ `${operation.toUpperCase()} ${key}`,
160
+ {
161
+ operation, // 'get', 'set', 'delete'
162
+ key,
163
+ ...metadata,
164
+ },
165
+ );
166
+
167
+ logBuffers.cache.push(log);
168
+ broadcast(log);
169
+ }
170
+
171
+ /**
172
+ * Get logs from a specific category
173
+ */
174
+ export function getLogs(category, since = null) {
175
+ if (!logBuffers[category]) {
176
+ return [];
177
+ }
178
+
179
+ if (since) {
180
+ return logBuffers[category].getSince(since);
181
+ }
182
+
183
+ return logBuffers[category].getAll();
184
+ }
185
+
186
+ /**
187
+ * Get all logs across all categories
188
+ */
189
+ export function getAllLogs(since = null) {
190
+ const allLogs = [];
191
+
192
+ for (const category of Object.keys(logBuffers)) {
193
+ const logs = since
194
+ ? logBuffers[category].getSince(since)
195
+ : logBuffers[category].getAll();
196
+ allLogs.push(...logs);
197
+ }
198
+
199
+ // Sort by timestamp (newest first)
200
+ return allLogs.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));
201
+ }
202
+
203
+ /**
204
+ * Get log statistics
205
+ */
206
+ export function getLogStats() {
207
+ return {
208
+ api: {
209
+ total: logBuffers.api.length,
210
+ recent: logBuffers.api.getSince(
211
+ new Date(Date.now() - 60000).toISOString(),
212
+ ).length, // Last minute
213
+ },
214
+ github: {
215
+ total: logBuffers.github.length,
216
+ recent: logBuffers.github.getSince(
217
+ new Date(Date.now() - 60000).toISOString(),
218
+ ).length,
219
+ },
220
+ errors: {
221
+ total: logBuffers.errors.length,
222
+ recent: logBuffers.errors.getSince(
223
+ new Date(Date.now() - 60000).toISOString(),
224
+ ).length,
225
+ },
226
+ cache: {
227
+ total: logBuffers.cache.length,
228
+ recent: logBuffers.cache.getSince(
229
+ new Date(Date.now() - 60000).toISOString(),
230
+ ).length,
231
+ },
232
+ };
233
+ }
234
+
235
+ /**
236
+ * Subscribe to log events (for SSE streaming)
237
+ */
238
+ export function subscribe(callback) {
239
+ subscribers.add(callback);
240
+ return () => subscribers.delete(callback);
241
+ }
242
+
243
+ /**
244
+ * Clear logs for a specific category or all categories
245
+ */
246
+ export function clearLogs(category = null) {
247
+ if (category && logBuffers[category]) {
248
+ logBuffers[category].clear();
249
+ } else if (!category) {
250
+ Object.values(logBuffers).forEach((buffer) => buffer.clear());
251
+ }
252
+ }