omni-sync-sdk 0.20.3 → 0.21.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/LICENSE ADDED
File without changes
package/dist/index.d.mts CHANGED
@@ -1692,15 +1692,27 @@ interface ShippingRate {
1692
1692
  * **Note:** Order is created automatically via webhook when payment succeeds.
1693
1693
  * No need to call `completeCheckout()` - it happens automatically.
1694
1694
  *
1695
+ * **IMPORTANT: Order Summary Display**
1696
+ * Always use `checkout.lineItems` for displaying the Order Summary during checkout!
1697
+ * This is especially important for **partial checkout** (AliExpress-style) where the user
1698
+ * selects only some items from their cart. The `lineItems` array contains ONLY the items
1699
+ * being purchased in this checkout, NOT the entire cart.
1700
+ *
1695
1701
  * **IMPORTANT: Price fields are strings**
1696
1702
  * All monetary fields (subtotal, discountAmount, shippingAmount, taxAmount, total)
1697
1703
  * are strings to preserve decimal precision. Use parseFloat() for calculations.
1698
1704
  *
1699
1705
  * @example
1700
1706
  * ```typescript
1701
- * // Display checkout summary
1707
+ * // Display checkout summary - use checkout.lineItems, NOT localCart!
1702
1708
  * const checkout = await omni.getCheckout(checkoutId);
1703
1709
  *
1710
+ * // Order Summary - ALWAYS use checkout.lineItems
1711
+ * checkout.lineItems.forEach(item => {
1712
+ * console.log(item.product.name, item.quantity, item.unitPrice);
1713
+ * });
1714
+ *
1715
+ * // Totals
1704
1716
  * const subtotal = parseFloat(checkout.subtotal);
1705
1717
  * const discount = parseFloat(checkout.discountAmount);
1706
1718
  * const shipping = parseFloat(checkout.shippingAmount);
@@ -1712,11 +1724,6 @@ interface ShippingRate {
1712
1724
  * console.log(`Shipping: $${shipping.toFixed(2)}`);
1713
1725
  * console.log(`Tax: $${tax.toFixed(2)}`);
1714
1726
  * console.log(`Total: $${total.toFixed(2)}`);
1715
- *
1716
- * // Access line items (nested structure)
1717
- * checkout.lineItems.forEach(item => {
1718
- * console.log(item.product.name, item.quantity);
1719
- * });
1720
1727
  * ```
1721
1728
  *
1722
1729
  * @see CheckoutLineItem for item structure
@@ -3057,6 +3064,11 @@ declare class OmniSyncClient {
3057
3064
  * When a cart has this ID, operations use localStorage instead of server API.
3058
3065
  */
3059
3066
  private readonly VIRTUAL_LOCAL_CART_ID;
3067
+ /**
3068
+ * localStorage key for persisting active checkout across page redirects.
3069
+ * This is needed because Stripe redirects lose in-memory state.
3070
+ */
3071
+ private readonly ACTIVE_CHECKOUT_KEY;
3060
3072
  private readonly onAuthError?;
3061
3073
  constructor(options: OmniSyncClientOptions);
3062
3074
  /**
@@ -4748,6 +4760,11 @@ declare class OmniSyncClient {
4748
4760
  * Pass `selectedIndices` to checkout only specific items from the local cart.
4749
4761
  * Use the index of each item in the cart.items array.
4750
4762
  *
4763
+ * **IMPORTANT - Order Summary Display:**
4764
+ * After calling this function, use `getCheckout(checkoutId)` to get the checkout
4765
+ * and display `checkout.lineItems` in your Order Summary - NOT the local cart items!
4766
+ * The checkout.lineItems contains ONLY the selected items for this checkout.
4767
+ *
4751
4768
  * @param options.selectedIndices - Optional array of item indices for partial checkout
4752
4769
  * @returns Tracking result with checkoutId if enabled
4753
4770
  *
@@ -4760,19 +4777,22 @@ declare class OmniSyncClient {
4760
4777
  * const result = await omni.startGuestCheckout({ selectedIndices: [0, 2] });
4761
4778
  *
4762
4779
  * if (result.tracked) {
4763
- * // Store checkoutId for later use
4764
- * console.log('Checkout tracked:', result.checkoutId);
4780
+ * // IMPORTANT: Fetch checkout and use checkout.lineItems for Order Summary!
4781
+ * const checkout = await omni.getCheckout(result.checkoutId);
4782
+ *
4783
+ * // Display Order Summary using checkout.lineItems (NOT localCart.items!)
4784
+ * // checkout.lineItems contains ONLY the selected items
4785
+ * checkout.lineItems.forEach(item => {
4786
+ * console.log(item.product.name, item.quantity, item.unitPrice);
4787
+ * });
4765
4788
  *
4766
4789
  * // Update checkout with address
4767
- * await omni.updateGuestCheckout(result.checkoutId, {
4790
+ * await omni.updateGuestCheckoutAddress(result.checkoutId, {
4768
4791
  * shippingAddress: { ... },
4769
4792
  * });
4770
4793
  *
4771
- * // Complete checkout
4772
- * const order = await omni.completeGuestCheckout(result.checkoutId);
4773
- *
4774
- * // For partial checkout: remove only purchased items
4775
- * omni.removeLocalCartItemsByIndex([0, 2]);
4794
+ * // After payment success, call handlePaymentSuccess() to clear cart
4795
+ * omni.handlePaymentSuccess(result.checkoutId);
4776
4796
  * } else {
4777
4797
  * // Tracking not enabled, use regular submitGuestOrder
4778
4798
  * const order = await omni.submitGuestOrder();
@@ -4782,6 +4802,21 @@ declare class OmniSyncClient {
4782
4802
  startGuestCheckout(options?: {
4783
4803
  selectedIndices?: number[];
4784
4804
  }): Promise<GuestCheckoutStartResponse>;
4805
+ /**
4806
+ * Save active checkout to localStorage (persists across page redirects)
4807
+ * @internal
4808
+ */
4809
+ private saveActiveCheckout;
4810
+ /**
4811
+ * Load active checkout from localStorage
4812
+ * @internal
4813
+ */
4814
+ private loadActiveCheckout;
4815
+ /**
4816
+ * Clear active checkout from localStorage
4817
+ * @internal
4818
+ */
4819
+ private clearActiveCheckoutStorage;
4785
4820
  /**
4786
4821
  * Remove specific items from local cart by their indices.
4787
4822
  * Use after partial checkout to remove only the purchased items.
@@ -4829,6 +4864,83 @@ declare class OmniSyncClient {
4829
4864
  clearCartOnSuccess?: boolean;
4830
4865
  selectedIndices?: number[];
4831
4866
  }): Promise<GuestOrderResponse>;
4867
+ /**
4868
+ * Get the active guest checkout session info.
4869
+ * Use this to check if there's an active checkout before handling payment success.
4870
+ *
4871
+ * @returns The active checkout info or null if no checkout is active
4872
+ *
4873
+ * @example
4874
+ * ```typescript
4875
+ * const activeCheckout = omni.getActiveGuestCheckout();
4876
+ * if (activeCheckout) {
4877
+ * console.log('Active checkout:', activeCheckout.checkoutId);
4878
+ * console.log('Partial checkout:', activeCheckout.selectedIndices?.length);
4879
+ * }
4880
+ * ```
4881
+ */
4882
+ getActiveGuestCheckout(): {
4883
+ checkoutId: string;
4884
+ cartId: string;
4885
+ selectedIndices?: number[];
4886
+ } | null;
4887
+ /**
4888
+ * Handle payment success - automatically clears the cart (both local and server).
4889
+ *
4890
+ * Call this after Stripe payment succeeds (payment_intent.succeeded or confirmPayment success).
4891
+ * This handles ALL checkout scenarios:
4892
+ *
4893
+ * **For guest users (local cart):**
4894
+ * - Full checkout: clears entire localStorage cart
4895
+ * - Partial checkout: removes only the purchased items
4896
+ *
4897
+ * **For logged-in users (server cart):**
4898
+ * - Clears the cached cart ID so next `smartGetCart()` fetches fresh data
4899
+ * - The server cart is already marked as CONVERTED by the webhook
4900
+ *
4901
+ * **IMPORTANT:** Call this from your payment success handler (e.g., after stripe.confirmPayment succeeds,
4902
+ * or on your success page after redirect). This works for both guests AND logged-in users!
4903
+ *
4904
+ * @param checkoutId - Optional checkout ID for validation
4905
+ * @returns Object indicating whether cart was cleared and how
4906
+ *
4907
+ * @example
4908
+ * ```typescript
4909
+ * // After stripe.confirmPayment() succeeds (works for guests AND logged-in users)
4910
+ * const { error, paymentIntent } = await stripe.confirmPayment({
4911
+ * elements,
4912
+ * confirmParams: { return_url: '/checkout/success' },
4913
+ * redirect: 'if_required',
4914
+ * });
4915
+ *
4916
+ * if (!error && paymentIntent?.status === 'succeeded') {
4917
+ * // Clear the cart automatically - handles all scenarios!
4918
+ * const result = omni.handlePaymentSuccess(checkoutId);
4919
+ * console.log('Cart cleared:', result.cleared);
4920
+ * console.log('User type:', result.userType); // 'guest' or 'customer'
4921
+ * }
4922
+ * ```
4923
+ *
4924
+ * @example
4925
+ * ```typescript
4926
+ * // On success page (after redirect)
4927
+ * const checkoutId = new URLSearchParams(location.search).get('checkout_id');
4928
+ * if (checkoutId) {
4929
+ * omni.handlePaymentSuccess(checkoutId);
4930
+ * }
4931
+ * ```
4932
+ */
4933
+ handlePaymentSuccess(checkoutId?: string): {
4934
+ cleared: boolean;
4935
+ mode: 'full' | 'partial' | 'none';
4936
+ userType: 'guest' | 'customer';
4937
+ itemsRemoved?: number;
4938
+ };
4939
+ /**
4940
+ * Clear the active guest checkout tracking without clearing the cart.
4941
+ * Use this if the user abandons checkout or navigates away.
4942
+ */
4943
+ clearActiveGuestCheckout(): void;
4832
4944
  /**
4833
4945
  * Create order from custom data (not from local cart)
4834
4946
  * Use this if you manage cart state yourself
package/dist/index.d.ts CHANGED
@@ -1692,15 +1692,27 @@ interface ShippingRate {
1692
1692
  * **Note:** Order is created automatically via webhook when payment succeeds.
1693
1693
  * No need to call `completeCheckout()` - it happens automatically.
1694
1694
  *
1695
+ * **IMPORTANT: Order Summary Display**
1696
+ * Always use `checkout.lineItems` for displaying the Order Summary during checkout!
1697
+ * This is especially important for **partial checkout** (AliExpress-style) where the user
1698
+ * selects only some items from their cart. The `lineItems` array contains ONLY the items
1699
+ * being purchased in this checkout, NOT the entire cart.
1700
+ *
1695
1701
  * **IMPORTANT: Price fields are strings**
1696
1702
  * All monetary fields (subtotal, discountAmount, shippingAmount, taxAmount, total)
1697
1703
  * are strings to preserve decimal precision. Use parseFloat() for calculations.
1698
1704
  *
1699
1705
  * @example
1700
1706
  * ```typescript
1701
- * // Display checkout summary
1707
+ * // Display checkout summary - use checkout.lineItems, NOT localCart!
1702
1708
  * const checkout = await omni.getCheckout(checkoutId);
1703
1709
  *
1710
+ * // Order Summary - ALWAYS use checkout.lineItems
1711
+ * checkout.lineItems.forEach(item => {
1712
+ * console.log(item.product.name, item.quantity, item.unitPrice);
1713
+ * });
1714
+ *
1715
+ * // Totals
1704
1716
  * const subtotal = parseFloat(checkout.subtotal);
1705
1717
  * const discount = parseFloat(checkout.discountAmount);
1706
1718
  * const shipping = parseFloat(checkout.shippingAmount);
@@ -1712,11 +1724,6 @@ interface ShippingRate {
1712
1724
  * console.log(`Shipping: $${shipping.toFixed(2)}`);
1713
1725
  * console.log(`Tax: $${tax.toFixed(2)}`);
1714
1726
  * console.log(`Total: $${total.toFixed(2)}`);
1715
- *
1716
- * // Access line items (nested structure)
1717
- * checkout.lineItems.forEach(item => {
1718
- * console.log(item.product.name, item.quantity);
1719
- * });
1720
1727
  * ```
1721
1728
  *
1722
1729
  * @see CheckoutLineItem for item structure
@@ -3057,6 +3064,11 @@ declare class OmniSyncClient {
3057
3064
  * When a cart has this ID, operations use localStorage instead of server API.
3058
3065
  */
3059
3066
  private readonly VIRTUAL_LOCAL_CART_ID;
3067
+ /**
3068
+ * localStorage key for persisting active checkout across page redirects.
3069
+ * This is needed because Stripe redirects lose in-memory state.
3070
+ */
3071
+ private readonly ACTIVE_CHECKOUT_KEY;
3060
3072
  private readonly onAuthError?;
3061
3073
  constructor(options: OmniSyncClientOptions);
3062
3074
  /**
@@ -4748,6 +4760,11 @@ declare class OmniSyncClient {
4748
4760
  * Pass `selectedIndices` to checkout only specific items from the local cart.
4749
4761
  * Use the index of each item in the cart.items array.
4750
4762
  *
4763
+ * **IMPORTANT - Order Summary Display:**
4764
+ * After calling this function, use `getCheckout(checkoutId)` to get the checkout
4765
+ * and display `checkout.lineItems` in your Order Summary - NOT the local cart items!
4766
+ * The checkout.lineItems contains ONLY the selected items for this checkout.
4767
+ *
4751
4768
  * @param options.selectedIndices - Optional array of item indices for partial checkout
4752
4769
  * @returns Tracking result with checkoutId if enabled
4753
4770
  *
@@ -4760,19 +4777,22 @@ declare class OmniSyncClient {
4760
4777
  * const result = await omni.startGuestCheckout({ selectedIndices: [0, 2] });
4761
4778
  *
4762
4779
  * if (result.tracked) {
4763
- * // Store checkoutId for later use
4764
- * console.log('Checkout tracked:', result.checkoutId);
4780
+ * // IMPORTANT: Fetch checkout and use checkout.lineItems for Order Summary!
4781
+ * const checkout = await omni.getCheckout(result.checkoutId);
4782
+ *
4783
+ * // Display Order Summary using checkout.lineItems (NOT localCart.items!)
4784
+ * // checkout.lineItems contains ONLY the selected items
4785
+ * checkout.lineItems.forEach(item => {
4786
+ * console.log(item.product.name, item.quantity, item.unitPrice);
4787
+ * });
4765
4788
  *
4766
4789
  * // Update checkout with address
4767
- * await omni.updateGuestCheckout(result.checkoutId, {
4790
+ * await omni.updateGuestCheckoutAddress(result.checkoutId, {
4768
4791
  * shippingAddress: { ... },
4769
4792
  * });
4770
4793
  *
4771
- * // Complete checkout
4772
- * const order = await omni.completeGuestCheckout(result.checkoutId);
4773
- *
4774
- * // For partial checkout: remove only purchased items
4775
- * omni.removeLocalCartItemsByIndex([0, 2]);
4794
+ * // After payment success, call handlePaymentSuccess() to clear cart
4795
+ * omni.handlePaymentSuccess(result.checkoutId);
4776
4796
  * } else {
4777
4797
  * // Tracking not enabled, use regular submitGuestOrder
4778
4798
  * const order = await omni.submitGuestOrder();
@@ -4782,6 +4802,21 @@ declare class OmniSyncClient {
4782
4802
  startGuestCheckout(options?: {
4783
4803
  selectedIndices?: number[];
4784
4804
  }): Promise<GuestCheckoutStartResponse>;
4805
+ /**
4806
+ * Save active checkout to localStorage (persists across page redirects)
4807
+ * @internal
4808
+ */
4809
+ private saveActiveCheckout;
4810
+ /**
4811
+ * Load active checkout from localStorage
4812
+ * @internal
4813
+ */
4814
+ private loadActiveCheckout;
4815
+ /**
4816
+ * Clear active checkout from localStorage
4817
+ * @internal
4818
+ */
4819
+ private clearActiveCheckoutStorage;
4785
4820
  /**
4786
4821
  * Remove specific items from local cart by their indices.
4787
4822
  * Use after partial checkout to remove only the purchased items.
@@ -4829,6 +4864,83 @@ declare class OmniSyncClient {
4829
4864
  clearCartOnSuccess?: boolean;
4830
4865
  selectedIndices?: number[];
4831
4866
  }): Promise<GuestOrderResponse>;
4867
+ /**
4868
+ * Get the active guest checkout session info.
4869
+ * Use this to check if there's an active checkout before handling payment success.
4870
+ *
4871
+ * @returns The active checkout info or null if no checkout is active
4872
+ *
4873
+ * @example
4874
+ * ```typescript
4875
+ * const activeCheckout = omni.getActiveGuestCheckout();
4876
+ * if (activeCheckout) {
4877
+ * console.log('Active checkout:', activeCheckout.checkoutId);
4878
+ * console.log('Partial checkout:', activeCheckout.selectedIndices?.length);
4879
+ * }
4880
+ * ```
4881
+ */
4882
+ getActiveGuestCheckout(): {
4883
+ checkoutId: string;
4884
+ cartId: string;
4885
+ selectedIndices?: number[];
4886
+ } | null;
4887
+ /**
4888
+ * Handle payment success - automatically clears the cart (both local and server).
4889
+ *
4890
+ * Call this after Stripe payment succeeds (payment_intent.succeeded or confirmPayment success).
4891
+ * This handles ALL checkout scenarios:
4892
+ *
4893
+ * **For guest users (local cart):**
4894
+ * - Full checkout: clears entire localStorage cart
4895
+ * - Partial checkout: removes only the purchased items
4896
+ *
4897
+ * **For logged-in users (server cart):**
4898
+ * - Clears the cached cart ID so next `smartGetCart()` fetches fresh data
4899
+ * - The server cart is already marked as CONVERTED by the webhook
4900
+ *
4901
+ * **IMPORTANT:** Call this from your payment success handler (e.g., after stripe.confirmPayment succeeds,
4902
+ * or on your success page after redirect). This works for both guests AND logged-in users!
4903
+ *
4904
+ * @param checkoutId - Optional checkout ID for validation
4905
+ * @returns Object indicating whether cart was cleared and how
4906
+ *
4907
+ * @example
4908
+ * ```typescript
4909
+ * // After stripe.confirmPayment() succeeds (works for guests AND logged-in users)
4910
+ * const { error, paymentIntent } = await stripe.confirmPayment({
4911
+ * elements,
4912
+ * confirmParams: { return_url: '/checkout/success' },
4913
+ * redirect: 'if_required',
4914
+ * });
4915
+ *
4916
+ * if (!error && paymentIntent?.status === 'succeeded') {
4917
+ * // Clear the cart automatically - handles all scenarios!
4918
+ * const result = omni.handlePaymentSuccess(checkoutId);
4919
+ * console.log('Cart cleared:', result.cleared);
4920
+ * console.log('User type:', result.userType); // 'guest' or 'customer'
4921
+ * }
4922
+ * ```
4923
+ *
4924
+ * @example
4925
+ * ```typescript
4926
+ * // On success page (after redirect)
4927
+ * const checkoutId = new URLSearchParams(location.search).get('checkout_id');
4928
+ * if (checkoutId) {
4929
+ * omni.handlePaymentSuccess(checkoutId);
4930
+ * }
4931
+ * ```
4932
+ */
4933
+ handlePaymentSuccess(checkoutId?: string): {
4934
+ cleared: boolean;
4935
+ mode: 'full' | 'partial' | 'none';
4936
+ userType: 'guest' | 'customer';
4937
+ itemsRemoved?: number;
4938
+ };
4939
+ /**
4940
+ * Clear the active guest checkout tracking without clearing the cart.
4941
+ * Use this if the user abandons checkout or navigates away.
4942
+ */
4943
+ clearActiveGuestCheckout(): void;
4832
4944
  /**
4833
4945
  * Create order from custom data (not from local cart)
4834
4946
  * Use this if you manage cart state yourself
package/dist/index.js CHANGED
@@ -54,6 +54,11 @@ var OmniSyncClient = class {
54
54
  * When a cart has this ID, operations use localStorage instead of server API.
55
55
  */
56
56
  this.VIRTUAL_LOCAL_CART_ID = "__local__";
57
+ /**
58
+ * localStorage key for persisting active checkout across page redirects.
59
+ * This is needed because Stripe redirects lose in-memory state.
60
+ */
61
+ this.ACTIVE_CHECKOUT_KEY = "omni_active_checkout";
57
62
  // -------------------- Local Cart (Client-Side for Guests) --------------------
58
63
  // These methods store cart data in localStorage - NO API calls!
59
64
  // Use for guest users in vibe-coded sites
@@ -3069,6 +3074,11 @@ var OmniSyncClient = class {
3069
3074
  * Pass `selectedIndices` to checkout only specific items from the local cart.
3070
3075
  * Use the index of each item in the cart.items array.
3071
3076
  *
3077
+ * **IMPORTANT - Order Summary Display:**
3078
+ * After calling this function, use `getCheckout(checkoutId)` to get the checkout
3079
+ * and display `checkout.lineItems` in your Order Summary - NOT the local cart items!
3080
+ * The checkout.lineItems contains ONLY the selected items for this checkout.
3081
+ *
3072
3082
  * @param options.selectedIndices - Optional array of item indices for partial checkout
3073
3083
  * @returns Tracking result with checkoutId if enabled
3074
3084
  *
@@ -3081,19 +3091,22 @@ var OmniSyncClient = class {
3081
3091
  * const result = await omni.startGuestCheckout({ selectedIndices: [0, 2] });
3082
3092
  *
3083
3093
  * if (result.tracked) {
3084
- * // Store checkoutId for later use
3085
- * console.log('Checkout tracked:', result.checkoutId);
3094
+ * // IMPORTANT: Fetch checkout and use checkout.lineItems for Order Summary!
3095
+ * const checkout = await omni.getCheckout(result.checkoutId);
3096
+ *
3097
+ * // Display Order Summary using checkout.lineItems (NOT localCart.items!)
3098
+ * // checkout.lineItems contains ONLY the selected items
3099
+ * checkout.lineItems.forEach(item => {
3100
+ * console.log(item.product.name, item.quantity, item.unitPrice);
3101
+ * });
3086
3102
  *
3087
3103
  * // Update checkout with address
3088
- * await omni.updateGuestCheckout(result.checkoutId, {
3104
+ * await omni.updateGuestCheckoutAddress(result.checkoutId, {
3089
3105
  * shippingAddress: { ... },
3090
3106
  * });
3091
3107
  *
3092
- * // Complete checkout
3093
- * const order = await omni.completeGuestCheckout(result.checkoutId);
3094
- *
3095
- * // For partial checkout: remove only purchased items
3096
- * omni.removeLocalCartItemsByIndex([0, 2]);
3108
+ * // After payment success, call handlePaymentSuccess() to clear cart
3109
+ * omni.handlePaymentSuccess(result.checkoutId);
3097
3110
  * } else {
3098
3111
  * // Tracking not enabled, use regular submitGuestOrder
3099
3112
  * const order = await omni.submitGuestOrder();
@@ -3121,8 +3134,48 @@ var OmniSyncClient = class {
3121
3134
  customer: cart.customer
3122
3135
  }
3123
3136
  );
3137
+ if (response.tracked && response.checkoutId && response.cartId) {
3138
+ this.saveActiveCheckout({
3139
+ checkoutId: response.checkoutId,
3140
+ cartId: response.cartId,
3141
+ selectedIndices: options?.selectedIndices
3142
+ });
3143
+ }
3124
3144
  return response;
3125
3145
  }
3146
+ /**
3147
+ * Save active checkout to localStorage (persists across page redirects)
3148
+ * @internal
3149
+ */
3150
+ saveActiveCheckout(checkout) {
3151
+ if (typeof window !== "undefined" && window.localStorage) {
3152
+ localStorage.setItem(this.ACTIVE_CHECKOUT_KEY, JSON.stringify(checkout));
3153
+ }
3154
+ }
3155
+ /**
3156
+ * Load active checkout from localStorage
3157
+ * @internal
3158
+ */
3159
+ loadActiveCheckout() {
3160
+ if (typeof window === "undefined" || !window.localStorage) {
3161
+ return null;
3162
+ }
3163
+ try {
3164
+ const data = localStorage.getItem(this.ACTIVE_CHECKOUT_KEY);
3165
+ return data ? JSON.parse(data) : null;
3166
+ } catch {
3167
+ return null;
3168
+ }
3169
+ }
3170
+ /**
3171
+ * Clear active checkout from localStorage
3172
+ * @internal
3173
+ */
3174
+ clearActiveCheckoutStorage() {
3175
+ if (typeof window !== "undefined" && window.localStorage) {
3176
+ localStorage.removeItem(this.ACTIVE_CHECKOUT_KEY);
3177
+ }
3178
+ }
3126
3179
  /**
3127
3180
  * Remove specific items from local cart by their indices.
3128
3181
  * Use after partial checkout to remove only the purchased items.
@@ -3213,6 +3266,113 @@ var OmniSyncClient = class {
3213
3266
  }
3214
3267
  return result;
3215
3268
  }
3269
+ /**
3270
+ * Get the active guest checkout session info.
3271
+ * Use this to check if there's an active checkout before handling payment success.
3272
+ *
3273
+ * @returns The active checkout info or null if no checkout is active
3274
+ *
3275
+ * @example
3276
+ * ```typescript
3277
+ * const activeCheckout = omni.getActiveGuestCheckout();
3278
+ * if (activeCheckout) {
3279
+ * console.log('Active checkout:', activeCheckout.checkoutId);
3280
+ * console.log('Partial checkout:', activeCheckout.selectedIndices?.length);
3281
+ * }
3282
+ * ```
3283
+ */
3284
+ getActiveGuestCheckout() {
3285
+ return this.loadActiveCheckout();
3286
+ }
3287
+ /**
3288
+ * Handle payment success - automatically clears the cart (both local and server).
3289
+ *
3290
+ * Call this after Stripe payment succeeds (payment_intent.succeeded or confirmPayment success).
3291
+ * This handles ALL checkout scenarios:
3292
+ *
3293
+ * **For guest users (local cart):**
3294
+ * - Full checkout: clears entire localStorage cart
3295
+ * - Partial checkout: removes only the purchased items
3296
+ *
3297
+ * **For logged-in users (server cart):**
3298
+ * - Clears the cached cart ID so next `smartGetCart()` fetches fresh data
3299
+ * - The server cart is already marked as CONVERTED by the webhook
3300
+ *
3301
+ * **IMPORTANT:** Call this from your payment success handler (e.g., after stripe.confirmPayment succeeds,
3302
+ * or on your success page after redirect). This works for both guests AND logged-in users!
3303
+ *
3304
+ * @param checkoutId - Optional checkout ID for validation
3305
+ * @returns Object indicating whether cart was cleared and how
3306
+ *
3307
+ * @example
3308
+ * ```typescript
3309
+ * // After stripe.confirmPayment() succeeds (works for guests AND logged-in users)
3310
+ * const { error, paymentIntent } = await stripe.confirmPayment({
3311
+ * elements,
3312
+ * confirmParams: { return_url: '/checkout/success' },
3313
+ * redirect: 'if_required',
3314
+ * });
3315
+ *
3316
+ * if (!error && paymentIntent?.status === 'succeeded') {
3317
+ * // Clear the cart automatically - handles all scenarios!
3318
+ * const result = omni.handlePaymentSuccess(checkoutId);
3319
+ * console.log('Cart cleared:', result.cleared);
3320
+ * console.log('User type:', result.userType); // 'guest' or 'customer'
3321
+ * }
3322
+ * ```
3323
+ *
3324
+ * @example
3325
+ * ```typescript
3326
+ * // On success page (after redirect)
3327
+ * const checkoutId = new URLSearchParams(location.search).get('checkout_id');
3328
+ * if (checkoutId) {
3329
+ * omni.handlePaymentSuccess(checkoutId);
3330
+ * }
3331
+ * ```
3332
+ */
3333
+ handlePaymentSuccess(checkoutId) {
3334
+ const isLoggedIn = this.isCustomerLoggedIn();
3335
+ if (isLoggedIn) {
3336
+ this.customerCartId = null;
3337
+ }
3338
+ const activeCheckout = this.loadActiveCheckout();
3339
+ if (checkoutId && activeCheckout && activeCheckout.checkoutId !== checkoutId) {
3340
+ console.warn(
3341
+ `handlePaymentSuccess: checkoutId mismatch. Expected ${activeCheckout.checkoutId}, got ${checkoutId}. Proceeding with cleanup.`
3342
+ );
3343
+ }
3344
+ this.clearActiveCheckoutStorage();
3345
+ if (isLoggedIn) {
3346
+ this.clearLocalCart();
3347
+ return {
3348
+ cleared: true,
3349
+ mode: "full",
3350
+ userType: "customer"
3351
+ };
3352
+ }
3353
+ if (activeCheckout?.selectedIndices && activeCheckout.selectedIndices.length > 0) {
3354
+ this.removeLocalCartItemsByIndex(activeCheckout.selectedIndices);
3355
+ return {
3356
+ cleared: true,
3357
+ mode: "partial",
3358
+ userType: "guest",
3359
+ itemsRemoved: activeCheckout.selectedIndices.length
3360
+ };
3361
+ }
3362
+ this.clearLocalCart();
3363
+ return {
3364
+ cleared: true,
3365
+ mode: "full",
3366
+ userType: "guest"
3367
+ };
3368
+ }
3369
+ /**
3370
+ * Clear the active guest checkout tracking without clearing the cart.
3371
+ * Use this if the user abandons checkout or navigates away.
3372
+ */
3373
+ clearActiveGuestCheckout() {
3374
+ this.clearActiveCheckoutStorage();
3375
+ }
3216
3376
  /**
3217
3377
  * Create order from custom data (not from local cart)
3218
3378
  * Use this if you manage cart state yourself
package/dist/index.mjs CHANGED
@@ -17,6 +17,11 @@ var OmniSyncClient = class {
17
17
  * When a cart has this ID, operations use localStorage instead of server API.
18
18
  */
19
19
  this.VIRTUAL_LOCAL_CART_ID = "__local__";
20
+ /**
21
+ * localStorage key for persisting active checkout across page redirects.
22
+ * This is needed because Stripe redirects lose in-memory state.
23
+ */
24
+ this.ACTIVE_CHECKOUT_KEY = "omni_active_checkout";
20
25
  // -------------------- Local Cart (Client-Side for Guests) --------------------
21
26
  // These methods store cart data in localStorage - NO API calls!
22
27
  // Use for guest users in vibe-coded sites
@@ -3032,6 +3037,11 @@ var OmniSyncClient = class {
3032
3037
  * Pass `selectedIndices` to checkout only specific items from the local cart.
3033
3038
  * Use the index of each item in the cart.items array.
3034
3039
  *
3040
+ * **IMPORTANT - Order Summary Display:**
3041
+ * After calling this function, use `getCheckout(checkoutId)` to get the checkout
3042
+ * and display `checkout.lineItems` in your Order Summary - NOT the local cart items!
3043
+ * The checkout.lineItems contains ONLY the selected items for this checkout.
3044
+ *
3035
3045
  * @param options.selectedIndices - Optional array of item indices for partial checkout
3036
3046
  * @returns Tracking result with checkoutId if enabled
3037
3047
  *
@@ -3044,19 +3054,22 @@ var OmniSyncClient = class {
3044
3054
  * const result = await omni.startGuestCheckout({ selectedIndices: [0, 2] });
3045
3055
  *
3046
3056
  * if (result.tracked) {
3047
- * // Store checkoutId for later use
3048
- * console.log('Checkout tracked:', result.checkoutId);
3057
+ * // IMPORTANT: Fetch checkout and use checkout.lineItems for Order Summary!
3058
+ * const checkout = await omni.getCheckout(result.checkoutId);
3059
+ *
3060
+ * // Display Order Summary using checkout.lineItems (NOT localCart.items!)
3061
+ * // checkout.lineItems contains ONLY the selected items
3062
+ * checkout.lineItems.forEach(item => {
3063
+ * console.log(item.product.name, item.quantity, item.unitPrice);
3064
+ * });
3049
3065
  *
3050
3066
  * // Update checkout with address
3051
- * await omni.updateGuestCheckout(result.checkoutId, {
3067
+ * await omni.updateGuestCheckoutAddress(result.checkoutId, {
3052
3068
  * shippingAddress: { ... },
3053
3069
  * });
3054
3070
  *
3055
- * // Complete checkout
3056
- * const order = await omni.completeGuestCheckout(result.checkoutId);
3057
- *
3058
- * // For partial checkout: remove only purchased items
3059
- * omni.removeLocalCartItemsByIndex([0, 2]);
3071
+ * // After payment success, call handlePaymentSuccess() to clear cart
3072
+ * omni.handlePaymentSuccess(result.checkoutId);
3060
3073
  * } else {
3061
3074
  * // Tracking not enabled, use regular submitGuestOrder
3062
3075
  * const order = await omni.submitGuestOrder();
@@ -3084,8 +3097,48 @@ var OmniSyncClient = class {
3084
3097
  customer: cart.customer
3085
3098
  }
3086
3099
  );
3100
+ if (response.tracked && response.checkoutId && response.cartId) {
3101
+ this.saveActiveCheckout({
3102
+ checkoutId: response.checkoutId,
3103
+ cartId: response.cartId,
3104
+ selectedIndices: options?.selectedIndices
3105
+ });
3106
+ }
3087
3107
  return response;
3088
3108
  }
3109
+ /**
3110
+ * Save active checkout to localStorage (persists across page redirects)
3111
+ * @internal
3112
+ */
3113
+ saveActiveCheckout(checkout) {
3114
+ if (typeof window !== "undefined" && window.localStorage) {
3115
+ localStorage.setItem(this.ACTIVE_CHECKOUT_KEY, JSON.stringify(checkout));
3116
+ }
3117
+ }
3118
+ /**
3119
+ * Load active checkout from localStorage
3120
+ * @internal
3121
+ */
3122
+ loadActiveCheckout() {
3123
+ if (typeof window === "undefined" || !window.localStorage) {
3124
+ return null;
3125
+ }
3126
+ try {
3127
+ const data = localStorage.getItem(this.ACTIVE_CHECKOUT_KEY);
3128
+ return data ? JSON.parse(data) : null;
3129
+ } catch {
3130
+ return null;
3131
+ }
3132
+ }
3133
+ /**
3134
+ * Clear active checkout from localStorage
3135
+ * @internal
3136
+ */
3137
+ clearActiveCheckoutStorage() {
3138
+ if (typeof window !== "undefined" && window.localStorage) {
3139
+ localStorage.removeItem(this.ACTIVE_CHECKOUT_KEY);
3140
+ }
3141
+ }
3089
3142
  /**
3090
3143
  * Remove specific items from local cart by their indices.
3091
3144
  * Use after partial checkout to remove only the purchased items.
@@ -3176,6 +3229,113 @@ var OmniSyncClient = class {
3176
3229
  }
3177
3230
  return result;
3178
3231
  }
3232
+ /**
3233
+ * Get the active guest checkout session info.
3234
+ * Use this to check if there's an active checkout before handling payment success.
3235
+ *
3236
+ * @returns The active checkout info or null if no checkout is active
3237
+ *
3238
+ * @example
3239
+ * ```typescript
3240
+ * const activeCheckout = omni.getActiveGuestCheckout();
3241
+ * if (activeCheckout) {
3242
+ * console.log('Active checkout:', activeCheckout.checkoutId);
3243
+ * console.log('Partial checkout:', activeCheckout.selectedIndices?.length);
3244
+ * }
3245
+ * ```
3246
+ */
3247
+ getActiveGuestCheckout() {
3248
+ return this.loadActiveCheckout();
3249
+ }
3250
+ /**
3251
+ * Handle payment success - automatically clears the cart (both local and server).
3252
+ *
3253
+ * Call this after Stripe payment succeeds (payment_intent.succeeded or confirmPayment success).
3254
+ * This handles ALL checkout scenarios:
3255
+ *
3256
+ * **For guest users (local cart):**
3257
+ * - Full checkout: clears entire localStorage cart
3258
+ * - Partial checkout: removes only the purchased items
3259
+ *
3260
+ * **For logged-in users (server cart):**
3261
+ * - Clears the cached cart ID so next `smartGetCart()` fetches fresh data
3262
+ * - The server cart is already marked as CONVERTED by the webhook
3263
+ *
3264
+ * **IMPORTANT:** Call this from your payment success handler (e.g., after stripe.confirmPayment succeeds,
3265
+ * or on your success page after redirect). This works for both guests AND logged-in users!
3266
+ *
3267
+ * @param checkoutId - Optional checkout ID for validation
3268
+ * @returns Object indicating whether cart was cleared and how
3269
+ *
3270
+ * @example
3271
+ * ```typescript
3272
+ * // After stripe.confirmPayment() succeeds (works for guests AND logged-in users)
3273
+ * const { error, paymentIntent } = await stripe.confirmPayment({
3274
+ * elements,
3275
+ * confirmParams: { return_url: '/checkout/success' },
3276
+ * redirect: 'if_required',
3277
+ * });
3278
+ *
3279
+ * if (!error && paymentIntent?.status === 'succeeded') {
3280
+ * // Clear the cart automatically - handles all scenarios!
3281
+ * const result = omni.handlePaymentSuccess(checkoutId);
3282
+ * console.log('Cart cleared:', result.cleared);
3283
+ * console.log('User type:', result.userType); // 'guest' or 'customer'
3284
+ * }
3285
+ * ```
3286
+ *
3287
+ * @example
3288
+ * ```typescript
3289
+ * // On success page (after redirect)
3290
+ * const checkoutId = new URLSearchParams(location.search).get('checkout_id');
3291
+ * if (checkoutId) {
3292
+ * omni.handlePaymentSuccess(checkoutId);
3293
+ * }
3294
+ * ```
3295
+ */
3296
+ handlePaymentSuccess(checkoutId) {
3297
+ const isLoggedIn = this.isCustomerLoggedIn();
3298
+ if (isLoggedIn) {
3299
+ this.customerCartId = null;
3300
+ }
3301
+ const activeCheckout = this.loadActiveCheckout();
3302
+ if (checkoutId && activeCheckout && activeCheckout.checkoutId !== checkoutId) {
3303
+ console.warn(
3304
+ `handlePaymentSuccess: checkoutId mismatch. Expected ${activeCheckout.checkoutId}, got ${checkoutId}. Proceeding with cleanup.`
3305
+ );
3306
+ }
3307
+ this.clearActiveCheckoutStorage();
3308
+ if (isLoggedIn) {
3309
+ this.clearLocalCart();
3310
+ return {
3311
+ cleared: true,
3312
+ mode: "full",
3313
+ userType: "customer"
3314
+ };
3315
+ }
3316
+ if (activeCheckout?.selectedIndices && activeCheckout.selectedIndices.length > 0) {
3317
+ this.removeLocalCartItemsByIndex(activeCheckout.selectedIndices);
3318
+ return {
3319
+ cleared: true,
3320
+ mode: "partial",
3321
+ userType: "guest",
3322
+ itemsRemoved: activeCheckout.selectedIndices.length
3323
+ };
3324
+ }
3325
+ this.clearLocalCart();
3326
+ return {
3327
+ cleared: true,
3328
+ mode: "full",
3329
+ userType: "guest"
3330
+ };
3331
+ }
3332
+ /**
3333
+ * Clear the active guest checkout tracking without clearing the cart.
3334
+ * Use this if the user abandons checkout or navigates away.
3335
+ */
3336
+ clearActiveGuestCheckout() {
3337
+ this.clearActiveCheckoutStorage();
3338
+ }
3179
3339
  /**
3180
3340
  * Create order from custom data (not from local cart)
3181
3341
  * Use this if you manage cart state yourself
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omni-sync-sdk",
3
- "version": "0.20.3",
3
+ "version": "0.21.0",
4
4
  "description": "Official SDK for building e-commerce storefronts with OmniSync Platform. Perfect for vibe-coded sites, AI-built stores (Cursor, Lovable, v0), and custom storefronts.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -16,14 +16,6 @@
16
16
  "dist",
17
17
  "README.md"
18
18
  ],
19
- "scripts": {
20
- "build": "tsup src/index.ts --format cjs,esm --dts",
21
- "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
22
- "lint": "eslint \"src/**/*.ts\"",
23
- "test": "vitest run",
24
- "test:watch": "vitest",
25
- "prepublishOnly": "pnpm build"
26
- },
27
19
  "keywords": [
28
20
  "omni-sync",
29
21
  "e-commerce",
@@ -72,5 +64,12 @@
72
64
  "typescript": {
73
65
  "optional": true
74
66
  }
67
+ },
68
+ "scripts": {
69
+ "build": "tsup src/index.ts --format cjs,esm --dts",
70
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
71
+ "lint": "eslint \"src/**/*.ts\"",
72
+ "test": "vitest run",
73
+ "test:watch": "vitest"
75
74
  }
76
- }
75
+ }