torque-checkout 1.0.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 ADDED
@@ -0,0 +1,400 @@
1
+ # @torque/checkout
2
+
3
+ Official Torque checkout SDK for seamless ecommerce integrations. Generate multi-product checkout links, track orders, and manage customer data with our powerful API.
4
+
5
+ ## 🚀 Quick Start
6
+
7
+ ### Installation
8
+
9
+ ```bash
10
+ npm install @torque/checkout
11
+ # or
12
+ yarn add @torque/checkout
13
+ ```
14
+
15
+ ### Basic Usage
16
+
17
+ ```typescript
18
+ import { TorqueCheckout } from '@torque/checkout'
19
+
20
+ const torque = new TorqueCheckout({
21
+ businessId: 'your_business_id',
22
+ apiKey: 'your_api_key'
23
+ })
24
+
25
+ // Generate cart checkout link
26
+ const checkoutUrl = await torque.generateCartCheckoutUrl({
27
+ items: [
28
+ { productId: 'prod_123', quantity: 2, variant: 'large' },
29
+ { productId: 'prod_456', quantity: 1 }
30
+ ],
31
+ customer: {
32
+ email: 'customer@example.com',
33
+ firstName: 'John',
34
+ lastName: 'Doe'
35
+ }
36
+ })
37
+
38
+ // Redirect customer to checkout
39
+ window.location.href = checkoutUrl
40
+ ```
41
+
42
+ ## 📚 API Reference
43
+
44
+ ### Constructor
45
+
46
+ ```typescript
47
+ new TorqueCheckout(config: TorqueConfig)
48
+ ```
49
+
50
+ **Config Options:**
51
+ - `businessId` (required): Your Torque business ID
52
+ - `apiKey` (required): Your API authentication key
53
+ - `baseUrl` (optional): Custom API base URL (defaults to `https://torque.fi`)
54
+ - `timeout` (optional): Request timeout in milliseconds (defaults to 30000)
55
+
56
+ ### Methods
57
+
58
+ #### `generateCartCheckoutUrl(cart: CartData): Promise<string>`
59
+
60
+ Generate a checkout URL for a multi-product cart.
61
+
62
+ ```typescript
63
+ const checkoutUrl = await torque.generateCartCheckoutUrl({
64
+ items: [
65
+ { productId: 'prod_123', quantity: 2, variant: 'large' },
66
+ { productId: 'prod_456', quantity: 1 }
67
+ ],
68
+ customer: {
69
+ email: 'customer@example.com',
70
+ firstName: 'John',
71
+ lastName: 'Doe',
72
+ shippingAddress: {
73
+ street: '123 Main St',
74
+ city: 'New York',
75
+ state: 'NY',
76
+ zipCode: '10001',
77
+ country: 'US'
78
+ }
79
+ },
80
+ options: {
81
+ metadata: {
82
+ orderId: 'order_123',
83
+ source: 'shopify'
84
+ },
85
+ expiresIn: 24 * 60 * 60 * 1000 // 24 hours
86
+ }
87
+ })
88
+ ```
89
+
90
+ #### `generateProductCheckoutUrl(productId: string, quantity?: number, customer?: CustomerData, options?: CartOptions): Promise<string>`
91
+
92
+ Generate a checkout URL for a single product.
93
+
94
+ ```typescript
95
+ const checkoutUrl = await torque.generateProductCheckoutUrl(
96
+ 'prod_123',
97
+ 2,
98
+ { email: 'customer@example.com' }
99
+ )
100
+ ```
101
+
102
+ #### `validateCart(cart: CartData): Promise<CartValidation>`
103
+
104
+ Validate cart data before generating checkout links.
105
+
106
+ ```typescript
107
+ const validation = await torque.validateCart({
108
+ items: [
109
+ { productId: 'prod_123', quantity: 2 },
110
+ { productId: 'prod_456', quantity: 1 }
111
+ ]
112
+ })
113
+
114
+ if (validation.valid) {
115
+ console.log('Cart is valid, estimated total:', validation.estimatedTotal)
116
+ } else {
117
+ console.log('Cart validation errors:', validation.errors)
118
+ }
119
+ ```
120
+
121
+ #### `getOrderStatus(orderId: string): Promise<OrderStatus>`
122
+
123
+ Get the current status of an order.
124
+
125
+ ```typescript
126
+ const orderStatus = await torque.getOrderStatus('order_123')
127
+ console.log('Order status:', orderStatus.status)
128
+ console.log('Total amount:', orderStatus.totals.total)
129
+ ```
130
+
131
+ #### `sendWebhookEvent(orderId: string, status: string, customerData?: any, metadata?: Record<string, any>): Promise<void>`
132
+
133
+ Send webhook events to update order status.
134
+
135
+ ```typescript
136
+ await torque.sendWebhookEvent('order_123', 'shipped', {
137
+ trackingNumber: '1Z999AA1234567890',
138
+ carrier: 'UPS'
139
+ })
140
+ ```
141
+
142
+ #### `trackCartView(cartId: string, cartData: CartData): Promise<void>`
143
+
144
+ Track cart views for analytics.
145
+
146
+ ```typescript
147
+ await torque.trackCartView('cart_123', {
148
+ items: [{ productId: 'prod_123', quantity: 2 }]
149
+ })
150
+ ```
151
+
152
+ #### `trackCheckoutComplete(orderId: string, checkoutData: any): Promise<void>`
153
+
154
+ Track successful checkout completions.
155
+
156
+ ```typescript
157
+ await torque.trackCheckoutComplete('order_123', {
158
+ paymentMethod: 'card',
159
+ total: 99.99
160
+ })
161
+ ```
162
+
163
+ #### `generateCartHash(cart: CartData): string`
164
+
165
+ Generate a unique hash for cart identification and caching.
166
+
167
+ ```typescript
168
+ const cartHash = torque.generateCartHash({
169
+ items: [{ productId: 'prod_123', quantity: 2 }]
170
+ })
171
+ ```
172
+
173
+ ## 🛒 Data Types
174
+
175
+ ### CartItem
176
+
177
+ ```typescript
178
+ interface CartItem {
179
+ productId: string // Required: Torque product ID
180
+ quantity: number // Required: Quantity to purchase
181
+ variant?: string // Optional: Product variant (size, color, etc.)
182
+ price?: number // Optional: Override product price
183
+ metadata?: Record<string, any> // Optional: Custom data
184
+ }
185
+ ```
186
+
187
+ ### CustomerData
188
+
189
+ ```typescript
190
+ interface CustomerData {
191
+ email: string // Required: Customer email
192
+ firstName?: string // Optional: First name
193
+ lastName?: string // Optional: Last name
194
+ phone?: string // Optional: Phone number
195
+ shippingAddress?: { // Optional: Pre-fill shipping address
196
+ street: string
197
+ city: string
198
+ state: string
199
+ zipCode: string
200
+ country: string
201
+ }
202
+ billingAddress?: { // Optional: Pre-fill billing address
203
+ // Same structure as shippingAddress
204
+ }
205
+ }
206
+ ```
207
+
208
+ ### CartOptions
209
+
210
+ ```typescript
211
+ interface CartOptions {
212
+ domain?: string // Optional: Custom domain for checkout
213
+ expiresIn?: number // Optional: Link expiration time (ms)
214
+ metadata?: Record<string, any> // Optional: Custom metadata
215
+ redirectUrl?: string // Optional: Post-checkout redirect URL
216
+ }
217
+ ```
218
+
219
+ ## 🔌 Platform Integrations
220
+
221
+ ### Shopify
222
+
223
+ ```typescript
224
+ // Shopify app integration
225
+ app.post('/checkout', async (req, res) => {
226
+ const { cart, customer } = req.body
227
+
228
+ try {
229
+ const checkoutUrl = await torque.generateCartCheckoutUrl({
230
+ items: cart.items.map(item => ({
231
+ productId: item.product_id,
232
+ quantity: item.quantity,
233
+ variant: item.variant_title,
234
+ price: item.price
235
+ })),
236
+ customer: {
237
+ email: customer.email,
238
+ firstName: customer.first_name,
239
+ lastName: customer.last_name,
240
+ shippingAddress: customer.shipping_address
241
+ },
242
+ options: {
243
+ metadata: {
244
+ orderId: cart.order_id,
245
+ source: 'shopify'
246
+ }
247
+ }
248
+ })
249
+
250
+ res.json({ checkoutUrl })
251
+ } catch (error) {
252
+ res.status(500).json({ error: error.message })
253
+ }
254
+ })
255
+ ```
256
+
257
+ ### WooCommerce
258
+
259
+ ```php
260
+ // WooCommerce hook integration
261
+ add_action('woocommerce_checkout_order_processed', 'redirect_to_torque_checkout', 10, 3);
262
+
263
+ function redirect_to_torque_checkout($order_id, $posted_data, $order) {
264
+ $cart_items = [];
265
+
266
+ foreach ($order->get_items() as $item) {
267
+ $cart_items[] = [
268
+ 'productId' => $item->get_product_id(),
269
+ 'quantity' => $item->get_quantity(),
270
+ 'variant' => $item->get_variation_id() ? $item->get_name() : null,
271
+ 'price' => $item->get_total() / $item->get_quantity()
272
+ ];
273
+ }
274
+
275
+ $checkout_data = [
276
+ 'businessId' => get_option('torque_business_id'),
277
+ 'cart' => ['items' => $cart_items],
278
+ 'customerData' => [
279
+ 'email' => $order->get_billing_email(),
280
+ 'firstName' => $order->get_billing_first_name(),
281
+ 'lastName' => $order->get_billing_last_name()
282
+ ]
283
+ ];
284
+
285
+ // Use JavaScript SDK or direct API call
286
+ $response = wp_remote_post('https://torque.fi/api/checkout/generate-link', [
287
+ 'body' => json_encode($checkout_data),
288
+ 'headers' => ['Content-Type' => 'application/json'],
289
+ 'timeout' => 30
290
+ ]);
291
+
292
+ if (!is_wp_error($response)) {
293
+ $body = json_decode(wp_remote_retrieve_body($response), true);
294
+ if ($body['checkoutUrl']) {
295
+ wp_redirect($body['checkoutUrl']);
296
+ exit;
297
+ }
298
+ }
299
+ }
300
+ ```
301
+
302
+ ## 🧪 Testing
303
+
304
+ ### Test Environment
305
+
306
+ Use our sandbox environment for testing:
307
+
308
+ ```typescript
309
+ const torque = new TorqueCheckout({
310
+ businessId: 'test_business_123',
311
+ apiKey: 'test_api_key',
312
+ baseUrl: 'https://sandbox.torque.fi'
313
+ })
314
+ ```
315
+
316
+ ### Test Data
317
+
318
+ ```typescript
319
+ const testCart = {
320
+ items: [
321
+ { productId: 'test_prod_1', quantity: 1, price: 10.00 }
322
+ ],
323
+ customer: {
324
+ email: 'test@example.com'
325
+ }
326
+ }
327
+
328
+ const checkoutUrl = await torque.generateCartCheckoutUrl(testCart)
329
+ ```
330
+
331
+ ## 🚨 Error Handling
332
+
333
+ The SDK throws descriptive errors for various failure scenarios:
334
+
335
+ ```typescript
336
+ try {
337
+ const checkoutUrl = await torque.generateCartCheckoutUrl(cart)
338
+ } catch (error) {
339
+ if (error.message.includes('BUSINESS_NOT_FOUND')) {
340
+ console.error('Invalid business ID')
341
+ } else if (error.message.includes('PRODUCTS_NOT_FOUND')) {
342
+ console.error('Some products not found')
343
+ } else if (error.message.includes('Request timeout')) {
344
+ console.error('API request timed out')
345
+ } else {
346
+ console.error('Unexpected error:', error.message)
347
+ }
348
+ }
349
+ ```
350
+
351
+ ## 📊 Analytics & Tracking
352
+
353
+ Track customer behavior and optimize conversions:
354
+
355
+ ```typescript
356
+ // Track cart abandonment
357
+ await torque.trackCartView('cart_123', cartData)
358
+
359
+ // Track successful checkouts
360
+ await torque.trackCheckoutComplete('order_123', {
361
+ paymentMethod: 'card',
362
+ total: 99.99,
363
+ items: 3
364
+ })
365
+ ```
366
+
367
+ ## 🔒 Security
368
+
369
+ - API keys are automatically included in all requests
370
+ - All requests use HTTPS
371
+ - Request timeouts prevent hanging connections
372
+ - Input validation on all methods
373
+
374
+ ## 📈 Performance
375
+
376
+ - Built-in request caching with cart hashing
377
+ - Configurable timeouts
378
+ - Efficient error handling
379
+ - Minimal bundle size
380
+
381
+ ## 🆘 Support
382
+
383
+ - **Documentation**: [https://docs.torque.fi/sdk](https://docs.torque.fi/sdk)
384
+ - **API Reference**: [https://docs.torque.fi/api](https://docs.torque.fi/api)
385
+ - **Examples**: [https://github.com/torque-fi/examples](https://github.com/torque-fi/examples)
386
+ - **Support**: integrations@torque.fi
387
+
388
+ ## 📝 Changelog
389
+
390
+ ### v1.0.0
391
+ - Initial release
392
+ - Multi-product cart support
393
+ - Customer data pre-population
394
+ - Order status tracking
395
+ - Webhook integration
396
+ - Analytics tracking
397
+
398
+ ## 📄 License
399
+
400
+ MIT License - see [LICENSE](LICENSE) file for details.
@@ -0,0 +1,141 @@
1
+ export interface CartItem {
2
+ productId: string;
3
+ quantity: number;
4
+ variant?: string;
5
+ price?: number;
6
+ metadata?: Record<string, any>;
7
+ }
8
+ export interface CustomerData {
9
+ email: string;
10
+ firstName?: string;
11
+ lastName?: string;
12
+ phone?: string;
13
+ shippingAddress?: {
14
+ street: string;
15
+ city: string;
16
+ state: string;
17
+ zipCode: string;
18
+ country: string;
19
+ };
20
+ billingAddress?: {
21
+ street: string;
22
+ city: string;
23
+ state: string;
24
+ zipCode: string;
25
+ country: string;
26
+ };
27
+ }
28
+ export interface CartOptions {
29
+ domain?: string;
30
+ expiresIn?: number;
31
+ metadata?: Record<string, any>;
32
+ redirectUrl?: string;
33
+ }
34
+ export interface CartData {
35
+ items: CartItem[];
36
+ customer?: CustomerData;
37
+ options?: CartOptions;
38
+ }
39
+ export interface TorqueConfig {
40
+ businessId: string;
41
+ apiKey: string;
42
+ baseUrl?: string;
43
+ timeout?: number;
44
+ }
45
+ export interface CheckoutResponse {
46
+ success: boolean;
47
+ checkoutUrl: string;
48
+ expiresAt: string;
49
+ cartSummary: {
50
+ itemCount: number;
51
+ productCount: number;
52
+ estimatedTotal: number;
53
+ };
54
+ business: {
55
+ id: string;
56
+ name: string;
57
+ logo?: string;
58
+ };
59
+ }
60
+ export interface OrderStatus {
61
+ orderId: string;
62
+ status: string;
63
+ customer: {
64
+ email: string;
65
+ firstName?: string;
66
+ lastName?: string;
67
+ phone?: string;
68
+ } | null;
69
+ items: Array<{
70
+ productId: string;
71
+ productName: string;
72
+ productImage?: string;
73
+ quantity: number;
74
+ variant?: string;
75
+ price: number;
76
+ total: number;
77
+ }>;
78
+ totals: {
79
+ subtotal: number;
80
+ shipping: number;
81
+ tax: number;
82
+ total: number;
83
+ };
84
+ paymentStatus: string;
85
+ shippingAddress?: any;
86
+ billingAddress?: any;
87
+ createdAt: number;
88
+ updatedAt: number;
89
+ metadata: Record<string, any>;
90
+ }
91
+ export interface CartValidation {
92
+ valid: boolean;
93
+ errors: string[];
94
+ warnings: string[];
95
+ estimatedTotal: number;
96
+ }
97
+ export declare class TorqueCheckout {
98
+ private businessId;
99
+ private apiKey;
100
+ private baseUrl;
101
+ private timeout;
102
+ constructor(config: TorqueConfig);
103
+ /**
104
+ * Generate a cart checkout URL
105
+ */
106
+ generateCartCheckoutUrl(cart: CartData): Promise<string>;
107
+ /**
108
+ * Generate a single product checkout URL
109
+ */
110
+ generateProductCheckoutUrl(productId: string, quantity?: number, customer?: CustomerData, options?: CartOptions): Promise<string>;
111
+ /**
112
+ * Validate cart data before checkout
113
+ */
114
+ validateCart(cart: CartData): Promise<CartValidation>;
115
+ /**
116
+ * Get order status
117
+ */
118
+ getOrderStatus(orderId: string): Promise<OrderStatus>;
119
+ /**
120
+ * Send webhook event
121
+ */
122
+ sendWebhookEvent(orderId: string, status: string, customerData?: any, metadata?: Record<string, any>): Promise<void>;
123
+ /**
124
+ * Track cart view for analytics
125
+ */
126
+ trackCartView(cartId: string, cartData: CartData): Promise<void>;
127
+ /**
128
+ * Track checkout completion for analytics
129
+ */
130
+ trackCheckoutComplete(orderId: string, checkoutData: any): Promise<void>;
131
+ /**
132
+ * Generate cart hash for caching
133
+ */
134
+ generateCartHash(cart: CartData): string;
135
+ /**
136
+ * Make HTTP request to Torque API
137
+ */
138
+ private makeRequest;
139
+ }
140
+ export declare const createTorqueCheckout: (config: TorqueConfig) => TorqueCheckout;
141
+ export type { CartItem, CustomerData, CartOptions, CartData, TorqueConfig, CheckoutResponse, OrderStatus, CartValidation };
@@ -0,0 +1,181 @@
1
+ class TorqueCheckout {
2
+ constructor(config) {
3
+ this.businessId = config.businessId;
4
+ this.apiKey = config.apiKey;
5
+ this.baseUrl = config.baseUrl || 'https://torque.fi';
6
+ this.timeout = config.timeout || 30000;
7
+ }
8
+ /**
9
+ * Generate a cart checkout URL
10
+ */
11
+ async generateCartCheckoutUrl(cart) {
12
+ const response = await this.makeRequest('/api/checkout/generate-link', {
13
+ method: 'POST',
14
+ body: {
15
+ businessId: this.businessId,
16
+ cart: {
17
+ items: cart.items
18
+ },
19
+ customerData: cart.customer,
20
+ options: cart.options
21
+ }
22
+ });
23
+ if (!response.success) {
24
+ throw new Error(`Failed to generate checkout URL: ${response.error || 'Unknown error'}`);
25
+ }
26
+ return response.checkoutUrl;
27
+ }
28
+ /**
29
+ * Generate a single product checkout URL
30
+ */
31
+ async generateProductCheckoutUrl(productId, quantity = 1, customer, options) {
32
+ return this.generateCartCheckoutUrl({
33
+ items: [{ productId, quantity }],
34
+ customer,
35
+ options
36
+ });
37
+ }
38
+ /**
39
+ * Validate cart data before checkout
40
+ */
41
+ async validateCart(cart) {
42
+ try {
43
+ const response = await this.makeRequest('/api/checkout/validate-cart', {
44
+ method: 'POST',
45
+ body: {
46
+ businessId: this.businessId,
47
+ cart: cart.items,
48
+ customer: cart.customer
49
+ }
50
+ });
51
+ return response;
52
+ }
53
+ catch (error) {
54
+ return {
55
+ valid: false,
56
+ errors: [error instanceof Error ? error.message : 'Validation failed'],
57
+ warnings: [],
58
+ estimatedTotal: 0
59
+ };
60
+ }
61
+ }
62
+ /**
63
+ * Get order status
64
+ */
65
+ async getOrderStatus(orderId) {
66
+ const response = await this.makeRequest(`/api/checkout/order-status/${orderId}?businessId=${this.businessId}`);
67
+ if (response.error) {
68
+ throw new Error(`Failed to get order status: ${response.error}`);
69
+ }
70
+ return response;
71
+ }
72
+ /**
73
+ * Send webhook event
74
+ */
75
+ async sendWebhookEvent(orderId, status, customerData, metadata) {
76
+ await this.makeRequest('/api/webhooks/order-update', {
77
+ method: 'POST',
78
+ body: {
79
+ orderId,
80
+ status,
81
+ customerData,
82
+ metadata
83
+ }
84
+ });
85
+ }
86
+ /**
87
+ * Track cart view for analytics
88
+ */
89
+ async trackCartView(cartId, cartData) {
90
+ try {
91
+ await this.makeRequest('/api/analytics/cart-view', {
92
+ method: 'POST',
93
+ body: {
94
+ cartId,
95
+ businessId: this.businessId,
96
+ cartData,
97
+ timestamp: Date.now()
98
+ }
99
+ });
100
+ }
101
+ catch (error) {
102
+ console.warn('Failed to track cart view:', error);
103
+ }
104
+ }
105
+ /**
106
+ * Track checkout completion for analytics
107
+ */
108
+ async trackCheckoutComplete(orderId, checkoutData) {
109
+ try {
110
+ await this.makeRequest('/api/analytics/checkout-complete', {
111
+ method: 'POST',
112
+ body: {
113
+ orderId,
114
+ businessId: this.businessId,
115
+ checkoutData,
116
+ timestamp: Date.now()
117
+ }
118
+ });
119
+ }
120
+ catch (error) {
121
+ console.warn('Failed to track checkout completion:', error);
122
+ }
123
+ }
124
+ /**
125
+ * Generate cart hash for caching
126
+ */
127
+ generateCartHash(cart) {
128
+ const cartString = JSON.stringify({
129
+ items: cart.items.sort((a, b) => a.productId.localeCompare(b.productId)),
130
+ customer: cart.customer ? { email: cart.customer.email } : null
131
+ });
132
+ // Simple hash function for cart identification
133
+ let hash = 0;
134
+ for (let i = 0; i < cartString.length; i++) {
135
+ const char = cartString.charCodeAt(i);
136
+ hash = ((hash << 5) - hash) + char;
137
+ hash = hash & hash; // Convert to 32-bit integer
138
+ }
139
+ return Math.abs(hash).toString(36);
140
+ }
141
+ /**
142
+ * Make HTTP request to Torque API
143
+ */
144
+ async makeRequest(endpoint, options = {}) {
145
+ const url = `${this.baseUrl}${endpoint}`;
146
+ const controller = new AbortController();
147
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
148
+ try {
149
+ const response = await fetch(url, {
150
+ ...options,
151
+ headers: {
152
+ 'Content-Type': 'application/json',
153
+ 'Authorization': `Bearer ${this.apiKey}`,
154
+ ...options.headers
155
+ },
156
+ signal: controller.signal
157
+ });
158
+ clearTimeout(timeoutId);
159
+ if (!response.ok) {
160
+ const errorData = await response.json().catch(() => ({}));
161
+ throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
162
+ }
163
+ return await response.json();
164
+ }
165
+ catch (error) {
166
+ clearTimeout(timeoutId);
167
+ if (error instanceof Error) {
168
+ if (error.name === 'AbortError') {
169
+ throw new Error('Request timeout');
170
+ }
171
+ throw error;
172
+ }
173
+ throw new Error('Request failed');
174
+ }
175
+ }
176
+ }
177
+ // Export default instance factory
178
+ const createTorqueCheckout = (config) => new TorqueCheckout(config);
179
+
180
+ export { TorqueCheckout, createTorqueCheckout };
181
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/index.ts"],"sourcesContent":["export interface CartItem {\n productId: string\n quantity: number\n variant?: string\n price?: number\n metadata?: Record<string, any>\n}\n\nexport interface CustomerData {\n email: string\n firstName?: string\n lastName?: string\n phone?: string\n shippingAddress?: {\n street: string\n city: string\n state: string\n zipCode: string\n country: string\n }\n billingAddress?: {\n street: string\n city: string\n state: string\n zipCode: string\n country: string\n }\n}\n\nexport interface CartOptions {\n domain?: string\n expiresIn?: number\n metadata?: Record<string, any>\n redirectUrl?: string\n}\n\nexport interface CartData {\n items: CartItem[]\n customer?: CustomerData\n options?: CartOptions\n}\n\nexport interface TorqueConfig {\n businessId: string\n apiKey: string\n baseUrl?: string\n timeout?: number\n}\n\nexport interface CheckoutResponse {\n success: boolean\n checkoutUrl: string\n expiresAt: string\n cartSummary: {\n itemCount: number\n productCount: number\n estimatedTotal: number\n }\n business: {\n id: string\n name: string\n logo?: string\n }\n}\n\nexport interface OrderStatus {\n orderId: string\n status: string\n customer: {\n email: string\n firstName?: string\n lastName?: string\n phone?: string\n } | null\n items: Array<{\n productId: string\n productName: string\n productImage?: string\n quantity: number\n variant?: string\n price: number\n total: number\n }>\n totals: {\n subtotal: number\n shipping: number\n tax: number\n total: number\n }\n paymentStatus: string\n shippingAddress?: any\n billingAddress?: any\n createdAt: number\n updatedAt: number\n metadata: Record<string, any>\n}\n\nexport interface CartValidation {\n valid: boolean\n errors: string[]\n warnings: string[]\n estimatedTotal: number\n}\n\nexport class TorqueCheckout {\n private businessId: string\n private apiKey: string\n private baseUrl: string\n private timeout: number\n\n constructor(config: TorqueConfig) {\n this.businessId = config.businessId\n this.apiKey = config.apiKey\n this.baseUrl = config.baseUrl || 'https://torque.fi'\n this.timeout = config.timeout || 30000\n }\n\n /**\n * Generate a cart checkout URL\n */\n async generateCartCheckoutUrl(cart: CartData): Promise<string> {\n const response = await this.makeRequest('/api/checkout/generate-link', {\n method: 'POST',\n body: {\n businessId: this.businessId,\n cart: {\n items: cart.items\n },\n customerData: cart.customer,\n options: cart.options\n }\n })\n\n if (!response.success) {\n throw new Error(`Failed to generate checkout URL: ${response.error || 'Unknown error'}`)\n }\n\n return response.checkoutUrl\n }\n\n /**\n * Generate a single product checkout URL\n */\n async generateProductCheckoutUrl(productId: string, quantity: number = 1, customer?: CustomerData, options?: CartOptions): Promise<string> {\n return this.generateCartCheckoutUrl({\n items: [{ productId, quantity }],\n customer,\n options\n })\n }\n\n /**\n * Validate cart data before checkout\n */\n async validateCart(cart: CartData): Promise<CartValidation> {\n try {\n const response = await this.makeRequest('/api/checkout/validate-cart', {\n method: 'POST',\n body: {\n businessId: this.businessId,\n cart: cart.items,\n customer: cart.customer\n }\n })\n\n return response\n } catch (error) {\n return {\n valid: false,\n errors: [error instanceof Error ? error.message : 'Validation failed'],\n warnings: [],\n estimatedTotal: 0\n }\n }\n }\n\n /**\n * Get order status\n */\n async getOrderStatus(orderId: string): Promise<OrderStatus> {\n const response = await this.makeRequest(`/api/checkout/order-status/${orderId}?businessId=${this.businessId}`)\n \n if (response.error) {\n throw new Error(`Failed to get order status: ${response.error}`)\n }\n\n return response\n }\n\n /**\n * Send webhook event\n */\n async sendWebhookEvent(orderId: string, status: string, customerData?: any, metadata?: Record<string, any>): Promise<void> {\n await this.makeRequest('/api/webhooks/order-update', {\n method: 'POST',\n body: {\n orderId,\n status,\n customerData,\n metadata\n }\n })\n }\n\n /**\n * Track cart view for analytics\n */\n async trackCartView(cartId: string, cartData: CartData): Promise<void> {\n try {\n await this.makeRequest('/api/analytics/cart-view', {\n method: 'POST',\n body: {\n cartId,\n businessId: this.businessId,\n cartData,\n timestamp: Date.now()\n }\n })\n } catch (error) {\n console.warn('Failed to track cart view:', error)\n }\n }\n\n /**\n * Track checkout completion for analytics\n */\n async trackCheckoutComplete(orderId: string, checkoutData: any): Promise<void> {\n try {\n await this.makeRequest('/api/analytics/checkout-complete', {\n method: 'POST',\n body: {\n orderId,\n businessId: this.businessId,\n checkoutData,\n timestamp: Date.now()\n }\n })\n } catch (error) {\n console.warn('Failed to track checkout completion:', error)\n }\n }\n\n /**\n * Generate cart hash for caching\n */\n generateCartHash(cart: CartData): string {\n const cartString = JSON.stringify({\n items: cart.items.sort((a, b) => a.productId.localeCompare(b.productId)),\n customer: cart.customer ? { email: cart.customer.email } : null\n })\n \n // Simple hash function for cart identification\n let hash = 0\n for (let i = 0; i < cartString.length; i++) {\n const char = cartString.charCodeAt(i)\n hash = ((hash << 5) - hash) + char\n hash = hash & hash // Convert to 32-bit integer\n }\n return Math.abs(hash).toString(36)\n }\n\n /**\n * Make HTTP request to Torque API\n */\n private async makeRequest(endpoint: string, options: RequestInit = {}): Promise<any> {\n const url = `${this.baseUrl}${endpoint}`\n \n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.timeout)\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n ...options.headers\n },\n signal: controller.signal\n })\n\n clearTimeout(timeoutId)\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}))\n throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`)\n }\n\n return await response.json()\n } catch (error) {\n clearTimeout(timeoutId)\n \n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new Error('Request timeout')\n }\n throw error\n }\n \n throw new Error('Request failed')\n }\n }\n}\n\n// Export default instance factory\nexport const createTorqueCheckout = (config: TorqueConfig) => new TorqueCheckout(config)\n\n// Export types\nexport type {\n CartItem,\n CustomerData,\n CartOptions,\n CartData,\n TorqueConfig,\n CheckoutResponse,\n OrderStatus,\n CartValidation\n}\n"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,184 @@
1
+ 'use strict';
2
+
3
+ class TorqueCheckout {
4
+ constructor(config) {
5
+ this.businessId = config.businessId;
6
+ this.apiKey = config.apiKey;
7
+ this.baseUrl = config.baseUrl || 'https://torque.fi';
8
+ this.timeout = config.timeout || 30000;
9
+ }
10
+ /**
11
+ * Generate a cart checkout URL
12
+ */
13
+ async generateCartCheckoutUrl(cart) {
14
+ const response = await this.makeRequest('/api/checkout/generate-link', {
15
+ method: 'POST',
16
+ body: {
17
+ businessId: this.businessId,
18
+ cart: {
19
+ items: cart.items
20
+ },
21
+ customerData: cart.customer,
22
+ options: cart.options
23
+ }
24
+ });
25
+ if (!response.success) {
26
+ throw new Error(`Failed to generate checkout URL: ${response.error || 'Unknown error'}`);
27
+ }
28
+ return response.checkoutUrl;
29
+ }
30
+ /**
31
+ * Generate a single product checkout URL
32
+ */
33
+ async generateProductCheckoutUrl(productId, quantity = 1, customer, options) {
34
+ return this.generateCartCheckoutUrl({
35
+ items: [{ productId, quantity }],
36
+ customer,
37
+ options
38
+ });
39
+ }
40
+ /**
41
+ * Validate cart data before checkout
42
+ */
43
+ async validateCart(cart) {
44
+ try {
45
+ const response = await this.makeRequest('/api/checkout/validate-cart', {
46
+ method: 'POST',
47
+ body: {
48
+ businessId: this.businessId,
49
+ cart: cart.items,
50
+ customer: cart.customer
51
+ }
52
+ });
53
+ return response;
54
+ }
55
+ catch (error) {
56
+ return {
57
+ valid: false,
58
+ errors: [error instanceof Error ? error.message : 'Validation failed'],
59
+ warnings: [],
60
+ estimatedTotal: 0
61
+ };
62
+ }
63
+ }
64
+ /**
65
+ * Get order status
66
+ */
67
+ async getOrderStatus(orderId) {
68
+ const response = await this.makeRequest(`/api/checkout/order-status/${orderId}?businessId=${this.businessId}`);
69
+ if (response.error) {
70
+ throw new Error(`Failed to get order status: ${response.error}`);
71
+ }
72
+ return response;
73
+ }
74
+ /**
75
+ * Send webhook event
76
+ */
77
+ async sendWebhookEvent(orderId, status, customerData, metadata) {
78
+ await this.makeRequest('/api/webhooks/order-update', {
79
+ method: 'POST',
80
+ body: {
81
+ orderId,
82
+ status,
83
+ customerData,
84
+ metadata
85
+ }
86
+ });
87
+ }
88
+ /**
89
+ * Track cart view for analytics
90
+ */
91
+ async trackCartView(cartId, cartData) {
92
+ try {
93
+ await this.makeRequest('/api/analytics/cart-view', {
94
+ method: 'POST',
95
+ body: {
96
+ cartId,
97
+ businessId: this.businessId,
98
+ cartData,
99
+ timestamp: Date.now()
100
+ }
101
+ });
102
+ }
103
+ catch (error) {
104
+ console.warn('Failed to track cart view:', error);
105
+ }
106
+ }
107
+ /**
108
+ * Track checkout completion for analytics
109
+ */
110
+ async trackCheckoutComplete(orderId, checkoutData) {
111
+ try {
112
+ await this.makeRequest('/api/analytics/checkout-complete', {
113
+ method: 'POST',
114
+ body: {
115
+ orderId,
116
+ businessId: this.businessId,
117
+ checkoutData,
118
+ timestamp: Date.now()
119
+ }
120
+ });
121
+ }
122
+ catch (error) {
123
+ console.warn('Failed to track checkout completion:', error);
124
+ }
125
+ }
126
+ /**
127
+ * Generate cart hash for caching
128
+ */
129
+ generateCartHash(cart) {
130
+ const cartString = JSON.stringify({
131
+ items: cart.items.sort((a, b) => a.productId.localeCompare(b.productId)),
132
+ customer: cart.customer ? { email: cart.customer.email } : null
133
+ });
134
+ // Simple hash function for cart identification
135
+ let hash = 0;
136
+ for (let i = 0; i < cartString.length; i++) {
137
+ const char = cartString.charCodeAt(i);
138
+ hash = ((hash << 5) - hash) + char;
139
+ hash = hash & hash; // Convert to 32-bit integer
140
+ }
141
+ return Math.abs(hash).toString(36);
142
+ }
143
+ /**
144
+ * Make HTTP request to Torque API
145
+ */
146
+ async makeRequest(endpoint, options = {}) {
147
+ const url = `${this.baseUrl}${endpoint}`;
148
+ const controller = new AbortController();
149
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
150
+ try {
151
+ const response = await fetch(url, {
152
+ ...options,
153
+ headers: {
154
+ 'Content-Type': 'application/json',
155
+ 'Authorization': `Bearer ${this.apiKey}`,
156
+ ...options.headers
157
+ },
158
+ signal: controller.signal
159
+ });
160
+ clearTimeout(timeoutId);
161
+ if (!response.ok) {
162
+ const errorData = await response.json().catch(() => ({}));
163
+ throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
164
+ }
165
+ return await response.json();
166
+ }
167
+ catch (error) {
168
+ clearTimeout(timeoutId);
169
+ if (error instanceof Error) {
170
+ if (error.name === 'AbortError') {
171
+ throw new Error('Request timeout');
172
+ }
173
+ throw error;
174
+ }
175
+ throw new Error('Request failed');
176
+ }
177
+ }
178
+ }
179
+ // Export default instance factory
180
+ const createTorqueCheckout = (config) => new TorqueCheckout(config);
181
+
182
+ exports.TorqueCheckout = TorqueCheckout;
183
+ exports.createTorqueCheckout = createTorqueCheckout;
184
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["export interface CartItem {\n productId: string\n quantity: number\n variant?: string\n price?: number\n metadata?: Record<string, any>\n}\n\nexport interface CustomerData {\n email: string\n firstName?: string\n lastName?: string\n phone?: string\n shippingAddress?: {\n street: string\n city: string\n state: string\n zipCode: string\n country: string\n }\n billingAddress?: {\n street: string\n city: string\n state: string\n zipCode: string\n country: string\n }\n}\n\nexport interface CartOptions {\n domain?: string\n expiresIn?: number\n metadata?: Record<string, any>\n redirectUrl?: string\n}\n\nexport interface CartData {\n items: CartItem[]\n customer?: CustomerData\n options?: CartOptions\n}\n\nexport interface TorqueConfig {\n businessId: string\n apiKey: string\n baseUrl?: string\n timeout?: number\n}\n\nexport interface CheckoutResponse {\n success: boolean\n checkoutUrl: string\n expiresAt: string\n cartSummary: {\n itemCount: number\n productCount: number\n estimatedTotal: number\n }\n business: {\n id: string\n name: string\n logo?: string\n }\n}\n\nexport interface OrderStatus {\n orderId: string\n status: string\n customer: {\n email: string\n firstName?: string\n lastName?: string\n phone?: string\n } | null\n items: Array<{\n productId: string\n productName: string\n productImage?: string\n quantity: number\n variant?: string\n price: number\n total: number\n }>\n totals: {\n subtotal: number\n shipping: number\n tax: number\n total: number\n }\n paymentStatus: string\n shippingAddress?: any\n billingAddress?: any\n createdAt: number\n updatedAt: number\n metadata: Record<string, any>\n}\n\nexport interface CartValidation {\n valid: boolean\n errors: string[]\n warnings: string[]\n estimatedTotal: number\n}\n\nexport class TorqueCheckout {\n private businessId: string\n private apiKey: string\n private baseUrl: string\n private timeout: number\n\n constructor(config: TorqueConfig) {\n this.businessId = config.businessId\n this.apiKey = config.apiKey\n this.baseUrl = config.baseUrl || 'https://torque.fi'\n this.timeout = config.timeout || 30000\n }\n\n /**\n * Generate a cart checkout URL\n */\n async generateCartCheckoutUrl(cart: CartData): Promise<string> {\n const response = await this.makeRequest('/api/checkout/generate-link', {\n method: 'POST',\n body: {\n businessId: this.businessId,\n cart: {\n items: cart.items\n },\n customerData: cart.customer,\n options: cart.options\n }\n })\n\n if (!response.success) {\n throw new Error(`Failed to generate checkout URL: ${response.error || 'Unknown error'}`)\n }\n\n return response.checkoutUrl\n }\n\n /**\n * Generate a single product checkout URL\n */\n async generateProductCheckoutUrl(productId: string, quantity: number = 1, customer?: CustomerData, options?: CartOptions): Promise<string> {\n return this.generateCartCheckoutUrl({\n items: [{ productId, quantity }],\n customer,\n options\n })\n }\n\n /**\n * Validate cart data before checkout\n */\n async validateCart(cart: CartData): Promise<CartValidation> {\n try {\n const response = await this.makeRequest('/api/checkout/validate-cart', {\n method: 'POST',\n body: {\n businessId: this.businessId,\n cart: cart.items,\n customer: cart.customer\n }\n })\n\n return response\n } catch (error) {\n return {\n valid: false,\n errors: [error instanceof Error ? error.message : 'Validation failed'],\n warnings: [],\n estimatedTotal: 0\n }\n }\n }\n\n /**\n * Get order status\n */\n async getOrderStatus(orderId: string): Promise<OrderStatus> {\n const response = await this.makeRequest(`/api/checkout/order-status/${orderId}?businessId=${this.businessId}`)\n \n if (response.error) {\n throw new Error(`Failed to get order status: ${response.error}`)\n }\n\n return response\n }\n\n /**\n * Send webhook event\n */\n async sendWebhookEvent(orderId: string, status: string, customerData?: any, metadata?: Record<string, any>): Promise<void> {\n await this.makeRequest('/api/webhooks/order-update', {\n method: 'POST',\n body: {\n orderId,\n status,\n customerData,\n metadata\n }\n })\n }\n\n /**\n * Track cart view for analytics\n */\n async trackCartView(cartId: string, cartData: CartData): Promise<void> {\n try {\n await this.makeRequest('/api/analytics/cart-view', {\n method: 'POST',\n body: {\n cartId,\n businessId: this.businessId,\n cartData,\n timestamp: Date.now()\n }\n })\n } catch (error) {\n console.warn('Failed to track cart view:', error)\n }\n }\n\n /**\n * Track checkout completion for analytics\n */\n async trackCheckoutComplete(orderId: string, checkoutData: any): Promise<void> {\n try {\n await this.makeRequest('/api/analytics/checkout-complete', {\n method: 'POST',\n body: {\n orderId,\n businessId: this.businessId,\n checkoutData,\n timestamp: Date.now()\n }\n })\n } catch (error) {\n console.warn('Failed to track checkout completion:', error)\n }\n }\n\n /**\n * Generate cart hash for caching\n */\n generateCartHash(cart: CartData): string {\n const cartString = JSON.stringify({\n items: cart.items.sort((a, b) => a.productId.localeCompare(b.productId)),\n customer: cart.customer ? { email: cart.customer.email } : null\n })\n \n // Simple hash function for cart identification\n let hash = 0\n for (let i = 0; i < cartString.length; i++) {\n const char = cartString.charCodeAt(i)\n hash = ((hash << 5) - hash) + char\n hash = hash & hash // Convert to 32-bit integer\n }\n return Math.abs(hash).toString(36)\n }\n\n /**\n * Make HTTP request to Torque API\n */\n private async makeRequest(endpoint: string, options: RequestInit = {}): Promise<any> {\n const url = `${this.baseUrl}${endpoint}`\n \n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.timeout)\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n ...options.headers\n },\n signal: controller.signal\n })\n\n clearTimeout(timeoutId)\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}))\n throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`)\n }\n\n return await response.json()\n } catch (error) {\n clearTimeout(timeoutId)\n \n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new Error('Request timeout')\n }\n throw error\n }\n \n throw new Error('Request failed')\n }\n }\n}\n\n// Export default instance factory\nexport const createTorqueCheckout = (config: TorqueConfig) => new TorqueCheckout(config)\n\n// Export types\nexport type {\n CartItem,\n CustomerData,\n CartOptions,\n CartData,\n TorqueConfig,\n CheckoutResponse,\n OrderStatus,\n CartValidation\n}\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "torque-checkout",
3
+ "version": "1.0.0",
4
+ "description": "Official Torque checkout SDK for ecommerce integrations",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "scripts": {
14
+ "build": "rollup -c",
15
+ "dev": "rollup -c -w",
16
+ "test": "jest",
17
+ "lint": "eslint src --ext .ts",
18
+ "clean": "rimraf dist"
19
+ },
20
+ "keywords": [
21
+ "torque",
22
+ "checkout",
23
+ "ecommerce",
24
+ "payment",
25
+ "cart",
26
+ "multi-product"
27
+ ],
28
+ "author": "Torque Team <team@torque.fi>",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/camconrad/torque_webapp.git"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/camconrad/torque_webapp/issues"
36
+ },
37
+ "homepage": "https://github.com/camconrad/torque_webapp",
38
+ "devDependencies": {
39
+ "@rollup/plugin-typescript": "^12.1.4",
40
+ "@types/node": "^20.0.0",
41
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
42
+ "@typescript-eslint/parser": "^6.0.0",
43
+ "eslint": "^8.0.0",
44
+ "jest": "^29.0.0",
45
+ "rimraf": "^5.0.0",
46
+ "rollup": "^4.0.0",
47
+ "typescript": "^5.0.0"
48
+ },
49
+ "peerDependencies": {
50
+ "node": ">=16.0.0"
51
+ },
52
+ "engines": {
53
+ "node": ">=16.0.0"
54
+ }
55
+ }