@onexapis/cli 1.1.65 → 1.1.66

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.
@@ -130,6 +130,77 @@ try {
130
130
  // CommerceClient not available — safe to ignore
131
131
  }
132
132
 
133
+ // Fetch website settings once at startup for PageDataProvider.
134
+ // Cache in sessionStorage so full-page navigations don't re-fetch.
135
+ const WS_CACHE_KEY = "onex_website_settings";
136
+ let _websiteSettings: Record<string, unknown> = {};
137
+ let _settingsReady: Promise<void>;
138
+ {
139
+ // Restore from sessionStorage first (instant, no network)
140
+ try {
141
+ const raw = sessionStorage.getItem(WS_CACHE_KEY);
142
+ if (raw) _websiteSettings = JSON.parse(raw);
143
+ } catch {
144
+ /* ignore */
145
+ }
146
+
147
+ let resolve: () => void;
148
+ _settingsReady = new Promise<void>((r) => {
149
+ resolve = r;
150
+ });
151
+
152
+ if (Object.keys(_websiteSettings).length > 0) {
153
+ // Already have cached settings — skip fetch
154
+ resolve!();
155
+ } else {
156
+ // No cache — fetch from API
157
+ (async () => {
158
+ try {
159
+ const { getCommerceClient } = coreCommerce as any;
160
+ const client = getCommerceClient?.();
161
+ if (client?.getSettings) {
162
+ _websiteSettings = (await client.getSettings()) || {};
163
+ try {
164
+ sessionStorage.setItem(
165
+ WS_CACHE_KEY,
166
+ JSON.stringify(_websiteSettings)
167
+ );
168
+ } catch {
169
+ /* ignore */
170
+ }
171
+ }
172
+ } catch {
173
+ /* no-op */
174
+ }
175
+ resolve!();
176
+ })();
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Normalize ./assets/ → /assets/ so relative paths work on nested routes.
182
+ * Same logic as storefront's section-renderer.tsx.
183
+ */
184
+ function normalizeAssetPaths<T>(value: T): T {
185
+ if (typeof value === "string") {
186
+ if (value.startsWith("./assets/")) {
187
+ return value.replace(/^\.\/assets\//, "/assets/") as unknown as T;
188
+ }
189
+ return value;
190
+ }
191
+ if (Array.isArray(value)) {
192
+ return value.map(normalizeAssetPaths) as unknown as T;
193
+ }
194
+ if (value !== null && typeof value === "object") {
195
+ const result: Record<string, unknown> = {};
196
+ for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
197
+ result[k] = normalizeAssetPaths(v);
198
+ }
199
+ return result as T;
200
+ }
201
+ return value;
202
+ }
203
+
133
204
  // ===== 2. THEME LOADING =====
134
205
 
135
206
  interface ThemeExports {
@@ -454,6 +525,8 @@ function getInitialPageFromURL(
454
525
  function PreviewApp() {
455
526
  const [themeExports, setThemeExports] = useState<ThemeExports | null>(null);
456
527
  const [selectedPage, setSelectedPage] = useState(-1); // -1 = not yet resolved from URL
528
+ const [wsSettings, setWsSettings] =
529
+ useState<Record<string, unknown>>(_websiteSettings);
457
530
  const [wsStatus, setWsStatus] = useState<
458
531
  "connected" | "disconnected" | "rebuilding"
459
532
  >("disconnected");
@@ -485,6 +558,15 @@ function PreviewApp() {
485
558
  loadTheme();
486
559
  }, [loadTheme]);
487
560
 
561
+ // Resolve website settings from async startup fetch
562
+ useEffect(() => {
563
+ _settingsReady.then(() => {
564
+ if (Object.keys(_websiteSettings).length > 0) {
565
+ setWsSettings(_websiteSettings);
566
+ }
567
+ });
568
+ }, []);
569
+
488
570
  // Handle browser back/forward navigation
489
571
  useEffect(() => {
490
572
  const handlePopState = () => {
@@ -663,7 +745,7 @@ function PreviewApp() {
663
745
  page: currentPage.config,
664
746
  products: [],
665
747
  blogs: [],
666
- settings: {},
748
+ settings: wsSettings,
667
749
  routeParams,
668
750
  locale: urlLocale,
669
751
  };
@@ -707,10 +789,12 @@ function PreviewApp() {
707
789
  );
708
790
  }
709
791
  const { Component, schema, template } = registration;
792
+ // Normalize ./assets/ → /assets/ so relative paths work on nested routes
793
+ const normalizedSection = normalizeAssetPaths(section);
710
794
  return (
711
795
  <Component
712
796
  key={section.id}
713
- section={section}
797
+ section={normalizedSection}
714
798
  schema={schema}
715
799
  template={template}
716
800
  isEditing={isEditing}
@@ -720,7 +804,7 @@ function PreviewApp() {
720
804
  };
721
805
 
722
806
  return (
723
- <>
807
+ <PageDataProvider data={{ websiteSettings: wsSettings }}>
724
808
  {/* Inject theme CSS variables (Gap 2) */}
725
809
  {themeCSS && <style dangerouslySetInnerHTML={{ __html: themeCSS }} />}
726
810
 
@@ -740,7 +824,7 @@ function PreviewApp() {
740
824
  !currentPage.config?.metadata?.hideFooter && (
741
825
  <footer>{footerSections.map(renderSection)}</footer>
742
826
  )}
743
- </>
827
+ </PageDataProvider>
744
828
  );
745
829
  }
746
830
 
@@ -764,9 +848,7 @@ root.render(
764
848
  <LocaleProvider locale={_rootLocale as any}>
765
849
  <CartProvider>
766
850
  <FlyToCartProvider>
767
- <PageDataProvider data={{}}>
768
- <PreviewApp />
769
- </PageDataProvider>
851
+ <PreviewApp />
770
852
  </FlyToCartProvider>
771
853
  </CartProvider>
772
854
  </LocaleProvider>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onexapis/cli",
3
- "version": "1.1.65",
3
+ "version": "1.1.66",
4
4
  "description": "CLI tool for OneX theme development - scaffolds themes using @onexapis/core",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -49,7 +49,7 @@
49
49
  "registry": "https://registry.npmjs.org/"
50
50
  },
51
51
  "dependencies": {
52
- "@onexapis/core": "^1.0.21",
52
+ "@onexapis/core": "^1.0.22",
53
53
  "@tanstack/react-query": "^5.90.16",
54
54
  "adm-zip": "^0.5.16",
55
55
  "archiver": "^7.0.1",