@neowhale/storefront 0.1.2 → 0.2.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.
@@ -1,5 +1,6 @@
1
- import { WhaleClient } from '../chunk-PR4PUHVN.js';
2
- import { createContext, useContext, useRef, useCallback, useEffect, useMemo, useState } from 'react';
1
+ import { PixelManager } from '../chunk-NLH3W6JA.js';
2
+ import { WhaleClient } from '../chunk-QIIKQ7DN.js';
3
+ import { createContext, useContext, useRef, useCallback, useEffect, useState, useMemo } from 'react';
3
4
  import { usePathname } from 'next/navigation';
4
5
  import { createStore } from 'zustand/vanilla';
5
6
  import { persist } from 'zustand/middleware';
@@ -298,7 +299,7 @@ var SESSION_KEY_SUFFIX = "-analytics-session";
298
299
  function useAnalytics() {
299
300
  const ctx = useContext(WhaleContext);
300
301
  if (!ctx) throw new Error("useAnalytics must be used within <WhaleProvider>");
301
- const { client, config } = ctx;
302
+ const { client, config, pixelManager } = ctx;
302
303
  const sessionPromiseRef = useRef(null);
303
304
  const sessionKey = `${config.storagePrefix}${SESSION_KEY_SUFFIX}`;
304
305
  const getOrCreateSession = useCallback(async () => {
@@ -336,18 +337,27 @@ function useAnalytics() {
336
337
  });
337
338
  return sessionPromiseRef.current;
338
339
  }, [client, config.sessionTtl, sessionKey]);
340
+ const trackingEnabled = config.trackingEnabled;
339
341
  const track = useCallback(
340
342
  async (eventType, data = {}) => {
343
+ if (!trackingEnabled) return;
344
+ const eventId = crypto.randomUUID();
345
+ pixelManager?.track(eventType, { ...data, eventID: eventId });
341
346
  try {
342
347
  const sessionId = await getOrCreateSession();
343
- await client.trackEvent({ session_id: sessionId, event_type: eventType, event_data: data });
348
+ await client.trackEvent({
349
+ session_id: sessionId,
350
+ event_type: eventType,
351
+ event_data: { ...data, event_id: eventId }
352
+ });
344
353
  } catch {
345
354
  }
346
355
  },
347
- [client, getOrCreateSession]
356
+ [client, getOrCreateSession, pixelManager, trackingEnabled]
348
357
  );
349
358
  const linkCustomer = useCallback(
350
359
  async (customerId) => {
360
+ if (!trackingEnabled) return;
351
361
  try {
352
362
  const sessionId = await getOrCreateSession();
353
363
  if (sessionId.startsWith("local-")) return;
@@ -355,7 +365,7 @@ function useAnalytics() {
355
365
  } catch {
356
366
  }
357
367
  },
358
- [client, getOrCreateSession]
368
+ [client, getOrCreateSession, trackingEnabled]
359
369
  );
360
370
  const trackPageView = useCallback(
361
371
  (url, referrer) => {
@@ -416,7 +426,11 @@ function useAnalytics() {
416
426
  trackAddToCart,
417
427
  trackRemoveFromCart,
418
428
  linkCustomer,
419
- getOrCreateSession
429
+ getOrCreateSession,
430
+ /** Whether tracking is globally enabled for this storefront */
431
+ trackingEnabled,
432
+ /** Configured recording sample rate (0–1) for behavioral session replays */
433
+ recordingRate: config.recordingRate
420
434
  };
421
435
  }
422
436
  function useAuth() {
@@ -437,22 +451,26 @@ function useAuth() {
437
451
 
438
452
  // src/react/components/analytics-tracker.tsx
439
453
  function AnalyticsTracker({ pathname }) {
454
+ const ctx = useContext(WhaleContext);
440
455
  const { trackPageView, linkCustomer } = useAnalytics();
441
456
  const { customer } = useAuth();
442
457
  const prevPathname = useRef(null);
443
458
  const linkedCustomerId = useRef(null);
459
+ const trackingEnabled = ctx?.config.trackingEnabled ?? true;
444
460
  useEffect(() => {
461
+ if (!trackingEnabled) return;
445
462
  if (pathname === prevPathname.current) return;
446
463
  const referrer = prevPathname.current || (typeof document !== "undefined" ? document.referrer : "");
447
464
  prevPathname.current = pathname;
448
465
  trackPageView(pathname, referrer || void 0);
449
- }, [pathname, trackPageView]);
466
+ }, [pathname, trackPageView, trackingEnabled]);
450
467
  useEffect(() => {
468
+ if (!trackingEnabled) return;
451
469
  if (customer?.id && customer.id !== linkedCustomerId.current) {
452
470
  linkedCustomerId.current = customer.id;
453
471
  linkCustomer(customer.id);
454
472
  }
455
- }, [customer?.id, linkCustomer]);
473
+ }, [customer?.id, linkCustomer, trackingEnabled]);
456
474
  return null;
457
475
  }
458
476
  function useCart() {
@@ -516,6 +534,38 @@ function AuthInitializer() {
516
534
  }, []);
517
535
  return null;
518
536
  }
