@weaverse/hydrogen 5.14.1 → 5.15.1

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.d.mts CHANGED
@@ -293,6 +293,7 @@ declare function withWeaverse(Component: ComponentType<any>, options?: WithWeave
293
293
  */
294
294
  declare function useThemeSettings<T = HydrogenThemeSettings>(): T;
295
295
 
296
+ type BuilderApiCacheTarget = 'custom-pages' | 'merchant-overrides' | 'project' | 'theme-settings';
296
297
  declare class WeaverseClient {
297
298
  API: "v1";
298
299
  basePageConfigs: Omit<WeaverseProjectConfigs, 'requestInfo'>;
@@ -413,6 +414,7 @@ declare class WeaverseClient {
413
414
  * ```
414
415
  */
415
416
  fetchWithCache: <T = unknown>(url: string, options?: RequestInit & {
417
+ cacheTarget?: BuilderApiCacheTarget;
416
418
  strategy?: CachingStrategy;
417
419
  }) => Promise<T>;
418
420
  /**
package/dist/index.d.ts CHANGED
@@ -293,6 +293,7 @@ declare function withWeaverse(Component: ComponentType<any>, options?: WithWeave
293
293
  */
294
294
  declare function useThemeSettings<T = HydrogenThemeSettings>(): T;
295
295
 
296
+ type BuilderApiCacheTarget = 'custom-pages' | 'merchant-overrides' | 'project' | 'theme-settings';
296
297
  declare class WeaverseClient {
297
298
  API: "v1";
298
299
  basePageConfigs: Omit<WeaverseProjectConfigs, 'requestInfo'>;
@@ -413,6 +414,7 @@ declare class WeaverseClient {
413
414
  * ```
414
415
  */
415
416
  fetchWithCache: <T = unknown>(url: string, options?: RequestInit & {
417
+ cacheTarget?: BuilderApiCacheTarget;
416
418
  strategy?: CachingStrategy;
417
419
  }) => Promise<T>;
418
420
  /**
package/dist/index.js CHANGED
@@ -529,8 +529,8 @@ function getQueriesFromSearch(search) {
529
529
  }
530
530
  return queries;
531
531
  }
532
- function normalizeDesignModeRequestInfo(params, browserLocation = getBrowserLocation()) {
533
- if (!(params.isDesignMode && browserLocation)) {
532
+ function normalizeRequestInfo(params, browserLocation = getBrowserLocation()) {
533
+ if (!browserLocation) {
534
534
  return params;
535
535
  }
536
536
  let { pathname, search } = browserLocation;
@@ -547,6 +547,27 @@ function normalizeDesignModeRequestInfo(params, browserLocation = getBrowserLoca
547
547
  }
548
548
  };
549
549
  }
550
+
551
+ // src/utils/sync-reused-instance.ts
552
+ function syncReusedInstance(weaverse, params) {
553
+ weaverse.requestInfo = params.requestInfo;
554
+ weaverse.internal = params.internal;
555
+ let dataChanged = JSON.stringify(weaverse.data) !== JSON.stringify(params.data);
556
+ let contextChanged = JSON.stringify(weaverse.dataContext ?? null) !== JSON.stringify(params.dataContext ?? null);
557
+ if (contextChanged) {
558
+ weaverse.dataContext = params.dataContext ?? null;
559
+ }
560
+ if (dataChanged) {
561
+ weaverse.setProjectData(params.data);
562
+ } else if (contextChanged) {
563
+ for (const { id } of params.data?.items || []) {
564
+ weaverse.itemInstances.get(id)?.setData({});
565
+ }
566
+ }
567
+ if (dataChanged || contextChanged) {
568
+ weaverse.triggerUpdate();
569
+ }
570
+ }
550
571
  var ThemeSettingsStore = class {
551
572
  settings = {};
552
573
  schema;
@@ -651,6 +672,24 @@ function useThemeSettingsStore() {
651
672
  }
652
673
 
653
674
  // src/utils/use-studio.ts
675
+ var STUDIO_READY_POLL_MS = 50;
676
+ var STUDIO_READY_TIMEOUT_MS = 5e3;
677
+ function waitForStudio() {
678
+ return new Promise((resolve) => {
679
+ let startedAt = Date.now();
680
+ function check() {
681
+ if (hasWeaverseStudio(window)) {
682
+ return resolve(window.weaverseStudio);
683
+ }
684
+ if (Date.now() - startedAt >= STUDIO_READY_TIMEOUT_MS) {
685
+ console.warn("[Weaverse] Studio script did not initialize in time");
686
+ return resolve(null);
687
+ }
688
+ setTimeout(check, STUDIO_READY_POLL_MS);
689
+ }
690
+ check();
691
+ });
692
+ }
654
693
  function useStudio(weaverse) {
655
694
  let { revalidate } = reactRouter.useRevalidator();
656
695
  let navigation = reactRouter.useNavigation();
@@ -680,11 +719,7 @@ function useStudio(weaverse) {
680
719
  themeTextStore
681
720
  };
682
721
  let studioSrc = `${weaverseHost}/static/studio/hydrogen/index.js?v=${weaverseVersion}`;
683
- react.loadScript(studioSrc).then(() => {
684
- if (hasWeaverseStudio(window)) {
685
- window.weaverseStudio.init(weaverse);
686
- }
687
- }).catch(console.error);
722
+ react.loadScript(studioSrc).then(waitForStudio).then((studio) => studio?.init(weaverse)).catch(console.error);
688
723
  }
689
724
  }
690
725
  }, [pathname, search, navigation.state]);
@@ -866,19 +901,20 @@ var WeaverseHydrogen = class extends react.Weaverse {
866
901
  };
867
902
  };
868
903
  function createWeaverseInstance(params) {
869
- const normalizedParams = normalizeDesignModeRequestInfo(params);
904
+ const normalizedParams = normalizeRequestInfo(params);
870
905
  if (react.isBrowser) {
871
906
  window.__weaverses = window.__weaverses || {};
872
- let weaverse = window.__weaverses[normalizedParams.pageId];
873
- if (!weaverse || weaverse?.requestInfo?.pathname !== normalizedParams.requestInfo.pathname || weaverse?.requestInfo?.search !== normalizedParams.requestInfo.search) {
874
- weaverse = new WeaverseHydrogen(normalizedParams);
875
- window.__weaverses[normalizedParams.pageId] = weaverse;
876
- }
877
- if (weaverse?.isDesignMode) {
907
+ const existing = window.__weaverses[normalizedParams.pageId];
908
+ const isReused = existing?.requestInfo?.pathname === normalizedParams.requestInfo.pathname && existing?.requestInfo?.search === normalizedParams.requestInfo.search;
909
+ const weaverse = isReused ? existing : new WeaverseHydrogen(normalizedParams);
910
+ window.__weaverses[normalizedParams.pageId] = weaverse;
911
+ if (weaverse.isDesignMode) {
878
912
  weaverse.requestInfo = normalizedParams.requestInfo;
879
913
  if (hasWeaverseStudio(window)) {
880
914
  window.weaverseStudio.refreshStudio(normalizedParams);
881
915
  }
916
+ } else if (isReused) {
917
+ syncReusedInstance(weaverse, normalizedParams);
882
918
  }
883
919
  return weaverse;
884
920
  }
@@ -994,20 +1030,54 @@ function useThemeSettings() {
994
1030
  );
995
1031
  return settings;
996
1032
  }
1033
+
1034
+ // src/utils/normalize-page-url.ts
1035
+ var KEPT_PARAM_RE = /^(?:__revisionId|isDesignMode|weaverse)/;
1036
+ function normalizePageUrl(url) {
1037
+ let parsed;
1038
+ try {
1039
+ parsed = new URL(url);
1040
+ } catch {
1041
+ return url;
1042
+ }
1043
+ const kept = [...parsed.searchParams].filter(
1044
+ ([key]) => KEPT_PARAM_RE.test(key)
1045
+ );
1046
+ kept.sort(([a], [b]) => a.localeCompare(b));
1047
+ const search = new URLSearchParams(kept).toString();
1048
+ return `${parsed.origin}${parsed.pathname}${search ? `?${search}` : ""}`;
1049
+ }
1050
+
1051
+ // src/weaverse-client.ts
997
1052
  var CACHE_DURATIONS = {
998
- /** Short cache for frequently changing content (10 seconds) */
999
- SHORT: 10,
1000
- /** Long cache duration - 23 hours to maximize CDN hits before daily refresh */
1001
- LONG: 82800
1053
+ /** Short browser freshness for content that can change in Builder */
1054
+ SHORT: 60,
1055
+ /** Shared cache freshness for anonymous storefront traffic */
1056
+ SHARED_SHORT: 300,
1057
+ /** Long stale window so slow Builder responses do not block storefront rendering */
1058
+ LONG: 86400,
1059
+ /** Extra freshness for sitemap-like index data */
1060
+ STATIC: 3600
1002
1061
  };
1003
1062
  var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
1004
1063
  var API_PATH = "v1";
1005
1064
  var DEFAULT_CACHE_STRATEGY = {
1006
1065
  maxAge: CACHE_DURATIONS.SHORT,
1007
- sMaxAge: CACHE_DURATIONS.SHORT,
1066
+ sMaxAge: CACHE_DURATIONS.SHARED_SHORT,
1008
1067
  staleWhileRevalidate: CACHE_DURATIONS.LONG,
1009
1068
  staleIfError: CACHE_DURATIONS.LONG
1010
1069
  };
1070
+ var SMART_CACHE_STRATEGIES = {
1071
+ project: DEFAULT_CACHE_STRATEGY,
1072
+ "theme-settings": DEFAULT_CACHE_STRATEGY,
1073
+ "merchant-overrides": DEFAULT_CACHE_STRATEGY,
1074
+ "custom-pages": {
1075
+ maxAge: CACHE_DURATIONS.SHORT,
1076
+ sMaxAge: CACHE_DURATIONS.STATIC,
1077
+ staleWhileRevalidate: CACHE_DURATIONS.LONG,
1078
+ staleIfError: CACHE_DURATIONS.LONG
1079
+ }
1080
+ };
1011
1081
  var WeaverseClient = class {
1012
1082
  API = API_PATH;
1013
1083
  basePageConfigs;
@@ -1349,19 +1419,23 @@ var WeaverseClient = class {
1349
1419
  * ```
1350
1420
  */
1351
1421
  fetchWithCache = async (url, options = {}) => {
1352
- const strategy = options.strategy || hydrogen.CacheCustom(DEFAULT_CACHE_STRATEGY);
1422
+ const { cacheTarget, strategy: strategyOverride, ...fetchOptions } = options;
1423
+ const strategy = strategyOverride || hydrogen.CacheCustom(
1424
+ cacheTarget ? SMART_CACHE_STRATEGIES[cacheTarget] : DEFAULT_CACHE_STRATEGY
1425
+ );
1353
1426
  const cacheKey = [
1354
1427
  "weaverse-fetch",
1355
1428
  url,
1356
1429
  options.method || "GET",
1357
- options.body,
1358
- this.configs.projectId
1430
+ fetchOptions.body,
1431
+ this.configs.projectId,
1432
+ cacheTarget || "default"
1359
1433
  ];
1360
1434
  let result;
1361
- if (this.configs.isDesignMode) {
1362
- result = await this.directFetch(url, options);
1435
+ if (this.configs.isDesignMode || this.configs.isRevisionPreview) {
1436
+ result = await this.directFetch(url, fetchOptions);
1363
1437
  } else {
1364
- result = await this.withCache.fetch(url, options, {
1438
+ result = await this.withCache.fetch(url, fetchOptions, {
1365
1439
  cacheKey,
1366
1440
  cacheStrategy: strategy,
1367
1441
  shouldCacheResponse: (response) => {
@@ -1398,6 +1472,7 @@ var WeaverseClient = class {
1398
1472
  const [data, merchantOverrides] = await Promise.all([
1399
1473
  this.fetchWithCache(url, {
1400
1474
  method: "POST",
1475
+ cacheTarget: "theme-settings",
1401
1476
  strategy,
1402
1477
  body,
1403
1478
  headers: {
@@ -1492,6 +1567,7 @@ var WeaverseClient = class {
1492
1567
  url,
1493
1568
  {
1494
1569
  method: "GET",
1570
+ cacheTarget: "merchant-overrides",
1495
1571
  strategy,
1496
1572
  headers: {
1497
1573
  Accept: "application/json"
@@ -1555,7 +1631,7 @@ var WeaverseClient = class {
1555
1631
  const qs = params.toString();
1556
1632
  const url = `${weaverseHost}/api/public/v1/projects/${projectId}/custom-pages${qs ? `?${qs}` : ""}`;
1557
1633
  try {
1558
- const result = await this.fetchWithCache(url);
1634
+ const result = await this.fetchWithCache(url, { cacheTarget: "custom-pages" });
1559
1635
  entries.push(...result.data || []);
1560
1636
  if (!result.nextCursor) {
1561
1637
  return entries;
@@ -1640,7 +1716,9 @@ var WeaverseClient = class {
1640
1716
  projectId: effectiveProjectId,
1641
1717
  // Use effective (potentially overridden) projectId
1642
1718
  params: pageLoadParams,
1643
- url: request.url
1719
+ // Stripped to pathname + Weaverse params — tracking params would
1720
+ // fragment the subrequest cache key (see normalizePageUrl).
1721
+ url: normalizePageUrl(request.url)
1644
1722
  };
1645
1723
  const reqInit = {
1646
1724
  method: "POST",
@@ -1655,6 +1733,7 @@ var WeaverseClient = class {
1655
1733
  const url = this.getApiUrl("project");
1656
1734
  const projectData = await this.fetchWithCache(url, {
1657
1735
  ...reqInit,
1736
+ cacheTarget: "project",
1658
1737
  strategy
1659
1738
  });
1660
1739
  if (hasError(projectData)) {