@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.
- package/README.md +163 -0
- package/dist/auth/jwt.d.ts +14 -0
- package/dist/auth/jwt.js +109 -0
- package/dist/auth/session.d.ts +42 -0
- package/dist/auth/session.js +105 -0
- package/dist/components/admin/GutterManager.svelte +910 -0
- package/dist/components/admin/GutterManager.svelte.d.ts +15 -0
- package/dist/components/admin/MarkdownEditor.svelte +3114 -0
- package/dist/components/admin/MarkdownEditor.svelte.d.ts +43 -0
- package/dist/components/custom/CollapsibleSection.svelte +74 -0
- package/dist/components/custom/CollapsibleSection.svelte.d.ts +15 -0
- package/dist/components/custom/ContentWithGutter.svelte +646 -0
- package/dist/components/custom/ContentWithGutter.svelte.d.ts +19 -0
- package/dist/components/custom/GutterItem.svelte +201 -0
- package/dist/components/custom/GutterItem.svelte.d.ts +11 -0
- package/dist/components/custom/LeftGutter.svelte +271 -0
- package/dist/components/custom/LeftGutter.svelte.d.ts +17 -0
- package/dist/components/custom/MobileTOC.svelte +273 -0
- package/dist/components/custom/MobileTOC.svelte.d.ts +11 -0
- package/dist/components/custom/TableOfContents.svelte +163 -0
- package/dist/components/custom/TableOfContents.svelte.d.ts +11 -0
- package/dist/components/gallery/ImageGallery.svelte +681 -0
- package/dist/components/gallery/ImageGallery.svelte.d.ts +11 -0
- package/dist/components/gallery/Lightbox.svelte +107 -0
- package/dist/components/gallery/Lightbox.svelte.d.ts +19 -0
- package/dist/components/gallery/LightboxCaption.svelte +25 -0
- package/dist/components/gallery/LightboxCaption.svelte.d.ts +11 -0
- package/dist/components/gallery/ZoomableImage.svelte +163 -0
- package/dist/components/gallery/ZoomableImage.svelte.d.ts +17 -0
- package/dist/components/ui/Accordion.svelte +74 -0
- package/dist/components/ui/Accordion.svelte.d.ts +42 -0
- package/dist/components/ui/Badge.svelte +48 -0
- package/dist/components/ui/Badge.svelte.d.ts +26 -0
- package/dist/components/ui/Button.svelte +74 -0
- package/dist/components/ui/Button.svelte.d.ts +34 -0
- package/dist/components/ui/Card.svelte +102 -0
- package/dist/components/ui/Card.svelte.d.ts +46 -0
- package/dist/components/ui/Dialog.svelte +91 -0
- package/dist/components/ui/Dialog.svelte.d.ts +43 -0
- package/dist/components/ui/Input.svelte +81 -0
- package/dist/components/ui/Input.svelte.d.ts +35 -0
- package/dist/components/ui/Select.svelte +69 -0
- package/dist/components/ui/Select.svelte.d.ts +36 -0
- package/dist/components/ui/Sheet.svelte +98 -0
- package/dist/components/ui/Sheet.svelte.d.ts +45 -0
- package/dist/components/ui/Skeleton.svelte +31 -0
- package/dist/components/ui/Skeleton.svelte.d.ts +26 -0
- package/dist/components/ui/Table.svelte +59 -0
- package/dist/components/ui/Table.svelte.d.ts +44 -0
- package/dist/components/ui/Tabs.svelte +76 -0
- package/dist/components/ui/Tabs.svelte.d.ts +41 -0
- package/dist/components/ui/Textarea.svelte +81 -0
- package/dist/components/ui/Textarea.svelte.d.ts +35 -0
- package/dist/components/ui/Toast.svelte +18 -0
- package/dist/components/ui/Toast.svelte.d.ts +7 -0
- package/dist/components/ui/accordion/accordion-content.svelte +24 -0
- package/dist/components/ui/accordion/accordion-content.svelte.d.ts +4 -0
- package/dist/components/ui/accordion/accordion-item.svelte +12 -0
- package/dist/components/ui/accordion/accordion-item.svelte.d.ts +4 -0
- package/dist/components/ui/accordion/accordion-trigger.svelte +29 -0
- package/dist/components/ui/accordion/accordion-trigger.svelte.d.ts +7 -0
- package/dist/components/ui/accordion/index.d.ts +6 -0
- package/dist/components/ui/accordion/index.js +8 -0
- package/dist/components/ui/badge/badge.svelte +50 -0
- package/dist/components/ui/badge/badge.svelte.d.ts +60 -0
- package/dist/components/ui/badge/index.d.ts +2 -0
- package/dist/components/ui/badge/index.js +2 -0
- package/dist/components/ui/button/button.svelte +82 -0
- package/dist/components/ui/button/button.svelte.d.ts +132 -0
- package/dist/components/ui/button/index.d.ts +2 -0
- package/dist/components/ui/button/index.js +4 -0
- package/dist/components/ui/card/card-content.svelte +16 -0
- package/dist/components/ui/card/card-content.svelte.d.ts +5 -0
- package/dist/components/ui/card/card-description.svelte +16 -0
- package/dist/components/ui/card/card-description.svelte.d.ts +5 -0
- package/dist/components/ui/card/card-footer.svelte +16 -0
- package/dist/components/ui/card/card-footer.svelte.d.ts +5 -0
- package/dist/components/ui/card/card-header.svelte +16 -0
- package/dist/components/ui/card/card-header.svelte.d.ts +5 -0
- package/dist/components/ui/card/card-title.svelte +25 -0
- package/dist/components/ui/card/card-title.svelte.d.ts +8 -0
- package/dist/components/ui/card/card.svelte +20 -0
- package/dist/components/ui/card/card.svelte.d.ts +5 -0
- package/dist/components/ui/card/index.d.ts +7 -0
- package/dist/components/ui/card/index.js +9 -0
- package/dist/components/ui/dialog/dialog-content.svelte +38 -0
- package/dist/components/ui/dialog/dialog-content.svelte.d.ts +9 -0
- package/dist/components/ui/dialog/dialog-description.svelte +16 -0
- package/dist/components/ui/dialog/dialog-description.svelte.d.ts +4 -0
- package/dist/components/ui/dialog/dialog-footer.svelte +20 -0
- package/dist/components/ui/dialog/dialog-footer.svelte.d.ts +5 -0
- package/dist/components/ui/dialog/dialog-header.svelte +20 -0
- package/dist/components/ui/dialog/dialog-header.svelte.d.ts +5 -0
- package/dist/components/ui/dialog/dialog-overlay.svelte +19 -0
- package/dist/components/ui/dialog/dialog-overlay.svelte.d.ts +4 -0
- package/dist/components/ui/dialog/dialog-title.svelte +16 -0
- package/dist/components/ui/dialog/dialog-title.svelte.d.ts +4 -0
- package/dist/components/ui/dialog/index.d.ts +12 -0
- package/dist/components/ui/dialog/index.js +14 -0
- package/dist/components/ui/index.d.ts +26 -0
- package/dist/components/ui/index.js +29 -0
- package/dist/components/ui/input/index.d.ts +2 -0
- package/dist/components/ui/input/index.js +4 -0
- package/dist/components/ui/input/input.svelte +46 -0
- package/dist/components/ui/input/input.svelte.d.ts +13 -0
- package/dist/components/ui/select/index.d.ts +11 -0
- package/dist/components/ui/select/index.js +13 -0
- package/dist/components/ui/select/select-content.svelte +39 -0
- package/dist/components/ui/select/select-content.svelte.d.ts +7 -0
- package/dist/components/ui/select/select-group-heading.svelte +16 -0
- package/dist/components/ui/select/select-group-heading.svelte.d.ts +4 -0
- package/dist/components/ui/select/select-item.svelte +37 -0
- package/dist/components/ui/select/select-item.svelte.d.ts +4 -0
- package/dist/components/ui/select/select-scroll-down-button.svelte +19 -0
- package/dist/components/ui/select/select-scroll-down-button.svelte.d.ts +4 -0
- package/dist/components/ui/select/select-scroll-up-button.svelte +19 -0
- package/dist/components/ui/select/select-scroll-up-button.svelte.d.ts +4 -0
- package/dist/components/ui/select/select-separator.svelte +13 -0
- package/dist/components/ui/select/select-separator.svelte.d.ts +4 -0
- package/dist/components/ui/select/select-trigger.svelte +24 -0
- package/dist/components/ui/select/select-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/separator/index.d.ts +2 -0
- package/dist/components/ui/separator/index.js +4 -0
- package/dist/components/ui/separator/separator.svelte +22 -0
- package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/index.d.ts +12 -0
- package/dist/components/ui/sheet/index.js +14 -0
- package/dist/components/ui/sheet/sheet-content.svelte +53 -0
- package/dist/components/ui/sheet/sheet-content.svelte.d.ts +62 -0
- package/dist/components/ui/sheet/sheet-description.svelte +16 -0
- package/dist/components/ui/sheet/sheet-description.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-footer.svelte +20 -0
- package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-header.svelte +20 -0
- package/dist/components/ui/sheet/sheet-header.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-overlay.svelte +21 -0
- package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +6 -0
- package/dist/components/ui/sheet/sheet-title.svelte +16 -0
- package/dist/components/ui/sheet/sheet-title.svelte.d.ts +4 -0
- package/dist/components/ui/skeleton/index.d.ts +2 -0
- package/dist/components/ui/skeleton/index.js +4 -0
- package/dist/components/ui/skeleton/skeleton.svelte +17 -0
- package/dist/components/ui/skeleton/skeleton.svelte.d.ts +5 -0
- package/dist/components/ui/table/index.d.ts +9 -0
- package/dist/components/ui/table/index.js +11 -0
- package/dist/components/ui/table/table-body.svelte +16 -0
- package/dist/components/ui/table/table-body.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-caption.svelte +16 -0
- package/dist/components/ui/table/table-caption.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-cell.svelte +20 -0
- package/dist/components/ui/table/table-cell.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-footer.svelte +16 -0
- package/dist/components/ui/table/table-footer.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-head.svelte +23 -0
- package/dist/components/ui/table/table-head.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-header.svelte +16 -0
- package/dist/components/ui/table/table-header.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-row.svelte +23 -0
- package/dist/components/ui/table/table-row.svelte.d.ts +5 -0
- package/dist/components/ui/table/table.svelte +18 -0
- package/dist/components/ui/table/table.svelte.d.ts +5 -0
- package/dist/components/ui/tabs/index.d.ts +6 -0
- package/dist/components/ui/tabs/index.js +8 -0
- package/dist/components/ui/tabs/tabs-content.svelte +19 -0
- package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs-list.svelte +19 -0
- package/dist/components/ui/tabs/tabs-list.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte +19 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/textarea/index.d.ts +2 -0
- package/dist/components/ui/textarea/index.js +4 -0
- package/dist/components/ui/textarea/textarea.svelte +24 -0
- package/dist/components/ui/textarea/textarea.svelte.d.ts +6 -0
- package/dist/components/ui/toast.d.ts +86 -0
- package/dist/components/ui/toast.js +99 -0
- package/dist/db/schema.sql +238 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +20 -0
- package/dist/payments/index.d.ts +33 -0
- package/dist/payments/index.js +47 -0
- package/dist/payments/shop.d.ts +165 -0
- package/dist/payments/shop.js +588 -0
- package/dist/payments/stripe/client.d.ts +231 -0
- package/dist/payments/stripe/client.js +198 -0
- package/dist/payments/stripe/index.d.ts +18 -0
- package/dist/payments/stripe/index.js +17 -0
- package/dist/payments/stripe/provider.d.ts +50 -0
- package/dist/payments/stripe/provider.js +530 -0
- package/dist/payments/types.d.ts +355 -0
- package/dist/payments/types.js +7 -0
- package/dist/server/logger.d.ts +53 -0
- package/dist/server/logger.js +252 -0
- package/dist/styles/content.css +514 -0
- package/dist/styles/tokens.css +175 -0
- package/dist/utils/api.d.ts +20 -0
- package/dist/utils/api.js +109 -0
- package/dist/utils/cn.d.ts +15 -0
- package/dist/utils/cn.js +18 -0
- package/dist/utils/csrf.d.ts +22 -0
- package/dist/utils/csrf.js +72 -0
- package/dist/utils/debounce.d.ts +7 -0
- package/dist/utils/debounce.js +14 -0
- package/dist/utils/gallery.d.ts +66 -0
- package/dist/utils/gallery.js +181 -0
- package/dist/utils/gutter.d.ts +54 -0
- package/dist/utils/gutter.js +169 -0
- package/dist/utils/imageProcessor.d.ts +58 -0
- package/dist/utils/imageProcessor.js +205 -0
- package/dist/utils/json.d.ts +17 -0
- package/dist/utils/json.js +26 -0
- package/dist/utils/markdown.d.ts +101 -0
- package/dist/utils/markdown.js +947 -0
- package/dist/utils/sanitize.d.ts +25 -0
- package/dist/utils/sanitize.js +127 -0
- package/dist/utils/validation.d.ts +46 -0
- package/dist/utils/validation.js +169 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +5 -0
- 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,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
|
+
}
|