@weaverse/hydrogen 5.7.1 → 5.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -55,8 +55,9 @@ function useWeaverseDataContext() {
55
55
  function createWeaverseDataContext(matches) {
56
56
  return createFlatDataContext(matches);
57
57
  }
58
-
59
- // src/types.ts
58
+ function isProjectIdFunction(projectId) {
59
+ return typeof projectId === "function";
60
+ }
60
61
  var WeaverseError = class _WeaverseError extends Error {
61
62
  code;
62
63
  statusCode;
@@ -82,10 +83,14 @@ function hasError(response) {
82
83
  return typeof response === "object" && response !== null && "error" in response && typeof response.error === "string";
83
84
  }
84
85
  function isThemeSettingsResponse(data) {
85
- return typeof data === "object" && data !== null && data.theme !== void 0;
86
+ if (typeof data !== "object" || data === null) {
87
+ return false;
88
+ }
89
+ const record = data;
90
+ return "theme" in record && typeof record.theme === "object" && record.theme !== null;
86
91
  }
87
92
  function isValidHydrogenSchema(schema2) {
88
- return typeof schema2 === "object" && schema2 !== null && "type" in schema2 && "title" in schema2;
93
+ return schema$1.isValidSchema(schema2);
89
94
  }
90
95
 
91
96
  // src/utils/index.ts
@@ -111,15 +116,22 @@ function mergeInspectorSettings(settings, inspector, type) {
111
116
  );
112
117
  return deepMergeArrays(settings, inspector);
113
118
  }
114
- function getRequestQueries(request) {
119
+ function getRequestQueries(request, options) {
115
120
  let url = new URL(request.url);
116
- return Array.from(url.searchParams.entries()).reduce(
117
- (q, [k, v]) => {
118
- q[k] = v === "true" ? true : v === "false" ? false : v;
119
- return q;
120
- },
121
- {}
122
- );
121
+ let queries = {};
122
+ for (let [key, value] of url.searchParams.entries()) {
123
+ if (options?.allowedKeys && !options.allowedKeys.includes(key)) {
124
+ continue;
125
+ }
126
+ if (value === "true") {
127
+ queries[key] = true;
128
+ } else if (value === "false") {
129
+ queries[key] = false;
130
+ } else {
131
+ queries[key] = value;
132
+ }
133
+ }
134
+ return queries;
123
135
  }
124
136
  function getWeaverseConfigs(request, env) {
125
137
  let queries = getRequestQueries(request);
@@ -156,7 +168,12 @@ function getWeaverseConfigs(request, env) {
156
168
  }
157
169
  };
158
170
  }
171
+ var schemaDefaultsCache = /* @__PURE__ */ new WeakMap();
159
172
  function generateDataFromSchema(schema2) {
173
+ const cached = schemaDefaultsCache.get(schema2);
174
+ if (cached) {
175
+ return cached;
176
+ }
160
177
  let data = {};
161
178
  let inspectorGroups = [];
162
179
  const isComponentSchema = (s) => "type" in s && typeof s.type === "string";
@@ -211,6 +228,7 @@ function generateDataFromSchema(schema2) {
211
228
  }
212
229
  }
213
230
  }
231
+ schemaDefaultsCache.set(schema2, data);
214
232
  return data;
215
233
  }
