omni-sync-sdk 0.21.1 → 0.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +162 -7
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -121,7 +121,32 @@ const { data: products } = await omni.getProducts();
121
121
 
122
122
  > **AI Agents / Vibe-Coders:** Read this section carefully! These are common misunderstandings.
123
123
 
124
- ### 1. All Types Are Exported - Don't Create Local Interfaces!
124
+ ### 1. Guest Checkout - Don't Use createCheckout with Local Cart!
125
+
126
+ **This is the #1 cause of "Cart not found" errors!**
127
+
128
+ ```typescript
129
+ // ❌ WRONG - Local cart ID "__local__" doesn't exist on server!
130
+ const cart = await omni.smartGetCart(); // Returns { id: "__local__", ... }
131
+ const checkout = await omni.createCheckout({ cartId: cart.id }); // 💥 ERROR: Cart not found
132
+
133
+ // ✅ CORRECT - Use startGuestCheckout() for guest users
134
+ const result = await omni.startGuestCheckout();
135
+ if (result.tracked) {
136
+ const checkout = await omni.getCheckout(result.checkoutId);
137
+ // Continue with payment flow...
138
+ }
139
+
140
+ // ✅ ALTERNATIVE - Use submitGuestOrder() for simple checkout without payment UI
141
+ const order = await omni.submitGuestOrder();
142
+ ```
143
+
144
+ **Rule of thumb:**
145
+
146
+ - Guest user + Local cart → `startGuestCheckout()` or `submitGuestOrder()`
147
+ - Logged-in user + Server cart → `createCheckout({ cartId })`
148
+
149
+ ### 2. All Types Are Exported - Don't Create Local Interfaces!
125
150
 
126
151
  ```typescript
127
152
  // ❌ WRONG - Don't create these locally
@@ -331,16 +356,74 @@ suggestions.products.map(p => (
331
356
  ));
332
357
  ```
333
358
 
359
+ ### 15. Forgetting to Clear Cart After Payment
360
+
361
+ **This causes "ghost items" in the cart after successful payment!**
362
+
363
+ ```typescript
364
+ // ❌ WRONG - Cart items remain after payment!
365
+ // In your success page:
366
+ export default function SuccessPage() {
367
+ return <div>Thank you for your order!</div>;
368
+ // User goes back to shop → still sees purchased items in cart!
369
+ }
370
+
371
+ // ✅ CORRECT - Call handlePaymentSuccess() on success page
372
+ export default function SuccessPage() {
373
+ const checkoutId = new URLSearchParams(window.location.search).get('checkout_id');
374
+
375
+ useEffect(() => {
376
+ // Clear cart items that were purchased
377
+ omni.handlePaymentSuccess(checkoutId);
378
+ }, []);
379
+
380
+ return <div>Thank you for your order!</div>;
381
+ }
382
+ ```
383
+
384
+ **Why is this needed?**
385
+
386
+ - Guest users: Local cart persists in localStorage across page refreshes and Stripe redirects
387
+ - Without cleanup, purchased items remain visible in cart
388
+ - `handlePaymentSuccess()` handles both full and partial checkout cleanup
389
+
334
390
  ---
335
391
 
336
392
  ## Checkout: Guest vs Logged-In Customer
337
393
 
338
- > **IMPORTANT:** There are TWO different checkout flows. You MUST use the correct one based on whether the customer is logged in or not.
394
+ > **⚠️ CRITICAL:** There are TWO different checkout flows. Using the wrong one will cause errors!
395
+
396
+ | Customer Type | Cart Type | With Payment (Stripe) | Without Payment UI |
397
+ | ------------- | ------------------------- | ---------------------- | -------------------- |
398
+ | **Guest** | Local Cart (localStorage) | `startGuestCheckout()` | `submitGuestOrder()` |
399
+ | **Logged In** | Server Cart | `createCheckout()` | `completeCheckout()` |
400
+
401
+ ### ❌ COMMON MISTAKE - Don't Do This!
402
+
403
+ ```typescript
404
+ // ❌ WRONG - This will FAIL with "Cart not found" error!
405
+ const cart = omni.getLocalCart(); // Returns cart with id: "__local__"
406
+ const checkout = await omni.createCheckout({ cartId: cart.id }); // ERROR!
407
+
408
+ // The "__local__" ID is virtual - it doesn't exist on the server!
409
+ ```
339
410
 
340
- | Customer Type | Cart Type | Checkout Method | Orders Linked to Account? |
341
- | ------------- | ------------------------- | -------------------- | ------------------------- |
342
- | **Guest** | Local Cart (localStorage) | `submitGuestOrder()` | No |
343
- | **Logged In** | Server Cart | `completeCheckout()` | Yes |
411
+ ### Correct Flow for Guest Checkout with Payment
412
+
413
+ ```typescript
414
+ // CORRECT - Use startGuestCheckout() for guests with local cart
415
+ const result = await omni.startGuestCheckout();
416
+
417
+ if (result.tracked) {
418
+ // Now you have a REAL checkout on the server
419
+ const checkout = await omni.getCheckout(result.checkoutId);
420
+
421
+ // Continue with shipping, payment, etc.
422
+ await omni.setShippingAddress(result.checkoutId, { ... });
423
+ const intent = await omni.createPaymentIntent(result.checkoutId);
424
+ // ... Stripe payment ...
425
+ }
426
+ ```
344
427
 
