brainerce 1.0.1 → 1.0.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.
package/dist/index.js CHANGED
@@ -179,9 +179,16 @@ var BrainerceClient = class {
179
179
  constructor(options) {
180
180
  this.customerToken = null;
181
181
  this.customerCartId = null;
182
+ // Session cart state (server-side guest carts)
183
+ this.sessionCartId = null;
184
+ this.sessionToken = null;
185
+ this._sessionCartPromise = null;
186
+ this._migrationDone = false;
187
+ /** localStorage key for session cart reference (sessionToken + cartId) */
188
+ this.SESSION_CART_KEY = "brainerce_session";
182
189
  /**
183
190
  * Virtual cart ID used for localStorage carts (guest users not logged in).
184
- * When a cart has this ID, operations use localStorage instead of server API.
191
+ * @deprecated Guest carts now use server-side sessions. Kept for backward compatibility.
185
192
  */
186
193
  this.VIRTUAL_LOCAL_CART_ID = "__local__";
187
194
  /**
@@ -213,6 +220,7 @@ var BrainerceClient = class {
213
220
  this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
214
221
  this.timeout = options.timeout || DEFAULT_TIMEOUT;
215
222
  this.onAuthError = options.onAuthError;
223
+ this.hydrateSessionCart();
216
224
  }
217
225
  withGuards(result, type) {
218
226
  if (!isDevGuardsEnabled()) return result;
@@ -1911,10 +1919,6 @@ var BrainerceClient = class {
1911
1919
  * ```
1912
1920
  */
1913
1921
  async createCart() {
1914
- if (this.isVibeCodedMode() && !this.isCustomerLoggedIn()) {
1915
- const localCart = this.getLocalCart();
1916
- return this.localCartToCart(localCart);
1917
- }
1918
1922
  if (this.isVibeCodedMode()) {
1919
1923
  return this.vibeCodedRequest("POST", "/cart");
1920
1924
  }
@@ -1933,6 +1937,9 @@ var BrainerceClient = class {
1933
1937
  * ```
1934
1938
  */
1935
1939
  async getCartBySession(sessionToken) {
1940
+ if (this.isVibeCodedMode()) {
1941
+ return this.vibeCodedRequest("GET", `/cart/session/${sessionToken}`);
1942
+ }
1936
1943
  if (this.storeId && !this.apiKey) {
1937
1944
  return this.storefrontRequest("GET", `/cart/session/${sessionToken}`);
1938
1945
  }
@@ -1958,6 +1965,7 @@ var BrainerceClient = class {
1958
1965
  */
1959
1966
  async getCart(cartId) {
1960
1967
  if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
1968
+ console.warn('getCart("__local__") is deprecated. Use smartGetCart() instead.');
1961
1969
  return this.withGuards(this.localCartToCart(this.getLocalCart()), "cart");
1962
1970
  }
1963
1971
  if (this.isVibeCodedMode()) {
@@ -1982,38 +1990,14 @@ var BrainerceClient = class {
1982
1990
  */
1983
1991
  async addToCart(cartId, item) {
1984
1992
  if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
1985
- let productName = "Unknown Product";
1986
- let productPrice = "0";
1987
- let productImage;
1988
- if (item.productInfo) {
1989
- productName = item.productInfo.name;
1990
- productPrice = item.productInfo.price;
1991
- productImage = item.productInfo.image;
1992
- } else {
1993
- try {
1994
- const product = await this.getProduct(item.productId);
1995
- productName = product.name;
1996
- productPrice = product.salePrice || product.basePrice;
1997
- productImage = product.images?.[0]?.url;
1998
- if (item.variantId && product.variants) {
1999
- const variant = product.variants.find((v) => v.id === item.variantId);
2000
- if (variant) {
2001
- productPrice = variant.salePrice || variant.price || productPrice;
2002
- if (variant.image) {
2003
- productImage = typeof variant.image === "string" ? variant.image : variant.image.url;
2004
- }
2005
- }
2006
- }
2007
- } catch {
2008
- }
2009
- }
1993
+ console.warn('addToCart("__local__", ...) is deprecated. Use smartAddToCart() instead.');
2010
1994
  this.addToLocalCart({
2011
1995
  productId: item.productId,
2012
1996
  variantId: item.variantId,
2013
1997
  quantity: item.quantity,
2014
- name: productName,
2015
- price: productPrice,
2016
- image: productImage
1998
+ name: item.productInfo?.name || "Unknown Product",
1999
+ price: item.productInfo?.price || "0",
2000
+ image: item.productInfo?.image
2017
2001
  });
2018
2002
  return this.withGuards(this.localCartToCart(this.getLocalCart()), "cart");
2019
2003
  }
@@ -2044,6 +2028,7 @@ var BrainerceClient = class {
2044
2028
  */
2045
2029
  async updateCartItem(cartId, itemId, data) {
2046
2030
  if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
2031
+ console.warn('updateCartItem("__local__", ...) is deprecated. Use smartUpdateCartItem() instead.');
2047
2032
  const index = parseInt(itemId.replace("local_", ""), 10);
2048
2033
  const localCart = this.getLocalCart();
2049
2034
  if (index >= 0 && index < localCart.items.length) {
@@ -2079,6 +2064,7 @@ var BrainerceClient = class {
2079
2064
  */
2080
2065
  async removeCartItem(cartId, itemId) {
2081
2066
  if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
2067
+ console.warn('removeCartItem("__local__", ...) is deprecated. Use smartRemoveFromCart() instead.');
2082
2068
  const index = parseInt(itemId.replace("local_", ""), 10);
2083
2069
  const localCart = this.getLocalCart();
2084
2070
  if (index >= 0 && index < localCart.items.length) {
@@ -2114,6 +2100,7 @@ var BrainerceClient = class {
2114
2100
  */
2115
2101
  async clearCart(cartId) {
2116
2102
  if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
2103
+ console.warn('clearCart("__local__") is deprecated. Use onCheckoutComplete() or clearLocalCart() directly.');
2117
2104
  this.clearLocalCart();
2118
2105
  return this.withGuards(this.localCartToCart(this.getLocalCart()), "cart");
2119
2106
  }
@@ -2394,6 +2381,230 @@ var BrainerceClient = class {
2394
2381
  isCustomerLoggedIn() {
2395
2382
  return !!this.customerToken;
2396
2383
  }
2384
+ // -------------------- Session Cart Helpers --------------------
2385
+ /**
2386
+ * Hydrate session cart state from localStorage on construction.
2387
+ * @internal
2388
+ */
2389
+ hydrateSessionCart() {
2390
+ if (!this.isLocalStorageAvailable()) return;
2391
+ try {
2392
+ const stored = window.localStorage.getItem(this.SESSION_CART_KEY);
2393
+ if (stored) {
2394
+ const ref = JSON.parse(stored);
2395
+ this.sessionToken = ref.sessionToken;
2396
+ this.sessionCartId = ref.cartId;
2397
+ }
2398
+ } catch {
2399
+ }
2400
+ }
2401
+ /**
2402
+ * Persist session cart reference to localStorage.
2403
+ * @internal
2404
+ */
2405
+ saveSessionCart(ref) {
2406
+ this.sessionToken = ref.sessionToken;
2407
+ this.sessionCartId = ref.cartId;
2408
+ if (!this.isLocalStorageAvailable()) return;
2409
+ window.localStorage.setItem(this.SESSION_CART_KEY, JSON.stringify(ref));
2410
+ }
2411
+ /**
2412
+ * Clear session cart reference from localStorage and memory.
2413
+ * @internal
2414
+ */
2415
+ clearSessionCart() {
2416
+ this.sessionToken = null;
2417
+ this.sessionCartId = null;
2418
+ this._sessionCartPromise = null;
2419
+ if (!this.isLocalStorageAvailable()) return;
2420
+ window.localStorage.removeItem(this.SESSION_CART_KEY);
2421
+ }
2422
+ /**
2423
+ * Update the cached item count in the session reference.
2424
+ * @internal
2425
+ */
2426
+ updateSessionCartItemCount(count) {
2427
+ if (!this.sessionToken || !this.sessionCartId) return;
2428
+ this.saveSessionCart({
2429
+ sessionToken: this.sessionToken,
2430
+ cartId: this.sessionCartId,
2431
+ itemCount: count
2432
+ });
2433
+ }
2434
+ /**
2435
+ * Return a synthetic empty Cart object for display when no server cart exists yet.
2436
+ * Avoids creating a server cart just to show "your cart is empty."
2437
+ * @internal
2438
+ */
2439
+ emptyCart() {
2440
+ return {
2441
+ id: "",
2442
+ sessionToken: null,
2443
+ customerId: null,
2444
+ status: "ACTIVE",
2445
+ currency: "USD",
2446
+ notes: null,
2447
+ subtotal: "0",
2448
+ discountAmount: "0",
2449
+ couponCode: null,
2450
+ items: [],
2451
+ itemCount: 0,
2452
+ expiresAt: null,
2453
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
2454
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
2455
+ };
2456
+ }
2457
+ /**
2458
+ * Create a server-side cart via API. Never falls back to localStorage.
2459
+ * @internal
2460
+ */
2461
+ async createServerCart() {
2462
+ if (this.isVibeCodedMode()) {
2463
+ return this.vibeCodedRequest("POST", "/cart");
2464
+ }
2465
+ if (this.storeId && !this.apiKey) {
2466
+ return this.storefrontRequest("POST", "/cart");
2467
+ }
2468
+ return this.adminRequest("POST", "/api/v1/cart");
2469
+ }
2470
+ /**
2471
+ * Get or create a server-side session cart for guest users.
2472
+ * Lazily creates the cart on first call (e.g., first add-to-cart).
2473
+ * Uses promise dedup lock to prevent race conditions on parallel calls.
2474
+ * @internal
2475
+ */
2476
+ async getOrCreateSessionCart() {
2477
+ if (this._sessionCartPromise) return this._sessionCartPromise;
2478
+ this._sessionCartPromise = this._getOrCreateSessionCartImpl();
2479
+ try {
2480
+ return await this._sessionCartPromise;
2481
+ } finally {
2482
+ this._sessionCartPromise = null;
2483
+ }
2484
+ }
2485
+ /** @internal */
2486
+ async _getOrCreateSessionCartImpl() {
2487
+ const migrated = await this.migrateLocalCartToSession();
2488
+ if (migrated) return migrated;
2489
+ if (this.sessionCartId && this.sessionToken) {
2490
+ try {
2491
+ const cart2 = await this.getCart(this.sessionCartId);
2492
+ if (cart2.status === "ACTIVE") {
2493
+ return cart2;
2494
+ }
2495
+ this.clearSessionCart();
2496
+ } catch {
2497
+ this.clearSessionCart();
2498
+ }
2499
+ }
2500
+ if (this.sessionToken) {
2501
+ try {
2502
+ const cart2 = await this.getCartBySession(this.sessionToken);
2503
+ if (cart2 && cart2.status === "ACTIVE") {
2504
+ this.saveSessionCart({
2505
+ sessionToken: this.sessionToken,
2506
+ cartId: cart2.id,
2507
+ itemCount: cart2.itemCount
2508
+ });
2509
+ return cart2;
2510
+ }
2511
+ } catch {
2512
+ this.clearSessionCart();
2513
+ }
2514
+ }
2515
+ const cart = await this.createServerCart();
2516
+ if (cart.sessionToken) {
2517
+ this.saveSessionCart({
2518
+ sessionToken: cart.sessionToken,
2519
+ cartId: cart.id,
2520
+ itemCount: cart.itemCount
2521
+ });
2522
+ }
2523
+ return cart;
2524
+ }
2525
+ /**
2526
+ * Migrate legacy localStorage cart to server session cart.
2527
+ * Called once, on first smart method call if migration is needed.
2528
+ * @internal
2529
+ */
2530
+ async migrateLocalCartToSession() {
2531
+ if (this._migrationDone) return null;
2532
+ this._migrationDone = true;
2533
+ if (this.sessionToken || this.sessionCartId) return null;
2534
+ const localCart = this.getLocalCart();
2535
+ if (localCart.items.length === 0) return null;
2536
+ try {
2537
+ const cart = await this.createServerCart();
2538
+ for (const item of localCart.items) {
2539
+ try {
2540
+ await this.addToCart(cart.id, {
2541
+ productId: item.productId,
2542
+ variantId: item.variantId,
2543
+ quantity: item.quantity
2544
+ });
2545
+ } catch {
2546
+ }
2547
+ }
2548
+ if (cart.sessionToken) {
2549
+ this.saveSessionCart({
2550
+ sessionToken: cart.sessionToken,
2551
+ cartId: cart.id
2552
+ });
2553
+ }
2554
+ this.clearLocalCart();
2555
+ return this.getCart(cart.id);
2556
+ } catch {
2557
+ this._migrationDone = false;
2558
+ return null;
2559
+ }
2560
+ }
2561
+ /**
2562
+ * Merge the guest session cart into the customer's cart on the server.
2563
+ * Tries linkCart first (fast, single call), falls back to mergeCarts endpoint.
2564
+ * @internal
2565
+ */
2566
+ async mergeSessionCartOnLogin() {
2567
+ if (this.sessionCartId) {
2568
+ try {
2569
+ return await this.linkCart(this.sessionCartId);
2570
+ } catch {
2571
+ }
2572
+ }
2573
+ if (this.isVibeCodedMode()) {
2574
+ return this.vibeCodedRequest("POST", "/cart/merge", {
2575
+ sessionToken: this.sessionToken
2576
+ });
2577
+ }
2578
+ if (this.storeId && !this.apiKey) {
2579
+ return this.storefrontRequest("POST", "/cart/merge", {
2580
+ sessionToken: this.sessionToken
2581
+ });
2582
+ }
2583
+ return this.adminRequest("POST", "/api/v1/cart/merge", {
2584
+ sessionToken: this.sessionToken
2585
+ });
2586
+ }
2587
+ /**
2588
+ * Get the cart item count without a full cart fetch.
2589
+ * Returns the cached count from localStorage if available, or 0.
2590
+ * For accurate counts, use smartGetCart() and read cart.itemCount.
2591
+ */
2592
+ getSmartCartItemCount() {
2593
+ if (this.isCustomerLoggedIn()) {
2594
+ return 0;
2595
+ }
2596
+ if (!this.isLocalStorageAvailable()) return 0;
2597
+ try {
2598
+ const stored = window.localStorage.getItem(this.SESSION_CART_KEY);
2599
+ if (stored) {
2600
+ const ref = JSON.parse(stored);
2601
+ return ref.itemCount ?? 0;
2602
+ }
2603
+ } catch {
2604
+ }
2605
+ return 0;
2606
+ }
2607
+ // -------------------- Customer Cart --------------------
2397
2608
  /**
2398
2609
  * Get or create a server cart for the logged-in customer
2399
2610
  * Caches the cart ID for subsequent calls
@@ -2446,10 +2657,10 @@ var BrainerceClient = class {
2446
2657
  throw new BrainerceError("fetchCustomerCart requires vibe-coded or storefront mode", 400);
2447
2658
  }
2448
2659
  /**
2449
- * Smart add to cart - automatically uses localStorage or server based on auth state
2660
+ * Smart add to cart - automatically uses the correct cart based on auth state
2450
2661
  *
2451
- * - **Guest (not logged in)**: Stores in localStorage
2452
- * - **Logged in**: Stores on server (database)
2662
+ * - **Logged in**: Uses customer's server cart
2663
+ * - **Guest**: Uses server-side session cart (creates one if needed)
2453
2664
  *
2454
2665
  * @example
2455
2666
  * ```typescript
@@ -2457,25 +2668,35 @@ var BrainerceClient = class {
2457
2668
  * await client.smartAddToCart({
2458
2669
  * productId: 'prod_123',
2459
2670
  * quantity: 2,
2460
- * name: 'Cool Product', // Optional: for localStorage display
2461
- * price: '29.99',
2462
2671
  * });
2463
2672
  * ```
2464
2673
  */
2465
2674
  async smartAddToCart(item) {
2466
2675
  if (this.isCustomerLoggedIn()) {
2467
2676
  const cart = await this.getOrCreateCustomerCart();
2468
- return this.addToCart(cart.id, {
2677
+ const updated = await this.addToCart(cart.id, {
2469
2678
  productId: item.productId,
2470
2679
  variantId: item.variantId,
2471
2680
  quantity: item.quantity
2472
2681
  });
2682
+ return updated;
2473
2683
  } else {
2474
- return this.addToLocalCart(item);
2684
+ const cart = await this.getOrCreateSessionCart();
2685
+ const updated = await this.addToCart(cart.id, {
2686
+ productId: item.productId,
2687
+ variantId: item.variantId,
2688
+ quantity: item.quantity
2689
+ });
2690
+ this.updateSessionCartItemCount(updated.items?.length ?? 0);
2691
+ return updated;
2475
2692
  }
2476
2693
  }
2477
2694
  /**
2478
- * Smart get cart - returns server cart if logged in, localStorage if guest
2695
+ * Smart get cart - returns the current cart (server-side for both guests and logged-in users)
2696
+ *
2697
+ * - **Logged in**: Returns customer's server cart
2698
+ * - **Guest with session**: Returns server-side session cart
2699
+ * - **Guest without session**: Returns empty cart (no server call, cart created lazily on add)
2479
2700
  *
2480
2701
  * @example
2481
2702
  * ```typescript
@@ -2487,7 +2708,10 @@ var BrainerceClient = class {
2487
2708
  if (this.isCustomerLoggedIn()) {
2488
2709
  return this.getOrCreateCustomerCart();
2489
2710
  } else {
2490
- return this.withGuards(this.getLocalCart(), "cart");
2711
+ if (!this.sessionToken) {
2712
+ return this.emptyCart();
2713
+ }
2714
+ return this.getOrCreateSessionCart();
2491
2715
  }
2492
2716
  }
2493
2717
  /**
@@ -2513,7 +2737,24 @@ var BrainerceClient = class {
2513
2737
  }
2514
2738
  return this.updateCartItem(cart.id, item.id, { quantity });
2515
2739
  } else {
2516
- return this.updateLocalCartItem(productId, quantity, variantId);
2740
+ if (!this.sessionToken) {
2741
+ return this.emptyCart();
2742
+ }
2743
+ const cart = await this.getOrCreateSessionCart();
2744
+ const item = cart.items.find(
2745
+ (i) => i.productId === productId && i.variantId === (variantId ?? null)
2746
+ );
2747
+ if (!item) {
2748
+ return cart;
2749
+ }
2750
+ let updated;
2751
+ if (quantity <= 0) {
2752
+ updated = await this.removeCartItem(cart.id, item.id);
2753
+ } else {
2754
+ updated = await this.updateCartItem(cart.id, item.id, { quantity });
2755
+ }
2756
+ this.updateSessionCartItemCount(updated.items?.length ?? 0);
2757
+ return updated;
2517
2758
  }
2518
2759
  }
2519
2760
  /**
@@ -2529,15 +2770,13 @@ var BrainerceClient = class {
2529
2770
  return this.smartUpdateCartItem(productId, 0, variantId);
2530
2771
  }
2531
2772
  /**
2532
- * Sync local cart to server on login
2773
+ * Sync guest cart to customer cart on login
2533
2774
  *
2534
2775
  * Call this AFTER setCustomerToken() when a customer logs in.
2535
2776
  * This will:
2536
- * 1. Get or create a server cart for the customer
2537
- * 2. Add all items from localStorage to the server cart (merging with existing)
2538
- * 3. Clear localStorage
2539
- *
2540
- * Items that fail to sync (e.g., out of stock) are silently skipped.
2777
+ * 1. If a server-side session cart exists, merge it into the customer cart (atomic, server-side)
2778
+ * 2. If only a legacy localStorage cart exists, sync items one by one (backward compat)
2779
+ * 3. Clear the session/localStorage after merge
2541
2780
  *
2542
2781
  * @example
2543
2782
  * ```typescript
@@ -2545,7 +2784,7 @@ var BrainerceClient = class {
2545
2784
  * const auth = await client.login(email, password);
2546
2785
  * client.setCustomerToken(auth.token);
2547
2786
  *
2548
- * // Sync their local cart to server
2787
+ * // Merge their guest cart into customer cart
2549
2788
  * const cart = await client.syncCartOnLogin();
2550
2789
  * console.log('Cart synced, items:', cart.items.length);
2551
2790
  * ```
@@ -2557,6 +2796,14 @@ var BrainerceClient = class {
2557
2796
  401
2558
2797
  );
2559
2798
  }
2799
+ if (this.sessionToken) {
2800
+ try {
2801
+ const merged = await this.mergeSessionCartOnLogin();
2802
+ this.clearSessionCart();
2803
+ return merged;
2804
+ } catch {
2805
+ }
2806
+ }
2560
2807
  const localCart = this.getLocalCart();
2561
2808
  const serverCart = await this.getOrCreateCustomerCart();
2562
2809
  if (localCart.items.length === 0) {
@@ -2578,15 +2825,15 @@ var BrainerceClient = class {
2578
2825
  /**
2579
2826
  * Clear cart state on logout
2580
2827
  *
2581
- * Call this when a customer logs out to clear the cached cart ID.
2582
- * The localStorage cart remains available for the next guest session.
2828
+ * Call this when a customer logs out to clear the cached customer cart ID.
2829
+ * The session cart (if any) remains available for the next guest session.
2583
2830
  *
2584
2831
  * @example
2585
2832
  * ```typescript
2586
2833
  * client.clearCustomerToken();
2587
2834
  * client.onLogout();
2588
2835
  *
2589
- * // Now back to guest mode - cart uses localStorage
2836
+ * // Now back to guest mode - cart uses server-side session
2590
2837
  * await client.smartAddToCart({ productId: 'prod_123', quantity: 1 });
2591
2838
  * ```
2592
2839
  */
@@ -2604,12 +2851,12 @@ var BrainerceClient = class {
2604
2851
  * // After payment success
2605
2852
  * if (paymentStatus === 'succeeded') {
2606
2853
  * client.onCheckoutComplete();
2607
- * client.clearLocalCart(); // Also clear localStorage for guests
2608
2854
  * }
2609
2855
  * ```
2610
2856
  */
2611
2857
  onCheckoutComplete() {
2612
2858
  this.customerCartId = null;
2859
+ this.clearSessionCart();
2613
2860
  }
2614
2861
  // -------------------- Checkout --------------------
2615
2862
  /**
@@ -2636,7 +2883,7 @@ var BrainerceClient = class {
2636
2883
  async createCheckout(data) {
2637
2884
  if (data.cartId === this.VIRTUAL_LOCAL_CART_ID) {
2638
2885
  throw new BrainerceError(
2639
- "Cannot create checkout from local cart directly. Use startGuestCheckout() for guest checkout with localStorage cart, or sync cart to server first with syncCartOnLogin().",
2886
+ 'Cannot create checkout from "__local__" cart. Use startGuestCheckout() or smartAddToCart() to create a server-side cart first.',
2640
2887
  400
2641
2888
  );
2642
2889
  }
@@ -3172,14 +3419,8 @@ var BrainerceClient = class {
3172
3419
  }
3173
3420
  }
3174
3421
  /**
3175
- * Get local cart from localStorage
3176
- * Returns empty cart if none exists
3177
- *
3178
- * @example
3179
- * ```typescript
3180
- * const cart = client.getLocalCart();
3181
- * console.log('Items in cart:', cart.items.length);
3182
- * ```
3422
+ * @deprecated Use `smartGetCart()` instead. Guest carts are now stored on the server.
3423
+ * Get local cart from localStorage. Returns empty cart if none exists.
3183
3424
  */
3184
3425
  getLocalCart() {
3185
3426
  if (!this.isLocalStorageAvailable()) {
@@ -3261,18 +3502,8 @@ var BrainerceClient = class {
3261
3502
  };
3262
3503
  }
3263
3504
  /**
3264
- * Add item to local cart (NO API call)
3265
- * If item already exists, updates quantity
3266
- *
3267
- * @example
3268
- * ```typescript
3269
- * client.addToLocalCart({
3270
- * productId: 'prod_123',
3271
- * quantity: 2,
3272
- * name: 'Cool Shirt',
3273
- * price: '29.99',
3274
- * });
3275
- * ```
3505
+ * @deprecated Use `smartAddToCart()` instead. Guest carts are now stored on the server.
3506
+ * Add item to local cart (NO API call). If item already exists, updates quantity.
3276
3507
  */
3277
3508
  addToLocalCart(item) {
3278
3509
  const cart = this.getLocalCart();
@@ -3294,14 +3525,8 @@ var BrainerceClient = class {
3294
3525
  return cart;
3295
3526
  }
3296
3527
  /**
3297
- * Update item quantity in local cart
3298
- * Set quantity to 0 to remove item
3299
- *
3300
- * @example
3301
- * ```typescript
3302
- * client.updateLocalCartItem('prod_123', 3); // Set quantity to 3
3303
- * client.updateLocalCartItem('prod_123', 0); // Remove item
3304
- * ```
3528
+ * @deprecated Use `smartUpdateCartItem()` instead. Guest carts are now stored on the server.
3529
+ * Update item quantity in local cart. Set quantity to 0 to remove item.
3305
3530
  */
3306
3531
  updateLocalCartItem(productId, quantity, variantId) {
3307
3532
  const cart = this.getLocalCart();
@@ -3319,24 +3544,13 @@ var BrainerceClient = class {
3319
3544
  return cart;
3320
3545
  }
3321
3546
  /**
3322
- * Remove item from local cart
3323
- *
3324
- * @example
3325
- * ```typescript
3326
- * client.removeFromLocalCart('prod_123');
3327
- * client.removeFromLocalCart('prod_456', 'variant_789');
3328
- * ```
3547
+ * @deprecated Use `smartRemoveFromCart()` instead. Guest carts are now stored on the server.
3329
3548
  */
3330
3549
  removeFromLocalCart(productId, variantId) {
3331
3550
  return this.updateLocalCartItem(productId, 0, variantId);
3332
3551
  }
3333
3552
  /**
3334
- * Clear all items from local cart
3335
- *
3336
- * @example
3337
- * ```typescript
3338
- * client.clearLocalCart();
3339
- * ```
3553
+ * @deprecated Use `onCheckoutComplete()` instead. Guest carts are now stored on the server.
3340
3554
  */
3341
3555
  clearLocalCart() {
3342
3556
  const cart = { items: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
@@ -3344,16 +3558,8 @@ var BrainerceClient = class {
3344
3558
  return cart;
3345
3559
  }
3346
3560
  /**
3347
- * Set customer info on local cart
3348
- *
3349
- * @example
3350
- * ```typescript
3351
- * client.setLocalCartCustomer({
3352
- * email: 'john@example.com',
3353
- * firstName: 'John',
3354
- * lastName: 'Doe',
3355
- * });
3356
- * ```
3561
+ * @deprecated Customer info is now set via checkout address methods.
3562
+ * Still used by `submitGuestOrder()` for backward compatibility.
3357
3563
  */
3358
3564
  setLocalCartCustomer(customer) {
3359
3565
  const cart = this.getLocalCart();
@@ -3362,19 +3568,8 @@ var BrainerceClient = class {
3362
3568
  return cart;
3363
3569
  }
3364
3570
  /**
3365
- * Set shipping address on local cart
3366
- *
3367
- * @example
3368
- * ```typescript
3369
- * client.setLocalCartShippingAddress({
3370
- * firstName: 'John',
3371
- * lastName: 'Doe',
3372
- * line1: '123 Main St',
3373
- * city: 'Tel Aviv',
3374
- * postalCode: '6100000',
3375
- * country: 'IL',
3376
- * });
3377
- * ```
3571
+ * @deprecated Address is now set via `updateGuestCheckoutAddress()` after `startGuestCheckout()`.
3572
+ * Still used by `submitGuestOrder()` for backward compatibility.
3378
3573
  */
3379
3574
  setLocalCartShippingAddress(address) {
3380
3575
  const cart = this.getLocalCart();
@@ -3383,7 +3578,8 @@ var BrainerceClient = class {
3383
3578
  return cart;
3384
3579
  }
3385
3580
  /**
3386
- * Set billing address on local cart
3581
+ * @deprecated Address is now set via `updateGuestCheckoutAddress()` after `startGuestCheckout()`.
3582
+ * Still used by `submitGuestOrder()` for backward compatibility.
3387
3583
  */
3388
3584
  setLocalCartBillingAddress(address) {
3389
3585
  const cart = this.getLocalCart();
@@ -3392,7 +3588,7 @@ var BrainerceClient = class {
3392
3588
  return cart;
3393
3589
  }
3394
3590
  /**
3395
- * Set coupon code on local cart
3591
+ * @deprecated Coupons are now applied via `applyCoupon()` on the server cart.
3396
3592
  */
3397
3593
  setLocalCartCoupon(couponCode) {
3398
3594
  const cart = this.getLocalCart();
@@ -3401,7 +3597,7 @@ var BrainerceClient = class {
3401
3597
  return cart;
3402
3598
  }
3403
3599
  /**
3404
- * Get total items count in local cart
3600
+ * @deprecated Use `getSmartCartItemCount()` instead.
3405
3601
  */
3406
3602
  getLocalCartItemCount() {
3407
3603
  const cart = this.getLocalCart();
@@ -3431,6 +3627,40 @@ var BrainerceClient = class {
3431
3627
  * ```
3432
3628
  */
3433
3629
  async submitGuestOrder(options) {
3630
+ if (this.sessionToken) {
3631
+ const serverCart = await this.getOrCreateSessionCart();
3632
+ if (!serverCart.items || serverCart.items.length === 0) {
3633
+ throw new BrainerceError("Cart is empty", 400);
3634
+ }
3635
+ const localCart = this.getLocalCart();
3636
+ if (!localCart.customer?.email) {
3637
+ throw new BrainerceError("Customer email is required. Call setLocalCartCustomer() first.", 400);
3638
+ }
3639
+ if (!localCart.shippingAddress) {
3640
+ throw new BrainerceError("Shipping address is required. Call setLocalCartShippingAddress() first.", 400);
3641
+ }
3642
+ const trackingResult = await this.startGuestCheckout();
3643
+ if (!trackingResult.tracked) {
3644
+ throw new BrainerceError("Failed to create checkout from session cart", 500);
3645
+ }
3646
+ await this.updateGuestCheckoutAddress(trackingResult.checkoutId, {
3647
+ shippingAddress: {
3648
+ ...localCart.shippingAddress,
3649
+ email: localCart.customer.email
3650
+ },
3651
+ billingAddress: localCart.billingAddress
3652
+ });
3653
+ const orderResult = await this.completeGuestCheckout(trackingResult.checkoutId, {
3654
+ clearCartOnSuccess: options?.clearCartOnSuccess
3655
+ });
3656
+ return {
3657
+ orderId: orderResult.orderId,
3658
+ orderNumber: orderResult.orderNumber || orderResult.orderId,
3659
+ status: orderResult.status || "pending",
3660
+ total: orderResult.total ?? 0,
3661
+ message: orderResult.message || "Order created successfully"
3662
+ };
3663
+ }
3434
3664
  const cart = this.getLocalCart();
3435
3665
  if (cart.items.length === 0) {
3436
3666
  throw new BrainerceError("Cart is empty", 400);
@@ -3448,7 +3678,6 @@ var BrainerceClient = class {
3448
3678
  shippingAddress: {
3449
3679
  ...cart.shippingAddress,
3450
3680
  email: cart.customer.email
3451
- // Already validated above
3452
3681
  },
3453
3682
  billingAddress: cart.billingAddress
3454
3683
  });
@@ -3536,6 +3765,34 @@ var BrainerceClient = class {
3536
3765
  * ```
3537
3766
  */
3538
3767
  async startGuestCheckout(options) {
3768
+ if (this.sessionToken) {
3769
+ const serverCart = await this.getOrCreateSessionCart();
3770
+ if (!serverCart.items || serverCart.items.length === 0) {
3771
+ throw new BrainerceError("Cart is empty", 400);
3772
+ }
3773
+ let selectedItemIds;
3774
+ if (options?.selectedIndices?.length) {
3775
+ selectedItemIds = options.selectedIndices.map((i) => serverCart.items[i]?.id).filter((id) => !!id);
3776
+ if (selectedItemIds.length === 0) {
3777
+ throw new BrainerceError("No items selected for checkout", 400);
3778
+ }
3779
+ }
3780
+ const checkout = await this.createCheckout({
3781
+ cartId: serverCart.id,
3782
+ selectedItemIds
3783
+ });
3784
+ this.saveActiveCheckout({
3785
+ checkoutId: checkout.id,
3786
+ cartId: serverCart.id,
3787
+ selectedIndices: options?.selectedIndices
3788
+ });
3789
+ return {
3790
+ tracked: true,
3791
+ checkoutId: checkout.id,
3792
+ cartId: serverCart.id,
3793
+ message: "Checkout created from session cart"
3794
+ };
3795
+ }
3539
3796
  const cart = this.getLocalCart();
3540
3797
  if (cart.items.length === 0) {
3541
3798
  throw new BrainerceError("Cart is empty", 400);
@@ -3599,16 +3856,8 @@ var BrainerceClient = class {
3599
3856
  }
3600
3857
  }
3601
3858
  /**
3859
+ * @deprecated Partial checkout is now handled server-side via `selectedItemIds`.
3602
3860
  * Remove specific items from local cart by their indices.
3603
- * Use after partial checkout to remove only the purchased items.
3604
- *
3605
- * @param indices - Array of item indices to remove
3606
- *
3607
- * @example
3608
- * ```typescript
3609
- * // After partial checkout success, remove purchased items
3610
- * client.removeLocalCartItemsByIndex([0, 2]); // Removes items at index 0 and 2
3611
- * ```
3612
3861
  */
3613
3862
  removeLocalCartItemsByIndex(indices) {
3614
3863
  const cart = this.getLocalCart();
@@ -3685,6 +3934,7 @@ var BrainerceClient = class {
3685
3934
  this.removeLocalCartItemsByIndex(indices);
3686
3935
  } else {
3687
3936
  this.clearLocalCart();
3937
+ this.clearSessionCart();
3688
3938
  }
3689
3939
  this.customerCartId = null;
3690
3940
  }
@@ -3782,6 +4032,7 @@ var BrainerceClient = class {
3782
4032
  }
3783
4033
  if (isLoggedIn) {
3784
4034
  this.clearLocalCart();
4035
+ this.clearSessionCart();
3785
4036
  return {
3786
4037
  cleared: true,
3787
4038
  mode: "full",
@@ -3798,6 +4049,7 @@ var BrainerceClient = class {
3798
4049
  };
3799
4050
  }
3800
4051
  this.clearLocalCart();
4052
+ this.clearSessionCart();
3801
4053
  return {
3802
4054
  cleared: true,
3803
4055
  mode: "full",