216
234
  function recursivelyAddDataItem(type, components, items, initData) {
@@ -447,13 +465,16 @@ var WeaverseHydrogenRoot = react$1.memo(
447
465
  }) => {
448
466
  const matches = reactRouter.useMatches();
449
467
  const enhancedDataContext = createWeaverseDataContext(matches);
450
- let weaverseData = null;
451
- for (const match of matches) {
452
- if (match.data && typeof match.data === "object" && match.data !== null && "weaverseData" in match.data) {
453
- weaverseData = match.data.weaverseData;
454
- break;
468
+ const weaverseData = react$1.useMemo(() => {
469
+ for (let i = matches.length - 1; i >= 0; i--) {
470
+ const match = matches[i];
471
+ const loaderData = match.loaderData;
472
+ if (loaderData && "weaverseData" in loaderData) {
473
+ return loaderData.weaverseData;
474
+ }
455
475
  }
456
- }
476
+ return null;
477
+ }, [matches]);
457
478
  if (weaverseData) {
458
479
  if (weaverseData instanceof Promise) {
459
480
  return /* @__PURE__ */ jsxRuntime.jsx(reactErrorBoundary.ErrorBoundary, { fallbackRender: ErrorComponent, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Suspense, { children: /* @__PURE__ */ jsxRuntime.jsx(reactRouter.Await, { resolve: weaverseData, children: (resolvedData) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -499,14 +520,19 @@ function useThemeSettings() {
499
520
  );
500
521
  return settings;
501
522
  }
523
+ var CACHE_DURATIONS = {
524
+ /** Short cache for frequently changing content (10 seconds) */
525
+ SHORT: 10,
526
+ /** Long cache duration - 23 hours to maximize CDN hits before daily refresh */
527
+ LONG: 82800
528
+ };
529
+ var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
502
530
  var API_PATH = "v1";
503
531
  var DEFAULT_CACHE_STRATEGY = {
504
- maxAge: 10,
505
- sMaxAge: 10,
506
- staleWhileRevalidate: 82800,
507
- // 23 hours
508
- staleIfError: 82800
509
- // 23 hours
532
+ maxAge: CACHE_DURATIONS.SHORT,
533
+ sMaxAge: CACHE_DURATIONS.SHORT,
534
+ staleWhileRevalidate: CACHE_DURATIONS.LONG,
535
+ staleIfError: CACHE_DURATIONS.LONG
510
536
  };
511
537
  var WeaverseClient = class {
512
538
  API = API_PATH;
@@ -523,31 +549,64 @@ var WeaverseClient = class {
523
549
  env;
524
550
  cache;
525
551
  waitUntil;
552
+ // Performance optimizations
553
+ parsedUrl;
554
+ componentsByType;
555
+ // Configuration
556
+ fetchTimeoutMs;
526
557
  constructor(args) {
527
- const {
528
- customerAccount,
529
- env,
530
- storefront,
531
- components,
532
- cache,
533
- waitUntil,
534
- themeSchema,
535
- request
536
- } = args;
537
- this.request = request;
538
- this.storefront = storefront;
539
- this.customerAccount = customerAccount;
540
- this.components = components;
541
- this.themeSchema = themeSchema;
542
- this.env = env;
543
- this.cache = cache;
544
- this.waitUntil = waitUntil;
558
+ this.request = args.request;
559
+ this.storefront = args.storefront;
560
+ this.customerAccount = args.customerAccount;
561
+ this.components = args.components;
562
+ this.themeSchema = args.themeSchema;
563
+ this.env = args.env;
564
+ this.cache = args.cache;
565
+ this.waitUntil = args.waitUntil;
566
+ this.parsedUrl = new URL(args.request.url);
567
+ this.componentsByType = this.buildComponentLookupMap(args.components);
568
+ this.fetchTimeoutMs = args.fetchTimeoutMs || DEFAULT_FETCH_TIMEOUT_MS;
569
+ this.initializeCache(args);
570
+ this.initializeConfigs(args);
571
+ }
572
+ /**
573
+ * Initialize Hydrogen cache with proper configuration.
574
+ * Logs warning if waitUntil is missing.
575
+ */
576
+ initializeCache(args) {
577
+ if (!args.waitUntil) {
578
+ console.warn(
579
+ "\u26A0\uFE0F WeaverseClient: waitUntil not provided, background operations may not complete"
580
+ );
581
+ }
545
582
  this.withCache = hydrogen.createWithCache({
546
- cache,
547
- waitUntil: waitUntil || (() => Promise.resolve()),
548
- request
583
+ cache: args.cache,
584
+ waitUntil: args.waitUntil || (() => Promise.resolve()),
585
+ request: args.request
549
586
  });
550
- this.configs = getWeaverseConfigs(request, env);
587
+ }
588
+ /**
589
+ * Initialize configs with projectId resolution and fail-fast validation.
590
+ * Throws WeaverseError if projectId cannot be resolved.
591
+ */
592
+ initializeConfigs(args) {
593
+ let baseConfigs = getWeaverseConfigs(args.request, args.env);
594
+ let resolvedProjectId = this.resolveProjectIdSync(
595
+ args.projectId,
596
+ args.request,
597
+ args.env,
598
+ baseConfigs
599
+ );
600
+ if (!resolvedProjectId || resolvedProjectId.trim() === "") {
601
+ throw new WeaverseError(
602
+ "Failed to initialize WeaverseClient: No valid projectId found. Set WEAVERSE_PROJECT_ID environment variable or provide projectId parameter.",
603
+ "MISSING_PROJECT_ID"
604
+ );
605
+ }
606
+ this.configs = {
607
+ ...baseConfigs,
608
+ projectId: resolvedProjectId
609
+ };
551
610
  this.basePageConfigs = {
552
611
  projectId: this.configs.projectId,
553
612
  weaverseHost: this.configs.weaverseHost,
@@ -558,35 +617,240 @@ var WeaverseClient = class {
558
617
  };
559
618
  this.basePageRequestBody = {
560
619
  isDesignMode: this.configs.isDesignMode,
561
- i18n: storefront.i18n,
620
+ i18n: args.storefront.i18n,
562
621
  projectId: this.configs.projectId
563
622
  };
623
+ Object.freeze(this.configs);
624
+ Object.freeze(this.basePageConfigs);
625
+ Object.freeze(this.basePageRequestBody);
626
+ }
627
+ /**
628
+ * Build component lookup map for O(1) access by type.
629
+ * Significantly improves performance for large component lists.
630
+ */
631
+ buildComponentLookupMap(components) {
632
+ return new Map(components.map((comp) => [comp.schema?.type, comp]));
564
633
  }
565
- // Helper method for direct fetching in design mode - returns same format as withCache.fetch
566
- directFetch = async (url, options = {}) => {
634
+ /**
635
+ * Extract comprehensive error information from unknown error type.
636
+ * Preserves error context, codes, and stack traces for debugging.
637
+ *
638
+ * @param error - Unknown error to extract information from
639
+ * @returns Structured error information with message, code, stack, and context
640
+ *
641
+ * @example
642
+ * ```typescript
643
+ * try {
644
+ * // ... operation
645
+ * } catch (error) {
646
+ * const errorInfo = this.extractErrorInfo(error)
647
+ * console.error('Operation failed:', errorInfo.message, errorInfo.context)
648
+ * }
649
+ * ```
650
+ */
651
+ extractErrorInfo(error) {
652
+ if (error instanceof WeaverseError) {
653
+ return {
654
+ message: error.message,
655
+ code: error.code,
656
+ context: error.context,
657
+ stack: error.stack
658
+ };
659
+ }
660
+ if (error instanceof Error) {
661
+ return {
662
+ message: error.message,
663
+ stack: error.stack
664
+ };
665
+ }
666
+ return {
667
+ message: String(error)
668
+ };
669
+ }
670
+ /**
671
+ * Extract error message only (for backward compatibility).
672
+ * Use extractErrorInfo() for more detailed error information.
673
+ *
674
+ * @deprecated Use extractErrorInfo() instead to preserve error context
675
+ */
676
+ extractErrorMessage(error) {
677
+ return this.extractErrorInfo(error).message;
678
+ }
679
+ /**
680
+ * Validates projectId format (alphanumeric, hyphens, underscores only).
681
+ * Returns detailed validation result with error message.
682
+ *
683
+ * @param projectId - Project identifier to validate
684
+ * @returns Validation result with error message if invalid
685
+ */
686
+ validateProjectId(projectId) {
687
+ if (!projectId || projectId.trim() === "") {
688
+ return {
689
+ valid: false,
690
+ error: "Project ID cannot be empty"
691
+ };
692
+ }
693
+ let validPattern = /^[a-zA-Z0-9_-]+$/;
694
+ if (!validPattern.test(projectId)) {
695
+ return {
696
+ valid: false,
697
+ error: `Invalid format: "${projectId}". Only alphanumeric characters, hyphens, and underscores are allowed.`
698
+ };
699
+ }
700
+ return { valid: true };
701
+ }
702
+ /**
703
+ * Resolves projectId with multi-project architecture support.
704
+ * Uses priority chain to determine the correct project ID.
705
+ *
706
+ * @param projectId - Project identifier (string, function, or undefined)
707
+ * @param request - HTTP request for context access
708
+ * @param env - Hydrogen environment with variables
709
+ * @param baseConfigs - Pre-fetched base configs to avoid duplicate calls
710
+ * @returns Resolved project ID string (empty string if none found)
711
+ */
712
+ resolveProjectIdSync(projectId, request, env, baseConfigs) {
713
+ return this.resolveFromQueryParams(request) || this.resolveFromFunction(projectId) || this.resolveFromString(projectId) || this.resolveFromEnvironment(baseConfigs, request, env) || "";
714
+ }
715
+ /**
716
+ * Priority 1: Resolve projectId from URL query parameters.
717
+ * Used for design mode and preview mode overrides.
718
+ */
719
+ resolveFromQueryParams(request) {
720
+ let queries = getRequestQueries(request);
721
+ return queries.weaverseProjectId || null;
722
+ }
723
+ /**
724
+ * Priority 2: Resolve projectId from function parameter.
725
+ * Detects and rejects async functions with helpful error.
726
+ */
727
+ resolveFromFunction(projectId) {
728
+ if (!isProjectIdFunction(projectId)) {
729
+ return null;
730
+ }
731
+ if (projectId.constructor.name === "AsyncFunction") {
732
+ throw new WeaverseError(
733
+ "Async projectId functions must be awaited before passing to WeaverseClient. Use: projectId: await getProjectAsync() instead of: projectId: getProjectAsync",
734
+ "ASYNC_PROJECT_ID"
735
+ );
736
+ }
567
737
  try {
568
- let response = await fetch(url, options);
738
+ let result = projectId();
739
+ if (result instanceof Promise) {
740
+ throw new WeaverseError(
741
+ "Async projectId functions must be awaited before passing to WeaverseClient. Use: projectId: await getProjectAsync() instead of: projectId: getProjectAsync",
742
+ "ASYNC_PROJECT_ID"
743
+ );
744
+ }
745
+ if (result && result.trim() !== "") {
746
+ let trimmed = result.trim();
747
+ let validation = this.validateProjectId(trimmed);
748
+ if (validation.valid) {
749
+ return trimmed;
750
+ }
751
+ throw new WeaverseError(
752
+ validation.error || "Invalid projectId format",
753
+ "INVALID_PROJECT_ID"
754
+ );
755
+ }
756
+ } catch (err) {
757
+ if (err instanceof WeaverseError) {
758
+ throw err;
759
+ }
760
+ throw new WeaverseError(
761
+ `Failed to evaluate projectId function: ${err instanceof Error ? err.message : String(err)}`,
762
+ "PROJECT_ID_FUNCTION_ERROR",
763
+ void 0,
764
+ { cause: err instanceof Error ? err.stack : String(err) }
765
+ );
766
+ }
767
+ return null;
768
+ }
769
+ /**
770
+ * Priority 3: Resolve projectId from explicit string parameter.
771
+ */
772
+ resolveFromString(projectId) {
773
+ if (typeof projectId !== "string") {
774
+ return null;
775
+ }
776
+ let trimmed = projectId.trim();
777
+ if (trimmed === "") {
778
+ return null;
779
+ }
780
+ let validation = this.validateProjectId(trimmed);
781
+ if (validation.valid) {
782
+ return trimmed;
783
+ }
784
+ throw new WeaverseError(
785
+ validation.error || "Invalid projectId format",
786
+ "INVALID_PROJECT_ID"
787
+ );
788
+ }
789
+ /**
790
+ * Priority 4: Resolve projectId from environment variables.
791
+ */
792
+ resolveFromEnvironment(baseConfigs, request, env) {
793
+ let configs = baseConfigs || getWeaverseConfigs(request, env);
794
+ if (configs.projectId && configs.projectId.trim() !== "") {
795
+ return configs.projectId.trim();
796
+ }
797
+ return null;
798
+ }
799
+ /**
800
+ * Helper method for direct fetching in design mode.
801
+ * Returns same format as withCache.fetch for consistency.
802
+ * Includes 10-second timeout to prevent hanging requests.
803
+ */
804
+ directFetch = async (url, options = {}, timeoutMs = this.fetchTimeoutMs) => {
805
+ let controller = new AbortController();
806
+ let timeoutId = setTimeout(
807
+ () => controller.abort(),
808
+ timeoutMs
809
+ );
810
+ try {
811
+ let response = await fetch(url, {
812
+ ...options,
813
+ signal: controller.signal
814
+ });
569
815
  if (!response.ok) {
570
- let error = await response.text();
571
- throw new Error(`${response.status} ${response.statusText} ${error}`);
816
+ let errorText = await response.text();
817
+ throw new WeaverseError(
818
+ `HTTP ${response.status}: ${response.statusText}`,
819
+ "FETCH_ERROR",
820
+ response.status,
821
+ { url, errorText }
822
+ );
572
823
  }
573
824
  let data = await response.json();
574
- return {
575
- data,
576
- response
577
- };
825
+ return { data, response };
578
826
  } catch (err) {
579
- throw new Error(`Failed to fetch data from ${url}`, { cause: err });
827
+ if (err instanceof WeaverseError) {
828
+ throw err;
829
+ }
830
+ if (err.name === "AbortError") {
831
+ throw new WeaverseError(
832
+ `Request timeout after ${timeoutMs}ms`,
833
+ "TIMEOUT_ERROR",
834
+ void 0,
835
+ { url, timeoutMs }
836
+ );
837
+ }
838
+ throw new WeaverseError(
839
+ "Network error during fetch",
840
+ "NETWORK_ERROR",
841
+ void 0,
842
+ { url, cause: err instanceof Error ? err.message : String(err) }
843
+ );
844
+ } finally {
845
+ if (timeoutId !== void 0) {
846
+ clearTimeout(timeoutId);
847
+ }
580
848
  }
581
849
  };
582
850
  // Helper method to detect if request is from localhost
583
851
  isLocalhost() {
584
- try {
585
- let url = new URL(this.request.url);
586
- return url.hostname === "localhost" || url.hostname === "127.0.0.1";
587
- } catch {
588
- return false;
589
- }
852
+ let hostname = this.parsedUrl.hostname;
853
+ return hostname === "localhost" || hostname === "127.0.0.1";
590
854
  }
591
855
  // Helper method for building API URLs consistently
592
856
  getApiUrl(endpoint, useProxy = !(this.configs.isDesignMode || this.isLocalhost())) {
@@ -598,7 +862,13 @@ var WeaverseClient = class {
598
862
  }
599
863
  fetchWithCache = async (url, options = {}) => {
600
864
  const strategy = options.strategy || this.storefront.CacheCustom(DEFAULT_CACHE_STRATEGY);
601
- const cacheKey = [url, options.method || "GET", options.body];
865
+ const cacheKey = [
866
+ "weaverse-fetch",
867
+ url,
868
+ options.method || "GET",
869
+ options.body,
870
+ this.configs.projectId
871
+ ];
602
872
  let result;
603
873
  if (this.configs.isDesignMode) {
604
874
  result = await this.directFetch(url, options);
@@ -678,9 +948,15 @@ var WeaverseClient = class {
678
948
  };
679
949
  }
680
950
  return data;
681
- } catch (e) {
682
- console.info("Unable to load theme settings", e);
683
- return { theme: defaultThemeSettings };
951
+ } catch (error) {
952
+ let errorMessage = "Unable to load theme settings";
953
+ let errorDetails = this.extractErrorMessage(error);
954
+ console.error(errorMessage, errorDetails);
955
+ return {
956
+ theme: defaultThemeSettings,
957
+ _error: errorDetails,
958
+ _loadFailed: true
959
+ };
684
960
  }
685
961
  };
686
962
  generateFallbackPage = (message) => {
@@ -701,16 +977,39 @@ var WeaverseClient = class {
701
977
  loadPage = async (params = {}) => {
702
978
  try {
703
979
  let { request, storefront, basePageRequestBody, basePageConfigs } = this;
704
- let { projectId, weaverseHost, isPreviewMode, sectionType } = this.configs;
980
+ let {
981
+ projectId: clientProjectId,
982
+ weaverseHost,
983
+ isPreviewMode,
984
+ sectionType
985
+ } = this.configs;
986
+ if (params.projectId !== void 0) {
987
+ if (typeof params.projectId !== "string") {
988
+ console.error(
989
+ `Route-level projectId validation failed: must be a string. Received: ${typeof params.projectId}`
990
+ );
991
+ return null;
992
+ }
993
+ let validation = this.validateProjectId(params.projectId);
994
+ if (!validation.valid) {
995
+ console.error(
996
+ `Route-level projectId validation failed: ${validation.error}`
997
+ );
998
+ return null;
999
+ }
1000
+ }
1001
+ let effectiveProjectId = params.projectId || clientProjectId;
705
1002
  if (isPreviewMode) {
706
1003
  return getPreviewData(sectionType || "", this.components, weaverseHost);
707
1004
  }
708
- if (!projectId) {
1005
+ if (!effectiveProjectId) {
709
1006
  throw new Error("Missing Weaverse projectId!");
710
1007
  }
711
1008
  let { strategy, ...pageLoadParams } = params;
712
1009
  let body = {
713
1010
  ...basePageRequestBody,
1011
+ projectId: effectiveProjectId,
1012
+ // Use effective (potentially overridden) projectId
714
1013
  params: pageLoadParams,
715
1014
  url: request.url
716
1015
  };
@@ -731,11 +1030,27 @@ var WeaverseClient = class {
731
1030
  if (hasError(projectData)) {
732
1031
  throw new Error(projectData.error);
733
1032
  }
734
- let { page, project, pageAssignment } = projectData;
1033
+ let page;
1034
+ let project;
1035
+ let pageAssignment;
1036
+ if (isFetchProjectPayload(projectData)) {
1037
+ page = projectData.page;
1038
+ project = projectData.project;
1039
+ pageAssignment = projectData.pageAssignment;
1040
+ } else {
1041
+ console.warn(
1042
+ "Invalid project data structure received from API, using fallback data",
1043
+ { projectId: effectiveProjectId }
1044
+ );
1045
+ let responseData = projectData;
1046
+ page = responseData?.page;
1047
+ project = responseData?.project;
1048
+ pageAssignment = responseData?.pageAssignment;
1049
+ }
735
1050
  if (!project) {
736
- console.warn("Weaverse project not found. Id:", projectId);
1051
+ console.warn("Weaverse project not found. Id:", effectiveProjectId);
737
1052
  project = {
738
- id: projectId,
1053
+ id: effectiveProjectId,
739
1054
  name: "Weaverse project not found.",
740
1055
  weaverseShopId: ""
741
1056
  };
@@ -756,19 +1071,42 @@ var WeaverseClient = class {
756
1071
  requestInfo: {
757
1072
  i18n: storefront.i18n,
758
1073
  queries: getRequestQueries(request),
759
- pathname: new URL(request.url).pathname,
760
- search: new URL(request.url).search
1074
+ pathname: this.parsedUrl.pathname,
1075
+ search: this.parsedUrl.search
761
1076
  }
762
1077
  }
763
1078
  };
764
- } catch (e) {
765
- console.error("\u274C Page load failed.", e);
1079
+ } catch (error) {
1080
+ let errorMessage = "\u274C Page load failed";
1081
+ let errorContext = {
1082
+ url: this.request.url,
1083
+ projectId: params.projectId || this.configs.projectId
1084
+ };
1085
+ if (error instanceof WeaverseError) {
1086
+ console.error(errorMessage, {
1087
+ code: error.code,
1088
+ message: error.message,
1089
+ ...errorContext,
1090
+ ...error.context
1091
+ });
1092
+ } else if (error instanceof Error) {
1093
+ console.error(errorMessage, {
1094
+ message: error.message,
1095
+ stack: error.stack,
1096
+ ...errorContext
1097
+ });
1098
+ } else {
1099
+ console.error(errorMessage, {
1100
+ error: String(error),
1101
+ ...errorContext
1102
+ });
1103
+ }
766
1104
  return null;
767
1105
  }
768
1106
  };
769
1107
  execComponentLoader = async (item) => {
770
1108
  let { data = {}, type, id } = item;
771
- let component = this.components?.find(({ schema: schema2 }) => schema2?.type === type);
1109
+ let component = this.componentsByType.get(type);
772
1110
  let loader = component?.loader;
773
1111
  if (typeof loader === "function" && component) {
774
1112
  try {
@@ -781,8 +1119,8 @@ var WeaverseClient = class {
781
1119
  })
782
1120
  )
783
1121
  };
784
- } catch (e) {
785
- console.warn("\u274C Item loader run failed.", type, id, e);
1122
+ } catch (error) {
1123
+ console.warn("\u274C Item loader run failed.", type, id, error);
786
1124
  return item;
787
1125
  }
788
1126
  }
@@ -868,6 +1206,7 @@ exports.getSelectedProductOptions = getSelectedProductOptions;
868
1206
  exports.getWeaverseConfigs = getWeaverseConfigs;
869
1207
  exports.hasError = hasError;
870
1208
  exports.isFetchProjectPayload = isFetchProjectPayload;
1209
+ exports.isProjectIdFunction = isProjectIdFunction;
871
1210
  exports.isThemeSettingsResponse = isThemeSettingsResponse;
872
1211
  exports.isValidHydrogenSchema = isValidHydrogenSchema;
873
1212
  exports.isWithCacheFetchResponse = isWithCacheFetchResponse;