@weaverse/hydrogen 5.7.1 → 5.8.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.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,67 @@ 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
+ const baseConfigs = getWeaverseConfigs(
594
+ args.request,
595
+ args.env
596
+ );
597
+ const resolvedProjectId = this.resolveProjectIdSync(
598
+ args.projectId,
599
+ args.request,
600
+ args.env,
601
+ baseConfigs
602
+ );
603
+ if (!resolvedProjectId || resolvedProjectId.trim() === "") {
604
+ throw new WeaverseError(
605
+ "Failed to initialize WeaverseClient: No valid projectId found. Set WEAVERSE_PROJECT_ID environment variable or provide projectId parameter.",
606
+ "MISSING_PROJECT_ID"
607
+ );
608
+ }
609
+ this.configs = {
610
+ ...baseConfigs,
611
+ projectId: resolvedProjectId
612
+ };
551
613
  this.basePageConfigs = {
552
614
  projectId: this.configs.projectId,
553
615
  weaverseHost: this.configs.weaverseHost,
@@ -558,35 +620,240 @@ var WeaverseClient = class {
558
620
  };
559
621
  this.basePageRequestBody = {
560
622
  isDesignMode: this.configs.isDesignMode,
561
- i18n: storefront.i18n,
623
+ i18n: args.storefront.i18n,
562
624
  projectId: this.configs.projectId
563
625
  };
626
+ Object.freeze(this.configs);
627
+ Object.freeze(this.basePageConfigs);
628
+ Object.freeze(this.basePageRequestBody);
629
+ }
630
+ /**
631
+ * Build component lookup map for O(1) access by type.
632
+ * Significantly improves performance for large component lists.
633
+ */
634
+ buildComponentLookupMap(components) {
635
+ return new Map(components.map((comp) => [comp.schema?.type, comp]));
636
+ }
637
+ /**
638
+ * Extract comprehensive error information from unknown error type.
639
+ * Preserves error context, codes, and stack traces for debugging.
640
+ *
641
+ * @param error - Unknown error to extract information from
642
+ * @returns Structured error information with message, code, stack, and context
643
+ *
644
+ * @example
645
+ * ```typescript
646
+ * try {
647
+ * // ... operation
648
+ * } catch (error) {
649
+ * const errorInfo = this.extractErrorInfo(error)
650
+ * console.error('Operation failed:', errorInfo.message, errorInfo.context)
651
+ * }
652
+ * ```
653
+ */
654
+ extractErrorInfo(error) {
655
+ if (error instanceof WeaverseError) {
656
+ return {
657
+ message: error.message,
658
+ code: error.code,
659
+ context: error.context,
660
+ stack: error.stack
661
+ };
662
+ }
663
+ if (error instanceof Error) {
664
+ return {
665
+ message: error.message,
666
+ stack: error.stack
667
+ };
668
+ }
669
+ return {
670
+ message: String(error)
671
+ };
672
+ }
673
+ /**
674
+ * Extract error message only (for backward compatibility).
675
+ * Use extractErrorInfo() for more detailed error information.
676
+ *
677
+ * @deprecated Use extractErrorInfo() instead to preserve error context
678
+ */
679
+ extractErrorMessage(error) {
680
+ return this.extractErrorInfo(error).message;
681
+ }
682
+ /**
683
+ * Validates projectId format (alphanumeric, hyphens, underscores only).
684
+ * Returns detailed validation result with error message.
685
+ *
686
+ * @param projectId - Project identifier to validate
687
+ * @returns Validation result with error message if invalid
688
+ */
689
+ validateProjectId(projectId) {
690
+ if (!projectId || projectId.trim() === "") {
691
+ return {
692
+ valid: false,
693
+ error: "Project ID cannot be empty"
694
+ };
695
+ }
696
+ const validPattern = /^[a-zA-Z0-9_-]+$/;
697
+ if (!validPattern.test(projectId)) {
698
+ return {
699
+ valid: false,
700
+ error: `Invalid format: "${projectId}". Only alphanumeric characters, hyphens, and underscores are allowed.`
701
+ };
702
+ }
703
+ return { valid: true };
704
+ }
705
+ /**
706
+ * Resolves projectId with multi-project architecture support.
707
+ * Uses priority chain to determine the correct project ID.
708
+ *
709
+ * @param projectId - Project identifier (string, function, or undefined)
710
+ * @param request - HTTP request for context access
711
+ * @param env - Hydrogen environment with variables
712
+ * @param baseConfigs - Pre-fetched base configs to avoid duplicate calls
713
+ * @returns Resolved project ID string (empty string if none found)
714
+ */
715
+ resolveProjectIdSync(projectId, request, env, baseConfigs) {
716
+ return this.resolveFromQueryParams(request) || this.resolveFromFunction(projectId) || this.resolveFromString(projectId) || this.resolveFromEnvironment(baseConfigs, request, env) || "";
717
+ }
718
+ /**
719
+ * Priority 1: Resolve projectId from URL query parameters.
720
+ * Used for design mode and preview mode overrides.
721
+ */
722
+ resolveFromQueryParams(request) {
723
+ const queries = getRequestQueries(request);
724
+ return queries.weaverseProjectId || null;
725
+ }
726
+ /**
727
+ * Priority 2: Resolve projectId from function parameter.
728
+ * Detects and rejects async functions with helpful error.
729
+ */
730
+ resolveFromFunction(projectId) {
731
+ if (!isProjectIdFunction(projectId)) {
732
+ return null;
733
+ }
734
+ if (projectId.constructor.name === "AsyncFunction") {
735
+ throw new WeaverseError(
736
+ "Async projectId functions must be awaited before passing to WeaverseClient. Use: projectId: await getProjectAsync() instead of: projectId: getProjectAsync",
737
+ "ASYNC_PROJECT_ID"
738
+ );
739
+ }
740
+ try {
741
+ const result = projectId();
742
+ if (result instanceof Promise) {
743
+ throw new WeaverseError(
744
+ "Async projectId functions must be awaited before passing to WeaverseClient. Use: projectId: await getProjectAsync() instead of: projectId: getProjectAsync",
745
+ "ASYNC_PROJECT_ID"
746
+ );
747
+ }
748
+ if (result && result.trim() !== "") {
749
+ const trimmed = result.trim();
750
+ const validation = this.validateProjectId(trimmed);
751
+ if (validation.valid) {
752
+ return trimmed;
753
+ }
754
+ throw new WeaverseError(
755
+ validation.error || "Invalid projectId format",
756
+ "INVALID_PROJECT_ID"
757
+ );
758
+ }
759
+ } catch (err) {
760
+ if (err instanceof WeaverseError) {
761
+ throw err;
762
+ }
763
+ throw new WeaverseError(
764
+ `Failed to evaluate projectId function: ${err instanceof Error ? err.message : String(err)}`,
765
+ "PROJECT_ID_FUNCTION_ERROR",
766
+ void 0,
767
+ { cause: err instanceof Error ? err.stack : String(err) }
768
+ );
769
+ }
770
+ return null;
771
+ }
772
+ /**
773
+ * Priority 3: Resolve projectId from explicit string parameter.
774
+ */
775
+ resolveFromString(projectId) {
776
+ if (typeof projectId !== "string") {
777
+ return null;
778
+ }
779
+ const trimmed = projectId.trim();
780
+ if (trimmed === "") {
781
+ return null;
782
+ }
783
+ const validation = this.validateProjectId(trimmed);
784
+ if (validation.valid) {
785
+ return trimmed;
786
+ }
787
+ throw new WeaverseError(
788
+ validation.error || "Invalid projectId format",
789
+ "INVALID_PROJECT_ID"
790
+ );
564
791
  }
