torque-checkout 3.1.1 → 3.2.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/CHANGELOG.md +17 -0
- package/README.md +37 -5
- package/dist/index.d.ts +22 -0
- package/dist/index.esm.js +49 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -1
- package/dist/nextjs.d.ts +7 -2
- package/dist/nextjs.esm.js +26 -15
- package/dist/nextjs.esm.js.map +1 -1
- package/dist/nextjs.js +26 -14
- package/dist/nextjs.js.map +1 -1
- package/dist/react.d.ts +3 -1
- package/dist/react.esm.js +24 -0
- package/dist/react.esm.js.map +1 -1
- package/dist/react.js +24 -0
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * Torque Checkout SDK\n * Official SDK for integrating Torque checkout into your eCommerce applications\n *\n * **Hosted app (app.torque.fi):** Use `generateCartCheckoutUrl`, `validateCart`, catalog getters, and `getOrderStatus`.\n * Subscription lifecycle and analytics helpers call routes that may not exist on every deployment; see package README.\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// Type Definitions\n// ============================================================================\n\nexport interface CartItem {\n productId: string // Must be a valid Torque product ID (Convex ID format)\n quantity: number\n variant?: string // Optional variant ID if product has variants\n metadata?: Record<string, any> // Optional merchant metadata\n // Note: price is NOT included - prices come from Torque product database\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 PaymentPlan {\n id: string\n name: string\n price: number\n interval: \"weekly\" | \"monthly\" | \"quarterly\" | \"yearly\"\n intervalCount: number\n trialDays?: number\n maxCycles?: number\n description?: string\n}\n\nexport interface Product {\n id: string // Torque product ID (Convex ID format, e.g., \"j1234567890abcdef\")\n name: string\n description?: string\n isSubscription: boolean\n paymentPlans?: PaymentPlan[]\n subscriptionContract?: {\n address: string\n chainId: number\n abi?: string\n }\n price: number // Base price (for non-subscription) or base price (for subscription)\n currency: string\n image?: string\n images?: string[]\n requiresShipping: boolean\n shippingCost?: number\n taxRate?: number\n inventory: number // -1 for unlimited\n status: 'active' | 'inactive' | 'draft' | 'archived'\n sku?: string\n category?: string\n tags?: string[]\n variants?: Array<{\n id: string\n name: string\n price: number\n inventory?: number\n }>\n metadata?: any\n createdAt: number\n updatedAt: number\n}\n\n// Alias for backward compatibility\nexport interface SubscriptionProduct extends Product {\n basePrice: number // Alias for price\n}\n\nexport interface Subscription {\n id: string\n businessId: string\n productId: string\n customerId?: string\n customerEmail: string\n customerName: string\n paymentPlanId: string\n status: \"active\" | \"cancelled\" | \"paused\" | \"expired\" | \"past_due\"\n currentPeriodStart: number\n currentPeriodEnd: number\n nextBillingDate: number\n trialStart?: number\n trialEnd?: number\n totalCycles: number\n maxCycles?: number\n lastPaymentDate?: number\n nextPaymentAmount: number\n currency: string\n contractSubscriptionId?: string\n contractAddress?: string\n billingHistory?: Array<{\n cycleNumber: number\n amount: number\n date: number\n status: \"paid\" | \"failed\" | \"pending\"\n transactionId?: string\n }>\n metadata?: any\n createdAt: number\n updatedAt: number\n}\n\nexport interface CreateSubscriptionData {\n businessId: string\n productId: string\n customerEmail: string\n customerName: string\n paymentPlanId: string\n customerId?: string\n metadata?: any\n}\n\nexport interface UpdateSubscriptionData {\n status?: \"active\" | \"cancelled\" | \"paused\" | \"expired\" | \"past_due\"\n pauseUntil?: number\n resumeDate?: number\n metadata?: any\n}\n\nexport interface TorqueConfig {\n businessId: string\n apiKey: string\n baseUrl?: string\n timeout?: number\n}\n\nexport interface BusinessCreationData {\n name: string\n description?: string\n email: string\n phone?: string\n website?: string\n currency?: string\n timezone?: string\n walletAddress: string\n logo?: string\n}\n\nexport interface BusinessProfile {\n id: string\n name: string\n email: string\n apiKey: string\n walletAddress: string\n logo?: string\n website?: string\n status: 'active' | 'pending' | 'suspended'\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 interface TorqueError extends Error {\n code?: string\n statusCode?: number\n details?: any\n}\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\nexport class TorqueCheckoutError extends Error implements TorqueError {\n code?: string\n statusCode?: number\n details?: any\n\n constructor(message: string, code?: string, statusCode?: number, details?: any) {\n super(message)\n this.name = 'TorqueCheckoutError'\n this.code = code\n this.statusCode = statusCode\n this.details = details\n Object.setPrototypeOf(this, TorqueCheckoutError.prototype)\n }\n}\n\n// ============================================================================\n// Validation Utilities\n// ============================================================================\n\n/**\n * Validates a Convex ID format (e.g., \"j1234567890abcdef\")\n * Convex IDs are alphanumeric strings starting with a letter\n */\nfunction isValidConvexId(id: string): boolean {\n return /^[a-z][a-z0-9]{15,}$/i.test(id)\n}\n\nexport function validateCartItem(item: CartItem): string[] {\n const errors: string[] = []\n \n if (!item.productId || typeof item.productId !== 'string' || item.productId.trim() === '') {\n errors.push('Product ID is required and must be a non-empty string')\n } else if (!isValidConvexId(item.productId)) {\n errors.push('Product ID must be a valid Torque product ID. Products must be uploaded to Torque first at /business/products')\n }\n \n if (typeof item.quantity !== 'number' || item.quantity <= 0 || !Number.isInteger(item.quantity)) {\n errors.push('Quantity must be a positive integer')\n }\n \n // Price validation removed - prices come from Torque product database\n // Prices are fetched from Torque when generating checkout URL\n \n return errors\n}\n\nexport function validateCartData(cart: CartData): string[] {\n const errors: string[] = []\n \n if (!cart.items || !Array.isArray(cart.items) || cart.items.length === 0) {\n errors.push('Cart must contain at least one item')\n return errors\n }\n \n cart.items.forEach((item, index) => {\n const itemErrors = validateCartItem(item)\n itemErrors.forEach(error => errors.push(`Item ${index + 1}: ${error}`))\n })\n \n if (cart.customer?.email && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(cart.customer.email)) {\n errors.push('Customer email must be a valid email address')\n }\n \n return errors\n}\n\nexport function validateConfig(config: TorqueConfig): string[] {\n const errors: string[] = []\n \n if (!config.businessId || typeof config.businessId !== 'string' || config.businessId.trim() === '') {\n errors.push('Business ID is required')\n }\n \n if (!config.apiKey || typeof config.apiKey !== 'string' || config.apiKey.trim() === '') {\n errors.push('API key is required')\n }\n \n if (config.timeout !== undefined && (typeof config.timeout !== 'number' || config.timeout <= 0)) {\n errors.push('Timeout must be a positive number')\n }\n \n return errors\n}\n\n// ============================================================================\n// Main SDK Class\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 const configErrors = validateConfig(config)\n if (configErrors.length > 0) {\n throw new TorqueCheckoutError(\n `Invalid configuration: ${configErrors.join(', ')}`,\n 'INVALID_CONFIG',\n 400,\n { errors: configErrors }\n )\n }\n\n this.businessId = config.businessId.trim()\n this.apiKey = config.apiKey.trim()\n this.baseUrl = (config.baseUrl || 'https://app.torque.fi').replace(/\\/$/, '')\n this.timeout = config.timeout || 30000\n }\n\n /**\n * Generate a cart checkout URL\n * @param cart - Cart data containing items, customer info, and options\n * @returns Promise resolving to checkout URL\n * @throws {TorqueCheckoutError} If cart validation fails or API request fails\n */\n async generateCartCheckoutUrl(cart: CartData): Promise<string> {\n const validationErrors = validateCartData(cart)\n if (validationErrors.length > 0) {\n throw new TorqueCheckoutError(\n `Cart validation failed: ${validationErrors.join(', ')}`,\n 'VALIDATION_ERROR',\n 400,\n { errors: validationErrors }\n )\n }\n\n try {\n const response = await this.makeRequest('/api/torque-checkout', {\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 TorqueCheckoutError(\n response.message || 'Failed to generate checkout URL',\n response.error || 'CHECKOUT_GENERATION_FAILED',\n response.statusCode || 500,\n response.details\n )\n }\n\n return response.checkoutUrl\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to generate checkout URL',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Generate a single product checkout URL\n * @param productId - Product ID\n * @param quantity - Quantity (default: 1)\n * @param customer - Optional customer data\n * @param options - Optional cart options\n * @returns Promise resolving to checkout URL\n */\n async generateProductCheckoutUrl(\n productId: string,\n quantity: number = 1,\n customer?: CustomerData,\n options?: CartOptions\n ): Promise<string> {\n return this.generateCartCheckoutUrl({\n items: [{ productId, quantity }],\n customer,\n options\n })\n }\n\n /**\n * Generate a subscription checkout URL\n * @param productId - Subscription product ID\n * @param paymentPlanId - Payment plan ID\n * @param customer - Optional customer data\n * @param options - Optional cart options\n * @returns Promise resolving to checkout URL\n */\n async generateSubscriptionCheckoutUrl(\n productId: string,\n paymentPlanId: string,\n customer?: CustomerData,\n options?: CartOptions\n ): Promise<string> {\n return this.generateCartCheckoutUrl({\n items: [{ \n productId, \n quantity: 1,\n metadata: { \n isSubscription: true, \n paymentPlanId \n }\n }],\n customer,\n options\n })\n }\n\n /**\n * Validate cart data before checkout\n * @param cart - Cart data to validate\n * @returns Promise resolving to validation result\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 const validationErrors = validateCartData(cart)\n return {\n valid: false,\n errors: error instanceof Error \n ? [error.message, ...validationErrors]\n : ['Validation failed', ...validationErrors],\n warnings: [],\n estimatedTotal: 0\n }\n }\n }\n\n /**\n * Get order status\n * @param orderId - Order ID\n * @returns Promise resolving to order status\n * @throws {TorqueCheckoutError} If order not found or API request fails\n */\n async getOrderStatus(orderId: string): Promise<OrderStatus> {\n if (!orderId || typeof orderId !== 'string') {\n throw new TorqueCheckoutError('Order ID is required', 'INVALID_ORDER_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/checkout/order-status/${orderId}?businessId=${this.businessId}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get order status',\n response.error || 'ORDER_NOT_FOUND',\n response.statusCode || 404\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get order status',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Create a new subscription\n * @param data - Subscription creation data\n * @returns Promise resolving to created subscription\n */\n async createSubscription(data: CreateSubscriptionData): Promise<Subscription> {\n try {\n const response = await this.makeRequest('/api/subscriptions/create', {\n method: 'POST',\n body: data\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to create subscription',\n response.error || 'SUBSCRIPTION_CREATION_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to create subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get subscription by ID\n * @param subscriptionId - Subscription ID\n * @returns Promise resolving to subscription\n */\n async getSubscription(subscriptionId: string): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get subscription',\n response.error || 'SUBSCRIPTION_NOT_FOUND',\n response.statusCode || 404\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get subscriptions for a business\n * @param businessId - Business ID (optional, uses instance businessId if not provided)\n * @param status - Optional status filter\n * @param limit - Optional limit\n * @returns Promise resolving to array of subscriptions\n */\n async getBusinessSubscriptions(businessId?: string, status?: string, limit?: number): Promise<Subscription[]> {\n const bid = businessId || this.businessId\n const params = new URLSearchParams({ businessId: bid })\n if (status) params.append('status', status)\n if (limit) params.append('limit', limit.toString())\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/business?${params}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get business subscriptions',\n response.error || 'FETCH_FAILED',\n response.statusCode || 500\n )\n }\n\n return Array.isArray(response) ? response : []\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get business subscriptions',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get subscriptions for a customer\n * @param customerEmail - Customer email\n * @returns Promise resolving to array of subscriptions\n */\n async getCustomerSubscriptions(customerEmail: string): Promise<Subscription[]> {\n if (!customerEmail || typeof customerEmail !== 'string' || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(customerEmail)) {\n throw new TorqueCheckoutError('Valid customer email is required', 'INVALID_EMAIL', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/customer/${encodeURIComponent(customerEmail)}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get customer subscriptions',\n response.error || 'FETCH_FAILED',\n response.statusCode || 500\n )\n }\n\n return Array.isArray(response) ? response : []\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get customer subscriptions',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Update subscription status\n * @param subscriptionId - Subscription ID\n * @param data - Update data\n * @returns Promise resolving to updated subscription\n */\n async updateSubscription(subscriptionId: string, data: UpdateSubscriptionData): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}/update`, {\n method: 'PUT',\n body: data\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to update subscription',\n response.error || 'UPDATE_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to update subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Cancel subscription\n * @param subscriptionId - Subscription ID\n * @param effectiveDate - Optional effective date for cancellation\n * @returns Promise resolving to cancelled subscription\n */\n async cancelSubscription(subscriptionId: string, effectiveDate?: number): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}/cancel`, {\n method: 'PUT',\n body: { effectiveDate }\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to cancel subscription',\n response.error || 'CANCEL_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to cancel subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Pause subscription\n * @param subscriptionId - Subscription ID\n * @param resumeDate - Optional resume date\n * @returns Promise resolving to paused subscription\n */\n async pauseSubscription(subscriptionId: string, resumeDate?: number): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}/pause`, {\n method: 'PUT',\n body: { resumeDate }\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to pause subscription',\n response.error || 'PAUSE_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to pause subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Resume subscription\n * @param subscriptionId - Subscription ID\n * @returns Promise resolving to resumed subscription\n */\n async resumeSubscription(subscriptionId: string): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}/resume`, {\n method: 'PUT'\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to resume subscription',\n response.error || 'RESUME_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to resume subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Process subscription renewal\n * @param subscriptionId - Subscription ID\n * @returns Promise resolving to renewed subscription\n */\n async processSubscriptionRenewal(subscriptionId: string): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}/renew`, {\n method: 'PUT'\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to process subscription renewal',\n response.error || 'RENEWAL_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to process subscription renewal',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get subscriptions due for renewal\n * @param daysAhead - Number of days ahead to check (default: 7)\n * @returns Promise resolving to array of subscriptions\n */\n async getSubscriptionsDueForRenewal(daysAhead: number = 7): Promise<Subscription[]> {\n if (typeof daysAhead !== 'number' || daysAhead < 0) {\n throw new TorqueCheckoutError('Days ahead must be a non-negative number', 'INVALID_PARAMETER', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/due-for-renewal?daysAhead=${daysAhead}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get subscriptions due for renewal',\n response.error || 'FETCH_FAILED',\n response.statusCode || 500\n )\n }\n\n return Array.isArray(response) ? response : []\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get subscriptions due for renewal',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get all products for a business\n * Use this to sync your ecommerce catalog with Torque products\n * @param businessId - Business ID (optional, uses instance businessId if not provided)\n * @param status - Optional status filter ('active', 'inactive', 'draft', 'archived')\n * @returns Promise resolving to array of products\n * \n * @example\n * ```ts\n * const products = await torque.getProducts()\n * // Sync products with your database\n * products.forEach(product => {\n * await db.products.update({\n * where: { sku: product.sku },\n * data: { torqueProductId: product.id }\n * })\n * })\n * ```\n */\n async getProducts(businessId?: string, status?: 'active' | 'inactive' | 'draft' | 'archived'): Promise<Product[]> {\n const bid = businessId || this.businessId\n const params = new URLSearchParams({ businessId: bid })\n if (status) params.append('status', status)\n\n try {\n const response = await this.makeRequest(`/api/products?${params}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get products',\n response.error || 'FETCH_FAILED',\n response.statusCode || 500\n )\n }\n\n return Array.isArray(response) ? response : []\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get products',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get subscription products for a business\n * @param businessId - Business ID (optional, uses instance businessId if not provided)\n * @returns Promise resolving to array of subscription products\n */\n async getSubscriptionProducts(businessId?: string): Promise<SubscriptionProduct[]> {\n const bid = businessId || this.businessId\n\n try {\n const response = await this.makeRequest(`/api/products/subscriptions?businessId=${bid}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get subscription products',\n response.error || 'FETCH_FAILED',\n response.statusCode || 500\n )\n }\n\n const products = Array.isArray(response) ? response : []\n // Map to SubscriptionProduct format with basePrice alias\n return products.map(p => ({\n ...p,\n basePrice: p.price || p.basePrice || 0\n }))\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get subscription products',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get a single product by ID\n * @param productId - Product ID (Torque product ID)\n * @returns Promise resolving to product\n */\n async getProduct(productId: string): Promise<Product> {\n if (!productId || typeof productId !== 'string') {\n throw new TorqueCheckoutError('Product ID is required', 'INVALID_PRODUCT_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/products/${productId}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get product',\n response.error || 'PRODUCT_NOT_FOUND',\n response.statusCode || 404\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get product',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get product with payment plans\n * @param productId - Product ID\n * @returns Promise resolving to product with payment plans\n */\n async getProductWithPaymentPlans(productId: string): Promise<SubscriptionProduct> {\n if (!productId || typeof productId !== 'string') {\n throw new TorqueCheckoutError('Product ID is required', 'INVALID_PRODUCT_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/products/${productId}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get product',\n response.error || 'PRODUCT_NOT_FOUND',\n response.statusCode || 404\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get product',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Send webhook event\n * @param orderId - Order ID\n * @param status - Order status\n * @param customerData - Optional customer data\n * @param metadata - Optional metadata\n */\n async sendWebhookEvent(\n orderId: string,\n status: string,\n customerData?: any,\n metadata?: Record<string, any>\n ): Promise<void> {\n if (!orderId || typeof orderId !== 'string') {\n throw new TorqueCheckoutError('Order ID is required', 'INVALID_ORDER_ID', 400)\n }\n\n try {\n await this.makeRequest('/api/webhooks/order-update', {\n method: 'POST',\n body: {\n orderId,\n status,\n customerData,\n metadata\n }\n })\n } catch (error) {\n // Webhook events are non-critical, log but don't throw\n console.warn('Failed to send webhook event:', error)\n }\n }\n\n /**\n * Track cart view for analytics\n * @param cartId - Cart ID\n * @param cartData - Cart data\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 // Analytics tracking is non-critical, log but don't throw\n console.warn('Failed to track cart view:', error)\n }\n }\n\n /**\n * Track checkout completion for analytics\n * @param orderId - Order ID\n * @param checkoutData - Checkout data\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 // Analytics tracking is non-critical, log but don't throw\n console.warn('Failed to track checkout completion:', error)\n }\n }\n\n /**\n * Track subscription creation for analytics\n * @param subscriptionId - Subscription ID\n * @param subscriptionData - Subscription data\n */\n async trackSubscriptionCreated(subscriptionId: string, subscriptionData: any): Promise<void> {\n try {\n await this.makeRequest('/api/analytics/subscription-created', {\n method: 'POST',\n body: {\n subscriptionId,\n businessId: this.businessId,\n subscriptionData,\n timestamp: Date.now()\n }\n })\n } catch (error) {\n // Analytics tracking is non-critical, log but don't throw\n console.warn('Failed to track subscription creation:', error)\n }\n }\n\n /**\n * Generate cart hash for caching\n * @param cart - Cart data\n * @returns Cart hash string\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 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 * Generate subscription hash for caching\n * @param subscriptionData - Subscription data\n * @returns Subscription hash string\n */\n generateSubscriptionHash(subscriptionData: CreateSubscriptionData): string {\n const subscriptionString = JSON.stringify({\n businessId: subscriptionData.businessId,\n productId: subscriptionData.productId,\n customerEmail: subscriptionData.customerEmail,\n paymentPlanId: subscriptionData.paymentPlanId\n })\n \n let hash = 0\n for (let i = 0; i < subscriptionString.length; i++) {\n const char = subscriptionString.charCodeAt(i)\n hash = ((hash << 5) - hash) + char\n hash = hash & hash\n }\n return Math.abs(hash).toString(36)\n }\n\n /**\n * Make HTTP request to Torque API\n * @private\n */\n private async makeRequest(\n endpoint: string,\n options: { method?: string; body?: any; headers?: Record<string, string> } = {}\n ): 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 { body, ...fetchOptions } = options\n const response = await fetch(url, {\n ...fetchOptions,\n method: options.method || 'GET',\n body: body ? JSON.stringify(body) : undefined,\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 const responseData = await response.json().catch(() => ({}))\n\n if (!response.ok) {\n throw new TorqueCheckoutError(\n responseData.message || `HTTP ${response.status}: ${response.statusText}`,\n responseData.error || 'API_ERROR',\n response.status,\n responseData.details\n )\n }\n\n return responseData\n } catch (error) {\n clearTimeout(timeoutId)\n \n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new TorqueCheckoutError('Request timeout', 'TIMEOUT', 408)\n }\n throw new TorqueCheckoutError(error.message, 'NETWORK_ERROR', 500)\n }\n \n throw new TorqueCheckoutError('Request failed', 'UNKNOWN_ERROR', 500)\n }\n }\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a new TorqueCheckout instance\n * @param config - Configuration object\n * @returns TorqueCheckout instance\n */\nexport function createTorqueCheckout(config: TorqueConfig): TorqueCheckout {\n return new TorqueCheckout(config)\n}\n\n/**\n * Create a TorqueCheckout instance from environment variables\n * Requires TORQUE_BUSINESS_ID and TORQUE_API_KEY environment variables\n * @param overrides - Optional configuration overrides\n * @returns TorqueCheckout instance\n */\nexport function createTorqueCheckoutFromEnv(overrides?: Partial<TorqueConfig>): TorqueCheckout {\n const businessId = process.env.TORQUE_BUSINESS_ID || overrides?.businessId\n const apiKey = process.env.TORQUE_API_KEY || overrides?.apiKey\n\n if (!businessId || !apiKey) {\n throw new TorqueCheckoutError(\n 'TORQUE_BUSINESS_ID and TORQUE_API_KEY environment variables are required',\n 'MISSING_ENV_VARS',\n 400\n )\n }\n\n return new TorqueCheckout({\n businessId,\n apiKey,\n baseUrl: process.env.TORQUE_BASE_URL || overrides?.baseUrl,\n timeout: overrides?.timeout\n })\n}\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\n// Types are already exported above as interfaces/types\n// This section is for re-exporting if needed for convenience\n// All types are available via named exports from the main module\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * Torque Checkout SDK\n * Official SDK for integrating Torque checkout into your eCommerce applications\n *\n * **Hosted app (app.torque.fi):** Use `generateCartCheckoutUrl`, `validateCart`, catalog getters, and `getOrderStatus`.\n * Subscription lifecycle and analytics helpers call routes that may not exist on every deployment; see package README.\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// Type Definitions\n// ============================================================================\n\nexport interface CartItem {\n productId: string // Must be a valid Torque product ID (Convex ID format)\n quantity: number\n variant?: string // Optional variant ID if product has variants\n metadata?: Record<string, any> // Optional merchant metadata\n // Note: price is NOT included - prices come from Torque product database\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 /** @deprecated Prefer successUrl — passed through to hosted checkout cart payload */\n redirectUrl?: string\n /**\n * After a successful payment on the hosted checkout, the confirmation modal can show\n * “Return to store” (cart flows). Same idea as Suby’s `successUrl` redirect after pay.\n */\n successUrl?: string\n /** Shown if the buyer abandons before paying (optional future use / analytics). */\n cancelUrl?: string\n /** Your order reference — stored on the cart session for reconciliation & webhooks. */\n externalRef?: string\n}\n\nexport interface CartData {\n items: CartItem[]\n customer?: CustomerData\n options?: CartOptions\n}\n\nexport interface PaymentPlan {\n id: string\n name: string\n price: number\n interval: \"weekly\" | \"monthly\" | \"quarterly\" | \"yearly\"\n intervalCount: number\n trialDays?: number\n maxCycles?: number\n description?: string\n}\n\nexport interface Product {\n id: string // Torque product ID (Convex ID format, e.g., \"j1234567890abcdef\")\n name: string\n description?: string\n isSubscription: boolean\n paymentPlans?: PaymentPlan[]\n subscriptionContract?: {\n address: string\n chainId: number\n abi?: string\n }\n price: number // Base price (for non-subscription) or base price (for subscription)\n currency: string\n image?: string\n images?: string[]\n requiresShipping: boolean\n shippingCost?: number\n taxRate?: number\n inventory: number // -1 for unlimited\n status: 'active' | 'inactive' | 'draft' | 'archived'\n sku?: string\n category?: string\n tags?: string[]\n variants?: Array<{\n id: string\n name: string\n price: number\n inventory?: number\n }>\n metadata?: any\n createdAt: number\n updatedAt: number\n}\n\n// Alias for backward compatibility\nexport interface SubscriptionProduct extends Product {\n basePrice: number // Alias for price\n}\n\nexport interface Subscription {\n id: string\n businessId: string\n productId: string\n customerId?: string\n customerEmail: string\n customerName: string\n paymentPlanId: string\n status: \"active\" | \"cancelled\" | \"paused\" | \"expired\" | \"past_due\"\n currentPeriodStart: number\n currentPeriodEnd: number\n nextBillingDate: number\n trialStart?: number\n trialEnd?: number\n totalCycles: number\n maxCycles?: number\n lastPaymentDate?: number\n nextPaymentAmount: number\n currency: string\n contractSubscriptionId?: string\n contractAddress?: string\n billingHistory?: Array<{\n cycleNumber: number\n amount: number\n date: number\n status: \"paid\" | \"failed\" | \"pending\"\n transactionId?: string\n }>\n metadata?: any\n createdAt: number\n updatedAt: number\n}\n\nexport interface CreateSubscriptionData {\n businessId: string\n productId: string\n customerEmail: string\n customerName: string\n paymentPlanId: string\n customerId?: string\n metadata?: any\n}\n\nexport interface UpdateSubscriptionData {\n status?: \"active\" | \"cancelled\" | \"paused\" | \"expired\" | \"past_due\"\n pauseUntil?: number\n resumeDate?: number\n metadata?: any\n}\n\nexport interface TorqueConfig {\n businessId: string\n apiKey: string\n baseUrl?: string\n timeout?: number\n}\n\nexport interface BusinessCreationData {\n name: string\n description?: string\n email: string\n phone?: string\n website?: string\n currency?: string\n timezone?: string\n walletAddress: string\n logo?: string\n}\n\nexport interface BusinessProfile {\n id: string\n name: string\n email: string\n apiKey: string\n walletAddress: string\n logo?: string\n website?: string\n status: 'active' | 'pending' | 'suspended'\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\n/** Full API response from `POST /api/torque-checkout` (Suby-style session object). */\nexport type CheckoutSession = CheckoutResponse\n\n/**\n * Redirect the browser to a Torque-hosted checkout URL.\n * Prefer `same_tab` for a single continuous flow (matches common hosted-checkout UX).\n */\nexport function redirectToCheckout(\n checkoutUrl: string,\n mode: 'same_tab' | 'new_tab' = 'same_tab'\n): void {\n if (typeof window === 'undefined') {\n throw new TorqueCheckoutError(\n 'redirectToCheckout is browser-only',\n 'SSR_NOT_SUPPORTED',\n 400\n )\n }\n if (mode === 'new_tab') {\n window.open(checkoutUrl, '_blank', 'noopener,noreferrer')\n } else {\n window.location.assign(checkoutUrl)\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 interface TorqueError extends Error {\n code?: string\n statusCode?: number\n details?: any\n}\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\nexport class TorqueCheckoutError extends Error implements TorqueError {\n code?: string\n statusCode?: number\n details?: any\n\n constructor(message: string, code?: string, statusCode?: number, details?: any) {\n super(message)\n this.name = 'TorqueCheckoutError'\n this.code = code\n this.statusCode = statusCode\n this.details = details\n Object.setPrototypeOf(this, TorqueCheckoutError.prototype)\n }\n}\n\n// ============================================================================\n// Validation Utilities\n// ============================================================================\n\n/**\n * Validates a Convex ID format (e.g., \"j1234567890abcdef\")\n * Convex IDs are alphanumeric strings starting with a letter\n */\nfunction isValidConvexId(id: string): boolean {\n return /^[a-z][a-z0-9]{15,}$/i.test(id)\n}\n\nexport function validateCartItem(item: CartItem): string[] {\n const errors: string[] = []\n \n if (!item.productId || typeof item.productId !== 'string' || item.productId.trim() === '') {\n errors.push('Product ID is required and must be a non-empty string')\n } else if (!isValidConvexId(item.productId)) {\n errors.push('Product ID must be a valid Torque product ID. Products must be uploaded to Torque first at /business/products')\n }\n \n if (typeof item.quantity !== 'number' || item.quantity <= 0 || !Number.isInteger(item.quantity)) {\n errors.push('Quantity must be a positive integer')\n }\n \n // Price validation removed - prices come from Torque product database\n // Prices are fetched from Torque when generating checkout URL\n \n return errors\n}\n\nexport function validateCartData(cart: CartData): string[] {\n const errors: string[] = []\n \n if (!cart.items || !Array.isArray(cart.items) || cart.items.length === 0) {\n errors.push('Cart must contain at least one item')\n return errors\n }\n \n cart.items.forEach((item, index) => {\n const itemErrors = validateCartItem(item)\n itemErrors.forEach(error => errors.push(`Item ${index + 1}: ${error}`))\n })\n \n if (cart.customer?.email && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(cart.customer.email)) {\n errors.push('Customer email must be a valid email address')\n }\n \n return errors\n}\n\nexport function validateConfig(config: TorqueConfig): string[] {\n const errors: string[] = []\n \n if (!config.businessId || typeof config.businessId !== 'string' || config.businessId.trim() === '') {\n errors.push('Business ID is required')\n }\n \n if (!config.apiKey || typeof config.apiKey !== 'string' || config.apiKey.trim() === '') {\n errors.push('API key is required')\n }\n \n if (config.timeout !== undefined && (typeof config.timeout !== 'number' || config.timeout <= 0)) {\n errors.push('Timeout must be a positive number')\n }\n \n return errors\n}\n\n// ============================================================================\n// Main SDK Class\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 const configErrors = validateConfig(config)\n if (configErrors.length > 0) {\n throw new TorqueCheckoutError(\n `Invalid configuration: ${configErrors.join(', ')}`,\n 'INVALID_CONFIG',\n 400,\n { errors: configErrors }\n )\n }\n\n this.businessId = config.businessId.trim()\n this.apiKey = config.apiKey.trim()\n this.baseUrl = (config.baseUrl || 'https://app.torque.fi').replace(/\\/$/, '')\n this.timeout = config.timeout || 30000\n }\n\n /**\n * Generate a cart checkout URL\n * @param cart - Cart data containing items, customer info, and options\n * @returns Promise resolving to checkout URL\n * @throws {TorqueCheckoutError} If cart validation fails or API request fails\n */\n async generateCartCheckoutUrl(cart: CartData): Promise<string> {\n const validationErrors = validateCartData(cart)\n if (validationErrors.length > 0) {\n throw new TorqueCheckoutError(\n `Cart validation failed: ${validationErrors.join(', ')}`,\n 'VALIDATION_ERROR',\n 400,\n { errors: validationErrors }\n )\n }\n\n try {\n const response = await this.makeRequest('/api/torque-checkout', {\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 TorqueCheckoutError(\n response.message || 'Failed to generate checkout URL',\n response.error || 'CHECKOUT_GENERATION_FAILED',\n response.statusCode || 500,\n response.details\n )\n }\n\n return response.checkoutUrl\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to generate checkout URL',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Create a checkout session and return the full API payload (Suby-style: URL + expiry + summary).\n * Use this when you need `cartSummary`, `expiresAt`, or to pass `successUrl` / `externalRef` via `cart.options`.\n */\n async requestCheckoutSession(cart: CartData): Promise<CheckoutSession> {\n const validationErrors = validateCartData(cart)\n if (validationErrors.length > 0) {\n throw new TorqueCheckoutError(\n `Cart validation failed: ${validationErrors.join(', ')}`,\n 'VALIDATION_ERROR',\n 400,\n { errors: validationErrors }\n )\n }\n\n try {\n const response = await this.makeRequest('/api/torque-checkout', {\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 || !response.checkoutUrl) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to create checkout session',\n response.error || 'CHECKOUT_GENERATION_FAILED',\n response.statusCode || 500,\n response.details\n )\n }\n\n return response as CheckoutSession\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to create checkout session',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Generate a single product checkout URL\n * @param productId - Product ID\n * @param quantity - Quantity (default: 1)\n * @param customer - Optional customer data\n * @param options - Optional cart options\n * @returns Promise resolving to checkout URL\n */\n async generateProductCheckoutUrl(\n productId: string,\n quantity: number = 1,\n customer?: CustomerData,\n options?: CartOptions\n ): Promise<string> {\n return this.generateCartCheckoutUrl({\n items: [{ productId, quantity }],\n customer,\n options\n })\n }\n\n /**\n * Generate a subscription checkout URL\n * @param productId - Subscription product ID\n * @param paymentPlanId - Payment plan ID\n * @param customer - Optional customer data\n * @param options - Optional cart options\n * @returns Promise resolving to checkout URL\n */\n async generateSubscriptionCheckoutUrl(\n productId: string,\n paymentPlanId: string,\n customer?: CustomerData,\n options?: CartOptions\n ): Promise<string> {\n return this.generateCartCheckoutUrl({\n items: [{ \n productId, \n quantity: 1,\n metadata: { \n isSubscription: true, \n paymentPlanId \n }\n }],\n customer,\n options\n })\n }\n\n /**\n * Validate cart data before checkout\n * @param cart - Cart data to validate\n * @returns Promise resolving to validation result\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 const validationErrors = validateCartData(cart)\n return {\n valid: false,\n errors: error instanceof Error \n ? [error.message, ...validationErrors]\n : ['Validation failed', ...validationErrors],\n warnings: [],\n estimatedTotal: 0\n }\n }\n }\n\n /**\n * Get order status\n * @param orderId - Order ID\n * @returns Promise resolving to order status\n * @throws {TorqueCheckoutError} If order not found or API request fails\n */\n async getOrderStatus(orderId: string): Promise<OrderStatus> {\n if (!orderId || typeof orderId !== 'string') {\n throw new TorqueCheckoutError('Order ID is required', 'INVALID_ORDER_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/checkout/order-status/${orderId}?businessId=${this.businessId}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get order status',\n response.error || 'ORDER_NOT_FOUND',\n response.statusCode || 404\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get order status',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Create a new subscription\n * @param data - Subscription creation data\n * @returns Promise resolving to created subscription\n */\n async createSubscription(data: CreateSubscriptionData): Promise<Subscription> {\n try {\n const response = await this.makeRequest('/api/subscriptions/create', {\n method: 'POST',\n body: data\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to create subscription',\n response.error || 'SUBSCRIPTION_CREATION_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to create subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get subscription by ID\n * @param subscriptionId - Subscription ID\n * @returns Promise resolving to subscription\n */\n async getSubscription(subscriptionId: string): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get subscription',\n response.error || 'SUBSCRIPTION_NOT_FOUND',\n response.statusCode || 404\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get subscriptions for a business\n * @param businessId - Business ID (optional, uses instance businessId if not provided)\n * @param status - Optional status filter\n * @param limit - Optional limit\n * @returns Promise resolving to array of subscriptions\n */\n async getBusinessSubscriptions(businessId?: string, status?: string, limit?: number): Promise<Subscription[]> {\n const bid = businessId || this.businessId\n const params = new URLSearchParams({ businessId: bid })\n if (status) params.append('status', status)\n if (limit) params.append('limit', limit.toString())\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/business?${params}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get business subscriptions',\n response.error || 'FETCH_FAILED',\n response.statusCode || 500\n )\n }\n\n return Array.isArray(response) ? response : []\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get business subscriptions',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get subscriptions for a customer\n * @param customerEmail - Customer email\n * @returns Promise resolving to array of subscriptions\n */\n async getCustomerSubscriptions(customerEmail: string): Promise<Subscription[]> {\n if (!customerEmail || typeof customerEmail !== 'string' || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(customerEmail)) {\n throw new TorqueCheckoutError('Valid customer email is required', 'INVALID_EMAIL', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/customer/${encodeURIComponent(customerEmail)}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get customer subscriptions',\n response.error || 'FETCH_FAILED',\n response.statusCode || 500\n )\n }\n\n return Array.isArray(response) ? response : []\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get customer subscriptions',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Update subscription status\n * @param subscriptionId - Subscription ID\n * @param data - Update data\n * @returns Promise resolving to updated subscription\n */\n async updateSubscription(subscriptionId: string, data: UpdateSubscriptionData): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}/update`, {\n method: 'PUT',\n body: data\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to update subscription',\n response.error || 'UPDATE_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to update subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Cancel subscription\n * @param subscriptionId - Subscription ID\n * @param effectiveDate - Optional effective date for cancellation\n * @returns Promise resolving to cancelled subscription\n */\n async cancelSubscription(subscriptionId: string, effectiveDate?: number): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}/cancel`, {\n method: 'PUT',\n body: { effectiveDate }\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to cancel subscription',\n response.error || 'CANCEL_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to cancel subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Pause subscription\n * @param subscriptionId - Subscription ID\n * @param resumeDate - Optional resume date\n * @returns Promise resolving to paused subscription\n */\n async pauseSubscription(subscriptionId: string, resumeDate?: number): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}/pause`, {\n method: 'PUT',\n body: { resumeDate }\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to pause subscription',\n response.error || 'PAUSE_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to pause subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Resume subscription\n * @param subscriptionId - Subscription ID\n * @returns Promise resolving to resumed subscription\n */\n async resumeSubscription(subscriptionId: string): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}/resume`, {\n method: 'PUT'\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to resume subscription',\n response.error || 'RESUME_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to resume subscription',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Process subscription renewal\n * @param subscriptionId - Subscription ID\n * @returns Promise resolving to renewed subscription\n */\n async processSubscriptionRenewal(subscriptionId: string): Promise<Subscription> {\n if (!subscriptionId || typeof subscriptionId !== 'string') {\n throw new TorqueCheckoutError('Subscription ID is required', 'INVALID_SUBSCRIPTION_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/${subscriptionId}/renew`, {\n method: 'PUT'\n })\n\n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to process subscription renewal',\n response.error || 'RENEWAL_FAILED',\n response.statusCode || 500\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to process subscription renewal',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get subscriptions due for renewal\n * @param daysAhead - Number of days ahead to check (default: 7)\n * @returns Promise resolving to array of subscriptions\n */\n async getSubscriptionsDueForRenewal(daysAhead: number = 7): Promise<Subscription[]> {\n if (typeof daysAhead !== 'number' || daysAhead < 0) {\n throw new TorqueCheckoutError('Days ahead must be a non-negative number', 'INVALID_PARAMETER', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/subscriptions/due-for-renewal?daysAhead=${daysAhead}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get subscriptions due for renewal',\n response.error || 'FETCH_FAILED',\n response.statusCode || 500\n )\n }\n\n return Array.isArray(response) ? response : []\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get subscriptions due for renewal',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get all products for a business\n * Use this to sync your ecommerce catalog with Torque products\n * @param businessId - Business ID (optional, uses instance businessId if not provided)\n * @param status - Optional status filter ('active', 'inactive', 'draft', 'archived')\n * @returns Promise resolving to array of products\n * \n * @example\n * ```ts\n * const products = await torque.getProducts()\n * // Sync products with your database\n * products.forEach(product => {\n * await db.products.update({\n * where: { sku: product.sku },\n * data: { torqueProductId: product.id }\n * })\n * })\n * ```\n */\n async getProducts(businessId?: string, status?: 'active' | 'inactive' | 'draft' | 'archived'): Promise<Product[]> {\n const bid = businessId || this.businessId\n const params = new URLSearchParams({ businessId: bid })\n if (status) params.append('status', status)\n\n try {\n const response = await this.makeRequest(`/api/products?${params}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get products',\n response.error || 'FETCH_FAILED',\n response.statusCode || 500\n )\n }\n\n return Array.isArray(response) ? response : []\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get products',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get subscription products for a business\n * @param businessId - Business ID (optional, uses instance businessId if not provided)\n * @returns Promise resolving to array of subscription products\n */\n async getSubscriptionProducts(businessId?: string): Promise<SubscriptionProduct[]> {\n const bid = businessId || this.businessId\n\n try {\n const response = await this.makeRequest(`/api/products/subscriptions?businessId=${bid}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get subscription products',\n response.error || 'FETCH_FAILED',\n response.statusCode || 500\n )\n }\n\n const products = Array.isArray(response) ? response : []\n // Map to SubscriptionProduct format with basePrice alias\n return products.map(p => ({\n ...p,\n basePrice: p.price || p.basePrice || 0\n }))\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get subscription products',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get a single product by ID\n * @param productId - Product ID (Torque product ID)\n * @returns Promise resolving to product\n */\n async getProduct(productId: string): Promise<Product> {\n if (!productId || typeof productId !== 'string') {\n throw new TorqueCheckoutError('Product ID is required', 'INVALID_PRODUCT_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/products/${productId}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get product',\n response.error || 'PRODUCT_NOT_FOUND',\n response.statusCode || 404\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get product',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Get product with payment plans\n * @param productId - Product ID\n * @returns Promise resolving to product with payment plans\n */\n async getProductWithPaymentPlans(productId: string): Promise<SubscriptionProduct> {\n if (!productId || typeof productId !== 'string') {\n throw new TorqueCheckoutError('Product ID is required', 'INVALID_PRODUCT_ID', 400)\n }\n\n try {\n const response = await this.makeRequest(`/api/products/${productId}`)\n \n if (response.error) {\n throw new TorqueCheckoutError(\n response.message || 'Failed to get product',\n response.error || 'PRODUCT_NOT_FOUND',\n response.statusCode || 404\n )\n }\n\n return response\n } catch (error) {\n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n throw new TorqueCheckoutError(\n error instanceof Error ? error.message : 'Failed to get product',\n 'NETWORK_ERROR',\n 500\n )\n }\n }\n\n /**\n * Send webhook event\n * @param orderId - Order ID\n * @param status - Order status\n * @param customerData - Optional customer data\n * @param metadata - Optional metadata\n */\n async sendWebhookEvent(\n orderId: string,\n status: string,\n customerData?: any,\n metadata?: Record<string, any>\n ): Promise<void> {\n if (!orderId || typeof orderId !== 'string') {\n throw new TorqueCheckoutError('Order ID is required', 'INVALID_ORDER_ID', 400)\n }\n\n try {\n await this.makeRequest('/api/webhooks/order-update', {\n method: 'POST',\n body: {\n orderId,\n status,\n customerData,\n metadata\n }\n })\n } catch (error) {\n // Webhook events are non-critical, log but don't throw\n console.warn('Failed to send webhook event:', error)\n }\n }\n\n /**\n * Track cart view for analytics\n * @param cartId - Cart ID\n * @param cartData - Cart data\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 // Analytics tracking is non-critical, log but don't throw\n console.warn('Failed to track cart view:', error)\n }\n }\n\n /**\n * Track checkout completion for analytics\n * @param orderId - Order ID\n * @param checkoutData - Checkout data\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 // Analytics tracking is non-critical, log but don't throw\n console.warn('Failed to track checkout completion:', error)\n }\n }\n\n /**\n * Track subscription creation for analytics\n * @param subscriptionId - Subscription ID\n * @param subscriptionData - Subscription data\n */\n async trackSubscriptionCreated(subscriptionId: string, subscriptionData: any): Promise<void> {\n try {\n await this.makeRequest('/api/analytics/subscription-created', {\n method: 'POST',\n body: {\n subscriptionId,\n businessId: this.businessId,\n subscriptionData,\n timestamp: Date.now()\n }\n })\n } catch (error) {\n // Analytics tracking is non-critical, log but don't throw\n console.warn('Failed to track subscription creation:', error)\n }\n }\n\n /**\n * Generate cart hash for caching\n * @param cart - Cart data\n * @returns Cart hash string\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 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 * Generate subscription hash for caching\n * @param subscriptionData - Subscription data\n * @returns Subscription hash string\n */\n generateSubscriptionHash(subscriptionData: CreateSubscriptionData): string {\n const subscriptionString = JSON.stringify({\n businessId: subscriptionData.businessId,\n productId: subscriptionData.productId,\n customerEmail: subscriptionData.customerEmail,\n paymentPlanId: subscriptionData.paymentPlanId\n })\n \n let hash = 0\n for (let i = 0; i < subscriptionString.length; i++) {\n const char = subscriptionString.charCodeAt(i)\n hash = ((hash << 5) - hash) + char\n hash = hash & hash\n }\n return Math.abs(hash).toString(36)\n }\n\n /**\n * Make HTTP request to Torque API\n * @private\n */\n private async makeRequest(\n endpoint: string,\n options: { method?: string; body?: any; headers?: Record<string, string> } = {}\n ): 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 { body, ...fetchOptions } = options\n const response = await fetch(url, {\n ...fetchOptions,\n method: options.method || 'GET',\n body: body ? JSON.stringify(body) : undefined,\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 const responseData = await response.json().catch(() => ({}))\n\n if (!response.ok) {\n throw new TorqueCheckoutError(\n responseData.message || `HTTP ${response.status}: ${response.statusText}`,\n responseData.error || 'API_ERROR',\n response.status,\n responseData.details\n )\n }\n\n return responseData\n } catch (error) {\n clearTimeout(timeoutId)\n \n if (error instanceof TorqueCheckoutError) {\n throw error\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new TorqueCheckoutError('Request timeout', 'TIMEOUT', 408)\n }\n throw new TorqueCheckoutError(error.message, 'NETWORK_ERROR', 500)\n }\n \n throw new TorqueCheckoutError('Request failed', 'UNKNOWN_ERROR', 500)\n }\n }\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a new TorqueCheckout instance\n * @param config - Configuration object\n * @returns TorqueCheckout instance\n */\nexport function createTorqueCheckout(config: TorqueConfig): TorqueCheckout {\n return new TorqueCheckout(config)\n}\n\n/**\n * Create a TorqueCheckout instance from environment variables\n * Requires TORQUE_BUSINESS_ID and TORQUE_API_KEY environment variables\n * @param overrides - Optional configuration overrides\n * @returns TorqueCheckout instance\n */\nexport function createTorqueCheckoutFromEnv(overrides?: Partial<TorqueConfig>): TorqueCheckout {\n const businessId = process.env.TORQUE_BUSINESS_ID || overrides?.businessId\n const apiKey = process.env.TORQUE_API_KEY || overrides?.apiKey\n\n if (!businessId || !apiKey) {\n throw new TorqueCheckoutError(\n 'TORQUE_BUSINESS_ID and TORQUE_API_KEY environment variables are required',\n 'MISSING_ENV_VARS',\n 400\n )\n }\n\n return new TorqueCheckout({\n businessId,\n apiKey,\n baseUrl: process.env.TORQUE_BASE_URL || overrides?.baseUrl,\n timeout: overrides?.timeout\n })\n}\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\n// Types are already exported above as interfaces/types\n// This section is for re-exporting if needed for convenience\n// All types are available via named exports from the main module\n"],"names":[],"mappings":"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"}
|
package/dist/nextjs.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { type TorqueConfig, type CartData, type OrderStatus, type TorqueCheckout
|
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* ```ts
|
|
16
|
-
* // app/api/checkout/route.ts
|
|
16
|
+
* // app/api/checkout-session/route.ts (path is your choice)
|
|
17
17
|
* import { generateCheckoutUrl } from 'torque-checkout/nextjs'
|
|
18
18
|
*
|
|
19
19
|
* export async function POST(request: Request) {
|
|
@@ -37,7 +37,7 @@ export interface CheckoutApiHandlerOptions {
|
|
|
37
37
|
*
|
|
38
38
|
* @example
|
|
39
39
|
* ```ts
|
|
40
|
-
* // app/api/checkout/route.ts
|
|
40
|
+
* // app/api/checkout-session/route.ts (path is your choice)
|
|
41
41
|
* import { handleCheckoutRequest } from 'torque-checkout/nextjs'
|
|
42
42
|
*
|
|
43
43
|
* export const POST = handleCheckoutRequest({
|
|
@@ -94,6 +94,11 @@ export declare function handleWebhook(options?: WebhookHandlerOptions): (request
|
|
|
94
94
|
}> | NextResponse<{
|
|
95
95
|
received: boolean;
|
|
96
96
|
}>>;
|
|
97
|
+
/**
|
|
98
|
+
* Verify `X-Torque-Signature` (or raw hex) against HMAC-SHA256 of the **raw** webhook body.
|
|
99
|
+
* Accepts `hex`, `sha256=<hex>`, or `v1=<hex>` (Suby-style prefix).
|
|
100
|
+
*/
|
|
101
|
+
export declare function verifyTorqueWebhookSignature(rawBody: string, signatureHeader: string | null, secret: string): boolean;
|
|
97
102
|
/**
|
|
98
103
|
* Get order status on the server
|
|
99
104
|
*
|
package/dist/nextjs.esm.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from 'crypto';
|
|
1
2
|
import { NextResponse } from 'next/server';
|
|
2
3
|
import { createTorqueCheckout, createTorqueCheckoutFromEnv } from './index.esm.js';
|
|
3
4
|
|
|
@@ -16,7 +17,7 @@ import { createTorqueCheckout, createTorqueCheckoutFromEnv } from './index.esm.j
|
|
|
16
17
|
*
|
|
17
18
|
* @example
|
|
18
19
|
* ```ts
|
|
19
|
-
* // app/api/checkout/route.ts
|
|
20
|
+
* // app/api/checkout-session/route.ts (path is your choice)
|
|
20
21
|
* import { generateCheckoutUrl } from 'torque-checkout/nextjs'
|
|
21
22
|
*
|
|
22
23
|
* export async function POST(request: Request) {
|
|
@@ -40,7 +41,7 @@ async function generateCheckoutUrl(cart, config) {
|
|
|
40
41
|
*
|
|
41
42
|
* @example
|
|
42
43
|
* ```ts
|
|
43
|
-
* // app/api/checkout/route.ts
|
|
44
|
+
* // app/api/checkout-session/route.ts (path is your choice)
|
|
44
45
|
* import { handleCheckoutRequest } from 'torque-checkout/nextjs'
|
|
45
46
|
*
|
|
46
47
|
* export const POST = handleCheckoutRequest({
|
|
@@ -99,11 +100,18 @@ function handleCheckoutRequest(options = {}) {
|
|
|
99
100
|
function handleWebhook(options = {}) {
|
|
100
101
|
return async (request) => {
|
|
101
102
|
try {
|
|
102
|
-
const
|
|
103
|
-
|
|
103
|
+
const rawBody = await request.text();
|
|
104
|
+
let event;
|
|
105
|
+
try {
|
|
106
|
+
event = JSON.parse(rawBody);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 });
|
|
110
|
+
}
|
|
111
|
+
// Verify HMAC-SHA256 of raw body (same pattern as Suby-style signed webhooks)
|
|
104
112
|
if (options.secret) {
|
|
105
113
|
const signature = request.headers.get('x-torque-signature');
|
|
106
|
-
if (!
|
|
114
|
+
if (!verifyTorqueWebhookSignature(rawBody, signature, options.secret)) {
|
|
107
115
|
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
|
|
108
116
|
}
|
|
109
117
|
}
|
|
@@ -136,17 +144,20 @@ function handleWebhook(options = {}) {
|
|
|
136
144
|
};
|
|
137
145
|
}
|
|
138
146
|
/**
|
|
139
|
-
* Verify webhook
|
|
140
|
-
*
|
|
147
|
+
* Verify `X-Torque-Signature` (or raw hex) against HMAC-SHA256 of the **raw** webhook body.
|
|
148
|
+
* Accepts `hex`, `sha256=<hex>`, or `v1=<hex>` (Suby-style prefix).
|
|
141
149
|
*/
|
|
142
|
-
function
|
|
143
|
-
|
|
144
|
-
|
|
150
|
+
function verifyTorqueWebhookSignature(rawBody, signatureHeader, secret) {
|
|
151
|
+
if (!signatureHeader || !secret)
|
|
152
|
+
return false;
|
|
153
|
+
const expectedHex = createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');
|
|
154
|
+
const normalized = signatureHeader.trim().replace(/^(sha256|v1)=/i, '');
|
|
145
155
|
try {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
const a = Buffer.from(normalized, 'hex');
|
|
157
|
+
const b = Buffer.from(expectedHex, 'hex');
|
|
158
|
+
if (a.length !== b.length)
|
|
159
|
+
return false;
|
|
160
|
+
return timingSafeEqual(a, b);
|
|
150
161
|
}
|
|
151
162
|
catch {
|
|
152
163
|
return false;
|
|
@@ -176,5 +187,5 @@ async function getOrderStatus(orderId, config) {
|
|
|
176
187
|
return torque.getOrderStatus(orderId);
|
|
177
188
|
}
|
|
178
189
|
|
|
179
|
-
export { generateCheckoutUrl, getOrderStatus, handleCheckoutRequest, handleWebhook };
|
|
190
|
+
export { generateCheckoutUrl, getOrderStatus, handleCheckoutRequest, handleWebhook, verifyTorqueWebhookSignature };
|
|
180
191
|
//# sourceMappingURL=nextjs.esm.js.map
|
package/dist/nextjs.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextjs.esm.js","sources":["../src/nextjs.ts"],"sourcesContent":["/**\n * Next.js Server-Side Utilities\n * Server-side helpers for Next.js App Router and Pages Router\n * \n * @requires next >= 13.0.0\n */\n\n// Type-only imports for better compatibility\nimport type { NextRequest } from 'next/server'\nimport { NextResponse } from 'next/server'\nimport {\n TorqueCheckout,\n createTorqueCheckout,\n createTorqueCheckoutFromEnv,\n type TorqueConfig,\n type CartData,\n type OrderStatus,\n type TorqueCheckoutError\n} from './index'\n\n// ============================================================================\n// Server-Side Checkout Helper\n// ============================================================================\n\n/**\n * Generate checkout URL on the server\n * Use this in Next.js API routes or Server Components\n * \n * @example\n * ```ts\n * // app/api/checkout/route.ts\n * import { generateCheckoutUrl } from 'torque-checkout/nextjs'\n * \n * export async function POST(request: Request) {\n * const cart = await request.json()\n * const url = await generateCheckoutUrl(cart, {\n * businessId: process.env.TORQUE_BUSINESS_ID!,\n * apiKey: process.env.TORQUE_API_KEY!\n * })\n * return Response.json({ checkoutUrl: url })\n * }\n * ```\n */\nexport async function generateCheckoutUrl(\n cart: CartData,\n config?: TorqueConfig\n): Promise<string> {\n const torque = config \n ? createTorqueCheckout(config)\n : createTorqueCheckoutFromEnv()\n\n return torque.generateCartCheckoutUrl(cart)\n}\n\n// ============================================================================\n// API Route Handler Helpers\n// ============================================================================\n\nexport interface CheckoutApiHandlerOptions {\n config?: TorqueConfig\n onSuccess?: (checkoutUrl: string, cart: CartData) => Promise<void> | void\n onError?: (error: TorqueCheckoutError, cart: CartData) => Promise<void> | void\n}\n\n/**\n * Next.js API route handler for generating checkout URLs\n * \n * @example\n * ```ts\n * // app/api/checkout/route.ts\n * import { handleCheckoutRequest } from 'torque-checkout/nextjs'\n * \n * export const POST = handleCheckoutRequest({\n * onSuccess: async (url, cart) => {\n * // Log checkout generation\n * console.log('Checkout generated:', url)\n * }\n * })\n * ```\n */\nexport function handleCheckoutRequest(options: CheckoutApiHandlerOptions = {}) {\n return async (request: NextRequest) => {\n try {\n const cart: CartData = await request.json()\n\n const torque = options.config\n ? createTorqueCheckout(options.config)\n : createTorqueCheckoutFromEnv()\n\n const checkoutUrl = await torque.generateCartCheckoutUrl(cart)\n\n await options.onSuccess?.(checkoutUrl, cart)\n\n return NextResponse.json({\n success: true,\n checkoutUrl,\n expiresAt: new Date(Date.now() + (cart.options?.expiresIn || 24 * 60 * 60 * 1000)).toISOString()\n })\n } catch (error) {\n const torqueError = error instanceof Error && 'code' in error\n ? error as TorqueCheckoutError\n : new Error(error instanceof Error ? error.message : 'Unknown error') as TorqueCheckoutError\n\n await options.onError?.(torqueError, {} as CartData)\n\n return NextResponse.json(\n {\n success: false,\n error: torqueError.message,\n code: torqueError.code || 'UNKNOWN_ERROR'\n },\n { status: torqueError.statusCode || 500 }\n )\n }\n }\n}\n\n// ============================================================================\n// Webhook Handler\n// ============================================================================\n\nexport interface WebhookEvent {\n type: 'order.created' | 'order.completed' | 'order.failed' | 'subscription.created' | 'subscription.cancelled'\n orderId?: string\n subscriptionId?: string\n data: any\n timestamp: number\n}\n\nexport interface WebhookHandlerOptions {\n secret?: string\n onOrderCreated?: (event: WebhookEvent) => Promise<void> | void\n onOrderCompleted?: (event: WebhookEvent) => Promise<void> | void\n onOrderFailed?: (event: WebhookEvent) => Promise<void> | void\n onSubscriptionCreated?: (event: WebhookEvent) => Promise<void> | void\n onSubscriptionCancelled?: (event: WebhookEvent) => Promise<void> | void\n}\n\n/**\n * Next.js API route handler for webhook events\n * \n * @example\n * ```ts\n * // app/api/webhooks/torque/route.ts\n * import { handleWebhook } from 'torque-checkout/nextjs'\n * \n * export const POST = handleWebhook({\n * secret: process.env.TORQUE_WEBHOOK_SECRET,\n * onOrderCompleted: async (event) => {\n * // Fulfill order\n * await fulfillOrder(event.orderId!)\n * }\n * })\n * ```\n */\nexport function handleWebhook(options: WebhookHandlerOptions = {}) {\n return async (request: NextRequest) => {\n try {\n const event: WebhookEvent = await request.json()\n\n // Verify webhook secret if provided\n if (options.secret) {\n const signature = request.headers.get('x-torque-signature')\n if (!signature || !verifyWebhookSignature(event, signature, options.secret)) {\n return NextResponse.json(\n { error: 'Invalid signature' },\n { status: 401 }\n )\n }\n }\n\n // Route to appropriate handler\n switch (event.type) {\n case 'order.created':\n await options.onOrderCreated?.(event)\n break\n case 'order.completed':\n await options.onOrderCompleted?.(event)\n break\n case 'order.failed':\n await options.onOrderFailed?.(event)\n break\n case 'subscription.created':\n await options.onSubscriptionCreated?.(event)\n break\n case 'subscription.cancelled':\n await options.onSubscriptionCancelled?.(event)\n break\n default:\n console.warn('Unknown webhook event type:', event.type)\n }\n\n return NextResponse.json({ received: true })\n } catch (error) {\n console.error('Webhook handler error:', error)\n return NextResponse.json(\n { error: 'Webhook processing failed' },\n { status: 500 }\n )\n }\n }\n}\n\n/**\n * Verify webhook signature\n * @internal\n */\nfunction verifyWebhookSignature(event: WebhookEvent, signature: string, secret: string): boolean {\n // Simple signature verification - implement HMAC verification in production\n // This is a placeholder - implement proper crypto verification\n try {\n const payload = JSON.stringify(event)\n // In production, use crypto.createHmac('sha256', secret).update(payload).digest('hex')\n // and compare with signature\n return true // Placeholder\n } catch {\n return false\n }\n}\n\n// ============================================================================\n// Order Status Helper\n// ============================================================================\n\n/**\n * Get order status on the server\n * \n * @example\n * ```ts\n * // app/api/orders/[orderId]/route.ts\n * import { getOrderStatus } from 'torque-checkout/nextjs'\n * \n * export async function GET(request: Request, { params }: { params: { orderId: string } }) {\n * const status = await getOrderStatus(params.orderId)\n * return Response.json(status)\n * }\n * ```\n */\nexport async function getOrderStatus(\n orderId: string,\n config?: TorqueConfig\n): Promise<OrderStatus> {\n const torque = config\n ? createTorqueCheckout(config)\n : createTorqueCheckoutFromEnv()\n\n return torque.getOrderStatus(orderId)\n}\n\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nextjs.esm.js","sources":["../src/nextjs.ts"],"sourcesContent":["/**\n * Next.js Server-Side Utilities\n * Server-side helpers for Next.js App Router and Pages Router\n * \n * @requires next >= 13.0.0\n */\n\nimport { createHmac, timingSafeEqual } from 'crypto'\n// Type-only imports for better compatibility\nimport type { NextRequest } from 'next/server'\nimport { NextResponse } from 'next/server'\nimport {\n TorqueCheckout,\n createTorqueCheckout,\n createTorqueCheckoutFromEnv,\n type TorqueConfig,\n type CartData,\n type OrderStatus,\n type TorqueCheckoutError\n} from './index'\n\n// ============================================================================\n// Server-Side Checkout Helper\n// ============================================================================\n\n/**\n * Generate checkout URL on the server\n * Use this in Next.js API routes or Server Components\n * \n * @example\n * ```ts\n * // app/api/checkout-session/route.ts (path is your choice)\n * import { generateCheckoutUrl } from 'torque-checkout/nextjs'\n * \n * export async function POST(request: Request) {\n * const cart = await request.json()\n * const url = await generateCheckoutUrl(cart, {\n * businessId: process.env.TORQUE_BUSINESS_ID!,\n * apiKey: process.env.TORQUE_API_KEY!\n * })\n * return Response.json({ checkoutUrl: url })\n * }\n * ```\n */\nexport async function generateCheckoutUrl(\n cart: CartData,\n config?: TorqueConfig\n): Promise<string> {\n const torque = config \n ? createTorqueCheckout(config)\n : createTorqueCheckoutFromEnv()\n\n return torque.generateCartCheckoutUrl(cart)\n}\n\n// ============================================================================\n// API Route Handler Helpers\n// ============================================================================\n\nexport interface CheckoutApiHandlerOptions {\n config?: TorqueConfig\n onSuccess?: (checkoutUrl: string, cart: CartData) => Promise<void> | void\n onError?: (error: TorqueCheckoutError, cart: CartData) => Promise<void> | void\n}\n\n/**\n * Next.js API route handler for generating checkout URLs\n * \n * @example\n * ```ts\n * // app/api/checkout-session/route.ts (path is your choice)\n * import { handleCheckoutRequest } from 'torque-checkout/nextjs'\n * \n * export const POST = handleCheckoutRequest({\n * onSuccess: async (url, cart) => {\n * // Log checkout generation\n * console.log('Checkout generated:', url)\n * }\n * })\n * ```\n */\nexport function handleCheckoutRequest(options: CheckoutApiHandlerOptions = {}) {\n return async (request: NextRequest) => {\n try {\n const cart: CartData = await request.json()\n\n const torque = options.config\n ? createTorqueCheckout(options.config)\n : createTorqueCheckoutFromEnv()\n\n const checkoutUrl = await torque.generateCartCheckoutUrl(cart)\n\n await options.onSuccess?.(checkoutUrl, cart)\n\n return NextResponse.json({\n success: true,\n checkoutUrl,\n expiresAt: new Date(Date.now() + (cart.options?.expiresIn || 24 * 60 * 60 * 1000)).toISOString()\n })\n } catch (error) {\n const torqueError = error instanceof Error && 'code' in error\n ? error as TorqueCheckoutError\n : new Error(error instanceof Error ? error.message : 'Unknown error') as TorqueCheckoutError\n\n await options.onError?.(torqueError, {} as CartData)\n\n return NextResponse.json(\n {\n success: false,\n error: torqueError.message,\n code: torqueError.code || 'UNKNOWN_ERROR'\n },\n { status: torqueError.statusCode || 500 }\n )\n }\n }\n}\n\n// ============================================================================\n// Webhook Handler\n// ============================================================================\n\nexport interface WebhookEvent {\n type: 'order.created' | 'order.completed' | 'order.failed' | 'subscription.created' | 'subscription.cancelled'\n orderId?: string\n subscriptionId?: string\n data: any\n timestamp: number\n}\n\nexport interface WebhookHandlerOptions {\n secret?: string\n onOrderCreated?: (event: WebhookEvent) => Promise<void> | void\n onOrderCompleted?: (event: WebhookEvent) => Promise<void> | void\n onOrderFailed?: (event: WebhookEvent) => Promise<void> | void\n onSubscriptionCreated?: (event: WebhookEvent) => Promise<void> | void\n onSubscriptionCancelled?: (event: WebhookEvent) => Promise<void> | void\n}\n\n/**\n * Next.js API route handler for webhook events\n * \n * @example\n * ```ts\n * // app/api/webhooks/torque/route.ts\n * import { handleWebhook } from 'torque-checkout/nextjs'\n * \n * export const POST = handleWebhook({\n * secret: process.env.TORQUE_WEBHOOK_SECRET,\n * onOrderCompleted: async (event) => {\n * // Fulfill order\n * await fulfillOrder(event.orderId!)\n * }\n * })\n * ```\n */\nexport function handleWebhook(options: WebhookHandlerOptions = {}) {\n return async (request: NextRequest) => {\n try {\n const rawBody = await request.text()\n let event: WebhookEvent\n try {\n event = JSON.parse(rawBody) as WebhookEvent\n } catch {\n return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 })\n }\n\n // Verify HMAC-SHA256 of raw body (same pattern as Suby-style signed webhooks)\n if (options.secret) {\n const signature = request.headers.get('x-torque-signature')\n if (!verifyTorqueWebhookSignature(rawBody, signature, options.secret)) {\n return NextResponse.json(\n { error: 'Invalid signature' },\n { status: 401 }\n )\n }\n }\n\n // Route to appropriate handler\n switch (event.type) {\n case 'order.created':\n await options.onOrderCreated?.(event)\n break\n case 'order.completed':\n await options.onOrderCompleted?.(event)\n break\n case 'order.failed':\n await options.onOrderFailed?.(event)\n break\n case 'subscription.created':\n await options.onSubscriptionCreated?.(event)\n break\n case 'subscription.cancelled':\n await options.onSubscriptionCancelled?.(event)\n break\n default:\n console.warn('Unknown webhook event type:', event.type)\n }\n\n return NextResponse.json({ received: true })\n } catch (error) {\n console.error('Webhook handler error:', error)\n return NextResponse.json(\n { error: 'Webhook processing failed' },\n { status: 500 }\n )\n }\n }\n}\n\n/**\n * Verify `X-Torque-Signature` (or raw hex) against HMAC-SHA256 of the **raw** webhook body.\n * Accepts `hex`, `sha256=<hex>`, or `v1=<hex>` (Suby-style prefix).\n */\nexport function verifyTorqueWebhookSignature(\n rawBody: string,\n signatureHeader: string | null,\n secret: string\n): boolean {\n if (!signatureHeader || !secret) return false\n const expectedHex = createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex')\n const normalized = signatureHeader.trim().replace(/^(sha256|v1)=/i, '')\n try {\n const a = Buffer.from(normalized, 'hex')\n const b = Buffer.from(expectedHex, 'hex')\n if (a.length !== b.length) return false\n return timingSafeEqual(a, b)\n } catch {\n return false\n }\n}\n\n// ============================================================================\n// Order Status Helper\n// ============================================================================\n\n/**\n * Get order status on the server\n * \n * @example\n * ```ts\n * // app/api/orders/[orderId]/route.ts\n * import { getOrderStatus } from 'torque-checkout/nextjs'\n * \n * export async function GET(request: Request, { params }: { params: { orderId: string } }) {\n * const status = await getOrderStatus(params.orderId)\n * return Response.json(status)\n * }\n * ```\n */\nexport async function getOrderStatus(\n orderId: string,\n config?: TorqueConfig\n): Promise<OrderStatus> {\n const torque = config\n ? createTorqueCheckout(config)\n : createTorqueCheckoutFromEnv()\n\n return torque.getOrderStatus(orderId)\n}\n\n"],"names":[],"mappings":"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"}
|
package/dist/nextjs.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var crypto = require('crypto');
|
|
3
4
|
var server = require('next/server');
|
|
4
5
|
var index = require('./index.js');
|
|
5
6
|
|
|
@@ -18,7 +19,7 @@ var index = require('./index.js');
|
|
|
18
19
|
*
|
|
19
20
|
* @example
|
|
20
21
|
* ```ts
|
|
21
|
-
* // app/api/checkout/route.ts
|
|
22
|
+
* // app/api/checkout-session/route.ts (path is your choice)
|
|
22
23
|
* import { generateCheckoutUrl } from 'torque-checkout/nextjs'
|
|
23
24
|
*
|
|
24
25
|
* export async function POST(request: Request) {
|
|
@@ -42,7 +43,7 @@ async function generateCheckoutUrl(cart, config) {
|
|
|
42
43
|
*
|
|
43
44
|
* @example
|
|
44
45
|
* ```ts
|
|
45
|
-
* // app/api/checkout/route.ts
|
|
46
|
+
* // app/api/checkout-session/route.ts (path is your choice)
|
|
46
47
|
* import { handleCheckoutRequest } from 'torque-checkout/nextjs'
|
|
47
48
|
*
|
|
48
49
|
* export const POST = handleCheckoutRequest({
|
|
@@ -101,11 +102,18 @@ function handleCheckoutRequest(options = {}) {
|
|
|
101
102
|
function handleWebhook(options = {}) {
|
|
102
103
|
return async (request) => {
|
|
103
104
|
try {
|
|
104
|
-
const
|
|
105
|
-
|
|
105
|
+
const rawBody = await request.text();
|
|
106
|
+
let event;
|
|
107
|
+
try {
|
|
108
|
+
event = JSON.parse(rawBody);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return server.NextResponse.json({ error: 'Invalid JSON' }, { status: 400 });
|
|
112
|
+
}
|
|
113
|
+
// Verify HMAC-SHA256 of raw body (same pattern as Suby-style signed webhooks)
|
|
106
114
|
if (options.secret) {
|
|
107
115
|
const signature = request.headers.get('x-torque-signature');
|
|
108
|
-
if (!
|
|
116
|
+
if (!verifyTorqueWebhookSignature(rawBody, signature, options.secret)) {
|
|
109
117
|
return server.NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
|
|
110
118
|
}
|
|
111
119
|
}
|
|
@@ -138,17 +146,20 @@ function handleWebhook(options = {}) {
|
|
|
138
146
|
};
|
|
139
147
|
}
|
|
140
148
|
/**
|
|
141
|
-
* Verify webhook
|
|
142
|
-
*
|
|
149
|
+
* Verify `X-Torque-Signature` (or raw hex) against HMAC-SHA256 of the **raw** webhook body.
|
|
150
|
+
* Accepts `hex`, `sha256=<hex>`, or `v1=<hex>` (Suby-style prefix).
|
|
143
151
|
*/
|
|
144
|
-
function
|
|
145
|
-
|
|
146
|
-
|
|
152
|
+
function verifyTorqueWebhookSignature(rawBody, signatureHeader, secret) {
|
|
153
|
+
if (!signatureHeader || !secret)
|
|
154
|
+
return false;
|
|
155
|
+
const expectedHex = crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');
|
|
156
|
+
const normalized = signatureHeader.trim().replace(/^(sha256|v1)=/i, '');
|
|
147
157
|
try {
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
158
|
+
const a = Buffer.from(normalized, 'hex');
|
|
159
|
+
const b = Buffer.from(expectedHex, 'hex');
|
|
160
|
+
if (a.length !== b.length)
|
|
161
|
+
return false;
|
|
162
|
+
return crypto.timingSafeEqual(a, b);
|
|
152
163
|
}
|
|
153
164
|
catch {
|
|
154
165
|
return false;
|
|
@@ -182,4 +193,5 @@ exports.generateCheckoutUrl = generateCheckoutUrl;
|
|
|
182
193
|
exports.getOrderStatus = getOrderStatus;
|
|
183
194
|
exports.handleCheckoutRequest = handleCheckoutRequest;
|
|
184
195
|
exports.handleWebhook = handleWebhook;
|
|
196
|
+
exports.verifyTorqueWebhookSignature = verifyTorqueWebhookSignature;
|
|
185
197
|
//# sourceMappingURL=nextjs.js.map
|
package/dist/nextjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextjs.js","sources":["../src/nextjs.ts"],"sourcesContent":["/**\n * Next.js Server-Side Utilities\n * Server-side helpers for Next.js App Router and Pages Router\n * \n * @requires next >= 13.0.0\n */\n\n// Type-only imports for better compatibility\nimport type { NextRequest } from 'next/server'\nimport { NextResponse } from 'next/server'\nimport {\n TorqueCheckout,\n createTorqueCheckout,\n createTorqueCheckoutFromEnv,\n type TorqueConfig,\n type CartData,\n type OrderStatus,\n type TorqueCheckoutError\n} from './index'\n\n// ============================================================================\n// Server-Side Checkout Helper\n// ============================================================================\n\n/**\n * Generate checkout URL on the server\n * Use this in Next.js API routes or Server Components\n * \n * @example\n * ```ts\n * // app/api/checkout/route.ts\n * import { generateCheckoutUrl } from 'torque-checkout/nextjs'\n * \n * export async function POST(request: Request) {\n * const cart = await request.json()\n * const url = await generateCheckoutUrl(cart, {\n * businessId: process.env.TORQUE_BUSINESS_ID!,\n * apiKey: process.env.TORQUE_API_KEY!\n * })\n * return Response.json({ checkoutUrl: url })\n * }\n * ```\n */\nexport async function generateCheckoutUrl(\n cart: CartData,\n config?: TorqueConfig\n): Promise<string> {\n const torque = config \n ? createTorqueCheckout(config)\n : createTorqueCheckoutFromEnv()\n\n return torque.generateCartCheckoutUrl(cart)\n}\n\n// ============================================================================\n// API Route Handler Helpers\n// ============================================================================\n\nexport interface CheckoutApiHandlerOptions {\n config?: TorqueConfig\n onSuccess?: (checkoutUrl: string, cart: CartData) => Promise<void> | void\n onError?: (error: TorqueCheckoutError, cart: CartData) => Promise<void> | void\n}\n\n/**\n * Next.js API route handler for generating checkout URLs\n * \n * @example\n * ```ts\n * // app/api/checkout/route.ts\n * import { handleCheckoutRequest } from 'torque-checkout/nextjs'\n * \n * export const POST = handleCheckoutRequest({\n * onSuccess: async (url, cart) => {\n * // Log checkout generation\n * console.log('Checkout generated:', url)\n * }\n * })\n * ```\n */\nexport function handleCheckoutRequest(options: CheckoutApiHandlerOptions = {}) {\n return async (request: NextRequest) => {\n try {\n const cart: CartData = await request.json()\n\n const torque = options.config\n ? createTorqueCheckout(options.config)\n : createTorqueCheckoutFromEnv()\n\n const checkoutUrl = await torque.generateCartCheckoutUrl(cart)\n\n await options.onSuccess?.(checkoutUrl, cart)\n\n return NextResponse.json({\n success: true,\n checkoutUrl,\n expiresAt: new Date(Date.now() + (cart.options?.expiresIn || 24 * 60 * 60 * 1000)).toISOString()\n })\n } catch (error) {\n const torqueError = error instanceof Error && 'code' in error\n ? error as TorqueCheckoutError\n : new Error(error instanceof Error ? error.message : 'Unknown error') as TorqueCheckoutError\n\n await options.onError?.(torqueError, {} as CartData)\n\n return NextResponse.json(\n {\n success: false,\n error: torqueError.message,\n code: torqueError.code || 'UNKNOWN_ERROR'\n },\n { status: torqueError.statusCode || 500 }\n )\n }\n }\n}\n\n// ============================================================================\n// Webhook Handler\n// ============================================================================\n\nexport interface WebhookEvent {\n type: 'order.created' | 'order.completed' | 'order.failed' | 'subscription.created' | 'subscription.cancelled'\n orderId?: string\n subscriptionId?: string\n data: any\n timestamp: number\n}\n\nexport interface WebhookHandlerOptions {\n secret?: string\n onOrderCreated?: (event: WebhookEvent) => Promise<void> | void\n onOrderCompleted?: (event: WebhookEvent) => Promise<void> | void\n onOrderFailed?: (event: WebhookEvent) => Promise<void> | void\n onSubscriptionCreated?: (event: WebhookEvent) => Promise<void> | void\n onSubscriptionCancelled?: (event: WebhookEvent) => Promise<void> | void\n}\n\n/**\n * Next.js API route handler for webhook events\n * \n * @example\n * ```ts\n * // app/api/webhooks/torque/route.ts\n * import { handleWebhook } from 'torque-checkout/nextjs'\n * \n * export const POST = handleWebhook({\n * secret: process.env.TORQUE_WEBHOOK_SECRET,\n * onOrderCompleted: async (event) => {\n * // Fulfill order\n * await fulfillOrder(event.orderId!)\n * }\n * })\n * ```\n */\nexport function handleWebhook(options: WebhookHandlerOptions = {}) {\n return async (request: NextRequest) => {\n try {\n const event: WebhookEvent = await request.json()\n\n // Verify webhook secret if provided\n if (options.secret) {\n const signature = request.headers.get('x-torque-signature')\n if (!signature || !verifyWebhookSignature(event, signature, options.secret)) {\n return NextResponse.json(\n { error: 'Invalid signature' },\n { status: 401 }\n )\n }\n }\n\n // Route to appropriate handler\n switch (event.type) {\n case 'order.created':\n await options.onOrderCreated?.(event)\n break\n case 'order.completed':\n await options.onOrderCompleted?.(event)\n break\n case 'order.failed':\n await options.onOrderFailed?.(event)\n break\n case 'subscription.created':\n await options.onSubscriptionCreated?.(event)\n break\n case 'subscription.cancelled':\n await options.onSubscriptionCancelled?.(event)\n break\n default:\n console.warn('Unknown webhook event type:', event.type)\n }\n\n return NextResponse.json({ received: true })\n } catch (error) {\n console.error('Webhook handler error:', error)\n return NextResponse.json(\n { error: 'Webhook processing failed' },\n { status: 500 }\n )\n }\n }\n}\n\n/**\n * Verify webhook signature\n * @internal\n */\nfunction verifyWebhookSignature(event: WebhookEvent, signature: string, secret: string): boolean {\n // Simple signature verification - implement HMAC verification in production\n // This is a placeholder - implement proper crypto verification\n try {\n const payload = JSON.stringify(event)\n // In production, use crypto.createHmac('sha256', secret).update(payload).digest('hex')\n // and compare with signature\n return true // Placeholder\n } catch {\n return false\n }\n}\n\n// ============================================================================\n// Order Status Helper\n// ============================================================================\n\n/**\n * Get order status on the server\n * \n * @example\n * ```ts\n * // app/api/orders/[orderId]/route.ts\n * import { getOrderStatus } from 'torque-checkout/nextjs'\n * \n * export async function GET(request: Request, { params }: { params: { orderId: string } }) {\n * const status = await getOrderStatus(params.orderId)\n * return Response.json(status)\n * }\n * ```\n */\nexport async function getOrderStatus(\n orderId: string,\n config?: TorqueConfig\n): Promise<OrderStatus> {\n const torque = config\n ? createTorqueCheckout(config)\n : createTorqueCheckoutFromEnv()\n\n return torque.getOrderStatus(orderId)\n}\n\n"],"names":["createTorqueCheckout","createTorqueCheckoutFromEnv","NextResponse"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nextjs.js","sources":["../src/nextjs.ts"],"sourcesContent":["/**\n * Next.js Server-Side Utilities\n * Server-side helpers for Next.js App Router and Pages Router\n * \n * @requires next >= 13.0.0\n */\n\nimport { createHmac, timingSafeEqual } from 'crypto'\n// Type-only imports for better compatibility\nimport type { NextRequest } from 'next/server'\nimport { NextResponse } from 'next/server'\nimport {\n TorqueCheckout,\n createTorqueCheckout,\n createTorqueCheckoutFromEnv,\n type TorqueConfig,\n type CartData,\n type OrderStatus,\n type TorqueCheckoutError\n} from './index'\n\n// ============================================================================\n// Server-Side Checkout Helper\n// ============================================================================\n\n/**\n * Generate checkout URL on the server\n * Use this in Next.js API routes or Server Components\n * \n * @example\n * ```ts\n * // app/api/checkout-session/route.ts (path is your choice)\n * import { generateCheckoutUrl } from 'torque-checkout/nextjs'\n * \n * export async function POST(request: Request) {\n * const cart = await request.json()\n * const url = await generateCheckoutUrl(cart, {\n * businessId: process.env.TORQUE_BUSINESS_ID!,\n * apiKey: process.env.TORQUE_API_KEY!\n * })\n * return Response.json({ checkoutUrl: url })\n * }\n * ```\n */\nexport async function generateCheckoutUrl(\n cart: CartData,\n config?: TorqueConfig\n): Promise<string> {\n const torque = config \n ? createTorqueCheckout(config)\n : createTorqueCheckoutFromEnv()\n\n return torque.generateCartCheckoutUrl(cart)\n}\n\n// ============================================================================\n// API Route Handler Helpers\n// ============================================================================\n\nexport interface CheckoutApiHandlerOptions {\n config?: TorqueConfig\n onSuccess?: (checkoutUrl: string, cart: CartData) => Promise<void> | void\n onError?: (error: TorqueCheckoutError, cart: CartData) => Promise<void> | void\n}\n\n/**\n * Next.js API route handler for generating checkout URLs\n * \n * @example\n * ```ts\n * // app/api/checkout-session/route.ts (path is your choice)\n * import { handleCheckoutRequest } from 'torque-checkout/nextjs'\n * \n * export const POST = handleCheckoutRequest({\n * onSuccess: async (url, cart) => {\n * // Log checkout generation\n * console.log('Checkout generated:', url)\n * }\n * })\n * ```\n */\nexport function handleCheckoutRequest(options: CheckoutApiHandlerOptions = {}) {\n return async (request: NextRequest) => {\n try {\n const cart: CartData = await request.json()\n\n const torque = options.config\n ? createTorqueCheckout(options.config)\n : createTorqueCheckoutFromEnv()\n\n const checkoutUrl = await torque.generateCartCheckoutUrl(cart)\n\n await options.onSuccess?.(checkoutUrl, cart)\n\n return NextResponse.json({\n success: true,\n checkoutUrl,\n expiresAt: new Date(Date.now() + (cart.options?.expiresIn || 24 * 60 * 60 * 1000)).toISOString()\n })\n } catch (error) {\n const torqueError = error instanceof Error && 'code' in error\n ? error as TorqueCheckoutError\n : new Error(error instanceof Error ? error.message : 'Unknown error') as TorqueCheckoutError\n\n await options.onError?.(torqueError, {} as CartData)\n\n return NextResponse.json(\n {\n success: false,\n error: torqueError.message,\n code: torqueError.code || 'UNKNOWN_ERROR'\n },\n { status: torqueError.statusCode || 500 }\n )\n }\n }\n}\n\n// ============================================================================\n// Webhook Handler\n// ============================================================================\n\nexport interface WebhookEvent {\n type: 'order.created' | 'order.completed' | 'order.failed' | 'subscription.created' | 'subscription.cancelled'\n orderId?: string\n subscriptionId?: string\n data: any\n timestamp: number\n}\n\nexport interface WebhookHandlerOptions {\n secret?: string\n onOrderCreated?: (event: WebhookEvent) => Promise<void> | void\n onOrderCompleted?: (event: WebhookEvent) => Promise<void> | void\n onOrderFailed?: (event: WebhookEvent) => Promise<void> | void\n onSubscriptionCreated?: (event: WebhookEvent) => Promise<void> | void\n onSubscriptionCancelled?: (event: WebhookEvent) => Promise<void> | void\n}\n\n/**\n * Next.js API route handler for webhook events\n * \n * @example\n * ```ts\n * // app/api/webhooks/torque/route.ts\n * import { handleWebhook } from 'torque-checkout/nextjs'\n * \n * export const POST = handleWebhook({\n * secret: process.env.TORQUE_WEBHOOK_SECRET,\n * onOrderCompleted: async (event) => {\n * // Fulfill order\n * await fulfillOrder(event.orderId!)\n * }\n * })\n * ```\n */\nexport function handleWebhook(options: WebhookHandlerOptions = {}) {\n return async (request: NextRequest) => {\n try {\n const rawBody = await request.text()\n let event: WebhookEvent\n try {\n event = JSON.parse(rawBody) as WebhookEvent\n } catch {\n return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 })\n }\n\n // Verify HMAC-SHA256 of raw body (same pattern as Suby-style signed webhooks)\n if (options.secret) {\n const signature = request.headers.get('x-torque-signature')\n if (!verifyTorqueWebhookSignature(rawBody, signature, options.secret)) {\n return NextResponse.json(\n { error: 'Invalid signature' },\n { status: 401 }\n )\n }\n }\n\n // Route to appropriate handler\n switch (event.type) {\n case 'order.created':\n await options.onOrderCreated?.(event)\n break\n case 'order.completed':\n await options.onOrderCompleted?.(event)\n break\n case 'order.failed':\n await options.onOrderFailed?.(event)\n break\n case 'subscription.created':\n await options.onSubscriptionCreated?.(event)\n break\n case 'subscription.cancelled':\n await options.onSubscriptionCancelled?.(event)\n break\n default:\n console.warn('Unknown webhook event type:', event.type)\n }\n\n return NextResponse.json({ received: true })\n } catch (error) {\n console.error('Webhook handler error:', error)\n return NextResponse.json(\n { error: 'Webhook processing failed' },\n { status: 500 }\n )\n }\n }\n}\n\n/**\n * Verify `X-Torque-Signature` (or raw hex) against HMAC-SHA256 of the **raw** webhook body.\n * Accepts `hex`, `sha256=<hex>`, or `v1=<hex>` (Suby-style prefix).\n */\nexport function verifyTorqueWebhookSignature(\n rawBody: string,\n signatureHeader: string | null,\n secret: string\n): boolean {\n if (!signatureHeader || !secret) return false\n const expectedHex = createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex')\n const normalized = signatureHeader.trim().replace(/^(sha256|v1)=/i, '')\n try {\n const a = Buffer.from(normalized, 'hex')\n const b = Buffer.from(expectedHex, 'hex')\n if (a.length !== b.length) return false\n return timingSafeEqual(a, b)\n } catch {\n return false\n }\n}\n\n// ============================================================================\n// Order Status Helper\n// ============================================================================\n\n/**\n * Get order status on the server\n * \n * @example\n * ```ts\n * // app/api/orders/[orderId]/route.ts\n * import { getOrderStatus } from 'torque-checkout/nextjs'\n * \n * export async function GET(request: Request, { params }: { params: { orderId: string } }) {\n * const status = await getOrderStatus(params.orderId)\n * return Response.json(status)\n * }\n * ```\n */\nexport async function getOrderStatus(\n orderId: string,\n config?: TorqueConfig\n): Promise<OrderStatus> {\n const torque = config\n ? createTorqueCheckout(config)\n : createTorqueCheckoutFromEnv()\n\n return torque.getOrderStatus(orderId)\n}\n\n"],"names":["createTorqueCheckout","createTorqueCheckoutFromEnv","NextResponse","createHmac","timingSafeEqual"],"mappings":"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"}
|