345
428
  ### Decision Flow
346
429
 
@@ -1543,6 +1626,22 @@ function canProceedToPayment(checkout: Checkout, rates: ShippingRate[]): boolean
1543
1626
 
1544
1627
  For vibe-coded sites, the SDK provides payment integration with Stripe and PayPal. The store owner configures their payment provider(s) in the admin, and your site uses these methods to process payments.
1545
1628
 
1629
+ #### ⚠️ Important: Getting a Valid Checkout ID
1630
+
1631
+ Before creating a payment intent, you need a checkout ID. How you get it depends on the customer type:
1632
+
1633
+ ```typescript
1634
+ // For GUEST users (local cart in localStorage):
1635
+ const result = await omni.startGuestCheckout();
1636
+ const checkoutId = result.checkoutId;
1637
+
1638
+ // For LOGGED-IN users (server cart):
1639
+ const checkout = await omni.createCheckout({ cartId: serverCartId });
1640
+ const checkoutId = checkout.id;
1641
+
1642
+ // Then continue with shipping and payment...
1643
+ ```
1644
+
1546
1645
  #### Get All Payment Providers (Recommended)
1547
1646
 
1548
1647
  Use this method to get ALL enabled payment providers and build dynamic UI:
@@ -1753,6 +1852,20 @@ if (status.status === 'succeeded' && status.orderId) {
1753
1852
 
1754
1853
  #### Complete Checkout with Payment Example
1755
1854
 
1855
+ > **Note:** This example assumes you already have a `checkout_id`. See below for how to create one.
1856
+
1857
+ **How to get a checkout_id:**
1858
+
1859
+ ```typescript
1860
+ // For GUEST users (local cart):
1861
+ const result = await omni.startGuestCheckout();
1862
+ const checkoutId = result.checkoutId; // Use this!
1863
+
1864
+ // For LOGGED-IN users (server cart):
1865
+ const checkout = await omni.createCheckout({ cartId: cart.id });
1866
+ const checkoutId = checkout.id; // Use this!
1867
+ ```
1868
+
1756
1869
  ```typescript
1757
1870
  'use client';
1758
1871
  import { useState, useEffect } from 'react';
@@ -1772,7 +1885,7 @@ export default function CheckoutPaymentPage() {
1772
1885
  useEffect(() => {
1773
1886
  async function initPayment() {
1774
1887
  try {
1775
- // Assume checkout is already created and shipping is set
1888
+ // Get checkout_id from URL (set by previous step)
1776
1889
  const checkoutId = new URLSearchParams(window.location.search).get('checkout_id');
1777
1890
  if (!checkoutId) throw new Error('No checkout ID');
1778
1891
 
@@ -1857,6 +1970,48 @@ function PaymentForm({ checkoutId }: { checkoutId: string }) {
1857
1970
  }
1858
1971
  ```
1859
1972
 
1973
+ #### Cart Cleanup After Payment: `handlePaymentSuccess()`
1974
+
1975
+ **CRITICAL:** After payment succeeds, you MUST call `handlePaymentSuccess()` to clear the cart. This ensures:
1976
+
1977
+ - Guest users: Local cart items are removed (full or partial based on what was purchased)
1978
+ - Logged-in users: Server cart is cleared
1979
+
1980
+ ```typescript
1981
+ // On your /checkout/success page:
1982
+ export default function CheckoutSuccessPage() {
1983
+ const checkoutId = new URLSearchParams(window.location.search).get('checkout_id');
1984
+
1985
+ useEffect(() => {
1986
+ // IMPORTANT: Call this to clear the cart after successful payment
1987
+ const result = omni.handlePaymentSuccess(checkoutId);
1988
+
1989
+ console.log('Cart cleanup:', result);
1990
+ // { cleared: true, mode: 'full' | 'partial', userType: 'guest' | 'customer' }
1991
+ }, []);
1992
+
1993
+ return (
1994
+ <div className="text-center py-12">
1995
+ <h1 className="text-2xl font-bold text-green-600">Payment Received!</h1>
1996
+ {/* ... rest of success page */}
1997
+ </div>
1998
+ );
1999
+ }
2000
+ ```
2001
+
2002
+ **How it works:**
2003
+ | User Type | Cart Type | Behavior |
2004
+ |-----------|-----------|----------|
2005
+ | Guest (partial checkout) | Local cart | Only removes purchased items |
2006
+ | Guest (full checkout) | Local cart | Clears entire cart |
2007
+ | Logged-in | Server cart | Clears cart via SDK state |
2008
+
2009
+ **Why is this needed?**
2010
+
2011
+ - After Stripe redirects back to your success page, the cart is still in localStorage/memory
2012
+ - Without calling `handlePaymentSuccess()`, users will see their "purchased" items still in cart
2013
+ - For partial checkout (AliExpress-style), only the purchased items are removed
2014
+
1860
2015
  ---
1861
2016
 
1862
2017
  ### Customer Authentication
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omni-sync-sdk",
3
- "version": "0.21.1",
3
+ "version": "0.21.2",
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",