565
- // Helper method for direct fetching in design mode - returns same format as withCache.fetch
566
- directFetch = async (url, options = {}) => {
792
+ /**
793
+ * Priority 4: Resolve projectId from environment variables.
794
+ */
795
+ resolveFromEnvironment(baseConfigs, request, env) {
796
+ const configs = baseConfigs || getWeaverseConfigs(request, env);
797
+ if (configs.projectId && configs.projectId.trim() !== "") {
798
+ return configs.projectId.trim();
799
+ }
800
+ return null;
801
+ }
802
+ /**
803
+ * Helper method for direct fetching in design mode.
804
+ * Returns same format as withCache.fetch for consistency.
805
+ * Includes 10-second timeout to prevent hanging requests.
806
+ */
807
+ directFetch = async (url, options = {}, timeoutMs = this.fetchTimeoutMs) => {
808
+ const controller = new AbortController();
809
+ const timeoutId = setTimeout(
810
+ () => controller.abort(),
811
+ timeoutMs
812
+ );
567
813
  try {
568
- let response = await fetch(url, options);
814
+ const response = await fetch(url, {
815
+ ...options,
816
+ signal: controller.signal
817
+ });
569
818
  if (!response.ok) {
570
- let error = await response.text();
571
- throw new Error(`${response.status} ${response.statusText} ${error}`);
819
+ const errorText = await response.text();
820
+ throw new WeaverseError(
821
+ `HTTP ${response.status}: ${response.statusText}`,
822
+ "FETCH_ERROR",
823
+ response.status,
824
+ { url, errorText }
825
+ );
572
826
  }
573
- let data = await response.json();
574
- return {
575
- data,
576
- response
577
- };
827
+ const data = await response.json();
828
+ return { data, response };
578
829
  } catch (err) {
579
- throw new Error(`Failed to fetch data from ${url}`, { cause: err });
830
+ if (err instanceof WeaverseError) {
831
+ throw err;
832
+ }
833
+ if (err.name === "AbortError") {
834
+ throw new WeaverseError(
835
+ `Request timeout after ${timeoutMs}ms`,
836
+ "TIMEOUT_ERROR",
837
+ void 0,
838
+ { url, timeoutMs }
839
+ );
840
+ }
841
+ throw new WeaverseError(
842
+ "Network error during fetch",
843
+ "NETWORK_ERROR",
844
+ void 0,
845
+ { url, cause: err instanceof Error ? err.message : String(err) }
846
+ );
847
+ } finally {
848
+ if (timeoutId !== void 0) {
849
+ clearTimeout(timeoutId);
850
+ }
580
851
  }
581
852
  };
582
853
  // Helper method to detect if request is from localhost
583
854
  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
- }
855
+ const hostname = this.parsedUrl.hostname;
856
+ return hostname === "localhost" || hostname === "127.0.0.1";
590
857
  }
