@weaverse/hydrogen 1.1.0 → 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>;
@@ -129,7 +139,7 @@ interface HydrogenComponent<T extends HydrogenComponentProps = any> {
129
139
  type HydrogenPageConfigs = {
130
140
  projectId: string;
131
141
  weaverseHost: string;
132
- version?: string;
142
+ weaverseVersion?: string;
133
143
  isDesignMode?: boolean;
134
144
  requestInfo: WeaverseLoaderRequestInfo;
135
145
  [key: string]: any;
@@ -178,7 +188,12 @@ type NavigateOptions = {
178
188
  type NavigateFunction = (to: To, options?: NavigateOptions) => void;
179
189
  interface WeaverseHydrogenRootProps {
180
190
  components: HydrogenComponent[];
181
- themeSchema: HydrogenThemeSchema;
191
+ errorComponent: React.FC<{
192
+ error: {
193
+ message: string;
194
+ stack?: string;
195
+ };
196
+ }>;
182
197
  }
183
198
  type HydrogenThemeInfo = {
184
199
  name: string;
@@ -198,8 +213,13 @@ type WeaverseLoaderConfigs = {
198
213
  locale?: string;
199
214
  handle?: string;
200
215
  };
201
-
202
- 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
+ }
203
223
 
204
224
  type FetchWithServerCacheParams = {
205
225
  url: string;
@@ -211,8 +231,17 @@ type FetchWithServerCacheParams = {
211
231
  */
212
232
  declare function fetchWithServerCache(params: FetchWithServerCacheParams): Promise<any>;
213
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
+
214
238
  declare function weaverseLoader(args: LoaderArgs, components: HydrogenComponent[], loaderConfigs?: WeaverseLoaderConfigs): Promise<WeaverseLoaderData | null>;
215
239
 
216
- 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;
217
246
 
218
- 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>;
@@ -129,7 +139,7 @@ interface HydrogenComponent<T extends HydrogenComponentProps = any> {
129
139
  type HydrogenPageConfigs = {
130
140
  projectId: string;
131
141
  weaverseHost: string;
132
- version?: string;
142
+ weaverseVersion?: string;
133
143
  isDesignMode?: boolean;
134
144
  requestInfo: WeaverseLoaderRequestInfo;
135
145
  [key: string]: any;
@@ -178,7 +188,12 @@ type NavigateOptions = {
178
188
  type NavigateFunction = (to: To, options?: NavigateOptions) => void;
179
189
  interface WeaverseHydrogenRootProps {
180
190
  components: HydrogenComponent[];
181
- themeSchema: HydrogenThemeSchema;
191
+ errorComponent: React.FC<{
192
+ error: {
193
+ message: string;
194
+ stack?: string;
195
+ };
196
+ }>;
182
197
  }
183
198
  type HydrogenThemeInfo = {
184
199
  name: string;
@@ -198,8 +213,13 @@ type WeaverseLoaderConfigs = {
198
213
  locale?: string;
199
214
  handle?: string;
200
215
  };
201
-
202
- 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
+ }
203
223
 
204
224
  type FetchWithServerCacheParams = {
205
225
  url: string;
@@ -211,8 +231,17 @@ type FetchWithServerCacheParams = {
211
231
  */
212
232
  declare function fetchWithServerCache(params: FetchWithServerCacheParams): Promise<any>;
213
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
+
214
238
  declare function weaverseLoader(args: LoaderArgs, components: HydrogenComponent[], loaderConfigs?: WeaverseLoaderConfigs): Promise<WeaverseLoaderData | null>;
215
239
 
216
- 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;
217
246
 
218
- 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_react6 = require("@weaverse/react");
41
- var import_react7 = __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,59 +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
- var import_react4 = require("@remix-run/react");
83
- function useStudio(weaverse, themeSchema) {
84
- let revalidator = (0, import_react4.useRevalidator)();
85
- let navigate = (0, import_react4.useNavigate)();
86
- console.log("revalidator", revalidator);
87
- (0, import_react3.useEffect)(() => {
88
- let initialized = checkStudioInitialized(weaverse);
89
- if (import_react2.isIframe && weaverse.isDesignMode && !initialized) {
90
- window.__initializedWeaverseStudios[weaverse.pageId] = true;
91
- weaverse.internal.themeSchema = themeSchema;
92
- weaverse.internal.navigate = navigate;
93
- weaverse.internal.revalidator = revalidator;
94
- let host = weaverse.weaverseHost;
95
- let version = weaverse.weaverseVersion || Date.now();
96
- (0, import_react2.loadScript)(`${host}/assets/studio/studio-bridge.js?v=${version}`).then(
97
- () => {
98
- window?.createWeaverseStudioBridge(weaverse);
99
- setTimeout(() => {
100
- weaverse.triggerUpdate();
101
- }, 2e3);
102
- }
103
- );
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
+ }
104
105
  }
105
- window.__weaverse = weaverse;
106
106
  }, [weaverse]);
107
107
  }
108
- function checkStudioInitialized(weaverseInit) {
109
- window.__initializedWeaverseStudios = window.__initializedWeaverseStudios || {};
110
- let { pageId } = weaverseInit;
111
- let initialized = window.__initializedWeaverseStudios?.[pageId];
112
- if (initialized) {
113
- return true;
114
- }
115
- return false;
116
- }
117
108
 
118
- // src/hooks/use-theme-setting.ts
119
- var import_react5 = require("@weaverse/react");
120
- function useThemeSettings() {
121
- let weaverse = (0, import_react5.useWeaverse)();
122
- let settings = weaverse?.internal?.project?.config?.theme;
123
- let updateSettings = (newSettings) => {
124
- weaverse.internal.project.config.theme = Object.assign(
125
- {},
126
- settings,
127
- newSettings
128
- );
129
- weaverse.triggerUpdate();
130
- };
131
- return [settings, updateSettings];
132
- }
109
+ // src/index.tsx
110
+ __reExport(src_exports, require("@weaverse/react"), module.exports);
133
111
 
134
112
  // src/fetch.ts
135
113
  var import_hydrogen = require("@shopify/hydrogen");
@@ -189,121 +167,192 @@ async function fetchWithServerCache(params) {
189
167
  return response;
190
168
  }
191
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
+
192
195
  // src/loader.ts
193
196
  async function weaverseLoader(args, components, loaderConfigs) {
194
- try {
195
- let { request, context, params } = args;
196
- let queries = getRequestQueries(request);
197
- let { WEAVERSE_PROJECT_ID, WEAVERSE_HOST } = context?.env || {};
198
- let { weaverseProjectId, weaverseHost } = queries;
199
- let projectId = weaverseProjectId || WEAVERSE_PROJECT_ID;
200
- weaverseHost = weaverseHost || WEAVERSE_HOST || "https://weaverse.io";
201
- if (!projectId) {
202
- throw new Error("Missing project id");
203
- }
204
- let configs = {
205
- projectId,
206
- weaverseHost,
207
- ...queries,
208
- requestInfo: {
209
- params,
210
- pathname: new URL(request.url).pathname,
211
- 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
+ );
212
210
  }
213
- };
214
- let res = await fetchWithServerCache({
215
- url: `${weaverseHost}/api/public/project`,
216
- options: {
217
- method: "POST",
218
- body: JSON.stringify({
219
- projectId,
220
- url: request.url,
221
- i18n: context?.storefront?.i18n,
222
- loaderConfigs
223
- })
224
- },
225
- context
226
- });
227
- let payload = await res.json();
228
- let { page, project, pageAssignment } = payload;
229
- if (!page || !project || !pageAssignment) {
230
- throw new Error(payload?.error || "Invalid payload");
231
- }
232
- if (page?.items) {
233
- let items = page.items;
234
- page.items = await Promise.all(
235
- items.map(async (itemData) => {
236
- let type = itemData.type;
237
- let { loader } = components.find(({ schema }) => schema?.type === type) || {};
238
- if (loader && typeof loader === "function") {
239
- try {
240
- return {
241
- ...itemData,
242
- loaderData: await loader({
243
- itemData,
244
- configs,
245
- ...args
246
- })
247
- };
248
- } catch (err) {
249
- console.log(`\u274C Loader run failed! Item: ${itemData}: ${err}`);
250
- 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
+ }
251
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
+ )}`
252
302
  }
253
- return itemData;
254
- })
255
- );
303
+ }
304
+ ));
256
305
  }
257
- return { page, configs, project, pageAssignment };
258
- } catch (err) {
259
- console.log(`\u274C Error fetching project data: ${err?.toString()}`);
260
- return null;
261
306
  }
307
+ return null;
262
308
  }
263
309
 
264
310
  // src/index.tsx
265
- __reExport(src_exports, require("@weaverse/react"), module.exports);
266
- var import_react8 = require("@remix-run/react");
267
- function WeaverseHydrogenRoot(props) {
268
- let loaderData = (0, import_react8.useLoaderData)();
269
- console.log("loaderData111", loaderData);
270
- let weaverseDataFromLoader = loaderData?.weaverseData;
271
- let { components, themeSchema } = props;
311
+ function WeaverseHydrogenRoot({
312
+ components,
313
+ errorComponent: ErrorComponent
314
+ }) {
315
+ let data = (0, import_react8.useLoaderData)();
316
+ let weaverseDataFromLoader = data?.weaverseData;
272
317
  if (weaverseDataFromLoader) {
273
318
  if (weaverseDataFromLoader instanceof Promise) {
274
- return /* @__PURE__ */ import_react7.default.createElement(import_react7.Suspense, null, /* @__PURE__ */ import_react7.default.createElement(import_react8.Await, { resolve: weaverseDataFromLoader }, (resolvedData) => {
275
- console.log("resolvedData", resolvedData);
276
- return /* @__PURE__ */ import_react7.default.createElement(
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(
277
321
  RenderWeaverseRoot,
278
322
  {
279
- components,
280
- themeSchema,
281
- weaverseData: resolvedData
323
+ weaverseData: resolvedData,
324
+ components
282
325
  }
283
326
  );
284
- }));
327
+ })));
285
328
  }
286
- return /* @__PURE__ */ import_react7.default.createElement(
329
+ return /* @__PURE__ */ import_react10.default.createElement(
287
330
  RenderWeaverseRoot,
288
331
  {
289
- components,
290
- themeSchema,
291
- weaverseData: weaverseDataFromLoader
332
+ weaverseData: weaverseDataFromLoader,
333
+ components
292
334
  }
293
335
  );
294
336
  }
295
- return /* @__PURE__ */ import_react7.default.createElement("div", { style: { display: "none" } }, "No weaverseData return from Remix loader!");
337
+ return /* @__PURE__ */ import_react10.default.createElement(
338
+ ErrorComponent,
339
+ {
340
+ error: { message: "No Weaverse data return from route loader!" }
341
+ }
342
+ );
296
343
  }
297
- var RenderWeaverseRoot = (props) => {
298
- let { components, themeSchema, weaverseData } = props;
344
+ function RenderWeaverseRoot(props) {
345
+ let { components, weaverseData } = props;
299
346
  let weaverse = createWeaverseInstance(weaverseData, components);
300
- useStudio(weaverse, themeSchema);
301
- return /* @__PURE__ */ import_react7.default.createElement(import_react6.WeaverseRoot, { context: weaverse });
302
- };
347
+ useStudio(weaverse);
348
+ return /* @__PURE__ */ import_react10.default.createElement(import_react9.WeaverseRoot, { context: weaverse });
349
+ }
303
350
  // Annotate the CommonJS export names for ESM import in node:
304
351
  0 && (module.exports = {
352
+ HydrogenStudio,
305
353
  WeaverseHydrogenRoot,
306
354
  fetchWithServerCache,
355
+ getSelectedProductOptions,
307
356
  useThemeSettings,
308
357
  weaverseLoader,
309
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, { Suspense } 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,59 +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
- import { useRevalidator, useNavigate } from "@remix-run/react";
45
- function useStudio(weaverse, themeSchema) {
46
- let revalidator = useRevalidator();
51
+ function useStudio(weaverse) {
47
52
  let navigate = useNavigate();
48
- console.log("revalidator", revalidator);
53
+ let revalidator = useRevalidator();
49
54
  useEffect(() => {
50
- let initialized = checkStudioInitialized(weaverse);
51
- if (isIframe && weaverse.isDesignMode && !initialized) {
52
- window.__initializedWeaverseStudios[weaverse.pageId] = true;
53
- weaverse.internal.themeSchema = themeSchema;
54
- weaverse.internal.navigate = navigate;
55
- weaverse.internal.revalidator = revalidator;
56
- let host = weaverse.weaverseHost;
57
- let version = weaverse.weaverseVersion || Date.now();
58
- loadScript(`${host}/assets/studio/studio-bridge.js?v=${version}`).then(
59
- () => {
60
- window?.createWeaverseStudioBridge(weaverse);
61
- setTimeout(() => {
62
- weaverse.triggerUpdate();
63
- }, 2e3);
64
- }
65
- );
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
+ }
66
65
  }
67
- window.__weaverse = weaverse;
68
66
  }, [weaverse]);
69
67
  }
70
- function checkStudioInitialized(weaverseInit) {
71
- window.__initializedWeaverseStudios = window.__initializedWeaverseStudios || {};
72
- let { pageId } = weaverseInit;
73
- let initialized = window.__initializedWeaverseStudios?.[pageId];
74
- if (initialized) {
75
- return true;
76
- }
77
- return false;
78
- }
79
68
 
80
- // src/hooks/use-theme-setting.ts
81
- import { useWeaverse } from "@weaverse/react";
82
- function useThemeSettings() {
83
- let weaverse = useWeaverse();
84
- let settings = weaverse?.internal?.project?.config?.theme;
85
- let updateSettings = (newSettings) => {
86
- weaverse.internal.project.config.theme = Object.assign(
87
- {},
88
- settings,
89
- newSettings
90
- );
91
- weaverse.triggerUpdate();
92
- };
93
- return [settings, updateSettings];
94
- }
69
+ // src/index.tsx
70
+ export * from "@weaverse/react";
95
71
 
96
72
  // src/fetch.ts
97
73
  import { CacheShort, generateCacheControlHeader } from "@shopify/hydrogen";
@@ -151,120 +127,191 @@ async function fetchWithServerCache(params) {
151
127
  return response;
152
128
  }
153
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
+
154
155
  // src/loader.ts
155
156
  async function weaverseLoader(args, components, loaderConfigs) {
156
- try {
157
- let { request, context, params } = args;
158
- let queries = getRequestQueries(request);
159
- let { WEAVERSE_PROJECT_ID, WEAVERSE_HOST } = context?.env || {};
160
- let { weaverseProjectId, weaverseHost } = queries;
161
- let projectId = weaverseProjectId || WEAVERSE_PROJECT_ID;
162
- weaverseHost = weaverseHost || WEAVERSE_HOST || "https://weaverse.io";
163
- if (!projectId) {
164
- throw new Error("Missing project id");
165
- }
166
- let configs = {
167
- projectId,
168
- weaverseHost,
169
- ...queries,
170
- requestInfo: {
171
- params,
172
- pathname: new URL(request.url).pathname,
173
- 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
+ );
174
170
  }
175
- };
176
- let res = await fetchWithServerCache({
177
- url: `${weaverseHost}/api/public/project`,
178
- options: {
179
- method: "POST",
180
- body: JSON.stringify({
181
- projectId,
182
- url: request.url,
183
- i18n: context?.storefront?.i18n,
184
- loaderConfigs
185
- })
186
- },
187
- context
188
- });
189
- let payload = await res.json();
190
- let { page, project, pageAssignment } = payload;
191
- if (!page || !project || !pageAssignment) {
192
- throw new Error(payload?.error || "Invalid payload");
193
- }
194
- if (page?.items) {
195
- let items = page.items;
196
- page.items = await Promise.all(
197
- items.map(async (itemData) => {
198
- let type = itemData.type;
199
- let { loader } = components.find(({ schema }) => schema?.type === type) || {};
200
- if (loader && typeof loader === "function") {
201
- try {
202
- return {
203
- ...itemData,
204
- loaderData: await loader({
205
- itemData,
206
- configs,
207
- ...args
208
- })
209
- };
210
- } catch (err) {
211
- console.log(`\u274C Loader run failed! Item: ${itemData}: ${err}`);
212
- 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
+ }
213
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
+ )}`
214
262
  }
215
- return itemData;
216
- })
217
- );
263
+ }
264
+ ));
218
265
  }
219
- return { page, configs, project, pageAssignment };
220
- } catch (err) {
221
- console.log(`\u274C Error fetching project data: ${err?.toString()}`);
222
- return null;
223
266
  }
267
+ return null;
224
268
  }
225
269
 
226
270
  // src/index.tsx
227
- export * from "@weaverse/react";
228
- import { Await, useLoaderData } from "@remix-run/react";
229
- function WeaverseHydrogenRoot(props) {
230
- let loaderData = useLoaderData();
231
- console.log("loaderData111", loaderData);
232
- let weaverseDataFromLoader = loaderData?.weaverseData;
233
- let { components, themeSchema } = props;
271
+ function WeaverseHydrogenRoot({
272
+ components,
273
+ errorComponent: ErrorComponent
274
+ }) {
275
+ let data = useLoaderData();
276
+ let weaverseDataFromLoader = data?.weaverseData;
234
277
  if (weaverseDataFromLoader) {
235
278
  if (weaverseDataFromLoader instanceof Promise) {
236
- return /* @__PURE__ */ React.createElement(Suspense, null, /* @__PURE__ */ React.createElement(Await, { resolve: weaverseDataFromLoader }, (resolvedData) => {
237
- console.log("resolvedData", resolvedData);
238
- return /* @__PURE__ */ React.createElement(
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(
239
281
  RenderWeaverseRoot,
240
282
  {
241
- components,
242
- themeSchema,
243
- weaverseData: resolvedData
283
+ weaverseData: resolvedData,
284
+ components
244
285
  }
245
286
  );
246
- }));
287
+ })));
247
288
  }
248
- return /* @__PURE__ */ React.createElement(
289
+ return /* @__PURE__ */ React2.createElement(
249
290
  RenderWeaverseRoot,
250
291
  {
251
- components,
252
- themeSchema,
253
- weaverseData: weaverseDataFromLoader
292
+ weaverseData: weaverseDataFromLoader,
293
+ components
254
294
  }
255
295
  );
256
296
  }
257
- return /* @__PURE__ */ React.createElement("div", { style: { display: "none" } }, "No weaverseData return from Remix loader!");
297
+ return /* @__PURE__ */ React2.createElement(
298
+ ErrorComponent,
299
+ {
300
+ error: { message: "No Weaverse data return from route loader!" }
301
+ }
302
+ );
258
303
  }
259
- var RenderWeaverseRoot = (props) => {
260
- let { components, themeSchema, weaverseData } = props;
304
+ function RenderWeaverseRoot(props) {
305
+ let { components, weaverseData } = props;
261
306
  let weaverse = createWeaverseInstance(weaverseData, components);
262
- useStudio(weaverse, themeSchema);
263
- return /* @__PURE__ */ React.createElement(WeaverseRoot, { context: weaverse });
264
- };
307
+ useStudio(weaverse);
308
+ return /* @__PURE__ */ React2.createElement(WeaverseRoot, { context: weaverse });
309
+ }
265
310
  export {
311
+ HydrogenStudio,
266
312
  WeaverseHydrogenRoot,
267
313
  fetchWithServerCache,
314
+ getSelectedProductOptions,
268
315
  useThemeSettings,
269
316
  weaverseLoader
270
317
  };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.0",
2
+ "version": "1.1.1",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -34,7 +34,8 @@
34
34
  "dependencies": {
35
35
  "@remix-run/react": "1.19.1",
36
36
  "@shopify/hydrogen": "2023.7.1",
37
- "@weaverse/react": "1.1.0"
37
+ "@weaverse/react": "1.1.1",
38
+ "react-error-boundary": "^4.0.10"
38
39
  },
39
40
  "devDependencies": {
40
41
  "@shopify/remix-oxygen": "^1.1.2"