537
+ function PixelInitializer({ onReady }) {
538
+ const ctx = useContext(WhaleContext);
539
+ const initialized = useRef(false);
540
+ useEffect(() => {
541
+ if (!ctx || initialized.current) return;
542
+ if (typeof window === "undefined") return;
543
+ if (!ctx.config.trackingEnabled) return;
544
+ initialized.current = true;
545
+ const { client } = ctx;
546
+ client.fetchStorefrontConfig().then(async (config) => {
547
+ if (!config.pixels || config.pixels.length === 0) return;
548
+ const manager = new PixelManager(config.pixels);
549
+ await manager.initialize();
550
+ onReady(manager);
551
+ }).catch(() => {
552
+ });
553
+ }, [ctx, onReady]);
554
+ return null;
555
+ }
556
+ function envBool(name) {
557
+ if (typeof process === "undefined") return void 0;
558
+ const raw = process.env[name];
559
+ if (raw === void 0 || raw === "") return void 0;
560
+ return raw !== "0" && raw.toLowerCase() !== "false";
561
+ }
562
+ function envNumber(name) {
563
+ if (typeof process === "undefined") return void 0;
564
+ const raw = process.env[name];
565
+ if (raw === void 0 || raw === "") return void 0;
566
+ const n = Number(raw);
567
+ return Number.isFinite(n) ? n : void 0;
568
+ }
519
569
  function WhaleProvider({
520
570
  children,
521
571
  products = [],
@@ -527,9 +577,15 @@ function WhaleProvider({
527
577
  supabaseHost,
528
578
  storagePrefix,
529
579
  sessionTtl,
530
- debug
580
+ debug,
581
+ trackingEnabled,
582
+ recordingRate
531
583
  }) {
532
584
  const pathname = usePathname();
585
+ const [pixelManager, setPixelManager] = useState(null);
586
+ const handlePixelReady = useCallback((manager) => {
587
+ setPixelManager(manager);
588
+ }, []);
533
589
  const ctx = useMemo(() => {
534
590
  const resolvedConfig = {
535
591
  storeId,
@@ -540,7 +596,9 @@ function WhaleProvider({
540
596
  supabaseHost: supabaseHost || "",
541
597
  storagePrefix: storagePrefix || "whale",
542
598
  sessionTtl: sessionTtl || 30 * 60 * 1e3,
543
- debug: debug || false
599
+ debug: debug || false,
600
+ trackingEnabled: trackingEnabled ?? envBool("NEXT_PUBLIC_TRACKING_ENABLED") ?? true,
601
+ recordingRate: recordingRate ?? envNumber("NEXT_PUBLIC_RECORDING_RATE") ?? 0.1
544
602
  };
545
603
  const client = new WhaleClient({
546
604
  storeId,
@@ -555,17 +613,19 @@ function WhaleProvider({
555
613
  config: resolvedConfig,
556
614
  cartStore,
557
615
  authStore,
558
- products
616
+ products,
617
+ pixelManager: null
559
618
  };
560
619
  }, [storeId, apiKey]);
561
620
  const value = useMemo(
562
- () => ({ ...ctx, products }),
563
- [ctx, products]
621
+ () => ({ ...ctx, products, pixelManager }),
622
+ [ctx, products, pixelManager]
564
623
  );
565
624
  return /* @__PURE__ */ jsxs(WhaleContext.Provider, { value, children: [
566
625
  /* @__PURE__ */ jsx(AuthInitializer, {}),
567
626
  /* @__PURE__ */ jsx(CartInitializer, {}),
568
627
  /* @__PURE__ */ jsx(AnalyticsTracker, { pathname }),
628
+ /* @__PURE__ */ jsx(PixelInitializer, { onReady: handlePixelReady }),
569
629
  children
570
630
  ] });
571
631
  }
@@ -653,6 +713,6 @@ function useCustomerAnalytics() {
653
713
  return { analytics, loading };
654
714
  }
655
715
 
656
- export { AnalyticsTracker, AuthInitializer, CartInitializer, WhaleContext, WhaleProvider, useAnalytics, useAuth, useCart, useCartItemCount, useCartTotal, useCustomerAnalytics, useCustomerOrders, useProduct, useProducts, useWhaleClient };
716
+ export { AnalyticsTracker, AuthInitializer, CartInitializer, PixelInitializer, WhaleContext, WhaleProvider, useAnalytics, useAuth, useCart, useCartItemCount, useCartTotal, useCustomerAnalytics, useCustomerOrders, useProduct, useProducts, useWhaleClient };
657
717
  //# sourceMappingURL=index.js.map
658
718
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/context.ts","../../src/react/stores/cart-store.ts","../../src/react/stores/auth-store.ts","../../src/react/hooks/use-analytics.ts","../../src/react/hooks/use-auth.ts","../../src/react/components/analytics-tracker.tsx","../../src/react/hooks/use-cart.ts","../../src/react/components/cart-initializer.tsx","../../src/react/components/auth-initializer.tsx","../../src/react/provider.tsx","../../src/react/hooks/use-products.ts","../../src/react/hooks/use-client.ts","../../src/react/hooks/use-customer.ts"],"names":["createStore","persist","useContext","useRef","useStore","useShallow","useEffect","useMemo","useState","useCallback"],"mappings":";;;;;;;;;AAyBO,IAAM,YAAA,GAAe,cAAwC,IAAI;ACgBjE,SAAS,eAAA,CACd,MAAA,EACA,aAAA,EACA,WAAA,EACA,gBAAA,EACA;AACA,EAAA,OAAO,WAAA,EAAqC;AAAA,IAC1C,OAAA;AAAA,MACE,CAAC,KAAK,GAAA,MAAS;AAAA;AAAA,QAEb,MAAA,EAAQ,IAAA;AAAA,QACR,OAAO,EAAC;AAAA,QACR,SAAA,EAAW,CAAA;AAAA,QACX,QAAA,EAAU,CAAA;AAAA,QACV,SAAA,EAAW,CAAA;AAAA,QACX,KAAA,EAAO,CAAA;AAAA,QACP,cAAc,EAAC;AAAA,QACf,QAAA,EAAU,KAAA;AAAA,QACV,WAAA,EAAa,KAAA;AAAA,QACb,eAAe,EAAC;AAAA,QAChB,eAAA,EAAiB,KAAA;AAAA;AAAA,QAGjB,UAAU,MAAM,GAAA,CAAI,EAAE,QAAA,EAAU,MAAM,CAAA;AAAA,QACtC,WAAW,MAAM,GAAA,CAAI,EAAE,QAAA,EAAU,OAAO,CAAA;AAAA,QACxC,UAAA,EAAY,MAAM,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,QAAA,EAAU,CAAC,CAAA,CAAE,QAAA,EAAS,CAAE,CAAA;AAAA;AAAA,QAGxD,UAAU,YAAY;AACpB,UAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,GAAA,EAAI;AAEjC,UAAA,IAAI,MAAA,EAAQ;AACV,YAAA,IAAI;AACF,cAAA,MAAM,QAAA,EAAS;AAAA,YACjB,CAAA,CAAA,MAAQ;AACN,cAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,UAAA,EAAW;AACrC,cAAA,SAAA,CAAU,GAAA,EAAK,KAAK,IAAI,CAAA;AAAA,YAC1B;AACA,YAAA;AAAA,UACF;AAEA,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,UAAA,EAAW;AACrC,YAAA,SAAA,CAAU,GAAA,EAAK,KAAK,IAAI,CAAA;AAAA,UAC1B,SAAS,GAAA,EAAK;AACZ,YAAA,OAAA,CAAQ,KAAA,CAAM,uCAAuC,GAAG,CAAA;AAAA,UAC1D;AAAA,QACF,CAAA;AAAA,QAEA,UAAU,YAAY;AACpB,UAAA,MAAM,EAAE,MAAA,EAAQ,aAAA,EAAc,GAAI,GAAA,EAAI;AACtC,UAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA;AACxC,YAAA,MAAM,SAAS,IAAA,CAAK,KAAA,IAAS,EAAC,EAAG,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,cAC9C,GAAG,IAAA;AAAA,cACH,WAAW,IAAA,CAAK,SAAA,IAAa,aAAA,CAAc,IAAA,CAAK,UAAU,CAAA,IAAK;AAAA,aACjE,CAAE,CAAA;AACF,YAAA,GAAA,CAAI;AAAA,cACF,KAAA;AAAA,cACA,SAAA,EAAW,KAAK,UAAA,IAAc,CAAA;AAAA,cAC9B,QAAA,EAAU,KAAK,QAAA,IAAY,CAAA;AAAA,cAC3B,SAAA,EAAW,KAAK,UAAA,IAAc,CAAA;AAAA,cAC9B,KAAA,EAAO,KAAK,KAAA,IAAS,CAAA;AAAA,cACrB,YAAA,EAAc,IAAA,CAAK,aAAA,IAAiB;AAAC,aACtC,CAAA;AAAA,UACH,SAAS,GAAA,EAAK;AACZ,YAAA,OAAA,CAAQ,KAAA,CAAM,uCAAuC,GAAG,CAAA;AACxD,YAAA,MAAM,GAAA;AAAA,UACR;AAAA,QACF,CAAA;AAAA,QAEA,SAAS,OAAO,SAAA,EAAW,UAAU,IAAA,EAAM,SAAA,EAAW,UAAU,WAAA,KAAgB;AAE9E,UAAA,IAAI,GAAA,GAAM,eAAA,EAAiB;AAC3B,UAAA,GAAA,CAAI,EAAE,WAAA,EAAa,IAAA,EAAM,eAAA,EAAiB,MAAM,CAAA;AAEhD,UAAA,IAAI;AACF,YAAA,IAAI,EAAE,MAAA,EAAO,GAAI,GAAA,EAAI;AAErB,YAAA,IAAI,CAAC,MAAA,EAAQ;AACX,cAAA,MAAM,GAAA,GAAM,QAAA,EAAS;AACrB,cAAA,MAAA,GAAS,KAAI,CAAE,MAAA;AAAA,YACjB;AAEA,YAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAExD,YAAA,IAAI,QAAA,EAAU;AACZ,cAAA,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,aAAA,EAAe,EAAE,GAAG,CAAA,CAAE,aAAA,EAAe,CAAC,SAAS,GAAG,QAAA,IAAW,CAAE,CAAA;AAAA,YAC/E;AAEA,YAAA,IAAI;AACF,cAAA,MAAM,MAAA,CAAO,UAAU,MAAA,EAAQ,SAAA,EAAW,UAAU,EAAE,IAAA,EAAM,WAAW,CAAA;AAAA,YACzE,SAAS,GAAA,EAAc;AAErB,cAAA,MAAM,SAAU,GAAA,CAA4B,MAAA;AAC5C,cAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,EAAK;AACpC,gBAAA,MAAM,OAAA,GAAU,MAAM,MAAA,CAAO,UAAA,EAAW;AACxC,gBAAA,GAAA,CAAI,EAAE,MAAA,EAAQ,OAAA,CAAQ,EAAA,EAAI,CAAA;AAC1B,gBAAA,MAAM,MAAA,CAAO,UAAU,OAAA,CAAQ,EAAA,EAAI,WAAW,QAAA,EAAU,EAAE,IAAA,EAAM,SAAA,EAAW,CAAA;AAAA,cAC7E,CAAA,MAAO;AACL,gBAAA,MAAM,GAAA;AAAA,cACR;AAAA,YACF;AAEA,YAAA,MAAM,GAAA,GAAM,QAAA,EAAS;AAGrB,YAAA,WAAA,GAAc,WAAW,WAAA,IAAe,EAAA,EAAI,QAAA,EAAU,SAAA,IAAa,GAAG,IAAI,CAAA;AAAA,UAC5E,CAAA,SAAE;AACA,YAAA,GAAA,CAAI,EAAE,WAAA,EAAa,KAAA,EAAO,eAAA,EAAiB,OAAO,CAAA;AAAA,UACpD;AAAA,QACF,CAAA;AAAA,QAEA,cAAA,EAAgB,OAAO,MAAA,EAAQ,QAAA,KAAa;AAC1C,UAAA,GAAA,CAAI,EAAE,WAAA,EAAa,IAAA,EAAM,CAAA;AACzB,UAAA,IAAI;AACF,YAAA,MAAM,EAAE,MAAA,EAAO,GAAI,GAAA,EAAI;AACvB,YAAA,IAAI,CAAC,MAAA,EAAQ;AACb,YAAA,MAAM,MAAA,CAAO,cAAA,CAAe,MAAA,EAAQ,MAAA,EAAQ,QAAQ,CAAA;AACpD,YAAA,MAAM,GAAA,GAAM,QAAA,EAAS;AAAA,UACvB,CAAA,SAAE;AACA,YAAA,GAAA,CAAI,EAAE,WAAA,EAAa,KAAA,EAAO,CAAA;AAAA,UAC5B;AAAA,QACF,CAAA;AAAA,QAEA,UAAA,EAAY,OAAO,MAAA,EAAQ,WAAA,KAAgB;AACzC,UAAA,GAAA,CAAI,EAAE,WAAA,EAAa,IAAA,EAAM,CAAA;AACzB,UAAA,IAAI;AACF,YAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAM,GAAI,GAAA,EAAI;AAC9B,YAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,YAAA,MAAM,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,MAAM,CAAA;AAC9C,YAAA,MAAM,MAAA,CAAO,cAAA,CAAe,MAAA,EAAQ,MAAM,CAAA;AAC1C,YAAA,MAAM,GAAA,GAAM,QAAA,EAAS;AAErB,YAAA,IAAI,IAAA,EAAM;AACR,cAAA,gBAAA,GAAmB,IAAA,CAAK,UAAA,EAAY,WAAA,IAAe,IAAA,CAAK,YAAY,CAAA;AAAA,YACtE;AAAA,UACF,CAAA,SAAE;AACA,YAAA,GAAA,CAAI,EAAE,WAAA,EAAa,KAAA,EAAO,CAAA;AAAA,UAC5B;AAAA,QACF,CAAA;AAAA,QAEA,WAAW,MAAM;AACf,UAAA,GAAA,CAAI;AAAA,YACF,MAAA,EAAQ,IAAA;AAAA,YACR,OAAO,EAAC;AAAA,YACR,SAAA,EAAW,CAAA;AAAA,YACX,QAAA,EAAU,CAAA;AAAA,YACV,SAAA,EAAW,CAAA;AAAA,YACX,KAAA,EAAO,CAAA;AAAA,YACP,cAAc,EAAC;AAAA,YACf,eAAe;AAAC,WACjB,CAAA;AAAA,QACH,CAAA;AAAA,QAEA,QAAA,EAAU,OAAO,aAAA,EAAe,OAAA,KAAY;AAC1C,UAAA,MAAM,EAAE,MAAA,EAAO,GAAI,GAAA,EAAI;AACvB,UAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,gBAAgB,CAAA;AAE7C,UAAA,GAAA,CAAI,EAAE,WAAA,EAAa,IAAA,EAAM,CAAA;AACzB,UAAA,IAAI;AACF,YAAA,MAAM,QAAQ,MAAM,MAAA,CAAO,QAAA,CAAS,MAAA,EAAQ,eAAe,OAAO,CAAA;AAClE,YAAA,GAAA,CAAI;AAAA,cACF,MAAA,EAAQ,IAAA;AAAA,cACR,OAAO,EAAC;AAAA,cACR,SAAA,EAAW,CAAA;AAAA,cACX,QAAA,EAAU,CAAA;AAAA,cACV,SAAA,EAAW,CAAA;AAAA,cACX,KAAA,EAAO,CAAA;AAAA,cACP,cAAc,EAAC;AAAA,cACf,eAAe,EAAC;AAAA,cAChB,QAAA,EAAU;AAAA,aACX,CAAA;AACD,YAAA,OAAO,KAAA;AAAA,UACT,CAAA,SAAE;AACA,YAAA,GAAA,CAAI,EAAE,WAAA,EAAa,KAAA,EAAO,CAAA;AAAA,UAC5B;AAAA,QACF;AAAA,OACF,CAAA;AAAA;AAAA,MAGA;AAAA,QACE,IAAA,EAAM,GAAG,aAAa,CAAA,KAAA,CAAA;AAAA,QACtB,UAAA,EAAY,CAAC,KAAA,MAAW;AAAA,UACtB,QAAQ,KAAA,CAAM,MAAA;AAAA,UACd,eAAe,KAAA,CAAM;AAAA,SACvB;AAAA;AACF;AACF,GACF;AACF;AAEA,SAAS,SAAA,CACP,GAAA,EACA,GAAA,EACA,IAAA,EACA;AACA,EAAA,MAAM,aAAA,GAAgB,KAAI,CAAE,aAAA;AAC5B,EAAA,MAAM,SAAS,IAAA,CAAK,KAAA,IAAS,EAAC,EAAG,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,IAC9C,GAAG,IAAA;AAAA,IACH,WAAW,IAAA,CAAK,SAAA,IAAa,aAAA,CAAc,IAAA,CAAK,UAAU,CAAA,IAAK;AAAA,GACjE,CAAE,CAAA;AACF,EAAA,GAAA,CAAI;AAAA,IACF,QAAQ,IAAA,CAAK,EAAA;AAAA,IACb,KAAA;AAAA,IACA,SAAA,EAAW,KAAK,UAAA,IAAc,CAAA;AAAA,IAC9B,QAAA,EAAU,KAAK,QAAA,IAAY,CAAA;AAAA,IAC3B,SAAA,EAAW,KAAK,UAAA,IAAc,CAAA;AAAA,IAC9B,KAAA,EAAO,KAAK,KAAA,IAAS,CAAA;AAAA,IACrB,YAAA,EAAc,IAAA,CAAK,aAAA,IAAiB;AAAC,GACtC,CAAA;AACH;ACxOO,SAAS,eAAA,CAAgB,QAAqB,aAAA,EAAuB;AAC1E,EAAA,OAAOA,WAAAA,EAAqC;AAAA,IAC1CC,OAAAA;AAAA,MACE,CAAC,KAAK,GAAA,MAAS;AAAA;AAAA,QAEb,QAAA,EAAU,IAAA;AAAA,QACV,YAAA,EAAc,IAAA;AAAA,QACd,gBAAA,EAAkB,IAAA;AAAA,QAClB,WAAA,EAAa,KAAA;AAAA;AAAA,QAGb,OAAA,EAAS,OAAO,KAAA,KAAU;AACxB,UAAA,GAAA,CAAI,EAAE,WAAA,EAAa,IAAA,EAAM,CAAA;AACzB,UAAA,IAAI;AACF,YAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA;AACvC,YAAA,OAAO,GAAA,CAAI,IAAA;AAAA,UACb,SAAS,GAAA,EAAK;AACZ,YAAA,MAAM,OAAA,GAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,qBAAA;AACrD,YAAA,MAAM,IAAI,MAAM,OAAO,CAAA;AAAA,UACzB,CAAA,SAAE;AACA,YAAA,GAAA,CAAI,EAAE,WAAA,EAAa,KAAA,EAAO,CAAA;AAAA,UAC5B;AAAA,QACF,CAAA;AAAA,QAEA,SAAA,EAAW,OAAO,KAAA,EAAO,IAAA,KAAS;AAChC,UAAA,GAAA,CAAI,EAAE,WAAA,EAAa,IAAA,EAAM,CAAA;AACzB,UAAA,IAAI;AACF,YAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,UAAA,CAAW,OAAO,IAAI,CAAA;AAC/C,YAAA,MAAA,CAAO,eAAA,CAAgB,IAAI,UAAU,CAAA;AACrC,YAAA,GAAA,CAAI;AAAA,cACF,cAAc,GAAA,CAAI,UAAA;AAAA,cAClB,gBAAA,EAAkB,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,EAAI,GAAI,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAI,CAAA,CAAE,WAAA;AAAY,aAC/E,CAAA;AAED,YAAA,IAAI,GAAA,CAAI,UAAU,EAAA,EAAI;AACpB,cAAA,IAAI;AACF,gBAAA,MAAM,OAAO,MAAM,MAAA,CAAO,WAAA,CAAY,GAAA,CAAI,SAAS,EAAE,CAAA;AACrD,gBAAA,GAAA,CAAI,EAAE,QAAA,EAAU,IAAA,EAAM,CAAA;AAAA,cACxB,CAAA,CAAA,MAAQ;AACN,gBAAA,GAAA,CAAI,EAAE,QAAA,EAAU,GAAA,CAAI,QAAA,EAAU,CAAA;AAAA,cAChC;AAAA,YACF;AAEA,YAAA,OAAO,IAAI,aAAA,IAAiB,KAAA;AAAA,UAC9B,SAAS,GAAA,EAAK;AACZ,YAAA,MAAM,OAAA,GAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,qBAAA;AACrD,YAAA,MAAM,IAAI,MAAM,OAAO,CAAA;AAAA,UACzB,CAAA,SAAE;AACA,YAAA,GAAA,CAAI,EAAE,WAAA,EAAa,KAAA,EAAO,CAAA;AAAA,UAC5B;AAAA,QACF,CAAA;AAAA,QAEA,gBAAgB,YAAY;AAC1B,UAAA,MAAM,EAAE,YAAA,EAAc,gBAAA,EAAkB,QAAA,KAAa,GAAA,EAAI;AACzD,UAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,gBAAA,EAAkB;AAExC,UAAA,IAAI,IAAI,IAAA,CAAK,gBAAgB,CAAA,oBAAK,IAAI,MAAK,EAAG;AAC5C,YAAA,MAAA,CAAO,gBAAgB,IAAI,CAAA;AAC3B,YAAA,GAAA,CAAI,EAAE,YAAA,EAAc,IAAA,EAAM,kBAAkB,IAAA,EAAM,QAAA,EAAU,MAAM,CAAA;AAClE,YAAA;AAAA,UACF;AAEA,UAAA,MAAA,CAAO,gBAAgB,YAAY,CAAA;AAEnC,UAAA,IAAI,UAAU,EAAA,EAAI;AAChB,YAAA,IAAI;AACF,cAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,WAAA,CAAY,SAAS,EAAE,CAAA;AAClD,cAAA,GAAA,CAAI,EAAE,QAAA,EAAU,KAAA,EAAO,CAAA;AAAA,YACzB,CAAA,CAAA,MAAQ;AACN,cAAA,MAAA,CAAO,gBAAgB,IAAI,CAAA;AAC3B,cAAA,GAAA,CAAI,EAAE,YAAA,EAAc,IAAA,EAAM,kBAAkB,IAAA,EAAM,QAAA,EAAU,MAAM,CAAA;AAAA,YACpE;AAAA,UACF;AAAA,QACF,CAAA;AAAA,QAEA,gBAAgB,MAAM;AACpB,UAAA,MAAM,EAAE,YAAA,EAAc,gBAAA,EAAiB,GAAI,GAAA,EAAI;AAC/C,UAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,gBAAA,EAAkB,OAAO,KAAA;AAC/C,UAAA,OAAO,IAAI,IAAA,CAAK,gBAAgB,CAAA,uBAAQ,IAAA,EAAK;AAAA,QAC/C,CAAA;AAAA,QAEA,QAAQ,MAAM;AACZ,UAAA,MAAA,CAAO,gBAAgB,IAAI,CAAA;AAC3B,UAAA,GAAA,CAAI,EAAE,QAAA,EAAU,IAAA,EAAM,cAAc,IAAA,EAAM,gBAAA,EAAkB,MAAM,CAAA;AAAA,QACpE,CAAA;AAAA,QAEA,aAAA,EAAe,OAAO,EAAA,KAAO;AAC3B,UAAA,IAAI;AACF,YAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,WAAA,CAAY,EAAE,CAAA;AAC5C,YAAA,GAAA,CAAI,EAAE,UAAU,CAAA;AAAA,UAClB,SAAS,GAAA,EAAK;AACZ,YAAA,OAAA,CAAQ,KAAA,CAAM,4CAA4C,GAAG,CAAA;AAAA,UAC/D;AAAA,QACF;AAAA,OACF,CAAA;AAAA;AAAA,MAGA;AAAA,QACE,IAAA,EAAM,GAAG,aAAa,CAAA,KAAA,CAAA;AAAA,QACtB,UAAA,EAAY,CAAC,KAAA,MAAW;AAAA,UACtB,cAAc,KAAA,CAAM,YAAA;AAAA,UACpB,kBAAkB,KAAA,CAAM,gBAAA;AAAA,UACxB,QAAA,EAAU,MAAM,QAAA,GACZ;AAAA,YACE,EAAA,EAAI,MAAM,QAAA,CAAS,EAAA;AAAA,YACnB,KAAA,EAAO,MAAM,QAAA,CAAS,KAAA;AAAA,YACtB,UAAA,EAAY,MAAM,QAAA,CAAS,UAAA;AAAA,YAC3B,SAAA,EAAW,MAAM,QAAA,CAAS,SAAA;AAAA,YAC1B,KAAA,EAAO,MAAM,QAAA,CAAS,KAAA;AAAA,YACtB,cAAA,EAAgB,MAAM,QAAA,CAAS,cAAA;AAAA,YAC/B,YAAA,EAAc,MAAM,QAAA,CAAS,YAAA;AAAA,YAC7B,WAAA,EAAa,MAAM,QAAA,CAAS,WAAA;AAAA,YAC5B,YAAA,EAAc,MAAM,QAAA,CAAS;AAAA,WAC/B,GACA;AAAA,SACN;AAAA;AACF;AACF,GACF;AACF;ACxIA,IAAM,kBAAA,GAAqB,oBAAA;AAOpB,SAAS,YAAA,GAAe;AAC7B,EAAA,MAAM,GAAA,GAAM,WAAW,YAAY,CAAA;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAE5E,EAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAO,GAAI,GAAA;AAC3B,EAAA,MAAM,iBAAA,GAAoB,OAA+B,IAAI,CAAA;AAC7D,EAAA,MAAM,UAAA,GAAa,CAAA,EAAG,MAAA,CAAO,aAAa,GAAG,kBAAkB,CAAA,CAAA;AAE/D,EAAA,MAAM,kBAAA,GAAqB,YAAY,YAA6B;AAClE,IAAA,IAAI,iBAAA,CAAkB,OAAA,EAAS,OAAO,iBAAA,CAAkB,OAAA;AAExD,IAAA,iBAAA,CAAkB,WAAW,YAAY;AAEvC,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,UAAU,CAAA;AAC3C,QAAA,IAAI,GAAA,EAAK;AACP,UAAA,MAAM,MAAA,GAAsB,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC1C,UAAA,IAAI,KAAK,GAAA,EAAI,GAAI,MAAA,CAAO,SAAA,GAAY,OAAO,UAAA,EAAY;AAErD,YAAA,MAAA,CAAO,aAAA,CAAc,MAAA,CAAO,EAAA,EAAI,EAAE,cAAA,EAAA,iBAAgB,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY,EAAG,CAAA,CAAE,MAAM,MAAM;AAAA,YAAC,CAAC,CAAA;AAC5F,YAAA,OAAO,MAAA,CAAO,EAAA;AAAA,UAChB;AAAA,QACF;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAGA,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,MAAM,MAAA,CAAO,aAAA,CAAc;AAAA,UACzC,YAAY,SAAA,CAAU,SAAA;AAAA,UACtB,QAAA,EAAU,SAAS,QAAA,IAAY,KAAA;AAAA,SAChC,CAAA;AACD,QAAA,IAAI,SAAS,EAAA,EAAI;AACf,UAAA,YAAA,CAAa,OAAA,CAAQ,UAAA,EAAY,IAAA,CAAK,SAAA,CAAU,EAAE,EAAA,EAAI,OAAA,CAAQ,EAAA,EAAI,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,EAAG,CAAC,CAAA;AAC1F,UAAA,OAAO,OAAA,CAAQ,EAAA;AAAA,QACjB;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAGA,MAAA,MAAM,UAAA,GAAa,CAAA,MAAA,EAAS,IAAA,CAAK,GAAA,EAAK,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,EAAO,CAAE,SAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAChF,MAAA,YAAA,CAAa,OAAA,CAAQ,UAAA,EAAY,IAAA,CAAK,SAAA,CAAU,EAAE,EAAA,EAAI,UAAA,EAAY,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,EAAG,CAAC,CAAA;AAC1F,MAAA,OAAO,UAAA;AAAA,IACT,CAAA,GAAG;AAEH,IAAA,iBAAA,CAAkB,OAAA,CAAQ,QAAQ,MAAM;AACtC,MAAA,iBAAA,CAAkB,OAAA,GAAU,IAAA;AAAA,IAC9B,CAAC,CAAA;AAED,IAAA,OAAO,iBAAA,CAAkB,OAAA;AAAA,EAC3B,GAAG,CAAC,MAAA,EAAQ,MAAA,CAAO,UAAA,EAAY,UAAU,CAAC,CAAA;AAE1C,EAAA,MAAM,KAAA,GAAQ,WAAA;AAAA,IACZ,OAAO,SAAA,EAAsB,IAAA,GAAgC,EAAC,KAAM;AAClE,MAAA,IAAI;AACF,QAAA,MAAM,SAAA,GAAY,MAAM,kBAAA,EAAmB;AAC3C,QAAA,MAAM,MAAA,CAAO,WAAW,EAAE,UAAA,EAAY,WAAW,UAAA,EAAY,SAAA,EAAW,UAAA,EAAY,IAAA,EAAM,CAAA;AAAA,MAC5F,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IACA,CAAC,QAAQ,kBAAkB;AAAA,GAC7B;AAEA,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,OAAO,UAAA,KAAuB;AAC5B,MAAA,IAAI;AACF,QAAA,MAAM,SAAA,GAAY,MAAM,kBAAA,EAAmB;AAC3C,QAAA,IAAI,SAAA,CAAU,UAAA,CAAW,QAAQ,CAAA,EAAG;AACpC,QAAA,MAAM,OAAO,aAAA,CAAc,SAAA,EAAW,EAAE,WAAA,EAAa,YAAY,CAAA;AAAA,MACnE,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IACA,CAAC,QAAQ,kBAAkB;AAAA,GAC7B;AAEA,EAAA,MAAM,aAAA,GAAgB,WAAA;AAAA,IACpB,CAAC,KAAa,QAAA,KAAsB;AAClC,MAAA,KAAA,CAAM,WAAA,EAAa,EAAE,GAAA,EAAK,QAAA,EAAU,CAAA;AAAA,IACtC,CAAA;AAAA,IACA,CAAC,KAAK;AAAA,GACR;AAEA,EAAA,MAAM,gBAAA,GAAmB,WAAA;AAAA,IACvB,CAAC,SAAA,EAAmB,WAAA,EAAqB,QAAA,EAAkB,KAAA,KAAmB;AAC5E,MAAA,KAAA,CAAM,cAAA,EAAgB,EAAE,UAAA,EAAY,SAAA,EAAW,cAAc,WAAA,EAAa,QAAA,EAAU,OAAO,CAAA;AAAA,IAC7F,CAAA;AAAA,IACA,CAAC,KAAK;AAAA,GACR;AAEA,EAAA,MAAM,iBAAA,GAAoB,WAAA;AAAA,IACxB,CAAC,YAAoB,YAAA,KAAyB;AAC5C,MAAA,KAAA,CAAM,iBAAiB,EAAE,WAAA,EAAa,UAAA,EAAY,aAAA,EAAe,cAAc,CAAA;AAAA,IACjF,CAAA;AAAA,IACA,CAAC,KAAK;AAAA,GACR;AAEA,EAAA,MAAM,WAAA,GAAc,WAAA;AAAA,IAClB,CAAC,OAAe,WAAA,KAAyB;AACvC,MAAA,KAAA,CAAM,QAAA,EAAU,EAAE,KAAA,EAAO,YAAA,EAAc,aAAa,CAAA;AAAA,IACtD,CAAA;AAAA,IACA,CAAC,KAAK;AAAA,GACR;AAEA,EAAA,MAAM,kBAAA,GAAqB,WAAA;AAAA,IACzB,CAAC,MAAA,EAAgB,KAAA,EAAe,SAAA,KAAsB;AACpD,MAAA,KAAA,CAAM,kBAAkB,EAAE,OAAA,EAAS,QAAQ,KAAA,EAAO,UAAA,EAAY,WAAW,CAAA;AAAA,IAC3E,CAAA;AAAA,IACA,CAAC,KAAK;AAAA,GACR;AAEA,EAAA,MAAM,aAAA,GAAgB,WAAA;AAAA,IACpB,CAAC,OAAA,EAAiB,WAAA,EAAqB,KAAA,KAAkB;AACvD,MAAA,KAAA,CAAM,YAAY,EAAE,QAAA,EAAU,SAAS,YAAA,EAAc,WAAA,EAAa,OAAO,CAAA;AAAA,IAC3E,CAAA;AAAA,IACA,CAAC,KAAK;AAAA,GACR;AAEA,EAAA,MAAM,cAAA,GAAiB,WAAA;AAAA,IACrB,CAAC,SAAA,EAAmB,WAAA,EAAqB,QAAA,EAAkB,OAAe,IAAA,KAAkB;AAC1F,MAAA,KAAA,CAAM,aAAA,EAAe,EAAE,UAAA,EAAY,SAAA,EAAW,cAAc,WAAA,EAAa,QAAA,EAAU,KAAA,EAAO,IAAA,EAAM,CAAA;AAAA,IAClG,CAAA;AAAA,IACA,CAAC,KAAK;AAAA,GACR;AAEA,EAAA,MAAM,mBAAA,GAAsB,WAAA;AAAA,IAC1B,CAAC,WAAmB,WAAA,KAAwB;AAC1C,MAAA,KAAA,CAAM,oBAAoB,EAAE,UAAA,EAAY,SAAA,EAAW,YAAA,EAAc,aAAa,CAAA;AAAA,IAChF,CAAA;AAAA,IACA,CAAC,KAAK;AAAA,GACR;AAEA,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,aAAA;AAAA,IACA,gBAAA;AAAA,IACA,iBAAA;AAAA,IACA,WAAA;AAAA,IACA,kBAAA;AAAA,IACA,aAAA;AAAA,IACA,cAAA;AAAA,IACA,mBAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AACF;AC1JO,SAAS,OAAA,GAAU;AACxB,EAAA,MAAM,GAAA,GAAMC,WAAW,YAAY,CAAA;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAEvE,EAAA,OAAO,QAAA,CAAS,GAAA,CAAI,SAAA,EAAW,UAAA,CAAW,CAAC,CAAA,MAAO;AAAA,IAChD,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,aAAa,CAAA,CAAE,WAAA;AAAA,IACf,cAAc,CAAA,CAAE,YAAA;AAAA,IAChB,eAAA,EAAiB,EAAE,cAAA,EAAe;AAAA,IAClC,UAAU,CAAA,CAAE,OAAA;AAAA,IACZ,YAAY,CAAA,CAAE,SAAA;AAAA,IACd,gBAAgB,CAAA,CAAE,cAAA;AAAA,IAClB,QAAQ,CAAA,CAAE,MAAA;AAAA,IACV,eAAe,CAAA,CAAE;AAAA,IACjB,CAAC,CAAA;AACL;;;ACZO,SAAS,gBAAA,CAAiB,EAAE,QAAA,EAAS,EAAyB;AACnE,EAAA,MAAM,EAAE,aAAA,EAAe,YAAA,EAAa,GAAI,YAAA,EAAa;AACrD,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,OAAA,EAAQ;AAC7B,EAAA,MAAM,YAAA,GAAeC,OAAsB,IAAI,CAAA;AAC/C,EAAA,MAAM,gBAAA,GAAmBA,OAAsB,IAAI,CAAA;AAGnD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAA,KAAa,aAAa,OAAA,EAAS;AACvC,IAAA,MAAM,WAAW,YAAA,CAAa,OAAA,KAAY,OAAO,QAAA,KAAa,WAAA,GAAc,SAAS,QAAA,GAAW,EAAA,CAAA;AAChG,IAAA,YAAA,CAAa,OAAA,GAAU,QAAA;AACvB,IAAA,aAAA,CAAc,QAAA,EAAU,YAAY,MAAS,CAAA;AAAA,EAC/C,CAAA,EAAG,CAAC,QAAA,EAAU,aAAa,CAAC,CAAA;AAG5B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAA,EAAU,EAAA,IAAM,QAAA,CAAS,EAAA,KAAO,iBAAiB,OAAA,EAAS;AAC5D,MAAA,gBAAA,CAAiB,UAAU,QAAA,CAAS,EAAA;AACpC,MAAA,YAAA,CAAa,SAAS,EAAE,CAAA;AAAA,IAC1B;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,EAAA,EAAI,YAAY,CAAC,CAAA;AAE/B,EAAA,OAAO,IAAA;AACT;ACnBO,SAAS,OAAA,GAAU;AACxB,EAAA,MAAM,GAAA,GAAMD,WAAW,YAAY,CAAA;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAEvE,EAAA,OAAOE,QAAAA,CAAS,GAAA,CAAI,SAAA,EAAWC,UAAAA,CAAW,CAAC,CAAA,MAAO;AAAA,IAChD,QAAQ,CAAA,CAAE,MAAA;AAAA,IACV,OAAO,CAAA,CAAE,KAAA;AAAA,IACT,WAAW,CAAA,CAAE,SAAA;AAAA,IACb,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,WAAW,CAAA,CAAE,SAAA;AAAA,IACb,OAAO,CAAA,CAAE,KAAA;AAAA,IACT,cAAc,CAAA,CAAE,YAAA;AAAA,IAChB,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,aAAa,CAAA,CAAE,WAAA;AAAA,IACf,eAAe,CAAA,CAAE,aAAA;AAAA,IACjB,SAAS,CAAA,CAAE,OAAA;AAAA,IACX,YAAY,CAAA,CAAE,UAAA;AAAA,IACd,gBAAgB,CAAA,CAAE,cAAA;AAAA,IAClB,YAAY,CAAA,CAAE,UAAA;AAAA,IACd,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,WAAW,CAAA,CAAE,SAAA;AAAA,IACb,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,WAAW,CAAA,CAAE,SAAA;AAAA,IACb,UAAU,CAAA,CAAE;AAAA,IACZ,CAAC,CAAA;AACL;AAGO,SAAS,gBAAA,GAA2B;AACzC,EAAA,MAAM,GAAA,GAAMH,WAAW,YAAY,CAAA;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,sDAAsD,CAAA;AAChF,EAAA,OAAOE,SAAS,GAAA,CAAI,SAAA,EAAW,CAAC,CAAA,KAAM,EAAE,SAAS,CAAA;AACnD;AAGO,SAAS,YAAA,GAAuB;AACrC,EAAA,MAAM,GAAA,GAAMF,WAAW,YAAY,CAAA;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAC5E,EAAA,OAAOE,SAAS,GAAA,CAAI,SAAA,EAAW,CAAC,CAAA,KAAM,EAAE,KAAK,CAAA;AAC/C;;;AC7CO,SAAS,eAAA,GAAkB;AAChC,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,OAAA,EAAQ;AACrC,EAAA,MAAM,WAAA,GAAcD,OAAO,KAAK,CAAA;AAEhC,EAAAG,UAAU,MAAM;AACd,IAAA,IAAI,YAAY,OAAA,EAAS;AACzB,IAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,QAAA,EAAS,CAAE,MAAM,MAAM;AAAA,MAEvB,CAAC,CAAA;AAAA,IACH;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,IAAA;AACT;ACfO,SAAS,eAAA,GAAkB;AAChC,EAAA,MAAM,EAAE,cAAA,EAAe,GAAI,OAAA,EAAQ;AACnC,EAAA,MAAM,QAAA,GAAWH,OAAO,KAAK,CAAA;AAE7B,EAAAG,UAAU,MAAM;AACd,IAAA,IAAI,SAAS,OAAA,EAAS;AACtB,IAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AACnB,IAAA,cAAA,EAAe;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,IAAA;AACT;ACDO,SAAS,aAAA,CAAc;AAAA,EAC5B,QAAA;AAAA,EACA,WAAW,EAAC;AAAA,EACZ,OAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,kBAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAAuB;AACrB,EAAA,MAAM,WAAW,WAAA,EAAY;AAE7B,EAAA,MAAM,GAAA,GAAM,QAA2B,MAAM;AAC3C,IAAA,MAAM,cAAA,GAAiB;AAAA,MACrB,OAAA;AAAA,MACA,MAAA;AAAA,MACA,YAAY,UAAA,IAAc,+BAAA;AAAA,MAC1B,WAAW,SAAA,IAAa,SAAA;AAAA,MACxB,oBAAoB,kBAAA,IAAsB,EAAA;AAAA,MAC1C,cAAc,YAAA,IAAgB,EAAA;AAAA,MAC9B,eAAe,aAAA,IAAiB,OAAA;AAAA,MAChC,UAAA,EAAY,UAAA,IAAc,EAAA,GAAK,EAAA,GAAK,GAAA;AAAA,MACpC,OAAO,KAAA,IAAS;AAAA,KAClB;AAEA,IAAA,MAAM,MAAA,GAAS,IAAI,WAAA,CAAY;AAAA,MAC7B,OAAA;AAAA,MACA,MAAA;AAAA,MACA,YAAY,cAAA,CAAe,UAAA;AAAA,MAC3B,WAAW,cAAA,CAAe;AAAA,KAC3B,CAAA;AAMD,IAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,MAAA,EAAQ,cAAA,CAAe,aAAa,CAAA;AACtE,IAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,MAAA,EAAQ,cAAA,CAAe,aAAa,CAAA;AAEtE,IAAA,OAAO;AAAA,MACL,MAAA;AAAA,MACA,MAAA,EAAQ,cAAA;AAAA,MACR,SAAA;AAAA,MACA,SAAA;AAAA,MACA;AAAA,KACF;AAAA,EAGF,CAAA,EAAG,CAAC,OAAA,EAAS,MAAM,CAAC,CAAA;AAGpB,EAAA,MAAM,KAAA,GAAQ,OAAA;AAAA,IACZ,OAAO,EAAE,GAAG,GAAA,EAAK,QAAA,EAAS,CAAA;AAAA,IAC1B,CAAC,KAAK,QAAQ;AAAA,GAChB;AAEA,EAAA,uBACE,IAAA,CAAC,YAAA,CAAa,QAAA,EAAb,EAAsB,KAAA,EACrB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,eAAA,EAAA,EAAgB,CAAA;AAAA,wBAChB,eAAA,EAAA,EAAgB,CAAA;AAAA,oBACjB,GAAA,CAAC,oBAAiB,QAAA,EAAoB,CAAA;AAAA,IACrC;AAAA,GAAA,EACH,CAAA;AAEJ;AC5EO,SAAS,YAAY,IAAA,EAGzB;AACD,EAAA,MAAM,GAAA,GAAMJ,WAAW,YAAY,CAAA;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAE3E,EAAA,MAAM,cAAc,GAAA,CAAI,QAAA;AAExB,EAAA,MAAM,QAAA,GAAWK,QAAQ,MAAM;AAC7B,IAAA,IAAI,MAAA,GAAS,WAAA;AACb,IAAA,IAAI,MAAM,UAAA,EAAY;AACpB,MAAA,MAAA,GAAS,OAAO,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,mBAAA,KAAwB,KAAK,UAAU,CAAA;AAAA,IACzE;AACA,IAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,WAAA,EAAY;AAClC,MAAA,MAAA,GAAS,MAAA,CAAO,MAAA;AAAA,QACd,CAAC,MACC,CAAA,CAAE,IAAA,CAAK,aAAY,CAAE,QAAA,CAAS,CAAC,CAAA,IAC/B,CAAA,CAAE,aAAa,WAAA,EAAY,CAAE,SAAS,CAAC,CAAA,IACvC,EAAE,IAAA,CAAK,WAAA,EAAY,CAAE,QAAA,CAAS,CAAC;AAAA,OACnC;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT,GAAG,CAAC,WAAA,EAAa,MAAM,UAAA,EAAY,IAAA,EAAM,MAAM,CAAC,CAAA;AAEhD,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA,EAAS;AAAA,GACX;AACF;AAKO,SAAS,WAAW,IAAA,EAAiC;AAC1D,EAAA,MAAM,GAAA,GAAML,WAAW,YAAY,CAAA;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAE1E,EAAA,MAAM,OAAA,GAAUK,QAAQ,MAAM;AAC5B,IAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,IAAA,OAAO,GAAA,CAAI,SAAS,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,IAAI,CAAA,IAAK,IAAA;AAAA,EACtD,CAAA,EAAG,CAAC,GAAA,CAAI,QAAA,EAAU,IAAI,CAAC,CAAA;AAEvB,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,OAAA,EAAS;AAAA,GACX;AACF;ACrDO,SAAS,cAAA,GAA8B;AAC5C,EAAA,MAAM,GAAA,GAAML,WAAW,YAAY,CAAA;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,oDAAoD,CAAA;AAC9E,EAAA,OAAO,GAAA,CAAI,MAAA;AACb;ACHO,SAAS,iBAAA,GAAoB;AAClC,EAAA,MAAM,GAAA,GAAMA,WAAW,YAAY,CAAA;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAEjF,EAAA,MAAM,WAAWE,QAAAA,CAAS,GAAA,CAAI,WAAW,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAC1D,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAII,QAAAA,CAAkB,EAAE,CAAA;AAChD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,SAAS,KAAK,CAAA;AAE5C,EAAA,MAAM,OAAA,GAAUC,YAAY,YAAY;AACtC,IAAA,IAAI,CAAC,UAAU,EAAA,EAAI;AACjB,MAAA,SAAA,CAAU,EAAE,CAAA;AACZ,MAAA;AAAA,IACF;AACA,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,IAAI;AACF,MAAA,MAAM,OAAO,MAAM,GAAA,CAAI,MAAA,CAAO,iBAAA,CAAkB,SAAS,EAAE,CAAA;AAC3D,MAAA,SAAA,CAAU,IAAI,CAAA;AAAA,IAChB,CAAA,CAAA,MAAQ;AACN,MAAA,SAAA,CAAU,EAAE,CAAA;AAAA,IACd,CAAA,SAAE;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,QAAA,EAAU,EAAA,EAAI,GAAA,CAAI,MAAM,CAAC,CAAA;AAE7B,EAAAH,UAAU,MAAM;AACd,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,OAAA,EAAQ;AACpC;AAEO,SAAS,oBAAA,GAAuB;AACrC,EAAA,MAAM,GAAA,GAAMJ,WAAW,YAAY,CAAA;AACnC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,0DAA0D,CAAA;AAEpF,EAAA,MAAM,WAAWE,QAAAA,CAAS,GAAA,CAAI,WAAW,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAC1D,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAII,SAAmC,IAAI,CAAA;AACzE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,SAAS,KAAK,CAAA;AAE5C,EAAAF,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,UAAU,EAAA,EAAI;AACjB,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA;AAAA,IACF;AACA,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,MAAM,IAAA,GAAO,GAAG,QAAA,CAAS,UAAU,IAAI,QAAA,CAAS,SAAS,GAAG,IAAA,EAAK;AACjE,IAAA,GAAA,CAAI,MAAA,CACD,qBAAqB,QAAA,CAAS,EAAA,EAAI,QAAQ,MAAS,CAAA,CACnD,KAAK,YAAY,CAAA,CACjB,MAAM,MAAM,YAAA,CAAa,IAAI,CAAC,CAAA,CAC9B,QAAQ,MAAM,UAAA,CAAW,KAAK,CAAC,CAAA;AAAA,EACpC,CAAA,EAAG,CAAC,QAAA,EAAU,EAAA,EAAI,QAAA,EAAU,YAAY,QAAA,EAAU,SAAA,EAAW,GAAA,CAAI,MAAM,CAAC,CAAA;AAExE,EAAA,OAAO,EAAE,WAAW,OAAA,EAAQ;AAC9B","file":"index.js","sourcesContent":["import { createContext } from 'react'\nimport type { WhaleClient } from '../client.js'\nimport type { Product } from '../types.js'\nimport type { CartStore } from './stores/cart-store.js'\nimport type { AuthStore } from './stores/auth-store.js'\n\nexport interface WhaleContextValue {\n client: WhaleClient\n config: {\n storeId: string\n apiKey: string\n gatewayUrl: string\n proxyPath: string\n mediaSigningSecret: string\n supabaseHost: string\n storagePrefix: string\n sessionTtl: number\n debug: boolean\n }\n cartStore: CartStore\n authStore: AuthStore\n /** Products fetched server-side and passed via provider */\n products: Product[]\n}\n\nexport const WhaleContext = createContext<WhaleContextValue | null>(null)\n","import { createStore } from 'zustand/vanilla'\nimport { persist } from 'zustand/middleware'\nimport type { WhaleClient } from '../../client.js'\nimport type { Cart, CartItem, TaxBreakdown, PaymentData, Order } from '../../types.js'\n\nexport interface CartState {\n cartId: string | null\n items: CartItem[]\n itemCount: number\n subtotal: number\n taxAmount: number\n total: number\n taxBreakdown: TaxBreakdown[]\n cartOpen: boolean\n cartLoading: boolean\n productImages: Record<string, string>\n addItemInFlight: boolean\n}\n\nexport interface CartActions {\n openCart: () => void\n closeCart: () => void\n toggleCart: () => void\n initCart: () => Promise<void>\n syncCart: () => Promise<void>\n addItem: (\n productId: string,\n quantity: number,\n tier?: string,\n unitPrice?: number,\n imageUrl?: string | null,\n productName?: string\n ) => Promise<void>\n updateQuantity: (itemId: string, quantity: number) => Promise<void>\n removeItem: (itemId: string, productName?: string) => Promise<void>\n clearCart: () => void\n checkout: (customerEmail?: string, payment?: PaymentData) => Promise<Order>\n}\n\nexport type CartStore = ReturnType<typeof createCartStore>\n\nexport function createCartStore(\n client: WhaleClient,\n storagePrefix: string,\n onAddToCart?: (productId: string, productName: string, quantity: number, price: number, tier?: string) => void,\n onRemoveFromCart?: (productId: string, productName: string) => void\n) {\n return createStore<CartState & CartActions>()(\n persist(\n (set, get) => ({\n // ── Initial state ────────────────────────────────────────────────\n cartId: null,\n items: [],\n itemCount: 0,\n subtotal: 0,\n taxAmount: 0,\n total: 0,\n taxBreakdown: [],\n cartOpen: false,\n cartLoading: false,\n productImages: {},\n addItemInFlight: false,\n\n // ── Cart UI ──────────────────────────────────────────────────────\n openCart: () => set({ cartOpen: true }),\n closeCart: () => set({ cartOpen: false }),\n toggleCart: () => set((s) => ({ cartOpen: !s.cartOpen })),\n\n // ── Cart data ────────────────────────────────────────────────────\n initCart: async () => {\n const { cartId, syncCart } = get()\n\n if (cartId) {\n try {\n await syncCart()\n } catch {\n const cart = await client.createCart()\n applyCart(set, get, cart)\n }\n return\n }\n\n try {\n const cart = await client.createCart()\n applyCart(set, get, cart)\n } catch (err) {\n console.error('[whale-storefront] initCart failed:', err)\n }\n },\n\n syncCart: async () => {\n const { cartId, productImages } = get()\n if (!cartId) return\n\n try {\n const cart = await client.getCart(cartId)\n const items = (cart.items ?? []).map((item) => ({\n ...item,\n image_url: item.image_url || productImages[item.product_id] || null,\n }))\n set({\n items,\n itemCount: cart.item_count ?? 0,\n subtotal: cart.subtotal ?? 0,\n taxAmount: cart.tax_amount ?? 0,\n total: cart.total ?? 0,\n taxBreakdown: cart.tax_breakdown ?? [],\n })\n } catch (err) {\n console.error('[whale-storefront] syncCart failed:', err)\n throw err\n }\n },\n\n addItem: async (productId, quantity, tier, unitPrice, imageUrl, productName) => {\n // Race-condition guard: prevent double-click\n if (get().addItemInFlight) return\n set({ cartLoading: true, addItemInFlight: true })\n\n try {\n let { cartId } = get()\n\n if (!cartId) {\n await get().initCart()\n cartId = get().cartId\n }\n\n if (!cartId) throw new Error('Could not initialise cart')\n\n if (imageUrl) {\n set((s) => ({ productImages: { ...s.productImages, [productId]: imageUrl } }))\n }\n\n try {\n await client.addToCart(cartId, productId, quantity, { tier, unitPrice })\n } catch (err: unknown) {\n // Cart expired (404/410) — auto-recover\n const status = (err as { status?: number }).status\n if (status === 404 || status === 410) {\n const newCart = await client.createCart()\n set({ cartId: newCart.id })\n await client.addToCart(newCart.id, productId, quantity, { tier, unitPrice })\n } else {\n throw err\n }\n }\n\n await get().syncCart()\n\n // Analytics callback\n onAddToCart?.(productId, productName || '', quantity, unitPrice || 0, tier)\n } finally {\n set({ cartLoading: false, addItemInFlight: false })\n }\n },\n\n updateQuantity: async (itemId, quantity) => {\n set({ cartLoading: true })\n try {\n const { cartId } = get()\n if (!cartId) return\n await client.updateCartItem(cartId, itemId, quantity)\n await get().syncCart()\n } finally {\n set({ cartLoading: false })\n }\n },\n\n removeItem: async (itemId, productName) => {\n set({ cartLoading: true })\n try {\n const { cartId, items } = get()\n if (!cartId) return\n\n const item = items.find((i) => i.id === itemId)\n await client.removeCartItem(cartId, itemId)\n await get().syncCart()\n\n if (item) {\n onRemoveFromCart?.(item.product_id, productName || item.product_name)\n }\n } finally {\n set({ cartLoading: false })\n }\n },\n\n clearCart: () => {\n set({\n cartId: null,\n items: [],\n itemCount: 0,\n subtotal: 0,\n taxAmount: 0,\n total: 0,\n taxBreakdown: [],\n productImages: {},\n })\n },\n\n checkout: async (customerEmail, payment) => {\n const { cartId } = get()\n if (!cartId) throw new Error('No active cart')\n\n set({ cartLoading: true })\n try {\n const order = await client.checkout(cartId, customerEmail, payment)\n set({\n cartId: null,\n items: [],\n itemCount: 0,\n subtotal: 0,\n taxAmount: 0,\n total: 0,\n taxBreakdown: [],\n productImages: {},\n cartOpen: false,\n })\n return order\n } finally {\n set({ cartLoading: false })\n }\n },\n }),\n\n // ── Persist config ─────────────────────────────────────────────────\n {\n name: `${storagePrefix}-cart`,\n partialize: (state) => ({\n cartId: state.cartId,\n productImages: state.productImages,\n }),\n }\n )\n )\n}\n\nfunction applyCart(\n set: (partial: Partial<CartState>) => void,\n get: () => CartState,\n cart: Cart\n) {\n const productImages = get().productImages\n const items = (cart.items ?? []).map((item) => ({\n ...item,\n image_url: item.image_url || productImages[item.product_id] || null,\n }))\n set({\n cartId: cart.id,\n items,\n itemCount: cart.item_count ?? 0,\n subtotal: cart.subtotal ?? 0,\n taxAmount: cart.tax_amount ?? 0,\n total: cart.total ?? 0,\n taxBreakdown: cart.tax_breakdown ?? [],\n })\n}\n","import { createStore } from 'zustand/vanilla'\nimport { persist } from 'zustand/middleware'\nimport type { WhaleClient } from '../../client.js'\nimport type { Customer } from '../../types.js'\n\nexport interface AuthState {\n customer: Customer | null\n sessionToken: string | null\n sessionExpiresAt: string | null\n authLoading: boolean\n}\n\nexport interface AuthActions {\n sendOTP: (email: string) => Promise<boolean>\n verifyOTP: (email: string, code: string) => Promise<boolean>\n restoreSession: () => Promise<void>\n isSessionValid: () => boolean\n logout: () => void\n fetchCustomer: (id: string) => Promise<void>\n}\n\nexport type AuthStore = ReturnType<typeof createAuthStore>\n\nexport function createAuthStore(client: WhaleClient, storagePrefix: string) {\n return createStore<AuthState & AuthActions>()(\n persist(\n (set, get) => ({\n // ── Initial state ────────────────────────────────────────────────\n customer: null,\n sessionToken: null,\n sessionExpiresAt: null,\n authLoading: false,\n\n // ── Actions ──────────────────────────────────────────────────────\n sendOTP: async (email) => {\n set({ authLoading: true })\n try {\n const res = await client.sendCode(email)\n return res.sent\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Could not send code'\n throw new Error(message)\n } finally {\n set({ authLoading: false })\n }\n },\n\n verifyOTP: async (email, code) => {\n set({ authLoading: true })\n try {\n const res = await client.verifyCode(email, code)\n client.setSessionToken(res.token_hash)\n set({\n sessionToken: res.token_hash,\n sessionExpiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),\n })\n\n if (res.customer?.id) {\n try {\n const full = await client.getCustomer(res.customer.id)\n set({ customer: full })\n } catch {\n set({ customer: res.customer })\n }\n }\n\n return res.needs_profile ?? false\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Verification failed'\n throw new Error(message)\n } finally {\n set({ authLoading: false })\n }\n },\n\n restoreSession: async () => {\n const { sessionToken, sessionExpiresAt, customer } = get()\n if (!sessionToken || !sessionExpiresAt) return\n\n if (new Date(sessionExpiresAt) <= new Date()) {\n client.setSessionToken(null)\n set({ sessionToken: null, sessionExpiresAt: null, customer: null })\n return\n }\n\n client.setSessionToken(sessionToken)\n\n if (customer?.id) {\n try {\n const fresh = await client.getCustomer(customer.id)\n set({ customer: fresh })\n } catch {\n client.setSessionToken(null)\n set({ sessionToken: null, sessionExpiresAt: null, customer: null })\n }\n }\n },\n\n isSessionValid: () => {\n const { sessionToken, sessionExpiresAt } = get()\n if (!sessionToken || !sessionExpiresAt) return false\n return new Date(sessionExpiresAt) > new Date()\n },\n\n logout: () => {\n client.setSessionToken(null)\n set({ customer: null, sessionToken: null, sessionExpiresAt: null })\n },\n\n fetchCustomer: async (id) => {\n try {\n const customer = await client.getCustomer(id)\n set({ customer })\n } catch (err) {\n console.error('[whale-storefront] fetchCustomer failed:', err)\n }\n },\n }),\n\n // ── Persist config ─────────────────────────────────────────────────\n {\n name: `${storagePrefix}-auth`,\n partialize: (state) => ({\n sessionToken: state.sessionToken,\n sessionExpiresAt: state.sessionExpiresAt,\n customer: state.customer\n ? {\n id: state.customer.id,\n email: state.customer.email,\n first_name: state.customer.first_name,\n last_name: state.customer.last_name,\n phone: state.customer.phone,\n loyalty_points: state.customer.loyalty_points,\n loyalty_tier: state.customer.loyalty_tier,\n total_spent: state.customer.total_spent,\n total_orders: state.customer.total_orders,\n }\n : null,\n }),\n }\n )\n )\n}\n","'use client'\n\nimport { useContext, useRef, useCallback } from 'react'\nimport { WhaleContext } from '../context.js'\nimport type { EventType } from '../../types.js'\n\nconst SESSION_KEY_SUFFIX = '-analytics-session'\n\ninterface SessionData {\n id: string\n createdAt: number\n}\n\nexport function useAnalytics() {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useAnalytics must be used within <WhaleProvider>')\n\n const { client, config } = ctx\n const sessionPromiseRef = useRef<Promise<string> | null>(null)\n const sessionKey = `${config.storagePrefix}${SESSION_KEY_SUFFIX}`\n\n const getOrCreateSession = useCallback(async (): Promise<string> => {\n if (sessionPromiseRef.current) return sessionPromiseRef.current\n\n sessionPromiseRef.current = (async () => {\n // Check stored session\n try {\n const raw = localStorage.getItem(sessionKey)\n if (raw) {\n const stored: SessionData = JSON.parse(raw)\n if (Date.now() - stored.createdAt < config.sessionTtl) {\n // Refresh last_active silently\n client.updateSession(stored.id, { last_active_at: new Date().toISOString() }).catch(() => {})\n return stored.id\n }\n }\n } catch {\n // ignore\n }\n\n // Create new\n try {\n const session = await client.createSession({\n user_agent: navigator.userAgent,\n referrer: document.referrer || undefined,\n })\n if (session?.id) {\n localStorage.setItem(sessionKey, JSON.stringify({ id: session.id, createdAt: Date.now() }))\n return session.id\n }\n } catch {\n // ignore\n }\n\n // Fallback local ID\n const fallbackId = `local-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n localStorage.setItem(sessionKey, JSON.stringify({ id: fallbackId, createdAt: Date.now() }))\n return fallbackId\n })()\n\n sessionPromiseRef.current.finally(() => {\n sessionPromiseRef.current = null\n })\n\n return sessionPromiseRef.current\n }, [client, config.sessionTtl, sessionKey])\n\n const track = useCallback(\n async (eventType: EventType, data: Record<string, unknown> = {}) => {\n try {\n const sessionId = await getOrCreateSession()\n await client.trackEvent({ session_id: sessionId, event_type: eventType, event_data: data })\n } catch {\n // fire-and-forget\n }\n },\n [client, getOrCreateSession]\n )\n\n const linkCustomer = useCallback(\n async (customerId: string) => {\n try {\n const sessionId = await getOrCreateSession()\n if (sessionId.startsWith('local-')) return\n await client.updateSession(sessionId, { customer_id: customerId })\n } catch {\n // ignore\n }\n },\n [client, getOrCreateSession]\n )\n\n const trackPageView = useCallback(\n (url: string, referrer?: string) => {\n track('page_view', { url, referrer })\n },\n [track]\n )\n\n const trackProductView = useCallback(\n (productId: string, productName: string, category: string, price?: number) => {\n track('product_view', { product_id: productId, product_name: productName, category, price })\n },\n [track]\n )\n\n const trackCategoryView = useCallback(\n (categoryId: string, categoryName: string) => {\n track('category_view', { category_id: categoryId, category_name: categoryName })\n },\n [track]\n )\n\n const trackSearch = useCallback(\n (query: string, resultCount?: number) => {\n track('search', { query, result_count: resultCount })\n },\n [track]\n )\n\n const trackBeginCheckout = useCallback(\n (cartId: string, total: number, itemCount: number) => {\n track('begin_checkout', { cart_id: cartId, total, item_count: itemCount })\n },\n [track]\n )\n\n const trackPurchase = useCallback(\n (orderId: string, orderNumber: string, total: number) => {\n track('purchase', { order_id: orderId, order_number: orderNumber, total })\n },\n [track]\n )\n\n const trackAddToCart = useCallback(\n (productId: string, productName: string, quantity: number, price: number, tier?: string) => {\n track('add_to_cart', { product_id: productId, product_name: productName, quantity, price, tier })\n },\n [track]\n )\n\n const trackRemoveFromCart = useCallback(\n (productId: string, productName: string) => {\n track('remove_from_cart', { product_id: productId, product_name: productName })\n },\n [track]\n )\n\n return {\n track,\n trackPageView,\n trackProductView,\n trackCategoryView,\n trackSearch,\n trackBeginCheckout,\n trackPurchase,\n trackAddToCart,\n trackRemoveFromCart,\n linkCustomer,\n getOrCreateSession,\n }\n}\n","'use client'\n\nimport { useContext } from 'react'\nimport { useStore } from 'zustand'\nimport { useShallow } from 'zustand/react/shallow'\nimport { WhaleContext } from '../context.js'\n\nexport function useAuth() {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useAuth must be used within <WhaleProvider>')\n\n return useStore(ctx.authStore, useShallow((s) => ({\n customer: s.customer,\n authLoading: s.authLoading,\n sessionToken: s.sessionToken,\n isAuthenticated: s.isSessionValid(),\n sendCode: s.sendOTP,\n verifyCode: s.verifyOTP,\n restoreSession: s.restoreSession,\n logout: s.logout,\n fetchCustomer: s.fetchCustomer,\n })))\n}\n","'use client'\n\nimport { useEffect, useRef } from 'react'\nimport { useAnalytics } from '../hooks/use-analytics.js'\nimport { useAuth } from '../hooks/use-auth.js'\n\n/**\n * Auto-tracks page views on pathname change and links customer sessions.\n * Rendered internally by WhaleProvider — storefronts don't need to add this manually.\n */\nexport function AnalyticsTracker({ pathname }: { pathname: string }) {\n const { trackPageView, linkCustomer } = useAnalytics()\n const { customer } = useAuth()\n const prevPathname = useRef<string | null>(null)\n const linkedCustomerId = useRef<string | null>(null)\n\n // Track page views on route change\n useEffect(() => {\n if (pathname === prevPathname.current) return\n const referrer = prevPathname.current || (typeof document !== 'undefined' ? document.referrer : '')\n prevPathname.current = pathname\n trackPageView(pathname, referrer || undefined)\n }, [pathname, trackPageView])\n\n // Link customer session on login\n useEffect(() => {\n if (customer?.id && customer.id !== linkedCustomerId.current) {\n linkedCustomerId.current = customer.id\n linkCustomer(customer.id)\n }\n }, [customer?.id, linkCustomer])\n\n return null\n}\n","'use client'\n\nimport { useContext } from 'react'\nimport { useStore } from 'zustand'\nimport { useShallow } from 'zustand/react/shallow'\nimport { WhaleContext } from '../context.js'\nimport type { CartState, CartActions } from '../stores/cart-store.js'\n\ntype CartReturn = Pick<\n CartState & CartActions,\n 'cartId' | 'cartOpen' | 'cartLoading' | 'items' | 'itemCount' | 'subtotal' | 'taxAmount' | 'total' | 'taxBreakdown' | 'productImages' |\n 'addItem' | 'removeItem' | 'updateQuantity' | 'toggleCart' | 'openCart' | 'closeCart' | 'checkout' | 'initCart' | 'syncCart' | 'clearCart'\n>\n\nexport function useCart() {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useCart must be used within <WhaleProvider>')\n\n return useStore(ctx.cartStore, useShallow((s) => ({\n cartId: s.cartId,\n items: s.items,\n itemCount: s.itemCount,\n subtotal: s.subtotal,\n taxAmount: s.taxAmount,\n total: s.total,\n taxBreakdown: s.taxBreakdown,\n cartOpen: s.cartOpen,\n cartLoading: s.cartLoading,\n productImages: s.productImages,\n addItem: s.addItem,\n removeItem: s.removeItem,\n updateQuantity: s.updateQuantity,\n toggleCart: s.toggleCart,\n openCart: s.openCart,\n closeCart: s.closeCart,\n initCart: s.initCart,\n syncCart: s.syncCart,\n clearCart: s.clearCart,\n checkout: s.checkout,\n })))\n}\n\n/** Granular selector — only re-renders on count change */\nexport function useCartItemCount(): number {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useCartItemCount must be used within <WhaleProvider>')\n return useStore(ctx.cartStore, (s) => s.itemCount)\n}\n\n/** Granular selector — only re-renders on total change */\nexport function useCartTotal(): number {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useCartTotal must be used within <WhaleProvider>')\n return useStore(ctx.cartStore, (s) => s.total)\n}\n","'use client'\n\nimport { useEffect, useRef } from 'react'\nimport { useCart } from '../hooks/use-cart.js'\n\n/**\n * Hydrates cart from gateway on mount if a cartId is persisted.\n * Rendered internally by WhaleProvider.\n */\nexport function CartInitializer() {\n const { cartId, syncCart } = useCart()\n const initialized = useRef(false)\n\n useEffect(() => {\n if (initialized.current) return\n initialized.current = true\n if (cartId) {\n syncCart().catch(() => {\n // Cart may have expired — that's fine, addItem will auto-recover\n })\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n return null\n}\n","'use client'\n\nimport { useEffect, useRef } from 'react'\nimport { useAuth } from '../hooks/use-auth.js'\n\n/**\n * Restores auth session on mount — syncs persisted token to client.\n * Rendered internally by WhaleProvider.\n */\nexport function AuthInitializer() {\n const { restoreSession } = useAuth()\n const restored = useRef(false)\n\n useEffect(() => {\n if (restored.current) return\n restored.current = true\n restoreSession()\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n return null\n}\n","'use client'\n\nimport { useMemo, type ReactNode } from 'react'\nimport { usePathname } from 'next/navigation'\nimport { WhaleClient } from '../client.js'\nimport type { WhaleStorefrontConfig, Product } from '../types.js'\nimport { WhaleContext, type WhaleContextValue } from './context.js'\nimport { createCartStore } from './stores/cart-store.js'\nimport { createAuthStore } from './stores/auth-store.js'\nimport { AnalyticsTracker } from './components/analytics-tracker.js'\nimport { CartInitializer } from './components/cart-initializer.js'\nimport { AuthInitializer } from './components/auth-initializer.js'\n\nexport interface WhaleProviderProps extends WhaleStorefrontConfig {\n children: ReactNode\n /** Server-fetched products passed to client for hooks */\n products?: Product[]\n}\n\nexport function WhaleProvider({\n children,\n products = [],\n storeId,\n apiKey,\n gatewayUrl,\n proxyPath,\n mediaSigningSecret,\n supabaseHost,\n storagePrefix,\n sessionTtl,\n debug,\n}: WhaleProviderProps) {\n const pathname = usePathname()\n\n const ctx = useMemo<WhaleContextValue>(() => {\n const resolvedConfig = {\n storeId,\n apiKey,\n gatewayUrl: gatewayUrl || 'https://whale-gateway.fly.dev',\n proxyPath: proxyPath || '/api/gw',\n mediaSigningSecret: mediaSigningSecret || '',\n supabaseHost: supabaseHost || '',\n storagePrefix: storagePrefix || 'whale',\n sessionTtl: sessionTtl || 30 * 60 * 1000,\n debug: debug || false,\n }\n\n const client = new WhaleClient({\n storeId,\n apiKey,\n gatewayUrl: resolvedConfig.gatewayUrl,\n proxyPath: resolvedConfig.proxyPath,\n })\n\n // Analytics callbacks wired into cart store\n // These get called by the cart store on add/remove and fire analytics events.\n // We can't use the useAnalytics hook here (not in a component), so we use\n // the client directly — the AnalyticsTracker manages sessions.\n const cartStore = createCartStore(client, resolvedConfig.storagePrefix)\n const authStore = createAuthStore(client, resolvedConfig.storagePrefix)\n\n return {\n client,\n config: resolvedConfig,\n cartStore,\n authStore,\n products,\n }\n // Only recreate when identity changes — storeId + apiKey\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [storeId, apiKey])\n\n // Update products on the context when they change (e.g. re-fetched)\n const value = useMemo<WhaleContextValue>(\n () => ({ ...ctx, products }),\n [ctx, products]\n )\n\n return (\n <WhaleContext.Provider value={value}>\n <AuthInitializer />\n <CartInitializer />\n <AnalyticsTracker pathname={pathname} />\n {children}\n </WhaleContext.Provider>\n )\n}\n","'use client'\n\nimport { useContext, useState, useEffect, useMemo } from 'react'\nimport { WhaleContext } from '../context.js'\nimport type { Product } from '../../types.js'\n\n/**\n * Returns products passed via WhaleProvider.\n * Optionally filters by category or search.\n */\nexport function useProducts(opts?: {\n categoryId?: string\n search?: string\n}) {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useProducts must be used within <WhaleProvider>')\n\n const allProducts = ctx.products\n\n const products = useMemo(() => {\n let result = allProducts\n if (opts?.categoryId) {\n result = result.filter((p) => p.primary_category_id === opts.categoryId)\n }\n if (opts?.search) {\n const q = opts.search.toLowerCase()\n result = result.filter(\n (p) =>\n p.name.toLowerCase().includes(q) ||\n p.description?.toLowerCase().includes(q) ||\n p.slug.toLowerCase().includes(q)\n )\n }\n return result\n }, [allProducts, opts?.categoryId, opts?.search])\n\n return {\n products,\n allProducts,\n loading: false,\n }\n}\n\n/**\n * Returns a single product by slug from the provider's product list.\n */\nexport function useProduct(slug: string | null | undefined) {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useProduct must be used within <WhaleProvider>')\n\n const product = useMemo(() => {\n if (!slug) return null\n return ctx.products.find((p) => p.slug === slug) ?? null\n }, [ctx.products, slug])\n\n return {\n product,\n loading: false,\n }\n}\n","'use client'\n\nimport { useContext } from 'react'\nimport { WhaleContext } from '../context.js'\nimport type { WhaleClient } from '../../client.js'\n\nexport function useWhaleClient(): WhaleClient {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useWhaleClient must be used within <WhaleProvider>')\n return ctx.client\n}\n","'use client'\n\nimport { useContext, useState, useEffect, useCallback } from 'react'\nimport { useStore } from 'zustand'\nimport { WhaleContext } from '../context.js'\nimport type { Order, CustomerAnalytics } from '../../types.js'\n\nexport function useCustomerOrders() {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useCustomerOrders must be used within <WhaleProvider>')\n\n const customer = useStore(ctx.authStore, (s) => s.customer)\n const [orders, setOrders] = useState<Order[]>([])\n const [loading, setLoading] = useState(false)\n\n const refresh = useCallback(async () => {\n if (!customer?.id) {\n setOrders([])\n return\n }\n setLoading(true)\n try {\n const data = await ctx.client.getCustomerOrders(customer.id)\n setOrders(data)\n } catch {\n setOrders([])\n } finally {\n setLoading(false)\n }\n }, [customer?.id, ctx.client])\n\n useEffect(() => {\n refresh()\n }, [refresh])\n\n return { orders, loading, refresh }\n}\n\nexport function useCustomerAnalytics() {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useCustomerAnalytics must be used within <WhaleProvider>')\n\n const customer = useStore(ctx.authStore, (s) => s.customer)\n const [analytics, setAnalytics] = useState<CustomerAnalytics | null>(null)\n const [loading, setLoading] = useState(false)\n\n useEffect(() => {\n if (!customer?.id) {\n setAnalytics(null)\n return\n }\n setLoading(true)\n const name = `${customer.first_name} ${customer.last_name}`.trim()\n ctx.client\n .getCustomerAnalytics(customer.id, name || undefined)\n .then(setAnalytics)\n .catch(() => setAnalytics(null))\n .finally(() => setLoading(false))\n }, [customer?.id, customer?.first_name, customer?.last_name, ctx.client])\n\n return { analytics, loading }\n}\n"]}
1
+ {"version":3,"sources":["../../src/react/context.ts","../../src/react/stores/cart-store.ts","../../src/react/stores/auth-store.ts","../../src/react/hooks/use-analytics.ts","../../src/react/hooks/use-auth.ts","../../src/react/components/analytics-tracker.tsx","../../src/react/hooks/use-cart.ts","../../src/react/components/cart-initializer.tsx","../../src/react/components/auth-initializer.tsx","../../src/react/components/pixel-initializer.tsx","../../src/react/provider.tsx","../../src/react/hooks/use-products.ts","../../src/react/hooks/use-client.ts","../../src/react/hooks/use-customer.ts"],"names":["createStore","persist","useContext","useRef","useStore","useShallow","useEffect","useCallback","useMemo","useState"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext } from 'react'\nimport type { WhaleClient } from '../client.js'\nimport type { Product } from '../types.js'\nimport type { CartStore } from './stores/cart-store.js'\nimport type { AuthStore } from './stores/auth-store.js'\nimport type { PixelManager } from '../pixels/pixel-manager.js'\n\nexport interface WhaleContextValue {\n client: WhaleClient\n config: {\n storeId: string\n apiKey: string\n gatewayUrl: string\n proxyPath: string\n mediaSigningSecret: string\n supabaseHost: string\n storagePrefix: string\n sessionTtl: number\n debug: boolean\n trackingEnabled: boolean\n recordingRate: number\n }\n cartStore: CartStore\n authStore: AuthStore\n /** Products fetched server-side and passed via provider */\n products: Product[]\n /** Pixel manager — set after storefront config loads */\n pixelManager: PixelManager | null\n}\n\nexport const WhaleContext = createContext<WhaleContextValue | null>(null)\n","import { createStore } from 'zustand/vanilla'\nimport { persist } from 'zustand/middleware'\nimport type { WhaleClient } from '../../client.js'\nimport type { Cart, CartItem, TaxBreakdown, PaymentData, Order } from '../../types.js'\n\nexport interface CartState {\n cartId: string | null\n items: CartItem[]\n itemCount: number\n subtotal: number\n taxAmount: number\n total: number\n taxBreakdown: TaxBreakdown[]\n cartOpen: boolean\n cartLoading: boolean\n productImages: Record<string, string>\n addItemInFlight: boolean\n}\n\nexport interface CartActions {\n openCart: () => void\n closeCart: () => void\n toggleCart: () => void\n initCart: () => Promise<void>\n syncCart: () => Promise<void>\n addItem: (\n productId: string,\n quantity: number,\n tier?: string,\n unitPrice?: number,\n imageUrl?: string | null,\n productName?: string\n ) => Promise<void>\n updateQuantity: (itemId: string, quantity: number) => Promise<void>\n removeItem: (itemId: string, productName?: string) => Promise<void>\n clearCart: () => void\n checkout: (customerEmail?: string, payment?: PaymentData) => Promise<Order>\n}\n\nexport type CartStore = ReturnType<typeof createCartStore>\n\nexport function createCartStore(\n client: WhaleClient,\n storagePrefix: string,\n onAddToCart?: (productId: string, productName: string, quantity: number, price: number, tier?: string) => void,\n onRemoveFromCart?: (productId: string, productName: string) => void\n) {\n return createStore<CartState & CartActions>()(\n persist(\n (set, get) => ({\n // ── Initial state ────────────────────────────────────────────────\n cartId: null,\n items: [],\n itemCount: 0,\n subtotal: 0,\n taxAmount: 0,\n total: 0,\n taxBreakdown: [],\n cartOpen: false,\n cartLoading: false,\n productImages: {},\n addItemInFlight: false,\n\n // ── Cart UI ──────────────────────────────────────────────────────\n openCart: () => set({ cartOpen: true }),\n closeCart: () => set({ cartOpen: false }),\n toggleCart: () => set((s) => ({ cartOpen: !s.cartOpen })),\n\n // ── Cart data ────────────────────────────────────────────────────\n initCart: async () => {\n const { cartId, syncCart } = get()\n\n if (cartId) {\n try {\n await syncCart()\n } catch {\n const cart = await client.createCart()\n applyCart(set, get, cart)\n }\n return\n }\n\n try {\n const cart = await client.createCart()\n applyCart(set, get, cart)\n } catch (err) {\n console.error('[whale-storefront] initCart failed:', err)\n }\n },\n\n syncCart: async () => {\n const { cartId, productImages } = get()\n if (!cartId) return\n\n try {\n const cart = await client.getCart(cartId)\n const items = (cart.items ?? []).map((item) => ({\n ...item,\n image_url: item.image_url || productImages[item.product_id] || null,\n }))\n set({\n items,\n itemCount: cart.item_count ?? 0,\n subtotal: cart.subtotal ?? 0,\n taxAmount: cart.tax_amount ?? 0,\n total: cart.total ?? 0,\n taxBreakdown: cart.tax_breakdown ?? [],\n })\n } catch (err) {\n console.error('[whale-storefront] syncCart failed:', err)\n throw err\n }\n },\n\n addItem: async (productId, quantity, tier, unitPrice, imageUrl, productName) => {\n // Race-condition guard: prevent double-click\n if (get().addItemInFlight) return\n set({ cartLoading: true, addItemInFlight: true })\n\n try {\n let { cartId } = get()\n\n if (!cartId) {\n await get().initCart()\n cartId = get().cartId\n }\n\n if (!cartId) throw new Error('Could not initialise cart')\n\n if (imageUrl) {\n set((s) => ({ productImages: { ...s.productImages, [productId]: imageUrl } }))\n }\n\n try {\n await client.addToCart(cartId, productId, quantity, { tier, unitPrice })\n } catch (err: unknown) {\n // Cart expired (404/410) — auto-recover\n const status = (err as { status?: number }).status\n if (status === 404 || status === 410) {\n const newCart = await client.createCart()\n set({ cartId: newCart.id })\n await client.addToCart(newCart.id, productId, quantity, { tier, unitPrice })\n } else {\n throw err\n }\n }\n\n await get().syncCart()\n\n // Analytics callback\n onAddToCart?.(productId, productName || '', quantity, unitPrice || 0, tier)\n } finally {\n set({ cartLoading: false, addItemInFlight: false })\n }\n },\n\n updateQuantity: async (itemId, quantity) => {\n set({ cartLoading: true })\n try {\n const { cartId } = get()\n if (!cartId) return\n await client.updateCartItem(cartId, itemId, quantity)\n await get().syncCart()\n } finally {\n set({ cartLoading: false })\n }\n },\n\n removeItem: async (itemId, productName) => {\n set({ cartLoading: true })\n try {\n const { cartId, items } = get()\n if (!cartId) return\n\n const item = items.find((i) => i.id === itemId)\n await client.removeCartItem(cartId, itemId)\n await get().syncCart()\n\n if (item) {\n onRemoveFromCart?.(item.product_id, productName || item.product_name)\n }\n } finally {\n set({ cartLoading: false })\n }\n },\n\n clearCart: () => {\n set({\n cartId: null,\n items: [],\n itemCount: 0,\n subtotal: 0,\n taxAmount: 0,\n total: 0,\n taxBreakdown: [],\n productImages: {},\n })\n },\n\n checkout: async (customerEmail, payment) => {\n const { cartId } = get()\n if (!cartId) throw new Error('No active cart')\n\n set({ cartLoading: true })\n try {\n const order = await client.checkout(cartId, customerEmail, payment)\n set({\n cartId: null,\n items: [],\n itemCount: 0,\n subtotal: 0,\n taxAmount: 0,\n total: 0,\n taxBreakdown: [],\n productImages: {},\n cartOpen: false,\n })\n return order\n } finally {\n set({ cartLoading: false })\n }\n },\n }),\n\n // ── Persist config ─────────────────────────────────────────────────\n {\n name: `${storagePrefix}-cart`,\n partialize: (state) => ({\n cartId: state.cartId,\n productImages: state.productImages,\n }),\n }\n )\n )\n}\n\nfunction applyCart(\n set: (partial: Partial<CartState>) => void,\n get: () => CartState,\n cart: Cart\n) {\n const productImages = get().productImages\n const items = (cart.items ?? []).map((item) => ({\n ...item,\n image_url: item.image_url || productImages[item.product_id] || null,\n }))\n set({\n cartId: cart.id,\n items,\n itemCount: cart.item_count ?? 0,\n subtotal: cart.subtotal ?? 0,\n taxAmount: cart.tax_amount ?? 0,\n total: cart.total ?? 0,\n taxBreakdown: cart.tax_breakdown ?? [],\n })\n}\n","import { createStore } from 'zustand/vanilla'\nimport { persist } from 'zustand/middleware'\nimport type { WhaleClient } from '../../client.js'\nimport type { Customer } from '../../types.js'\n\nexport interface AuthState {\n customer: Customer | null\n sessionToken: string | null\n sessionExpiresAt: string | null\n authLoading: boolean\n}\n\nexport interface AuthActions {\n sendOTP: (email: string) => Promise<boolean>\n verifyOTP: (email: string, code: string) => Promise<boolean>\n restoreSession: () => Promise<void>\n isSessionValid: () => boolean\n logout: () => void\n fetchCustomer: (id: string) => Promise<void>\n}\n\nexport type AuthStore = ReturnType<typeof createAuthStore>\n\nexport function createAuthStore(client: WhaleClient, storagePrefix: string) {\n return createStore<AuthState & AuthActions>()(\n persist(\n (set, get) => ({\n // ── Initial state ────────────────────────────────────────────────\n customer: null,\n sessionToken: null,\n sessionExpiresAt: null,\n authLoading: false,\n\n // ── Actions ──────────────────────────────────────────────────────\n sendOTP: async (email) => {\n set({ authLoading: true })\n try {\n const res = await client.sendCode(email)\n return res.sent\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Could not send code'\n throw new Error(message)\n } finally {\n set({ authLoading: false })\n }\n },\n\n verifyOTP: async (email, code) => {\n set({ authLoading: true })\n try {\n const res = await client.verifyCode(email, code)\n client.setSessionToken(res.token_hash)\n set({\n sessionToken: res.token_hash,\n sessionExpiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),\n })\n\n if (res.customer?.id) {\n try {\n const full = await client.getCustomer(res.customer.id)\n set({ customer: full })\n } catch {\n set({ customer: res.customer })\n }\n }\n\n return res.needs_profile ?? false\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Verification failed'\n throw new Error(message)\n } finally {\n set({ authLoading: false })\n }\n },\n\n restoreSession: async () => {\n const { sessionToken, sessionExpiresAt, customer } = get()\n if (!sessionToken || !sessionExpiresAt) return\n\n if (new Date(sessionExpiresAt) <= new Date()) {\n client.setSessionToken(null)\n set({ sessionToken: null, sessionExpiresAt: null, customer: null })\n return\n }\n\n client.setSessionToken(sessionToken)\n\n if (customer?.id) {\n try {\n const fresh = await client.getCustomer(customer.id)\n set({ customer: fresh })\n } catch {\n client.setSessionToken(null)\n set({ sessionToken: null, sessionExpiresAt: null, customer: null })\n }\n }\n },\n\n isSessionValid: () => {\n const { sessionToken, sessionExpiresAt } = get()\n if (!sessionToken || !sessionExpiresAt) return false\n return new Date(sessionExpiresAt) > new Date()\n },\n\n logout: () => {\n client.setSessionToken(null)\n set({ customer: null, sessionToken: null, sessionExpiresAt: null })\n },\n\n fetchCustomer: async (id) => {\n try {\n const customer = await client.getCustomer(id)\n set({ customer })\n } catch (err) {\n console.error('[whale-storefront] fetchCustomer failed:', err)\n }\n },\n }),\n\n // ── Persist config ─────────────────────────────────────────────────\n {\n name: `${storagePrefix}-auth`,\n partialize: (state) => ({\n sessionToken: state.sessionToken,\n sessionExpiresAt: state.sessionExpiresAt,\n customer: state.customer\n ? {\n id: state.customer.id,\n email: state.customer.email,\n first_name: state.customer.first_name,\n last_name: state.customer.last_name,\n phone: state.customer.phone,\n loyalty_points: state.customer.loyalty_points,\n loyalty_tier: state.customer.loyalty_tier,\n total_spent: state.customer.total_spent,\n total_orders: state.customer.total_orders,\n }\n : null,\n }),\n }\n )\n )\n}\n","'use client'\n\nimport { useContext, useRef, useCallback } from 'react'\nimport { WhaleContext } from '../context.js'\nimport type { EventType } from '../../types.js'\n\nconst SESSION_KEY_SUFFIX = '-analytics-session'\n\ninterface SessionData {\n id: string\n createdAt: number\n}\n\nexport function useAnalytics() {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useAnalytics must be used within <WhaleProvider>')\n\n const { client, config, pixelManager } = ctx\n const sessionPromiseRef = useRef<Promise<string> | null>(null)\n const sessionKey = `${config.storagePrefix}${SESSION_KEY_SUFFIX}`\n\n const getOrCreateSession = useCallback(async (): Promise<string> => {\n if (sessionPromiseRef.current) return sessionPromiseRef.current\n\n sessionPromiseRef.current = (async () => {\n // Check stored session\n try {\n const raw = localStorage.getItem(sessionKey)\n if (raw) {\n const stored: SessionData = JSON.parse(raw)\n if (Date.now() - stored.createdAt < config.sessionTtl) {\n // Refresh last_active silently\n client.updateSession(stored.id, { last_active_at: new Date().toISOString() }).catch(() => {})\n return stored.id\n }\n }\n } catch {\n // ignore\n }\n\n // Create new\n try {\n const session = await client.createSession({\n user_agent: navigator.userAgent,\n referrer: document.referrer || undefined,\n })\n if (session?.id) {\n localStorage.setItem(sessionKey, JSON.stringify({ id: session.id, createdAt: Date.now() }))\n return session.id\n }\n } catch {\n // ignore\n }\n\n // Fallback local ID\n const fallbackId = `local-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n localStorage.setItem(sessionKey, JSON.stringify({ id: fallbackId, createdAt: Date.now() }))\n return fallbackId\n })()\n\n sessionPromiseRef.current.finally(() => {\n sessionPromiseRef.current = null\n })\n\n return sessionPromiseRef.current\n }, [client, config.sessionTtl, sessionKey])\n\n const trackingEnabled = config.trackingEnabled\n\n const track = useCallback(\n async (eventType: EventType, data: Record<string, unknown> = {}) => {\n if (!trackingEnabled) return\n\n // Generate shared event_id for Meta CAPI deduplication\n const eventId = crypto.randomUUID()\n\n // Fire pixel events instantly (client-side) with eventID for fbq dedup\n pixelManager?.track(eventType, { ...data, eventID: eventId })\n\n // Then fire gateway event (server-side attribution) with same event_id\n try {\n const sessionId = await getOrCreateSession()\n await client.trackEvent({\n session_id: sessionId,\n event_type: eventType,\n event_data: { ...data, event_id: eventId },\n })\n } catch {\n // fire-and-forget\n }\n },\n [client, getOrCreateSession, pixelManager, trackingEnabled]\n )\n\n const linkCustomer = useCallback(\n async (customerId: string) => {\n if (!trackingEnabled) return\n try {\n const sessionId = await getOrCreateSession()\n if (sessionId.startsWith('local-')) return\n await client.updateSession(sessionId, { customer_id: customerId })\n } catch {\n // ignore\n }\n },\n [client, getOrCreateSession, trackingEnabled]\n )\n\n const trackPageView = useCallback(\n (url: string, referrer?: string) => {\n track('page_view', { url, referrer })\n },\n [track]\n )\n\n const trackProductView = useCallback(\n (productId: string, productName: string, category: string, price?: number) => {\n track('product_view', { product_id: productId, product_name: productName, category, price })\n },\n [track]\n )\n\n const trackCategoryView = useCallback(\n (categoryId: string, categoryName: string) => {\n track('category_view', { category_id: categoryId, category_name: categoryName })\n },\n [track]\n )\n\n const trackSearch = useCallback(\n (query: string, resultCount?: number) => {\n track('search', { query, result_count: resultCount })\n },\n [track]\n )\n\n const trackBeginCheckout = useCallback(\n (cartId: string, total: number, itemCount: number) => {\n track('begin_checkout', { cart_id: cartId, total, item_count: itemCount })\n },\n [track]\n )\n\n const trackPurchase = useCallback(\n (orderId: string, orderNumber: string, total: number) => {\n track('purchase', { order_id: orderId, order_number: orderNumber, total })\n },\n [track]\n )\n\n const trackAddToCart = useCallback(\n (productId: string, productName: string, quantity: number, price: number, tier?: string) => {\n track('add_to_cart', { product_id: productId, product_name: productName, quantity, price, tier })\n },\n [track]\n )\n\n const trackRemoveFromCart = useCallback(\n (productId: string, productName: string) => {\n track('remove_from_cart', { product_id: productId, product_name: productName })\n },\n [track]\n )\n\n return {\n track,\n trackPageView,\n trackProductView,\n trackCategoryView,\n trackSearch,\n trackBeginCheckout,\n trackPurchase,\n trackAddToCart,\n trackRemoveFromCart,\n linkCustomer,\n getOrCreateSession,\n /** Whether tracking is globally enabled for this storefront */\n trackingEnabled,\n /** Configured recording sample rate (0–1) for behavioral session replays */\n recordingRate: config.recordingRate,\n }\n}\n","'use client'\n\nimport { useContext } from 'react'\nimport { useStore } from 'zustand'\nimport { useShallow } from 'zustand/react/shallow'\nimport { WhaleContext } from '../context.js'\n\nexport function useAuth() {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useAuth must be used within <WhaleProvider>')\n\n return useStore(ctx.authStore, useShallow((s) => ({\n customer: s.customer,\n authLoading: s.authLoading,\n sessionToken: s.sessionToken,\n isAuthenticated: s.isSessionValid(),\n sendCode: s.sendOTP,\n verifyCode: s.verifyOTP,\n restoreSession: s.restoreSession,\n logout: s.logout,\n fetchCustomer: s.fetchCustomer,\n })))\n}\n","'use client'\n\nimport { useEffect, useRef, useContext } from 'react'\nimport { WhaleContext } from '../context.js'\nimport { useAnalytics } from '../hooks/use-analytics.js'\nimport { useAuth } from '../hooks/use-auth.js'\n\n/**\n * Auto-tracks page views on pathname change and links customer sessions.\n * Rendered internally by WhaleProvider — storefronts don't need to add this manually.\n *\n * When `config.trackingEnabled` is false the component renders nothing and\n * skips all side-effects — the underlying hook guards individual calls too,\n * but short-circuiting here avoids session creation entirely.\n */\nexport function AnalyticsTracker({ pathname }: { pathname: string }) {\n const ctx = useContext(WhaleContext)\n const { trackPageView, linkCustomer } = useAnalytics()\n const { customer } = useAuth()\n const prevPathname = useRef<string | null>(null)\n const linkedCustomerId = useRef<string | null>(null)\n\n const trackingEnabled = ctx?.config.trackingEnabled ?? true\n\n // Track page views on route change\n useEffect(() => {\n if (!trackingEnabled) return\n if (pathname === prevPathname.current) return\n const referrer = prevPathname.current || (typeof document !== 'undefined' ? document.referrer : '')\n prevPathname.current = pathname\n trackPageView(pathname, referrer || undefined)\n }, [pathname, trackPageView, trackingEnabled])\n\n // Link customer session on login\n useEffect(() => {\n if (!trackingEnabled) return\n if (customer?.id && customer.id !== linkedCustomerId.current) {\n linkedCustomerId.current = customer.id\n linkCustomer(customer.id)\n }\n }, [customer?.id, linkCustomer, trackingEnabled])\n\n return null\n}\n","'use client'\n\nimport { useContext } from 'react'\nimport { useStore } from 'zustand'\nimport { useShallow } from 'zustand/react/shallow'\nimport { WhaleContext } from '../context.js'\nimport type { CartState, CartActions } from '../stores/cart-store.js'\n\ntype CartReturn = Pick<\n CartState & CartActions,\n 'cartId' | 'cartOpen' | 'cartLoading' | 'items' | 'itemCount' | 'subtotal' | 'taxAmount' | 'total' | 'taxBreakdown' | 'productImages' |\n 'addItem' | 'removeItem' | 'updateQuantity' | 'toggleCart' | 'openCart' | 'closeCart' | 'checkout' | 'initCart' | 'syncCart' | 'clearCart'\n>\n\nexport function useCart() {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useCart must be used within <WhaleProvider>')\n\n return useStore(ctx.cartStore, useShallow((s) => ({\n cartId: s.cartId,\n items: s.items,\n itemCount: s.itemCount,\n subtotal: s.subtotal,\n taxAmount: s.taxAmount,\n total: s.total,\n taxBreakdown: s.taxBreakdown,\n cartOpen: s.cartOpen,\n cartLoading: s.cartLoading,\n productImages: s.productImages,\n addItem: s.addItem,\n removeItem: s.removeItem,\n updateQuantity: s.updateQuantity,\n toggleCart: s.toggleCart,\n openCart: s.openCart,\n closeCart: s.closeCart,\n initCart: s.initCart,\n syncCart: s.syncCart,\n clearCart: s.clearCart,\n checkout: s.checkout,\n })))\n}\n\n/** Granular selector — only re-renders on count change */\nexport function useCartItemCount(): number {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useCartItemCount must be used within <WhaleProvider>')\n return useStore(ctx.cartStore, (s) => s.itemCount)\n}\n\n/** Granular selector — only re-renders on total change */\nexport function useCartTotal(): number {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useCartTotal must be used within <WhaleProvider>')\n return useStore(ctx.cartStore, (s) => s.total)\n}\n","'use client'\n\nimport { useEffect, useRef } from 'react'\nimport { useCart } from '../hooks/use-cart.js'\n\n/**\n * Hydrates cart from gateway on mount if a cartId is persisted.\n * Rendered internally by WhaleProvider.\n */\nexport function CartInitializer() {\n const { cartId, syncCart } = useCart()\n const initialized = useRef(false)\n\n useEffect(() => {\n if (initialized.current) return\n initialized.current = true\n if (cartId) {\n syncCart().catch(() => {\n // Cart may have expired — that's fine, addItem will auto-recover\n })\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n return null\n}\n","'use client'\n\nimport { useEffect, useRef } from 'react'\nimport { useAuth } from '../hooks/use-auth.js'\n\n/**\n * Restores auth session on mount — syncs persisted token to client.\n * Rendered internally by WhaleProvider.\n */\nexport function AuthInitializer() {\n const { restoreSession } = useAuth()\n const restored = useRef(false)\n\n useEffect(() => {\n if (restored.current) return\n restored.current = true\n restoreSession()\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n return null\n}\n","'use client'\n\nimport { useEffect, useRef, useContext } from 'react'\nimport { WhaleContext } from '../context.js'\nimport { PixelManager } from '../../pixels/pixel-manager.js'\nimport type { StorefrontConfig } from '../../pixels/types.js'\n\n/**\n * Fetches storefront pixel config on mount and initializes pixel providers.\n * Sets pixelManager on context so useAnalytics can dispatch events to it.\n * Rendered internally by WhaleProvider — storefronts don't need to add this manually.\n */\nexport function PixelInitializer({ onReady }: { onReady: (manager: PixelManager) => void }) {\n const ctx = useContext(WhaleContext)\n const initialized = useRef(false)\n\n useEffect(() => {\n if (!ctx || initialized.current) return\n if (typeof window === 'undefined') return\n if (!ctx.config.trackingEnabled) return\n initialized.current = true\n\n const { client } = ctx\n\n client.fetchStorefrontConfig().then(async (config: StorefrontConfig) => {\n if (!config.pixels || config.pixels.length === 0) return\n\n const manager = new PixelManager(config.pixels)\n await manager.initialize()\n onReady(manager)\n }).catch(() => {\n // Pixel config fetch failed — degrade silently\n })\n }, [ctx, onReady])\n\n return null\n}\n","'use client'\n\nimport { useMemo, useState, useCallback, type ReactNode } from 'react'\nimport { usePathname } from 'next/navigation'\nimport { WhaleClient } from '../client.js'\nimport type { WhaleStorefrontConfig, Product } from '../types.js'\nimport type { PixelManager } from '../pixels/pixel-manager.js'\nimport { WhaleContext, type WhaleContextValue } from './context.js'\nimport { createCartStore } from './stores/cart-store.js'\nimport { createAuthStore } from './stores/auth-store.js'\nimport { AnalyticsTracker } from './components/analytics-tracker.js'\nimport { CartInitializer } from './components/cart-initializer.js'\nimport { AuthInitializer } from './components/auth-initializer.js'\nimport { PixelInitializer } from './components/pixel-initializer.js'\n\n/** Read a boolean env var (NEXT_PUBLIC_*). Returns undefined when absent. */\nfunction envBool(name: string): boolean | undefined {\n if (typeof process === 'undefined') return undefined\n const raw = (process.env as Record<string, string | undefined>)[name]\n if (raw === undefined || raw === '') return undefined\n return raw !== '0' && raw.toLowerCase() !== 'false'\n}\n\n/** Read a numeric env var (NEXT_PUBLIC_*). Returns undefined when absent. */\nfunction envNumber(name: string): number | undefined {\n if (typeof process === 'undefined') return undefined\n const raw = (process.env as Record<string, string | undefined>)[name]\n if (raw === undefined || raw === '') return undefined\n const n = Number(raw)\n return Number.isFinite(n) ? n : undefined\n}\n\nexport interface WhaleProviderProps extends WhaleStorefrontConfig {\n children: ReactNode\n /** Server-fetched products passed to client for hooks */\n products?: Product[]\n}\n\nexport function WhaleProvider({\n children,\n products = [],\n storeId,\n apiKey,\n gatewayUrl,\n proxyPath,\n mediaSigningSecret,\n supabaseHost,\n storagePrefix,\n sessionTtl,\n debug,\n trackingEnabled,\n recordingRate,\n}: WhaleProviderProps) {\n const pathname = usePathname()\n const [pixelManager, setPixelManager] = useState<PixelManager | null>(null)\n\n const handlePixelReady = useCallback((manager: PixelManager) => {\n setPixelManager(manager)\n }, [])\n\n const ctx = useMemo<WhaleContextValue>(() => {\n const resolvedConfig = {\n storeId,\n apiKey,\n gatewayUrl: gatewayUrl || 'https://whale-gateway.fly.dev',\n proxyPath: proxyPath || '/api/gw',\n mediaSigningSecret: mediaSigningSecret || '',\n supabaseHost: supabaseHost || '',\n storagePrefix: storagePrefix || 'whale',\n sessionTtl: sessionTtl || 30 * 60 * 1000,\n debug: debug || false,\n trackingEnabled: trackingEnabled ?? envBool('NEXT_PUBLIC_TRACKING_ENABLED') ?? true,\n recordingRate: recordingRate ?? envNumber('NEXT_PUBLIC_RECORDING_RATE') ?? 0.1,\n }\n\n const client = new WhaleClient({\n storeId,\n apiKey,\n gatewayUrl: resolvedConfig.gatewayUrl,\n proxyPath: resolvedConfig.proxyPath,\n })\n\n // Analytics callbacks wired into cart store\n // These get called by the cart store on add/remove and fire analytics events.\n // We can't use the useAnalytics hook here (not in a component), so we use\n // the client directly — the AnalyticsTracker manages sessions.\n const cartStore = createCartStore(client, resolvedConfig.storagePrefix)\n const authStore = createAuthStore(client, resolvedConfig.storagePrefix)\n\n return {\n client,\n config: resolvedConfig,\n cartStore,\n authStore,\n products,\n pixelManager: null,\n }\n // Only recreate when identity changes — storeId + apiKey\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [storeId, apiKey])\n\n // Update products and pixelManager on the context when they change\n const value = useMemo<WhaleContextValue>(\n () => ({ ...ctx, products, pixelManager }),\n [ctx, products, pixelManager]\n )\n\n return (\n <WhaleContext.Provider value={value}>\n <AuthInitializer />\n <CartInitializer />\n <AnalyticsTracker pathname={pathname} />\n <PixelInitializer onReady={handlePixelReady} />\n {children}\n </WhaleContext.Provider>\n )\n}\n","'use client'\n\nimport { useContext, useState, useEffect, useMemo } from 'react'\nimport { WhaleContext } from '../context.js'\nimport type { Product } from '../../types.js'\n\n/**\n * Returns products passed via WhaleProvider.\n * Optionally filters by category or search.\n */\nexport function useProducts(opts?: {\n categoryId?: string\n search?: string\n}) {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useProducts must be used within <WhaleProvider>')\n\n const allProducts = ctx.products\n\n const products = useMemo(() => {\n let result = allProducts\n if (opts?.categoryId) {\n result = result.filter((p) => p.primary_category_id === opts.categoryId)\n }\n if (opts?.search) {\n const q = opts.search.toLowerCase()\n result = result.filter(\n (p) =>\n p.name.toLowerCase().includes(q) ||\n p.description?.toLowerCase().includes(q) ||\n p.slug.toLowerCase().includes(q)\n )\n }\n return result\n }, [allProducts, opts?.categoryId, opts?.search])\n\n return {\n products,\n allProducts,\n loading: false,\n }\n}\n\n/**\n * Returns a single product by slug from the provider's product list.\n */\nexport function useProduct(slug: string | null | undefined) {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useProduct must be used within <WhaleProvider>')\n\n const product = useMemo(() => {\n if (!slug) return null\n return ctx.products.find((p) => p.slug === slug) ?? null\n }, [ctx.products, slug])\n\n return {\n product,\n loading: false,\n }\n}\n","'use client'\n\nimport { useContext } from 'react'\nimport { WhaleContext } from '../context.js'\nimport type { WhaleClient } from '../../client.js'\n\nexport function useWhaleClient(): WhaleClient {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useWhaleClient must be used within <WhaleProvider>')\n return ctx.client\n}\n","'use client'\n\nimport { useContext, useState, useEffect, useCallback } from 'react'\nimport { useStore } from 'zustand'\nimport { WhaleContext } from '../context.js'\nimport type { Order, CustomerAnalytics } from '../../types.js'\n\nexport function useCustomerOrders() {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useCustomerOrders must be used within <WhaleProvider>')\n\n const customer = useStore(ctx.authStore, (s) => s.customer)\n const [orders, setOrders] = useState<Order[]>([])\n const [loading, setLoading] = useState(false)\n\n const refresh = useCallback(async () => {\n if (!customer?.id) {\n setOrders([])\n return\n }\n setLoading(true)\n try {\n const data = await ctx.client.getCustomerOrders(customer.id)\n setOrders(data)\n } catch {\n setOrders([])\n } finally {\n setLoading(false)\n }\n }, [customer?.id, ctx.client])\n\n useEffect(() => {\n refresh()\n }, [refresh])\n\n return { orders, loading, refresh }\n}\n\nexport function useCustomerAnalytics() {\n const ctx = useContext(WhaleContext)\n if (!ctx) throw new Error('useCustomerAnalytics must be used within <WhaleProvider>')\n\n const customer = useStore(ctx.authStore, (s) => s.customer)\n const [analytics, setAnalytics] = useState<CustomerAnalytics | null>(null)\n const [loading, setLoading] = useState(false)\n\n useEffect(() => {\n if (!customer?.id) {\n setAnalytics(null)\n return\n }\n setLoading(true)\n const name = `${customer.first_name} ${customer.last_name}`.trim()\n ctx.client\n .getCustomerAnalytics(customer.id, name || undefined)\n .then(setAnalytics)\n .catch(() => setAnalytics(null))\n .finally(() => setLoading(false))\n }, [customer?.id, customer?.first_name, customer?.last_name, ctx.client])\n\n return { analytics, loading }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neowhale/storefront",
3
- "version": "0.1.2",
3
+ "version": "0.2.2",
4
4
  "description": "React/Next.js SDK for WhaleTools storefronts — cart, auth, analytics, and more",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,6 +30,7 @@
30
30
  "build": "tsup",
31
31
  "dev": "tsup --watch",
32
32
  "typecheck": "tsc --noEmit",
33
+ "test:e2e": "npx playwright test",
33
34
  "prepublishOnly": "npm run build"
34
35
  },
35
36
  "keywords": [
@@ -42,6 +43,10 @@
42
43
  ],
43
44
  "author": "WhaleTools <dev@whaletools.dev>",
44
45
  "license": "MIT",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/floradistro/neowhale-storefront"
49
+ },
45
50
  "publishConfig": {
46
51
  "access": "public"
47
52
  },
@@ -57,12 +62,14 @@
57
62
  }
58
63
  },
59
64
  "devDependencies": {
65
+ "@playwright/test": "^1.58.2",
60
66
  "@types/node": "^22.0.0",
61
67
  "@types/react": "^19.0.0",
62
68
  "@types/react-dom": "^19.0.0",
63
69
  "next": "^15.0.0",
64
70
  "react": "^19.0.0",
65
71
  "react-dom": "^19.0.0",
72
+ "serve": "^14.2.6",
66
73
  "tsup": "^8.0.0",
67
74
  "typescript": "^5.7.0",
68
75
  "zustand": "^5.0.0"