591
858
  // Helper method for building API URLs consistently
592
859
  getApiUrl(endpoint, useProxy = !(this.configs.isDesignMode || this.isLocalhost())) {
@@ -597,8 +864,14 @@ var WeaverseClient = class {
597
864
  return `${weaverseHost}/api/public/${endpoint}`;
598
865
  }
599
866
  fetchWithCache = async (url, options = {}) => {
600
- const strategy = options.strategy || this.storefront.CacheCustom(DEFAULT_CACHE_STRATEGY);
601
- const cacheKey = [url, options.method || "GET", options.body];
867
+ const strategy = options.strategy || hydrogen.CacheCustom(DEFAULT_CACHE_STRATEGY);
868
+ const cacheKey = [
869
+ "weaverse-fetch",
870
+ url,
871
+ options.method || "GET",
872
+ options.body,
873
+ this.configs.projectId
874
+ ];
602
875
  let result;
603
876
  if (this.configs.isDesignMode) {
604
877
  result = await this.directFetch(url, options);
@@ -615,15 +888,15 @@ var WeaverseClient = class {
615
888
  return result.data;
616
889
  };
617
890
  loadThemeSettings = async (strategy) => {
618
- let defaultThemeSettings = generateDataFromSchema(this.themeSchema);
891
+ const defaultThemeSettings = generateDataFromSchema(this.themeSchema);
619
892
  try {
620
- let { configs } = this;
621
- let { projectId, isDesignMode } = configs;
893
+ const { configs } = this;
894
+ const { projectId, isDesignMode } = configs;
622
895
  if (!projectId) {
623
896
  throw new Error("Missing Weaverse projectId!");
624
897
  }
625
- let url = this.getApiUrl("project_configs");
626
- let body = JSON.stringify({ isDesignMode, projectId });
898
+ const url = this.getApiUrl("project_configs");
899
+ const body = JSON.stringify({ isDesignMode, projectId });
627
900
  let data = await this.fetchWithCache(url, {
628
901
  method: "POST",
629
902
  strategy,
@@ -678,13 +951,19 @@ var WeaverseClient = class {
678
951
  };
679
952
  }
680
953
  return data;
681
- } catch (e) {
682
- console.info("Unable to load theme settings", e);
683
- return { theme: defaultThemeSettings };
954
+ } catch (error) {
955
+ const errorMessage = "Unable to load theme settings";
956
+ const errorDetails = this.extractErrorMessage(error);
957
+ console.error(errorMessage, errorDetails);
958
+ return {
959
+ theme: defaultThemeSettings,
960
+ _error: errorDetails,
961
+ _loadFailed: true
962
+ };
684
963
  }
685
964
  };
686
965
  generateFallbackPage = (message) => {
687
- let rootId = crypto.randomUUID();
966
+ const rootId = crypto.randomUUID();
688
967
  return {
689
968
  id: `fallback_page_${Date.now()}`,
690
969
  rootId,
@@ -700,21 +979,44 @@ var WeaverseClient = class {
700
979
  };
701
980
  loadPage = async (params = {}) => {
702
981
  try {
703
- let { request, storefront, basePageRequestBody, basePageConfigs } = this;
704
- let { projectId, weaverseHost, isPreviewMode, sectionType } = this.configs;
982
+ const { request, storefront, basePageRequestBody, basePageConfigs } = this;
983
+ const {
984
+ projectId: clientProjectId,
985
+ weaverseHost,
986
+ isPreviewMode,
987
+ sectionType
988
+ } = this.configs;
989
+ if (params.projectId !== void 0) {
990
+ if (typeof params.projectId !== "string") {
991
+ console.error(
992
+ `Route-level projectId validation failed: must be a string. Received: ${typeof params.projectId}`
993
+ );
994
+ return null;
995
+ }
996
+ const validation = this.validateProjectId(params.projectId);
997
+ if (!validation.valid) {
998
+ console.error(
999
+ `Route-level projectId validation failed: ${validation.error}`
1000
+ );
1001
+ return null;
1002
+ }
1003
+ }
1004
+ const effectiveProjectId = params.projectId || clientProjectId;
705
1005
  if (isPreviewMode) {
706
1006
  return getPreviewData(sectionType || "", this.components, weaverseHost);
707
1007
  }
708
- if (!projectId) {
1008
+ if (!effectiveProjectId) {
709
1009
  throw new Error("Missing Weaverse projectId!");
710
1010
  }
711
- let { strategy, ...pageLoadParams } = params;
712
- let body = {
1011
+ const { strategy, ...pageLoadParams } = params;
1012
+ const body = {
713
1013
  ...basePageRequestBody,
1014
+ projectId: effectiveProjectId,
1015
+ // Use effective (potentially overridden) projectId
714
1016
  params: pageLoadParams,
715
1017
  url: request.url
716
1018
  };
717
- let reqInit = {
1019
+ const reqInit = {
718
1020
  method: "POST",
719
1021
  body: JSON.stringify(body),
720
1022
  headers: {
@@ -723,19 +1025,36 @@ var WeaverseClient = class {
723
1025
  "Accept-Encoding": "gzip, deflate, br"
724
1026
  }
725
1027
  };
726
- let url = this.getApiUrl("project");
727
- let projectData = await this.fetchWithCache(url, {
1028
+ const url = this.getApiUrl("project");
1029
+ const projectData = await this.fetchWithCache(url, {
728
1030
  ...reqInit,
729
1031
  strategy
730
1032
  });
731
1033
  if (hasError(projectData)) {
732
1034
  throw new Error(projectData.error);
733
1035
  }
734
- let { page, project, pageAssignment } = projectData;
1036
+ console.log("projectData", projectData);
1037
+ let page;
1038
+ let project;
1039
+ let pageAssignment;
1040
+ if (isFetchProjectPayload(projectData)) {
1041
+ page = projectData.page;
1042
+ project = projectData.project;
1043
+ pageAssignment = projectData.pageAssignment;
1044
+ } else {
1045
+ console.warn(
1046
+ "Invalid project data structure received from API, using fallback data",
1047
+ { projectId: effectiveProjectId }
1048
+ );
1049
+ const responseData = projectData;
1050
+ page = responseData?.page;
1051
+ project = responseData?.project;
1052
+ pageAssignment = responseData?.pageAssignment;
1053
+ }
735
1054
  if (!project) {
736
- console.warn("Weaverse project not found. Id:", projectId);
1055
+ console.warn("Weaverse project not found. Id:", effectiveProjectId);
737
1056
  project = {
738
- id: projectId,
1057
+ id: effectiveProjectId,
739
1058
  name: "Weaverse project not found.",
740
1059
  weaverseShopId: ""
741
1060
  };
@@ -744,7 +1063,7 @@ var WeaverseClient = class {
744
1063
  page = this.generateFallbackPage("Please add new section to start.");
745
1064
  }
746
1065
  if (page?.items) {
747
- let items = page.items;
1066
+ const items = page.items;
748
1067
  page.items = await Promise.all(items.map(this.execComponentLoader));
749
1068
  }
750
1069
  return {
@@ -756,20 +1075,43 @@ var WeaverseClient = class {
756
1075
  requestInfo: {
757
1076
  i18n: storefront.i18n,
758
1077
  queries: getRequestQueries(request),
759
- pathname: new URL(request.url).pathname,
760
- search: new URL(request.url).search
1078
+ pathname: this.parsedUrl.pathname,
1079
+ search: this.parsedUrl.search
761
1080
  }
762
1081
  }
763
1082
  };
764
- } catch (e) {
765
- console.error("\u274C Page load failed.", e);
1083
+ } catch (error) {
1084
+ const errorMessage = "\u274C Page load failed";
1085
+ const errorContext = {
1086
+ url: this.request.url,
1087
+ projectId: params.projectId || this.configs.projectId
1088
+ };
1089
+ if (error instanceof WeaverseError) {
1090
+ console.error(errorMessage, {
1091
+ code: error.code,
1092
+ message: error.message,
1093
+ ...errorContext,
1094
+ ...error.context
1095
+ });
1096
+ } else if (error instanceof Error) {
1097
+ console.error(errorMessage, {
1098
+ message: error.message,
1099
+ stack: error.stack,
1100
+ ...errorContext
1101
+ });
1102
+ } else {
1103
+ console.error(errorMessage, {
1104
+ error: String(error),
1105
+ ...errorContext
1106
+ });
1107
+ }
766
1108
  return null;
767
1109
  }
768
1110
  };
769
1111
  execComponentLoader = async (item) => {
770
- let { data = {}, type, id } = item;
771
- let component = this.components?.find(({ schema: schema2 }) => schema2?.type === type);
772
- let loader = component?.loader;
1112
+ const { data = {}, type, id } = item;
1113
+ const component = this.componentsByType.get(type);
1114
+ const loader = component?.loader;
773
1115
  if (typeof loader === "function" && component) {
774
1116
  try {
775
1117
  return {
@@ -781,8 +1123,8 @@ var WeaverseClient = class {
781
1123
  })
782
1124
  )
783
1125
  };
784
- } catch (e) {
785
- console.warn("\u274C Item loader run failed.", type, id, e);
1126
+ } catch (error) {
1127
+ console.warn("\u274C Item loader run failed.", type, id, error);
786
1128
  return item;
787
1129
  }
788
1130
  }
@@ -868,6 +1210,7 @@ exports.getSelectedProductOptions = getSelectedProductOptions;
868
1210
  exports.getWeaverseConfigs = getWeaverseConfigs;
869
1211
  exports.hasError = hasError;
870
1212
  exports.isFetchProjectPayload = isFetchProjectPayload;
1213
+ exports.isProjectIdFunction = isProjectIdFunction;
871
1214
  exports.isThemeSettingsResponse = isThemeSettingsResponse;
872
1215
  exports.isValidHydrogenSchema = isValidHydrogenSchema;
873
1216
  exports.isWithCacheFetchResponse = isWithCacheFetchResponse;