omni-sync-sdk 0.21.8 → 0.22.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.
@@ -30,7 +30,7 @@ if (omni.isCustomerLoggedIn()) {
30
30
  | **Guest** | localStorage | `startGuestCheckout()` | `result.checkoutId` |
31
31
  | **Logged-in** | Server | `createCheckout({ cartId })` | `checkout.id` |
32
32
 
33
- ### Rule 2: Clear Cart After Successful Payment!
33
+ ### Rule 2: Complete Checkout & Clear Cart After Payment!
34
34
 
35
35
  ```typescript
36
36
  // On /checkout/success page - MUST DO THIS!
@@ -38,14 +38,21 @@ export default function CheckoutSuccessPage() {
38
38
  const checkoutId = new URLSearchParams(window.location.search).get('checkout_id');
39
39
 
40
40
  useEffect(() => {
41
- // This clears the cart (full or partial based on what was purchased)
42
- omni.handlePaymentSuccess(checkoutId);
41
+ if (checkoutId) {
42
+ // ⚠️ CRITICAL: This sends the order to the server AND clears the cart!
43
+ // handlePaymentSuccess() only clears the local cart - it does NOT create the order!
44
+ omni.completeGuestCheckout(checkoutId);
45
+ }
43
46
  }, []);
44
47
 
45
48
  return <div>Thank you for your order!</div>;
46
49
  }
47
50
  ```
48
51
 
52
+ > **WARNING:** Do NOT use `handlePaymentSuccess()` to complete an order. It only clears
53
+ > the local cart (localStorage) and does NOT communicate with the server.
54
+ > Always use `completeGuestCheckout()` after payment succeeds.
55
+
49
56
  ### Rule 3: Never Hardcode Products!
50
57
 
51
58
  ```typescript
@@ -193,7 +200,7 @@ const handleCheckout = async () => {
193
200
  **Why this matters:**
194
201
 
195
202
  - Users can buy some items now, leave others for later
196
- - After payment, `handlePaymentSuccess()` only removes purchased items
203
+ - After payment, `completeGuestCheckout()` sends the order and only removes purchased items
197
204
  - Remaining items stay in cart for future purchase
198
205
 
199
206
  **⚠️ Order Summary on Checkout Page - Use checkout.lineItems!**
@@ -323,7 +330,7 @@ if (error) {
323
330
  // If no error, Stripe redirects to success page
324
331
  ```
325
332
 
326
- ### Step 5: Success Page (Clear Cart!)
333
+ ### Step 5: Success Page (Complete Order & Clear Cart!)
327
334
 
328
335
  ```typescript
329
336
  // /checkout/success/page.tsx
@@ -333,19 +340,25 @@ import { omni } from '@/lib/omni-sync';
333
340
 
334
341
  export default function CheckoutSuccessPage() {
335
342
  const [orderNumber, setOrderNumber] = useState<string>();
343
+ const [loading, setLoading] = useState(true);
336
344
 
337
345
  useEffect(() => {
338
346
  const checkoutId = new URLSearchParams(window.location.search).get('checkout_id');
339
347
 
340
- // ⚠️ CRITICAL: Clear the cart!
341
- omni.handlePaymentSuccess(checkoutId);
342
-
343
- // Optional: Get order details
344
348
  if (checkoutId) {
345
- omni.getPaymentStatus(checkoutId).then(status => {
346
- if (status.orderNumber) {
347
- setOrderNumber(status.orderNumber);
348
- }
349
+ // ⚠️ CRITICAL: Complete the order on the server AND clear the cart!
350
+ // Do NOT use handlePaymentSuccess() - it only clears localStorage!
351
+ omni.completeGuestCheckout(checkoutId).then(result => {
352
+ setOrderNumber(result.orderNumber);
353
+ setLoading(false);
354
+ }).catch(() => {
355
+ // Order may already be completed (e.g., page refresh) - check status
356
+ omni.getPaymentStatus(checkoutId).then(status => {
357
+ if (status.orderNumber) {
358
+ setOrderNumber(status.orderNumber);
359
+ }
360
+ setLoading(false);
361
+ });
349
362
  });
350
363
  }
351
364
  }, []);
@@ -353,6 +366,7 @@ export default function CheckoutSuccessPage() {
353
366
  return (
354
367
  <div className="text-center py-12">
355
368
  <h1 className="text-2xl font-bold text-green-600">Thank you for your order!</h1>
369
+ {loading && <p className="mt-2">Processing your order...</p>}
356
370
  {orderNumber && <p className="mt-2">Order #{orderNumber}</p>}
357
371
  <p className="mt-4">A confirmation email will be sent shortly.</p>
358
372
  </div>
@@ -372,7 +386,7 @@ const result = await omni.startGuestCheckout({
372
386
  selectedIndices: [0, 2], // Buy items at index 0 and 2 only
373
387
  });
374
388
 
375
- // After payment, handlePaymentSuccess() will only remove those items!
389
+ // After payment, completeGuestCheckout() sends the order AND removes only those items!
376
390
  // Other items stay in cart.
377
391
  ```
378
392
 
@@ -399,6 +413,34 @@ const suggestions = await omni.getSearchSuggestions('blue', 5);
399
413
 
400
414
  ---
401
415
 
416
+ ## Product Custom Fields (Metafields)
417
+
418
+ Products may have custom fields defined by the store owner (e.g., "Material", "Care Instructions", "Warranty").
419
+
420
+ ```typescript
421
+ import { getProductMetafield, getProductMetafieldValue } from 'omni-sync-sdk';
422
+
423
+ // Access metafields on a product
424
+ const product = await omni.getProductBySlug('blue-shirt');
425
+
426
+ // Get all custom fields
427
+ product.metafields?.forEach((field) => {
428
+ console.log(`${field.definitionName}: ${field.value}`);
429
+ });
430
+
431
+ // Get specific field by key
432
+ const material = getProductMetafieldValue(product, 'material');
433
+ const careInstructions = getProductMetafield(product, 'care_instructions');
434
+
435
+ // Get available metafield definitions (schema)
436
+ const { definitions } = await omni.getPublicMetafieldDefinitions();
437
+ // Use definitions to build dynamic UI (filters, forms, etc.)
438
+ ```
439
+
440
+ > **Tip:** `metafields` may be empty if the store hasn't defined custom fields. Always use optional chaining.
441
+
442
+ ---
443
+
402
444
  ## Customer Authentication
403
445
 
404
446
  ```typescript
@@ -456,7 +498,7 @@ setCustomerToken(token);
456
498
  - [ ] **Product Detail** (`/products/[slug]`) - Use `getProductBySlug(slug)`
457
499
  - [ ] **Cart** (`/cart`) - Show items, quantities, totals
458
500
  - [ ] **Checkout** (`/checkout`) - Address → Shipping → Payment
459
- - [ ] **Success** (`/checkout/success`) - **Must call `handlePaymentSuccess()`!**
501
+ - [ ] **Success** (`/checkout/success`) - **Must call `completeGuestCheckout()`!**
460
502
  - [ ] **Login** (`/login`) - Email/password + social buttons
461
503
  - [ ] **Register** (`/register`) - Registration form
462
504
  - [ ] **Account** (`/account`) - Profile + order history
@@ -475,6 +517,8 @@ item.name (in cart) item.product.name
475
517
  response.url (OAuth) response.authorizationUrl
476
518
  providers.forEach (OAuth) response.providers.forEach
477
519
  status === 'completed' status === 'succeeded'
520
+ product.metafields.name product.metafields[0].definitionName
521
+ product.metafields.key product.metafields[0].definitionKey
478
522
  ```
479
523
 
480
524
  ---