@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.d.mts +366 -20
- package/dist/index.d.ts +366 -20
- package/dist/index.js +439 -96
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +442 -100
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -3
- package/readme.md +91 -1
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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:
|
|
505
|
-
sMaxAge:
|
|
506
|
-
staleWhileRevalidate:
|
|
507
|
-
|
|
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
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
this.
|
|
538
|
-
this.
|
|
539
|
-
this.
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
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
|
-
|
|
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
|
-
|
|
566
|
-
|
|
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
|
-
|
|
814
|
+
const response = await fetch(url, {
|
|
815
|
+
...options,
|
|
816
|
+
signal: controller.signal
|
|
817
|
+
});
|
|
569
818
|
if (!response.ok) {
|
|
570
|
-
|
|
571
|
-
throw new
|
|
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
|
-
|
|
574
|
-
return {
|
|
575
|
-
data,
|
|
576
|
-
response
|
|
577
|
-
};
|
|
827
|
+
const data = await response.json();
|
|
828
|
+
return { data, response };
|
|
578
829
|
} catch (err) {
|
|
579
|
-
|
|
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
|
-
|
|
585
|
-
|
|
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 ||
|
|
601
|
-
const cacheKey = [
|
|
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
|
-
|
|
891
|
+
const defaultThemeSettings = generateDataFromSchema(this.themeSchema);
|
|
619
892
|
try {
|
|
620
|
-
|
|
621
|
-
|
|
893
|
+
const { configs } = this;
|
|
894
|
+
const { projectId, isDesignMode } = configs;
|
|
622
895
|
if (!projectId) {
|
|
623
896
|
throw new Error("Missing Weaverse projectId!");
|
|
624
897
|
}
|
|
625
|
-
|
|
626
|
-
|
|
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 (
|
|
682
|
-
|
|
683
|
-
|
|
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
|
-
|
|
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
|
-
|
|
704
|
-
|
|
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 (!
|
|
1008
|
+
if (!effectiveProjectId) {
|
|
709
1009
|
throw new Error("Missing Weaverse projectId!");
|
|
710
1010
|
}
|
|
711
|
-
|
|
712
|
-
|
|
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
|
-
|
|
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
|
-
|
|
727
|
-
|
|
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
|
-
|
|
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:",
|
|
1055
|
+
console.warn("Weaverse project not found. Id:", effectiveProjectId);
|
|
737
1056
|
project = {
|
|
738
|
-
id:
|
|
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
|
-
|
|
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:
|
|
760
|
-
search:
|
|
1078
|
+
pathname: this.parsedUrl.pathname,
|
|
1079
|
+
search: this.parsedUrl.search
|
|
761
1080
|
}
|
|
762
1081
|
}
|
|
763
1082
|
};
|
|
764
|
-
} catch (
|
|
765
|
-
|
|
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
|
-
|
|
771
|
-
|
|
772
|
-
|
|
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 (
|
|
785
|
-
console.warn("\u274C Item loader run failed.", type, id,
|
|
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;
|