@weaverse/hydrogen 1.0.65 → 1.1.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
@@ -2,6 +2,7 @@ import React, { ForwardRefExoticComponent } from 'react';
2
2
  import { LoaderArgs, AppLoadContext } from '@shopify/remix-oxygen';
3
3
  import { ElementData, ElementSchema, BasicInput, WeaverseElement, Weaverse, WeaverseItemStore } from '@weaverse/react';
4
4
  export * from '@weaverse/react';
5
+ import * as _shopify_hydrogen_react_storefront_api_types from '@shopify/hydrogen-react/storefront-api-types';
5
6
 
6
7
  declare let STORE_PAGES: {
7
8
  INDEX: string;
@@ -69,10 +70,19 @@ interface HydrogenComponentProps<L = any> extends WeaverseElement {
69
70
  loaderData?: L;
70
71
  children?: React.JSX.Element[];
71
72
  }
73
+ type I18nLocale = {
74
+ country: string;
75
+ currency: string;
76
+ language: string;
77
+ label: string;
78
+ pathPrefix: string;
79
+ };
72
80
  type WeaverseLoaderRequestInfo = {
73
81
  params: any;
74
82
  pathname: string;
75
83
  search: string;
84
+ queries: Record<string, string | boolean>;
85
+ i18n: I18nLocale;
76
86
  };
77
87
  interface WeaverseHydrogen extends Omit<Weaverse, 'itemInstances' | 'elementInstances' | 'registerElement' | 'data'> {
78
88
  itemInstances: Map<string | number, HydrogenComponentInstance>;
@@ -103,6 +113,7 @@ type WeaverseInternal = {
103
113
  pageAssignment: HydrogenPageAssignment;
104
114
  project: HydrogenProjectType;
105
115
  navigate: NavigateFunction;
116
+ revalidator: TODO;
106
117
  };
107
118
  type HydrogenComponentPresets = {
108
119
  type: string;
@@ -128,7 +139,7 @@ interface HydrogenComponent<T extends HydrogenComponentProps = any> {
128
139
  type HydrogenPageConfigs = {
129
140
  projectId: string;
130
141
  weaverseHost: string;
131
- version?: string;
142
+ weaverseVersion?: string;
132
143
  isDesignMode?: boolean;
133
144
  requestInfo: WeaverseLoaderRequestInfo;
134
145
  [key: string]: any;
@@ -176,10 +187,13 @@ type NavigateOptions = {
176
187
  };
177
188
  type NavigateFunction = (to: To, options?: NavigateOptions) => void;
178
189
  interface WeaverseHydrogenRootProps {
179
- weaverseData: WeaverseLoaderData;
180
190
  components: HydrogenComponent[];
181
- themeSchema: HydrogenThemeSchema;
182
- navigate: NavigateFunction;
191
+ errorComponent: React.FC<{
192
+ error: {
193
+ message: string;
194
+ stack?: string;
195
+ };
196
+ }>;
183
197
  }
184
198
  type HydrogenThemeInfo = {
185
199
  name: string;
@@ -199,8 +213,13 @@ type WeaverseLoaderConfigs = {
199
213
  locale?: string;
200
214
  handle?: string;
201
215
  };
202
-
203
- declare function useThemeSettings(): (Record<string, any> | ((newSettings: any) => void))[];
216
+ declare global {
217
+ interface Window {
218
+ __weaverse: WeaverseHydrogen;
219
+ __weaverses: WeaverseHydrogen[];
220
+ __weaverseHydrogenThemeSchema: HydrogenThemeSchema;
221
+ }
222
+ }
204
223
 
205
224
  type FetchWithServerCacheParams = {
206
225
  url: string;
@@ -212,8 +231,17 @@ type FetchWithServerCacheParams = {
212
231
  */
213
232
  declare function fetchWithServerCache(params: FetchWithServerCacheParams): Promise<any>;
214
233
 
234
+ declare function useThemeSettings(): (Record<string, any> | ((newSettings: any) => void))[];
235
+
236
+ declare function getSelectedProductOptions(request: Request): _shopify_hydrogen_react_storefront_api_types.SelectedOptionInput[];
237
+
215
238
  declare function weaverseLoader(args: LoaderArgs, components: HydrogenComponent[], loaderConfigs?: WeaverseLoaderConfigs): Promise<WeaverseLoaderData | null>;
216
239
 
217
- declare function WeaverseHydrogenRoot(props: WeaverseHydrogenRootProps): React.JSX.Element;
240
+ type StudioProps = {
241
+ themeSchema: HydrogenThemeSchema;
242
+ };
243
+ declare function HydrogenStudio({ themeSchema }: StudioProps): React.JSX.Element | null;
244
+
245
+ declare function WeaverseHydrogenRoot({ components, errorComponent: ErrorComponent, }: WeaverseHydrogenRootProps): React.JSX.Element;
218
246
 
219
- export { HydrogenComponent, HydrogenComponentData, HydrogenComponentInstance, HydrogenComponentPresets, HydrogenComponentProps, HydrogenComponentSchema, HydrogenElement, HydrogenPageAssignment, HydrogenPageConfigs, HydrogenPageData, HydrogenProjectConfig, HydrogenProjectType, HydrogenThemeInfo, HydrogenThemeSchema, HydrogenToolbarAction, InspectorGroup, NavigateFunction, PageType, TODO, WeaverseHydrogen, WeaverseHydrogenRoot, WeaverseHydrogenRootProps, WeaverseInternal, WeaverseLoaderArgs, WeaverseLoaderConfigs, WeaverseLoaderData, WeaverseLoaderRequestInfo, WeaverseStorefrontData, fetchWithServerCache, useThemeSettings, weaverseLoader };
247
+ export { HydrogenComponent, HydrogenComponentData, HydrogenComponentInstance, HydrogenComponentPresets, HydrogenComponentProps, HydrogenComponentSchema, HydrogenElement, HydrogenPageAssignment, HydrogenPageConfigs, HydrogenPageData, HydrogenProjectConfig, HydrogenProjectType, HydrogenStudio, HydrogenThemeInfo, HydrogenThemeSchema, HydrogenToolbarAction, InspectorGroup, NavigateFunction, PageType, TODO, WeaverseHydrogen, WeaverseHydrogenRoot, WeaverseHydrogenRootProps, WeaverseInternal, WeaverseLoaderArgs, WeaverseLoaderConfigs, WeaverseLoaderData, WeaverseLoaderRequestInfo, WeaverseStorefrontData, fetchWithServerCache, getSelectedProductOptions, useThemeSettings, weaverseLoader };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import React, { ForwardRefExoticComponent } from 'react';
2
2
  import { LoaderArgs, AppLoadContext } from '@shopify/remix-oxygen';
3
3
  import { ElementData, ElementSchema, BasicInput, WeaverseElement, Weaverse, WeaverseItemStore } from '@weaverse/react';
4
4
  export * from '@weaverse/react';
5
+ import * as _shopify_hydrogen_react_storefront_api_types from '@shopify/hydrogen-react/storefront-api-types';
5
6
 
6
7
  declare let STORE_PAGES: {
7
8
  INDEX: string;
@@ -69,10 +70,19 @@ interface HydrogenComponentProps<L = any> extends WeaverseElement {
69
70
  loaderData?: L;
70
71
  children?: React.JSX.Element[];
71
72
  }
73
+ type I18nLocale = {
74
+ country: string;
75
+ currency: string;
76
+ language: string;
77
+ label: string;
78
+ pathPrefix: string;
79
+ };
72
80
  type WeaverseLoaderRequestInfo = {
73
81
  params: any;
74
82
  pathname: string;
75
83
  search: string;
84
+ queries: Record<string, string | boolean>;
85
+ i18n: I18nLocale;
76
86
  };
77
87
  interface WeaverseHydrogen extends Omit<Weaverse, 'itemInstances' | 'elementInstances' | 'registerElement' | 'data'> {
78
88
  itemInstances: Map<string | number, HydrogenComponentInstance>;
@@ -103,6 +113,7 @@ type WeaverseInternal = {
103
113
  pageAssignment: HydrogenPageAssignment;
104
114
  project: HydrogenProjectType;
105
115
  navigate: NavigateFunction;
116
+ revalidator: TODO;
106
117
  };
107
118
  type HydrogenComponentPresets = {
108
119
  type: string;
@@ -128,7 +139,7 @@ interface HydrogenComponent<T extends HydrogenComponentProps = any> {
128
139
  type HydrogenPageConfigs = {
129
140
  projectId: string;
130
141
  weaverseHost: string;
131
- version?: string;
142
+ weaverseVersion?: string;
132
143
  isDesignMode?: boolean;
133
144
  requestInfo: WeaverseLoaderRequestInfo;
134
145
  [key: string]: any;
@@ -176,10 +187,13 @@ type NavigateOptions = {
176
187
  };
177
188
  type NavigateFunction = (to: To, options?: NavigateOptions) => void;
178
189
  interface WeaverseHydrogenRootProps {
179
- weaverseData: WeaverseLoaderData;
180
190
  components: HydrogenComponent[];
181
- themeSchema: HydrogenThemeSchema;
182
- navigate: NavigateFunction;
191
+ errorComponent: React.FC<{
192
+ error: {
193
+ message: string;
194
+ stack?: string;
195
+ };
196
+ }>;
183
197
  }
184
198
  type HydrogenThemeInfo = {
185
199
  name: string;
@@ -199,8 +213,13 @@ type WeaverseLoaderConfigs = {
199
213
  locale?: string;
200
214
  handle?: string;
201
215
  };
202
-
203
- declare function useThemeSettings(): (Record<string, any> | ((newSettings: any) => void))[];
216
+ declare global {
217
+ interface Window {
218
+ __weaverse: WeaverseHydrogen;
219
+ __weaverses: WeaverseHydrogen[];
220
+ __weaverseHydrogenThemeSchema: HydrogenThemeSchema;
221
+ }
222
+ }
204
223
 
205
224
  type FetchWithServerCacheParams = {
206
225
  url: string;
@@ -212,8 +231,17 @@ type FetchWithServerCacheParams = {
212
231
  */
213
232
  declare function fetchWithServerCache(params: FetchWithServerCacheParams): Promise<any>;
214
233
 
234
+ declare function useThemeSettings(): (Record<string, any> | ((newSettings: any) => void))[];
235
+
236
+ declare function getSelectedProductOptions(request: Request): _shopify_hydrogen_react_storefront_api_types.SelectedOptionInput[];
237
+
215
238
  declare function weaverseLoader(args: LoaderArgs, components: HydrogenComponent[], loaderConfigs?: WeaverseLoaderConfigs): Promise<WeaverseLoaderData | null>;
216
239
 
217
- declare function WeaverseHydrogenRoot(props: WeaverseHydrogenRootProps): React.JSX.Element;
240
+ type StudioProps = {
241
+ themeSchema: HydrogenThemeSchema;
242
+ };
243
+ declare function HydrogenStudio({ themeSchema }: StudioProps): React.JSX.Element | null;
244
+
245
+ declare function WeaverseHydrogenRoot({ components, errorComponent: ErrorComponent, }: WeaverseHydrogenRootProps): React.JSX.Element;
218
246
 
219
- export { HydrogenComponent, HydrogenComponentData, HydrogenComponentInstance, HydrogenComponentPresets, HydrogenComponentProps, HydrogenComponentSchema, HydrogenElement, HydrogenPageAssignment, HydrogenPageConfigs, HydrogenPageData, HydrogenProjectConfig, HydrogenProjectType, HydrogenThemeInfo, HydrogenThemeSchema, HydrogenToolbarAction, InspectorGroup, NavigateFunction, PageType, TODO, WeaverseHydrogen, WeaverseHydrogenRoot, WeaverseHydrogenRootProps, WeaverseInternal, WeaverseLoaderArgs, WeaverseLoaderConfigs, WeaverseLoaderData, WeaverseLoaderRequestInfo, WeaverseStorefrontData, fetchWithServerCache, useThemeSettings, weaverseLoader };
247
+ export { HydrogenComponent, HydrogenComponentData, HydrogenComponentInstance, HydrogenComponentPresets, HydrogenComponentProps, HydrogenComponentSchema, HydrogenElement, HydrogenPageAssignment, HydrogenPageConfigs, HydrogenPageData, HydrogenProjectConfig, HydrogenProjectType, HydrogenStudio, HydrogenThemeInfo, HydrogenThemeSchema, HydrogenToolbarAction, InspectorGroup, NavigateFunction, PageType, TODO, WeaverseHydrogen, WeaverseHydrogenRoot, WeaverseHydrogenRootProps, WeaverseInternal, WeaverseLoaderArgs, WeaverseLoaderConfigs, WeaverseLoaderData, WeaverseLoaderRequestInfo, WeaverseStorefrontData, fetchWithServerCache, getSelectedProductOptions, useThemeSettings, weaverseLoader };
package/dist/index.js CHANGED
@@ -31,25 +31,33 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.tsx
32
32
  var src_exports = {};
33
33
  __export(src_exports, {
34
+ HydrogenStudio: () => HydrogenStudio,
34
35
  WeaverseHydrogenRoot: () => WeaverseHydrogenRoot,
35
36
  fetchWithServerCache: () => fetchWithServerCache,
37
+ getSelectedProductOptions: () => getSelectedProductOptions,
36
38
  useThemeSettings: () => useThemeSettings,
37
39
  weaverseLoader: () => weaverseLoader
38
40
  });
39
41
  module.exports = __toCommonJS(src_exports);
40
- var import_react5 = require("@weaverse/react");
41
- var import_react6 = __toESM(require("react"));
42
+ var import_react8 = require("@remix-run/react");
43
+ var import_react9 = require("@weaverse/react");
44
+ var import_react10 = __toESM(require("react"));
45
+ var import_react_error_boundary = require("react-error-boundary");
42
46
 
43
47
  // src/context.ts
44
48
  var import_react = require("@weaverse/react");
45
49
  function createCachedWeaverseInstance(init) {
46
50
  if (import_react.isBrowser) {
47
- window.__weaverses = window.__weaverses || {};
48
- let { pathname } = init.requestInfo;
49
- if (!window.__weaverses[pathname]) {
50
- window.__weaverses[pathname] = new import_react.Weaverse(init);
51
+ window.__weaverses = window.__weaverses || [];
52
+ let weaverse = window.__weaverses.find((w) => {
53
+ let { pathname, search } = w.requestInfo;
54
+ return pathname === init.requestInfo.pathname && search === init.requestInfo.search;
55
+ });
56
+ if (!weaverse) {
57
+ weaverse = new import_react.Weaverse(init);
58
+ window.__weaverses.push(weaverse);
51
59
  }
52
- return window.__weaverses[pathname];
60
+ return weaverse;
53
61
  }
54
62
  return new import_react.Weaverse(init);
55
63
  }
@@ -77,54 +85,29 @@ function createWeaverseInstance(weaverseData, components) {
77
85
  }
78
86
 
79
87
  // src/hooks/use-studio.ts
80
- var import_react2 = require("@weaverse/react");
81
- var import_react3 = require("react");
82
- function useStudio(weaverse, themeSchema, navigate) {
83
- (0, import_react3.useEffect)(() => {
84
- let initialized = checkStudioInitialized(weaverse);
85
- if (import_react2.isIframe && weaverse.isDesignMode && !initialized) {
86
- window.__initializedWeaverseStudios[weaverse.pageId] = true;
87
- weaverse.internal.themeSchema = themeSchema;
88
- weaverse.internal.navigate = navigate;
89
- let host = weaverse.weaverseHost;
90
- let version = weaverse.weaverseVersion || Date.now();
91
- (0, import_react2.loadScript)(`${host}/assets/studio/studio-bridge.js?v=${version}`).then(
92
- () => {
93
- window?.createWeaverseStudioBridge(weaverse);
94
- setTimeout(() => {
95
- weaverse.triggerUpdate();
96
- }, 2e3);
97
- }
98
- );
88
+ var import_react2 = require("@remix-run/react");
89
+ var import_react3 = require("@weaverse/react");
90
+ var import_react4 = require("react");
91
+ function useStudio(weaverse) {
92
+ let navigate = (0, import_react2.useNavigate)();
93
+ let revalidator = (0, import_react2.useRevalidator)();
94
+ (0, import_react4.useEffect)(() => {
95
+ if (import_react3.isIframe && weaverse.isDesignMode) {
96
+ weaverse.internal = {
97
+ ...weaverse.internal,
98
+ navigate,
99
+ revalidator
100
+ };
101
+ window.__weaverse = weaverse;
102
+ if (window.weaverseStudio) {
103
+ window.weaverseStudio.init(weaverse);
104
+ }
99
105
  }
100
- window.__weaverse = weaverse;
101
106
  }, [weaverse]);
102
107
  }
103
- function checkStudioInitialized(weaverseInit) {
104
- window.__initializedWeaverseStudios = window.__initializedWeaverseStudios || {};
105
- let { pageId } = weaverseInit;
106
- let initialized = window.__initializedWeaverseStudios?.[pageId];
107
- if (initialized) {
108
- return true;
109
- }
110
- return false;
111
- }
112
108
 
113
- // src/hooks/use-theme-setting.ts
114
- var import_react4 = require("@weaverse/react");
115
- function useThemeSettings() {
116
- let weaverse = (0, import_react4.useWeaverse)();
117
- let settings = weaverse?.internal?.project?.config?.theme;
118
- let updateSettings = (newSettings) => {
119
- weaverse.internal.project.config.theme = Object.assign(
120
- {},
121
- settings,
122
- newSettings
123
- );
124
- weaverse.triggerUpdate();
125
- };
126
- return [settings, updateSettings];
127
- }
109
+ // src/index.tsx
110
+ __reExport(src_exports, require("@weaverse/react"), module.exports);
128
111
 
129
112
  // src/fetch.ts
130
113
  var import_hydrogen = require("@shopify/hydrogen");
@@ -184,90 +167,192 @@ async function fetchWithServerCache(params) {
184
167
  return response;
185
168
  }
186
169
 
170
+ // src/hooks/use-theme-settings.ts
171
+ var import_react5 = require("@weaverse/react");
172
+ function useThemeSettings() {
173
+ let weaverse = (0, import_react5.useWeaverse)();
174
+ let settings = weaverse?.internal?.project?.config?.theme;
175
+ let updateSettings = (newSettings) => {
176
+ weaverse.internal.project.config.theme = Object.assign(
177
+ {},
178
+ settings,
179
+ newSettings
180
+ );
181
+ weaverse.triggerUpdate();
182
+ };
183
+ return [settings, updateSettings];
184
+ }
185
+
186
+ // src/hydrogen-wrappers.ts
187
+ var import_hydrogen2 = require("@shopify/hydrogen");
188
+ function getSelectedProductOptions(request) {
189
+ let options = (0, import_hydrogen2.getSelectedProductOptions)(request);
190
+ return options.filter(
191
+ ({ name }) => name !== "isDesignMode" && !name.startsWith("weaverse")
192
+ );
193
+ }
194
+
187
195
  // src/loader.ts
188
196
  async function weaverseLoader(args, components, loaderConfigs) {
189
- try {
190
- let { request, context, params } = args;
191
- let queries = getRequestQueries(request);
192
- let { WEAVERSE_PROJECT_ID, WEAVERSE_HOST } = context?.env || {};
193
- let { weaverseProjectId, weaverseHost } = queries;
194
- let projectId = weaverseProjectId || WEAVERSE_PROJECT_ID;
195
- weaverseHost = weaverseHost || WEAVERSE_HOST || "https://weaverse.io";
196
- if (!projectId) {
197
- throw new Error("Missing project id");
198
- }
199
- let configs = {
200
- projectId,
201
- weaverseHost,
202
- ...queries,
203
- requestInfo: {
204
- params,
205
- pathname: new URL(request.url).pathname,
206
- search: new URL(request.url).search
197
+ return new Promise(async (resolve, reject) => {
198
+ try {
199
+ let { request, context, params } = args;
200
+ let i18n = context?.storefront?.i18n;
201
+ let queries = getRequestQueries(request);
202
+ let { WEAVERSE_PROJECT_ID, WEAVERSE_HOST } = context?.env || {};
203
+ let { weaverseProjectId, weaverseHost, weaverseVersion, isDesignMode } = queries;
204
+ let projectId = weaverseProjectId || WEAVERSE_PROJECT_ID;
205
+ weaverseHost = weaverseHost || WEAVERSE_HOST || "https://weaverse.io";
206
+ if (!projectId) {
207
+ throw new Error(
208
+ `Missing Weaverse project's id. Try adding WEAVERSE_PROJECT_ID to your .env file then restart the server.`
209
+ );
207
210
  }
208
- };
209
- let res = await fetchWithServerCache({
210
- url: `${weaverseHost}/api/public/project`,
211
- options: {
212
- method: "POST",
213
- body: JSON.stringify({
214
- projectId,
215
- url: request.url,
216
- i18n: context?.storefront?.i18n,
217
- loaderConfigs
218
- })
219
- },
220
- context
221
- });
222
- let payload = await res.json();
223
- let { page, project, pageAssignment } = payload;
224
- if (!page || !project || !pageAssignment) {
225
- throw new Error(payload?.error || "Invalid payload");
226
- }
227
- if (page?.items) {
228
- let items = page.items;
229
- page.items = await Promise.all(
230
- items.map(async (itemData) => {
231
- let type = itemData.type;
232
- let { loader } = components.find(({ schema }) => schema?.type === type) || {};
233
- if (loader && typeof loader === "function") {
234
- try {
235
- return {
236
- ...itemData,
237
- loaderData: await loader({
238
- itemData,
239
- configs,
240
- ...args
241
- })
242
- };
243
- } catch (err) {
244
- console.log(`\u274C Loader run failed! Item: ${itemData}: ${err}`);
245
- return itemData;
211
+ let configs = {
212
+ projectId,
213
+ weaverseHost,
214
+ weaverseVersion,
215
+ isDesignMode,
216
+ requestInfo: {
217
+ i18n,
218
+ params,
219
+ queries,
220
+ pathname: new URL(request.url).pathname,
221
+ search: new URL(request.url).search
222
+ }
223
+ };
224
+ let res = await fetchWithServerCache({
225
+ url: `${weaverseHost}/api/public/project`,
226
+ options: {
227
+ method: "POST",
228
+ body: JSON.stringify({
229
+ i18n,
230
+ projectId,
231
+ loaderConfigs,
232
+ url: request.url
233
+ })
234
+ },
235
+ context
236
+ });
237
+ let payload = await res.json();
238
+ let { page, project, pageAssignment } = payload;
239
+ if (!page || !project || !pageAssignment) {
240
+ throw new Error(
241
+ // @ts-ignore
242
+ payload?.error || "Invalid Weaverse project payload!"
243
+ );
244
+ }
245
+ if (page?.items) {
246
+ let items = page.items;
247
+ page.items = await Promise.all(
248
+ items.map(async (itemData) => {
249
+ let type = itemData.type;
250
+ let { loader } = components.find(({ schema }) => schema?.type === type) || {};
251
+ if (loader && typeof loader === "function") {
252
+ try {
253
+ return {
254
+ ...itemData,
255
+ loaderData: await loader({
256
+ itemData,
257
+ configs,
258
+ ...args
259
+ })
260
+ };
261
+ } catch (err) {
262
+ console.log(`\u274C Loader run failed! Item: ${itemData}: ${err}`);
263
+ return itemData;
264
+ }
246
265
  }
266
+ return itemData;
267
+ })
268
+ );
269
+ }
270
+ resolve({ page, configs, project, pageAssignment });
271
+ } catch (err) {
272
+ console.log(`\u274C Error fetching project data: ${err?.toString()}`);
273
+ reject(err);
274
+ }
275
+ });
276
+ }
277
+
278
+ // src/studio.tsx
279
+ var import_react6 = require("@remix-run/react");
280
+ var import_react7 = __toESM(require("react"));
281
+ function HydrogenStudio({ themeSchema }) {
282
+ let { search } = (0, import_react6.useLocation)();
283
+ let params = new URLSearchParams(search);
284
+ if (params) {
285
+ let isDesignMode = params.get("isDesignMode") === "true";
286
+ let weaverseHost = params.get("weaverseHost");
287
+ let weaverseVersion = params.get("weaverseVersion");
288
+ if (isDesignMode && weaverseHost && weaverseVersion) {
289
+ return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(
290
+ "script",
291
+ {
292
+ src: `${weaverseHost}/assets/studio/hydrogen/index.js?v=${weaverseVersion}`,
293
+ async: true
294
+ }
295
+ ), /* @__PURE__ */ import_react7.default.createElement(
296
+ "script",
297
+ {
298
+ dangerouslySetInnerHTML: {
299
+ __html: `window.__weaverseHydrogenThemeSchema = ${JSON.stringify(
300
+ themeSchema
301
+ )}`
247
302
  }
248
- return itemData;
249
- })
250
- );
303
+ }
304
+ ));
251
305
  }
252
- return { page, configs, project, pageAssignment };
253
- } catch (err) {
254
- console.log(`\u274C Error fetching project data: ${err?.toString()}`);
255
- return null;
256
306
  }
307
+ return null;
257
308
  }
258
309
 
259
310
  // src/index.tsx
260
- __reExport(src_exports, require("@weaverse/react"), module.exports);
261
- function WeaverseHydrogenRoot(props) {
262
- let { components, weaverseData, themeSchema, navigate } = props;
311
+ function WeaverseHydrogenRoot({
312
+ components,
313
+ errorComponent: ErrorComponent
314
+ }) {
315
+ let data = (0, import_react8.useLoaderData)();
316
+ let weaverseDataFromLoader = data?.weaverseData;
317
+ if (weaverseDataFromLoader) {
318
+ if (weaverseDataFromLoader instanceof Promise) {
319
+ return /* @__PURE__ */ import_react10.default.createElement(import_react_error_boundary.ErrorBoundary, { fallbackRender: ErrorComponent }, /* @__PURE__ */ import_react10.default.createElement(import_react10.Suspense, null, /* @__PURE__ */ import_react10.default.createElement(import_react8.Await, { resolve: weaverseDataFromLoader }, (resolvedData) => {
320
+ return /* @__PURE__ */ import_react10.default.createElement(
321
+ RenderWeaverseRoot,
322
+ {
323
+ weaverseData: resolvedData,
324
+ components
325
+ }
326
+ );
327
+ })));
328
+ }
329
+ return /* @__PURE__ */ import_react10.default.createElement(
330
+ RenderWeaverseRoot,
331
+ {
332
+ weaverseData: weaverseDataFromLoader,
333
+ components
334
+ }
335
+ );
336
+ }
337
+ return /* @__PURE__ */ import_react10.default.createElement(
338
+ ErrorComponent,
339
+ {
340
+ error: { message: "No Weaverse data return from route loader!" }
341
+ }
342
+ );
343
+ }
344
+ function RenderWeaverseRoot(props) {
345
+ let { components, weaverseData } = props;
263
346
  let weaverse = createWeaverseInstance(weaverseData, components);
264
- useStudio(weaverse, themeSchema, navigate);
265
- return /* @__PURE__ */ import_react6.default.createElement(import_react5.WeaverseRoot, { context: weaverse });
347
+ useStudio(weaverse);
348
+ return /* @__PURE__ */ import_react10.default.createElement(import_react9.WeaverseRoot, { context: weaverse });
266
349
  }
267
350
  // Annotate the CommonJS export names for ESM import in node:
268
351
  0 && (module.exports = {
352
+ HydrogenStudio,
269
353
  WeaverseHydrogenRoot,
270
354
  fetchWithServerCache,
355
+ getSelectedProductOptions,
271
356
  useThemeSettings,
272
357
  weaverseLoader,
273
358
  ...require("@weaverse/react")
package/dist/index.mjs CHANGED
@@ -1,17 +1,23 @@
1
1
  // src/index.tsx
2
+ import { Await, useLoaderData } from "@remix-run/react";
2
3
  import { WeaverseRoot } from "@weaverse/react";
3
- import React from "react";
4
+ import React2, { Suspense } from "react";
5
+ import { ErrorBoundary } from "react-error-boundary";
4
6
 
5
7
  // src/context.ts
6
8
  import { Weaverse, isBrowser } from "@weaverse/react";
7
9
  function createCachedWeaverseInstance(init) {
8
10
  if (isBrowser) {
9
- window.__weaverses = window.__weaverses || {};
10
- let { pathname } = init.requestInfo;
11
- if (!window.__weaverses[pathname]) {
12
- window.__weaverses[pathname] = new Weaverse(init);
11
+ window.__weaverses = window.__weaverses || [];
12
+ let weaverse = window.__weaverses.find((w) => {
13
+ let { pathname, search } = w.requestInfo;
14
+ return pathname === init.requestInfo.pathname && search === init.requestInfo.search;
15
+ });
16
+ if (!weaverse) {
17
+ weaverse = new Weaverse(init);
18
+ window.__weaverses.push(weaverse);
13
19
  }
14
- return window.__weaverses[pathname];
20
+ return weaverse;
15
21
  }
16
22
  return new Weaverse(init);
17
23
  }
@@ -39,54 +45,29 @@ function createWeaverseInstance(weaverseData, components) {
39
45
  }
40
46
 
41
47
  // src/hooks/use-studio.ts
42
- import { isIframe, loadScript } from "@weaverse/react";
48
+ import { useNavigate, useRevalidator } from "@remix-run/react";
49
+ import { isIframe } from "@weaverse/react";
43
50
  import { useEffect } from "react";
44
- function useStudio(weaverse, themeSchema, navigate) {
51
+ function useStudio(weaverse) {
52
+ let navigate = useNavigate();
53
+ let revalidator = useRevalidator();
45
54
  useEffect(() => {
46
- let initialized = checkStudioInitialized(weaverse);
47
- if (isIframe && weaverse.isDesignMode && !initialized) {
48
- window.__initializedWeaverseStudios[weaverse.pageId] = true;
49
- weaverse.internal.themeSchema = themeSchema;
50
- weaverse.internal.navigate = navigate;
51
- let host = weaverse.weaverseHost;
52
- let version = weaverse.weaverseVersion || Date.now();
53
- loadScript(`${host}/assets/studio/studio-bridge.js?v=${version}`).then(
54
- () => {
55
- window?.createWeaverseStudioBridge(weaverse);
56
- setTimeout(() => {
57
- weaverse.triggerUpdate();
58
- }, 2e3);
59
- }
60
- );
55
+ if (isIframe && weaverse.isDesignMode) {
56
+ weaverse.internal = {
57
+ ...weaverse.internal,
58
+ navigate,
59
+ revalidator
60
+ };
61
+ window.__weaverse = weaverse;
62
+ if (window.weaverseStudio) {
63
+ window.weaverseStudio.init(weaverse);
64
+ }
61
65
  }
62
- window.__weaverse = weaverse;
63
66
  }, [weaverse]);
64
67
  }
65
- function checkStudioInitialized(weaverseInit) {
66
- window.__initializedWeaverseStudios = window.__initializedWeaverseStudios || {};
67
- let { pageId } = weaverseInit;
68
- let initialized = window.__initializedWeaverseStudios?.[pageId];
69
- if (initialized) {
70
- return true;
71
- }
72
- return false;
73
- }
74
68
 
75
- // src/hooks/use-theme-setting.ts
76
- import { useWeaverse } from "@weaverse/react";
77
- function useThemeSettings() {
78
- let weaverse = useWeaverse();
79
- let settings = weaverse?.internal?.project?.config?.theme;
80
- let updateSettings = (newSettings) => {
81
- weaverse.internal.project.config.theme = Object.assign(
82
- {},
83
- settings,
84
- newSettings
85
- );
86
- weaverse.triggerUpdate();
87
- };
88
- return [settings, updateSettings];
89
- }
69
+ // src/index.tsx
70
+ export * from "@weaverse/react";
90
71
 
91
72
  // src/fetch.ts
92
73
  import { CacheShort, generateCacheControlHeader } from "@shopify/hydrogen";
@@ -146,89 +127,191 @@ async function fetchWithServerCache(params) {
146
127
  return response;
147
128
  }
148
129
 
130
+ // src/hooks/use-theme-settings.ts
131
+ import { useWeaverse } from "@weaverse/react";
132
+ function useThemeSettings() {
133
+ let weaverse = useWeaverse();
134
+ let settings = weaverse?.internal?.project?.config?.theme;
135
+ let updateSettings = (newSettings) => {
136
+ weaverse.internal.project.config.theme = Object.assign(
137
+ {},
138
+ settings,
139
+ newSettings
140
+ );
141
+ weaverse.triggerUpdate();
142
+ };
143
+ return [settings, updateSettings];
144
+ }
145
+
146
+ // src/hydrogen-wrappers.ts
147
+ import { getSelectedProductOptions as hydrogen_getSelectedProductOptions } from "@shopify/hydrogen";
148
+ function getSelectedProductOptions(request) {
149
+ let options = hydrogen_getSelectedProductOptions(request);
150
+ return options.filter(
151
+ ({ name }) => name !== "isDesignMode" && !name.startsWith("weaverse")
152
+ );
153
+ }
154
+
149
155
  // src/loader.ts
150
156
  async function weaverseLoader(args, components, loaderConfigs) {
151
- try {
152
- let { request, context, params } = args;
153
- let queries = getRequestQueries(request);
154
- let { WEAVERSE_PROJECT_ID, WEAVERSE_HOST } = context?.env || {};
155
- let { weaverseProjectId, weaverseHost } = queries;
156
- let projectId = weaverseProjectId || WEAVERSE_PROJECT_ID;
157
- weaverseHost = weaverseHost || WEAVERSE_HOST || "https://weaverse.io";
158
- if (!projectId) {
159
- throw new Error("Missing project id");
160
- }
161
- let configs = {
162
- projectId,
163
- weaverseHost,
164
- ...queries,
165
- requestInfo: {
166
- params,
167
- pathname: new URL(request.url).pathname,
168
- search: new URL(request.url).search
157
+ return new Promise(async (resolve, reject) => {
158
+ try {
159
+ let { request, context, params } = args;
160
+ let i18n = context?.storefront?.i18n;
161
+ let queries = getRequestQueries(request);
162
+ let { WEAVERSE_PROJECT_ID, WEAVERSE_HOST } = context?.env || {};
163
+ let { weaverseProjectId, weaverseHost, weaverseVersion, isDesignMode } = queries;
164
+ let projectId = weaverseProjectId || WEAVERSE_PROJECT_ID;
165
+ weaverseHost = weaverseHost || WEAVERSE_HOST || "https://weaverse.io";
166
+ if (!projectId) {
167
+ throw new Error(
168
+ `Missing Weaverse project's id. Try adding WEAVERSE_PROJECT_ID to your .env file then restart the server.`
169
+ );
169
170
  }
170
- };
171
- let res = await fetchWithServerCache({
172
- url: `${weaverseHost}/api/public/project`,
173
- options: {
174
- method: "POST",
175
- body: JSON.stringify({
176
- projectId,
177
- url: request.url,
178
- i18n: context?.storefront?.i18n,
179
- loaderConfigs
180
- })
181
- },
182
- context
183
- });
184
- let payload = await res.json();
185
- let { page, project, pageAssignment } = payload;
186
- if (!page || !project || !pageAssignment) {
187
- throw new Error(payload?.error || "Invalid payload");
188
- }
189
- if (page?.items) {
190
- let items = page.items;
191
- page.items = await Promise.all(
192
- items.map(async (itemData) => {
193
- let type = itemData.type;
194
- let { loader } = components.find(({ schema }) => schema?.type === type) || {};
195
- if (loader && typeof loader === "function") {
196
- try {
197
- return {
198
- ...itemData,
199
- loaderData: await loader({
200
- itemData,
201
- configs,
202
- ...args
203
- })
204
- };
205
- } catch (err) {
206
- console.log(`\u274C Loader run failed! Item: ${itemData}: ${err}`);
207
- return itemData;
171
+ let configs = {
172
+ projectId,
173
+ weaverseHost,
174
+ weaverseVersion,
175
+ isDesignMode,
176
+ requestInfo: {
177
+ i18n,
178
+ params,
179
+ queries,
180
+ pathname: new URL(request.url).pathname,
181
+ search: new URL(request.url).search
182
+ }
183
+ };
184
+ let res = await fetchWithServerCache({
185
+ url: `${weaverseHost}/api/public/project`,
186
+ options: {
187
+ method: "POST",
188
+ body: JSON.stringify({
189
+ i18n,
190
+ projectId,
191
+ loaderConfigs,
192
+ url: request.url
193
+ })
194
+ },
195
+ context
196
+ });
197
+ let payload = await res.json();
198
+ let { page, project, pageAssignment } = payload;
199
+ if (!page || !project || !pageAssignment) {
200
+ throw new Error(
201
+ // @ts-ignore
202
+ payload?.error || "Invalid Weaverse project payload!"
203
+ );
204
+ }
205
+ if (page?.items) {
206
+ let items = page.items;
207
+ page.items = await Promise.all(
208
+ items.map(async (itemData) => {
209
+ let type = itemData.type;
210
+ let { loader } = components.find(({ schema }) => schema?.type === type) || {};
211
+ if (loader && typeof loader === "function") {
212
+ try {
213
+ return {
214
+ ...itemData,
215
+ loaderData: await loader({
216
+ itemData,
217
+ configs,
218
+ ...args
219
+ })
220
+ };
221
+ } catch (err) {
222
+ console.log(`\u274C Loader run failed! Item: ${itemData}: ${err}`);
223
+ return itemData;
224
+ }
208
225
  }
226
+ return itemData;
227
+ })
228
+ );
229
+ }
230
+ resolve({ page, configs, project, pageAssignment });
231
+ } catch (err) {
232
+ console.log(`\u274C Error fetching project data: ${err?.toString()}`);
233
+ reject(err);
234
+ }
235
+ });
236
+ }
237
+
238
+ // src/studio.tsx
239
+ import { useLocation } from "@remix-run/react";
240
+ import React from "react";
241
+ function HydrogenStudio({ themeSchema }) {
242
+ let { search } = useLocation();
243
+ let params = new URLSearchParams(search);
244
+ if (params) {
245
+ let isDesignMode = params.get("isDesignMode") === "true";
246
+ let weaverseHost = params.get("weaverseHost");
247
+ let weaverseVersion = params.get("weaverseVersion");
248
+ if (isDesignMode && weaverseHost && weaverseVersion) {
249
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
250
+ "script",
251
+ {
252
+ src: `${weaverseHost}/assets/studio/hydrogen/index.js?v=${weaverseVersion}`,
253
+ async: true
254
+ }
255
+ ), /* @__PURE__ */ React.createElement(
256
+ "script",
257
+ {
258
+ dangerouslySetInnerHTML: {
259
+ __html: `window.__weaverseHydrogenThemeSchema = ${JSON.stringify(
260
+ themeSchema
261
+ )}`
209
262
  }
210
- return itemData;
211
- })
212
- );
263
+ }
264
+ ));
213
265
  }
214
- return { page, configs, project, pageAssignment };
215
- } catch (err) {
216
- console.log(`\u274C Error fetching project data: ${err?.toString()}`);
217
- return null;
218
266
  }
267
+ return null;
219
268
  }
220
269
 
221
270
  // src/index.tsx
222
- export * from "@weaverse/react";
223
- function WeaverseHydrogenRoot(props) {
224
- let { components, weaverseData, themeSchema, navigate } = props;
271
+ function WeaverseHydrogenRoot({
272
+ components,
273
+ errorComponent: ErrorComponent
274
+ }) {
275
+ let data = useLoaderData();
276
+ let weaverseDataFromLoader = data?.weaverseData;
277
+ if (weaverseDataFromLoader) {
278
+ if (weaverseDataFromLoader instanceof Promise) {
279
+ return /* @__PURE__ */ React2.createElement(ErrorBoundary, { fallbackRender: ErrorComponent }, /* @__PURE__ */ React2.createElement(Suspense, null, /* @__PURE__ */ React2.createElement(Await, { resolve: weaverseDataFromLoader }, (resolvedData) => {
280
+ return /* @__PURE__ */ React2.createElement(
281
+ RenderWeaverseRoot,
282
+ {
283
+ weaverseData: resolvedData,
284
+ components
285
+ }
286
+ );
287
+ })));
288
+ }
289
+ return /* @__PURE__ */ React2.createElement(
290
+ RenderWeaverseRoot,
291
+ {
292
+ weaverseData: weaverseDataFromLoader,
293
+ components
294
+ }
295
+ );
296
+ }
297
+ return /* @__PURE__ */ React2.createElement(
298
+ ErrorComponent,
299
+ {
300
+ error: { message: "No Weaverse data return from route loader!" }
301
+ }
302
+ );
303
+ }
304
+ function RenderWeaverseRoot(props) {
305
+ let { components, weaverseData } = props;
225
306
  let weaverse = createWeaverseInstance(weaverseData, components);
226
- useStudio(weaverse, themeSchema, navigate);
227
- return /* @__PURE__ */ React.createElement(WeaverseRoot, { context: weaverse });
307
+ useStudio(weaverse);
308
+ return /* @__PURE__ */ React2.createElement(WeaverseRoot, { context: weaverse });
228
309
  }
229
310
  export {
311
+ HydrogenStudio,
230
312
  WeaverseHydrogenRoot,
231
313
  fetchWithServerCache,
314
+ getSelectedProductOptions,
232
315
  useThemeSettings,
233
316
  weaverseLoader
234
317
  };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.65",
2
+ "version": "1.1.1",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -15,8 +15,8 @@
15
15
  },
16
16
  "scripts": {
17
17
  "start": "npm run dev",
18
- "dev": "tsup src/index.tsx --format esm,cjs --dts --outDir dist --watch --external @weaverse/react,@shopify/hydrogen",
19
- "build": "tsup src/index.tsx --format esm,cjs --dts --outDir dist --external @weaverse/react,@shopify/hydrogen",
18
+ "dev": "tsup src/index.tsx --format esm,cjs --dts --outDir dist --watch --external @remix-run/react,@shopify/hydrogen",
19
+ "build": "tsup src/index.tsx --format esm,cjs --dts --outDir dist --external @remix-run/react,@shopify/hydrogen",
20
20
  "clean": "rimraf dist",
21
21
  "prepublish": "npm run build"
22
22
  },
@@ -32,8 +32,10 @@
32
32
  "name": "@weaverse/hydrogen",
33
33
  "author": "Weaverse Team",
34
34
  "dependencies": {
35
+ "@remix-run/react": "1.19.1",
35
36
  "@shopify/hydrogen": "2023.7.1",
36
- "@weaverse/react": "1.0.65"
37
+ "@weaverse/react": "1.1.1",
38
+ "react-error-boundary": "^4.0.10"
37
39
  },
38
40
  "devDependencies": {
39
41
  "@shopify/remix-oxygen": "^1.1.2"