@shopify/hydrogen 0.11.0 → 0.11.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +511 -0
  2. package/dist/esnext/components/AddToCartButton/AddToCartButton.client.js +2 -2
  3. package/dist/esnext/components/CartLinePrice/CartLinePrice.client.d.ts +2 -2
  4. package/dist/esnext/components/CartLineProductTitle/CartLineProductTitle.client.d.ts +1 -1
  5. package/dist/esnext/components/CartLineQuantity/CartLineQuantity.client.d.ts +1 -1
  6. package/dist/esnext/components/LocalizationProvider/LocalizationProvider.server.d.ts +5 -2
  7. package/dist/esnext/components/Metafield/Metafield.client.d.ts +3 -3
  8. package/dist/esnext/components/Metafield/components/StarRating/StarRating.d.ts +3 -3
  9. package/dist/esnext/components/Money/Money.client.d.ts +3 -3
  10. package/dist/esnext/components/ProductMetafield/ProductMetafield.client.d.ts +2 -2
  11. package/dist/esnext/components/ProductPrice/ProductPrice.client.d.ts +2 -2
  12. package/dist/esnext/components/ProductTitle/ProductTitle.client.d.ts +1 -1
  13. package/dist/esnext/components/RawHtml/RawHtml.d.ts +3 -3
  14. package/dist/esnext/components/Seo/ProductSeo.client.js +3 -1
  15. package/dist/esnext/components/Seo/types.d.ts +1 -1
  16. package/dist/esnext/components/UnitPrice/UnitPrice.client.d.ts +3 -3
  17. package/dist/esnext/entry-client.js +9 -6
  18. package/dist/esnext/foundation/ServerRequestProvider/ServerRequestProvider.js +8 -1
  19. package/dist/esnext/foundation/useQuery/hooks.d.ts +15 -5
  20. package/dist/esnext/foundation/useQuery/hooks.js +5 -4
  21. package/dist/esnext/framework/Hydration/ServerComponentRequest.server.js +4 -1
  22. package/dist/esnext/framework/plugins/vite-plugin-platform-entry.js +1 -1
  23. package/dist/esnext/hooks/useProductOptions/useProductOptions.d.ts +1 -1
  24. package/dist/esnext/hooks/useProductOptions/useProductOptions.js +8 -8
  25. package/dist/esnext/hooks/useShopQuery/hooks.d.ts +7 -2
  26. package/dist/esnext/types.d.ts +3 -1
  27. package/dist/esnext/utilities/log/log-query-timeline.d.ts +1 -1
  28. package/dist/esnext/utilities/log/log-query-timeline.js +4 -3
  29. package/dist/esnext/version.d.ts +1 -1
  30. package/dist/esnext/version.js +1 -1
  31. package/dist/node/foundation/ServerRequestProvider/ServerRequestProvider.js +8 -1
  32. package/dist/node/framework/Hydration/ServerComponentRequest.server.js +4 -1
  33. package/dist/node/framework/plugins/vite-plugin-platform-entry.js +1 -1
  34. package/dist/node/types.d.ts +3 -1
  35. package/dist/node/utilities/log/log-query-timeline.d.ts +1 -1
  36. package/dist/node/utilities/log/log-query-timeline.js +4 -3
  37. package/package.json +2 -3
  38. package/LICENSE.md +0 -7
package/CHANGELOG.md ADDED
@@ -0,0 +1,511 @@
1
+ # Changelog
2
+
3
+ ## 0.11.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#770](https://github.com/Shopify/hydrogen/pull/770) [`71e0255`](https://github.com/Shopify/hydrogen/commit/71e0255ea48dc1caa34d2c05a1556cc0ce6d4ce9) Thanks [@mcvinci](https://github.com/mcvinci)! - Hydrogen docs: Framework and global hooks content updates
8
+
9
+ * [#761](https://github.com/Shopify/hydrogen/pull/761) [`1142647`](https://github.com/Shopify/hydrogen/commit/114264716bc8f3027e3e6395d523714adbc92014) Thanks [@frehner](https://github.com/frehner)! - Fix issue with components that take in the `as` prop not validating other props when a component is passed to `as`.
10
+
11
+ - [#752](https://github.com/Shopify/hydrogen/pull/752) [`b96179f`](https://github.com/Shopify/hydrogen/commit/b96179fdf960da52332a981e29a742b677826834) Thanks [@jplhomer](https://github.com/jplhomer)! - Ensure ProductSeo knows how to handle `featuredImage = null`
12
+
13
+ * [#774](https://github.com/Shopify/hydrogen/pull/774) [`052f148`](https://github.com/Shopify/hydrogen/commit/052f148e0d33029cdc2540afa5ead32825962f3a) Thanks [@frandiox](https://github.com/frandiox)! - Fix internal url usage in platforms like Vercel, which already provides protocol and host in `request.url`.
14
+
15
+ - [#744](https://github.com/Shopify/hydrogen/pull/744) [`2e487b7`](https://github.com/Shopify/hydrogen/commit/2e487b7e70fe0572538dc2a24b6b6b36ba9fc804) Thanks [@jplhomer](https://github.com/jplhomer)! - Switch to using Changesets for changelogs.
16
+
17
+ * [#775](https://github.com/Shopify/hydrogen/pull/775) [`d5b7ee1`](https://github.com/Shopify/hydrogen/commit/d5b7ee1d8312f64922d1f78afc82ec5ad4a3f457) Thanks [@cartogram](https://github.com/cartogram)! - In cases where the `initialVariantId` is missing on the `<ProductProvider />`, the `selectedVariantId` in the returned `object` from `useProduct()` will now use the first available variant _or_ the first variant (if non are available).
18
+
19
+ - [#773](https://github.com/Shopify/hydrogen/pull/773) [`b6a053e`](https://github.com/Shopify/hydrogen/commit/b6a053e774da443b5692dec51546f5558b3018ad) Thanks [@frandiox](https://github.com/frandiox)! - Fix server bundle name in cases where CSS or images are imported in server components.
20
+
21
+ * [#764](https://github.com/Shopify/hydrogen/pull/764) [`5e55da4`](https://github.com/Shopify/hydrogen/commit/5e55da4090692369ff6a3d57fbc6d29124bdf2e9) Thanks [@wizardlyhel](https://github.com/wizardlyhel)! - Preload queries breaking fetch on Cloudfare [#764](https://github.com/Shopify/hydrogen/pull/764)
22
+
23
+ - [#763](https://github.com/Shopify/hydrogen/pull/763) [`ea2857a`](https://github.com/Shopify/hydrogen/commit/ea2857a515866f37f392bca5da8be1139c055a64) Thanks [@frehner](https://github.com/frehner)! - Client-side apps now have React's `StrictMode` component wrapping the whole app, with an option to disable it. If you do turn it off, it is recommended that you still include the `StrictMode` component at as high of a level as possible in your React tree.
24
+
25
+ See also [React 17's docs](https://reactjs.org/docs/strict-mode.html) on `StrictMode`, and [React 18's updates](https://github.com/reactwg/react-18/discussions/19) to `StrictMode`.
26
+
27
+ * [#747](https://github.com/Shopify/hydrogen/pull/747) [`2d8ab7e`](https://github.com/Shopify/hydrogen/commit/2d8ab7e2a8038ff8b43e6e9398e0bb2da72220a0) Thanks [@mcvinci](https://github.com/mcvinci)! - Hydrogen docs: Preloaded queries and query timing
28
+
29
+ ## [0.11.0] - 2022-02-24
30
+
31
+ ### Added
32
+
33
+ - New React hook `useScriptLoader` is available to more easily load external scripts
34
+ - Add `totalQuantity` to the returned object from `useCart()`
35
+ - Export `ProductPrice` and `ProductMetafield` standalone components
36
+ - Added `useUrl` hook that allows the consumer to get the current url in server or client component
37
+ - Added logging option `showCacheApiStatus` and `cacheControlHeader` by @wizardlyhel in [#472](https://github.com/Shopify/hydrogen/pull/472)
38
+ - Pass HYDROGEN_ASSET_BASE_URL into config to set base URL for compiled assets
39
+ - Introduce Hydrogen the `<Link>` component and `useNavigate` hook for routing
40
+ - Add a default virtual entry-client in `/@shopify/hydrogen/entry-client` that can be used in `index.html`
41
+ - Enable early hydration when streaming
42
+ - Add variantId prop to `<ProductMetafield />` component [#730](https://github.com/Shopify/hydrogen/pull/730)
43
+ - Add query timing logging option `showQueryTiming` [#699](https://github.com/Shopify/hydrogen/pull/699)
44
+ - Add variantId prop to `<ProductPrice />` component
45
+ - Add `preload` option to `useQuery` and `useShopQuery` [#700](https://github.com/Shopify/hydrogen/pull/700)
46
+
47
+ ### Breaking Change
48
+
49
+ - `<Model3D>` has been renamed to `<ModelViewer>`
50
+ - `<Product />` and `<CartLine />` aliases have been removed; use the original components `<ProductProvider />` and `<CartLineProvider />` instead. Their nested component aliases, such as `<Product.Image />`, have also been removed; in this example you should use `<ProductImage />`.
51
+ - Merge `/src/entry-server.jsx` entry point into `App.server.jsx`
52
+ - The following components had their prop name renamed. Refer to the documentation or [#627](https://github.com/Shopify/hydrogen/issues/627) for more details.
53
+ - `<ExternalVideo />`: renamed video prop to data
54
+ - `<Video />`: renamed video prop to data
55
+ - `<Image>`: renamed image prop to data
56
+ - `<MediaFile>`: renamed media prop to data
57
+ - `<ModelViewer>`: renamed model prop to data
58
+ - `<Metafield>`: renamed metafield prop to data
59
+ - `<Money>`: renamed money prop to data
60
+ - `<UnitPrice>`: renamed unitPrice prop to data, unitPriceMeasurement prop to measurement
61
+ - `<ProductProvider>`: renamed product prop to data
62
+ - `<CartProvider>`: renamed cart prop to data
63
+ - Helmet component has been renamed to Head
64
+ - Remove the `<SelectedVariantBuyNowButton />` component in favour of using `<BuyNowButton variantId={product.selectedVariant.id} />`
65
+ - `<SelectedVariantAddToCartButton />` has been removed; the `<AddToCartButton />` will now use the selectedVariant by default.
66
+ - Remove the `<SelectedVariantImage />` component in favour of using `<Image data={product.selectedVariant.image} />`
67
+ - Remove the `<SelectedVariantMetafield />` component in favour of using `<ProductMetafield variantId={product.selectedVariant.id} />`
68
+ - Remove the `<SelectedVariantShopPayButton />` component in favour of using `<ShopPayButton variantId={product.selectedVariant.id} />`
69
+ - Remove the `<SelectedVariantPrice/>` and `<SelectedVariantUnitPrice/>` component in favour of using `<ProductPrice variantId={product.selectedVariant.id} />`
70
+
71
+ ### Changed
72
+
73
+ - Change `/react` RSC path to `/__rsc`
74
+ - `<ShopifyProvider>` can again be used in server components
75
+ - Use hashes as client component ids instead of absolute paths
76
+ - Transition away from deprecated currency selector in favor of country selector
77
+ - Simplify Helmet usage and make it compatible with RSC
78
+ - The `Seo.client` component has been moved from `src/components` to `@shopify/hydrogen`. The props of the `Seo.client` component also changed to always take in `type` and `data`. Refer to the [`Seo` component reference](../src/components/Seo/README.md) for more details. [#539](https://github.com/Shopify/hydrogen/pull/539)
79
+ - Standardize cache control header into caching strategies by @wizardlyhel in [#629](https://github.com/Shopify/hydrogen/pull/629)
80
+ - Target future release to use '2022-01' API Version
81
+ - Correct Typescript issue where `as` was a default prop for all components when it should not be
82
+ - Update types and docs for `useCart()` hook and `<CartProvider>`
83
+ - Track page load performance
84
+ - The following money components no longer allow the function-as-a-child (also known as "render props") pattern; see [#589](https://github.com/Shopify/hydrogen/pull/589)
85
+ - `<Money>` Use `useMoney()` for customization
86
+ - `<CartLinePrice>` Use `useMoney()` for customization
87
+ - `<ProductPrice>` Use `useMoney()` for customization
88
+ - `<SelectedVariantPrice>` Use `useMoney()` for customization
89
+ - `<Metafield>` Use `useParsedMetafields()` for customization
90
+ - `<ProductMetafield>` Use `useParsedMetafields()` for customization
91
+ - `<SelectedVariantMetafield>` Use `useParsedMetafields()` for customization
92
+ - `<UnitPrice>` Use `useMoney()` for customization
93
+ - `<CartLines>` Use `useCart()` for customization
94
+ - `<Metafield>` now renders `ratings` as a `<span>` with text instead of stars; `multi_line_text_field` inside of a `<span>` instead of a `<div>`
95
+ - Use `featureImage` instead of images(first:1) on product query
96
+ - Update `react-helmet-async` to 1.2.3 and remove our custom types
97
+
98
+ ### Fixed
99
+
100
+ - Fix index routes. See [#562](https://github.com/Shopify/hydrogen/issues/562)
101
+ - Fix missing server state on SSR pass
102
+ - Fix mobile navigation in example that scrolls the body underneath when shown by @Francismori7 in [#582](https://github.com/Shopify/hydrogen/pull/582)
103
+ - Add charset to content type in HTML responses
104
+ - Fix header shift when cart is opened by @Francismori7 in [#600](https://github.com/Shopify/hydrogen/pull/600)
105
+ - Fix bug where search param is not being pass along during RSC streaming call [#623](https://github.com/Shopify/hydrogen/pull/623)
106
+ - Allow custom entry-client filenames
107
+ - Clear browser fetch cache by @wizardlyhel in [#591](https://github.com/Shopify/hydrogen/pull/591)
108
+ - Cannot redefine property error when updating client components
109
+ - `ShopPayButton` supports quantities greater than 1. Also fixed issues with IDs in Storefront API version 2022-01
110
+ - Render error in `Gallery.client.jsx` component when product resource has an external video or no images.
111
+ - Ensure youtube external videos are embed compatible urls
112
+ - Prevent client components from being cached during development
113
+ - Backticks in HTML break RSC hydration.
114
+
115
+ ### Removed
116
+
117
+ - <CartLineSelectedOptions /> and <CartLineAttributes /> components. These components used the “function-as-a-child” pattern which doesn’t allow the `children` prop to be serialized, preventing them from being rendered within Server components.
118
+
119
+ _Migration_
120
+
121
+ The functionality provided by these components can be replicated using the `useCartLine()` hook instead.
122
+
123
+ _Example_
124
+
125
+ ```tsx
126
+ // Before
127
+ function SomeComponent() {
128
+ return (
129
+ <>
130
+ <CartLineSelectedOptions as="ul" className="text-xs space-y-1">
131
+ {({name, value}) => (
132
+ <>
133
+ {name}: {value}
134
+ </>
135
+ )}
136
+ </CartLineSelectedOptions>
137
+ <CartLineAttributes as="ul" className="text-sm space-y-1">
138
+ {({key, value}) => (
139
+ <>
140
+ {key}: {value}
141
+ </>
142
+ )}
143
+ </CartLineAttributes>
144
+ </>
145
+ );
146
+ }
147
+
148
+ // After
149
+ function SomeComponent() {
150
+ const {merchandise} = useCartLine();
151
+
152
+ return (
153
+ <>
154
+ <ul className="text-xs space-y-1">
155
+ {merchandise.selectedOptions.map(({name, value}) => (
156
+ <li key={name}>
157
+ {name}: {value}
158
+ </li>
159
+ ))}
160
+ </ul>
161
+ </>
162
+ );
163
+ }
164
+ ```
165
+
166
+ - Remove `fetch` workaround
167
+ - Remove the following hooks. (All the same functionality can be retrieved through the `useCart()` hook)
168
+ - `useCartAttributesUpdateCallback`
169
+ - `useCartBuyerIdentityUpdateCallback`
170
+ - `useCartCheckoutUrl`
171
+ - `useCartCreateCallback`
172
+ - `useCartDiscountCodesUpdateCallback`
173
+ - `useCartLinesAddCallback`
174
+ - `useCartLinesRemoveCallback`
175
+ - `useCartLinesTotalQuantity`
176
+ - `useCartLinesUpdateCallback`
177
+ - `useCartNoteUpdateCallback`
178
+ - Remove React Router on the client
179
+ - Remove `handleEvent` in favor of `handleRequest`
180
+ - Remove `assetHandler` parameter in the new `handleRequest`
181
+ - `<SelectedVariantAddToCartButton />` has been removed; the `<AddToCartButton />` will now use the selectedVariant by default.
182
+ - Remove the `<SelectedVariantImage />` component in favour of using `<Image data={product.selectedVariant.image} />`
183
+ - Remove the `<SelectedVariantMetafield />` component in favour of using `<ProductMetafield variantId={product.selectedVariant.id} />`
184
+ - Remove the `<SelectedVariantBuyNowButton />` component in favour of using `<BuyNowButton variantId={product.selectedVariant.id} />`
185
+ - Remove the `<SelectedVariantShopPayButton />` component in favour of using `<ShopPayButton variantId={product.selectedVariant.id} />`
186
+
187
+ ## [0.10.1] - 2022-01-26
188
+
189
+ ### Fixed
190
+
191
+ - Hot reload for newly added page files
192
+
193
+ ## [0.10.0] - 2022-01-25
194
+
195
+ ### Changed
196
+
197
+ - Warn instead of error when a page server component is missing valid exports
198
+ - Adopt upstream version of React Server Components. See [#498](https://github.com/Shopify/hydrogen/pull/498) for breaking changes
199
+ - Bump to latest version of React experimental to include [upstream context bugfix](https://github.com/facebook/react/issues/23089)
200
+ - Improve API routes by allowing [strings and JS objects](https://github.com/Shopify/hydrogen/issues/476) to be returned.
201
+
202
+ ### Breaking Change
203
+
204
+ - The 'locale' option in shopify.config.js had been renamed to 'defaultLocale'
205
+ - Rename `graphqlApiVersion` to `storefrontApiVersion` in `shopify.config.js`
206
+
207
+ ### Fixed
208
+
209
+ - Make sure that API routes [hot reload properly](https://github.com/Shopify/hydrogen/issues/497)
210
+
211
+ ## [0.9.1] - 2022-01-20
212
+
213
+ ### Changed
214
+
215
+ - Transitive dependency bump.
216
+
217
+ ## [0.9.0] - 2022-01-20
218
+
219
+ ### Added
220
+
221
+ - API routes 🎉
222
+
223
+ ### Changed
224
+
225
+ - Move to undici instead of node-fetch
226
+
227
+ ## [0.8.3] - 2022-01-13
228
+
229
+ ### Added
230
+
231
+ - Add optional `locale` param to `useShopQuery` to be used as `Accept-Language` in the store Storefront API query
232
+ - Optional purge query cache per build
233
+
234
+ ### Fixed
235
+
236
+ - Replace log abbreviations with full text.
237
+
238
+ ## [0.8.2] - 2022-01-07
239
+
240
+ ### Changed
241
+
242
+ - Warn when requests take longer than 3000ms instead of erroring
243
+ - `useQuery` returns an error if the query's fetch was unsuccessful
244
+ - `useShopQuery` will give error hints to look at `shopify.config.js` when the Storefront API responds with a 403
245
+
246
+ ### Fixed
247
+
248
+ - Load logger only once.
249
+ - Do not attempt to decode product IDs, as they are no longer base64-encoded in `unstable`
250
+
251
+ ## [0.8.1] - 2022-01-04
252
+
253
+ ### Added
254
+
255
+ - Detect bot user agents and give bots a non-streamed response.
256
+ - Add global `Oxygen.env` for server-only environment variables.
257
+ - Logging abstraction with default timing information
258
+
259
+ ### Changed
260
+
261
+ - Upgrade to latest React 18 experimental version
262
+
263
+ ### Fixed
264
+
265
+ - Cart decrease button removes at zero quantity
266
+
267
+ ## [0.8.0] - 2021-12-07
268
+
269
+ ### Fixed
270
+
271
+ - Export `CartLineSelectedOptions` properly
272
+ - Fix suspense utility function
273
+
274
+ ## [0.7.1] - 2021-12-02
275
+
276
+ ### Changed
277
+
278
+ - Allow `useShopQuery` to be skippable if no query is passed
279
+ - Remove usage of `react-query` (Not a breaking change)
280
+
281
+ ### Fixed
282
+
283
+ - Avoid repeating the same identifier for default and named exports
284
+ - Remove sourcemap warnings
285
+
286
+ ## [0.7.0] - 2021-11-22
287
+
288
+ ### Added
289
+
290
+ - Add file reference metafield support
291
+ - Allow custom Model3D poster
292
+ - Support synchronous server redirects
293
+
294
+ ### Fixed
295
+
296
+ - Binding of waitUntil in playground/server-components-worker
297
+ - Default to `retry: false` in `useQuery`
298
+ - Warn and ignore reserved properties in server state
299
+ - Run graphiql middleware before vite, fixing graphiql
300
+
301
+ ## [0.6.4] - 2021-11-11
302
+
303
+ ### Fixed
304
+
305
+ - Let Vite handle public assets in development
306
+ - New lines in hydration request break JSON.parse
307
+ - Normalize POSIX separators to support windows [#201](https://github.com/Shopify/hydrogen/pull/201)
308
+ - Scroll to top on app first load
309
+ - Update variantID to variantId [#78](https://github.com/Shopify/hydrogen/pull/78)
310
+
311
+ ## [0.6.3] - 2021-11-10
312
+
313
+ ### Fixed
314
+
315
+ - Add trailing slash to user components glob
316
+
317
+ ## [0.6.2] - 2021-11-10
318
+
319
+ ### Fixed
320
+
321
+ - Remove CartProvider from BuyNowButton
322
+ - Reading property of null for component props
323
+ - Transform deeply-imported client components
324
+ - Duplicated files and contexts in browser
325
+
326
+ ## [0.6.1] - 2021-11-08
327
+
328
+ ### Changed
329
+
330
+ - Transitive dependency bump.
331
+
332
+ ### Fixed
333
+
334
+ - Do not set headers after they are sent to client
335
+
336
+ ## [0.6.0] - 2021-11-05
337
+
338
+ ### Changed
339
+
340
+ - Disable the quantity adjust button when the cart is not idle
341
+ - Use country server state in cart for the inContext directive
342
+ - Use Image url field instead of deprecated originalSrc field
343
+ - Switch to unstable API
344
+
345
+ ### Fixed
346
+
347
+ - Update interaction prompt and interaction promp style attributes for Model3d
348
+ - Make sure all errors show an error dialog when hydrogen is in dev mode
349
+ - MediaFile component warning on non-Model3D types
350
+ - Remove console logs for caching
351
+ - Lowercased SVG tags in RSC
352
+ - Make the URL search property available via hooks
353
+
354
+ ## 0.5.8 - 2021-11-04
355
+
356
+ ### Fixed
357
+
358
+ - Ensure delayed callback is fired for cache purposes in Workers runtimes.
359
+
360
+ ## 0.5.3 - 2021-11-02
361
+
362
+ ### Changed
363
+
364
+ - No updates. Transitive dependency bump.
365
+
366
+ ## 0.5.2 - 2021-11-02
367
+
368
+ ### Changed
369
+
370
+ - No updates. Transitive dependency bump.
371
+
372
+ ## 0.5.1 - 2021-11-02
373
+
374
+ ### Changed
375
+
376
+ - No updates. Transitive dependency bump.
377
+
378
+ ## 0.5.0 - 2021-11-01
379
+
380
+ ### Fixed
381
+
382
+ - Update the ServerStateProvider context
383
+ - Add tabIndex to ShopPayButton
384
+ - Update LocalizationProvider query, context, and exports
385
+
386
+ ## 0.4.3 - 2021-10-29
387
+
388
+ ### Added
389
+
390
+ - Introduct full-page and sub-request caching API.
391
+
392
+ ## 0.4.2 - 2021-10-29
393
+
394
+ ### Changed
395
+
396
+ - Update Model3D props and add binding to model-viewer events
397
+
398
+ ### Fixed
399
+
400
+ - Add `passthoughProps.disabled` to `AddToCartButton`
401
+ - Do not show undefined currency symbol in production
402
+
403
+ ## 0.4.0 - 2021-10-27
404
+
405
+ ### Added
406
+
407
+ - Add external image support to Image component
408
+
409
+ ### Changed
410
+
411
+ - Make `CartProvider` a client-only concern. [#631](https://github.com/Shopify/hydrogen/pull/631)
412
+ - Use `Accept: application/hydrogen` as a header when making `fetch` calls against a Hydrogen page. Useful for Custom Responses.
413
+
414
+ ### Fixed
415
+
416
+ - Lock model-viewer.js version to 1.8
417
+ - Use the Intl.NumberFormat parts for determining the amount value returned by the useMoney hook
418
+ - Optimize React related dependencies at server start to avoid page reloads
419
+ - Do not throw when `storeDomain` contains protocol.
420
+
421
+ ## 0.3.0 - 2021-10-20
422
+
423
+ ### Added
424
+
425
+ - Export utilities in client bundle
426
+
427
+ ### Fixed
428
+
429
+ - `parseCookies` will split only on first =
430
+ - Make BuyNowButton a client component since it uses useEffect
431
+ - Preserve original aspect ratio for product images
432
+ - Invoke CartProvider callbacks before performing the GraphQL mutations
433
+ - Fix the accessible label in the AddToCartButton component when an item is added to cart
434
+ - Cart fetch to return stringified error
435
+
436
+ ### Removed
437
+
438
+ - Remove sourcemap warnings
439
+
440
+ ## 0.2.1 - 2021-10-12
441
+
442
+ ### Fixed
443
+
444
+ - Starter template GalleryPreview unique key warning
445
+ - Mitigation for upcoming breaking minor Vite update
446
+
447
+ ## 0.2.0 - 2021-10-08
448
+
449
+ ### Added
450
+
451
+ - Added support for images and collections in the ProductProvider component
452
+ - Added more GraphQL fragments for building block components (Metafield, UnitPrice) and updated exports of these fragments
453
+
454
+ ### Breaking Change
455
+
456
+ - `useQuery` now behaves exactly like [react-query's hook of the same name](https://react-query.tanstack.com/reference/useQuery#_top)
457
+
458
+ ### Fixed
459
+
460
+ - Handle products with selling plans
461
+
462
+ ## 0.1.2 - 2021-09-30
463
+
464
+ ### Fixed
465
+
466
+ - SSR issue when running Vite 2.6
467
+ - Occasional `ProductProviderFragment` error when booting Hydrogen dev server [#571](https://github.com/Shopify/hydrogen/issues/571)
468
+
469
+ ## 0.1.1 - 2021-09-24
470
+
471
+ ### Added
472
+
473
+ - New GraphQL fragments for Variants, SellingPlans, and SellingPlanGroups
474
+
475
+ ### Changed
476
+
477
+ - Updated types for the `useProductOptions` hook
478
+
479
+ ### Fixed
480
+
481
+ - `Dynamic require of "stream" is not supported` error in browser logs
482
+
483
+ ## 0.1.0 - 2021-09-23
484
+
485
+ ### Changed
486
+
487
+ - No updates. Transitive dependency bump.
488
+
489
+ ## 1.0.0-alpha.22 - 2021-09-22
490
+
491
+ ### Changed
492
+
493
+ - No updates. Transitive dependency bump.
494
+
495
+ [0.6.0]: https://github.com/Shopify/hydrogen/releases/tag/v0.6.0
496
+ [0.6.1]: https://github.com/Shopify/hydrogen/releases/tag/v0.6.1
497
+ [0.6.2]: https://github.com/Shopify/hydrogen/releases/tag/v0.6.2
498
+ [0.6.3]: https://github.com/Shopify/hydrogen/releases/tag/v0.6.3
499
+ [0.6.4]: https://github.com/Shopify/hydrogen/releases/tag/v0.6.4
500
+ [0.7.0]: https://github.com/Shopify/hydrogen/releases/tag/v0.7.0
501
+ [0.7.1]: https://github.com/Shopify/hydrogen/releases/tag/v0.7.1
502
+ [0.8.0]: https://github.com/Shopify/hydrogen/releases/tag/v0.8.0
503
+ [0.8.1]: https://github.com/Shopify/hydrogen/releases/tag/v0.8.1
504
+ [0.8.2]: https://github.com/Shopify/hydrogen/releases/tag/v0.8.2
505
+ [0.8.3]: https://github.com/Shopify/hydrogen/releases/tag/v0.8.3
506
+ [0.9.0]: https://github.com/Shopify/hydrogen/releases/tag/v0.9.0
507
+ [0.9.1]: https://github.com/Shopify/hydrogen/releases/tag/v0.9.1
508
+ [0.10.0]: https://github.com/Shopify/hydrogen/releases/tag/v0.10.0
509
+ [0.10.1]: https://github.com/Shopify/hydrogen/releases/tag/v0.10.1
510
+ [0.11.0]: https://github.com/Shopify/hydrogen/releases/tag/v0.11.0
511
+ [unreleased]: https://github.com/Shopify/hydrogen/compare/v0.11.0...HEAD
@@ -6,12 +6,12 @@ import { useProduct } from '../ProductProvider';
6
6
  * It must be a descendent of the `CartProvider` component.
7
7
  */
8
8
  export function AddToCartButton(props) {
9
- var _a, _b, _c, _d, _e, _f, _g, _h;
9
+ var _a, _b;
10
10
  const [addingItem, setAddingItem] = useState(false);
11
11
  const { variantId: explicitVariantId, quantity = 1, attributes, children, onAdd, accessibleAddingToCartLabel, ...passthroughProps } = props;
12
12
  const { status, id, cartCreate, linesAdd } = useCart();
13
13
  const product = useProduct();
14
- const variantId = (_h = (_e = (_b = explicitVariantId !== null && explicitVariantId !== void 0 ? explicitVariantId : (_a = product === null || product === void 0 ? void 0 : product.selectedVariant) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : (_d = (_c = product === null || product === void 0 ? void 0 : product.variants) === null || _c === void 0 ? void 0 : _c.find((variant) => variant.availableForSale)) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : (_g = (_f = product === null || product === void 0 ? void 0 : product.variants) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.id) !== null && _h !== void 0 ? _h : '';
14
+ const variantId = (_b = explicitVariantId !== null && explicitVariantId !== void 0 ? explicitVariantId : (_a = product === null || product === void 0 ? void 0 : product.selectedVariant) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : '';
15
15
  const disabled = explicitVariantId === null ||
16
16
  variantId === '' ||
17
17
  (product === null || product === void 0 ? void 0 : product.selectedVariant) === null ||
@@ -1,7 +1,7 @@
1
1
  import { ElementType } from 'react';
2
2
  import { MoneyProps } from '../Money';
3
3
  import { Props } from '../types';
4
- export interface CartLinePriceProps extends Omit<MoneyProps, 'data'> {
4
+ export interface CartLinePriceProps<TTag> extends Omit<MoneyProps<TTag>, 'data'> {
5
5
  /** The type of price. Valid values:`regular` (default) or `compareAt`. */
6
6
  priceType?: 'regular' | 'compareAt';
7
7
  }
@@ -9,4 +9,4 @@ export interface CartLinePriceProps extends Omit<MoneyProps, 'data'> {
9
9
  * The `CartLinePrice` component renders a `Money` component for the cart line merchandise's price or
10
10
  * compare at price. It must be a descendent of a `CartLineProvider` component.
11
11
  */
12
- export declare function CartLinePrice<TTag extends ElementType>(props: Props<TTag> & CartLinePriceProps): JSX.Element | null;
12
+ export declare function CartLinePrice<TTag extends ElementType>(props: Props<TTag> & CartLinePriceProps<TTag>): JSX.Element | null;
@@ -6,5 +6,5 @@ import { Props } from '../types';
6
6
  */
7
7
  export declare function CartLineProductTitle<TTag extends ElementType>(props: Props<TTag> & {
8
8
  /** An HTML tag to be rendered as the base element wrapper. The default is `span`. */
9
- as?: ElementType;
9
+ as?: TTag;
10
10
  }): JSX.Element;
@@ -6,5 +6,5 @@ import { Props } from '../types';
6
6
  */
7
7
  export declare function CartLineQuantity<TTag extends ElementType>(props: Props<TTag> & {
8
8
  /** An HTML tag to be rendered as the base element wrapper. The default is `div`. */
9
- as?: ElementType;
9
+ as?: TTag;
10
10
  }): JSX.Element;
@@ -2,9 +2,12 @@ import { ReactNode, ElementType } from 'react';
2
2
  import { PreloadOptions } from '../../types';
3
3
  import { Props } from '../types';
4
4
  export interface LocalizationProviderProps {
5
- /** Any ReactNode elements. */
5
+ /** A `ReactNode` element. */
6
6
  children: ReactNode;
7
- /** `true` to preload the localization query for the url or `'*'` to preload the localization query for all urls */
7
+ /** Whether to preload the query. Defaults to `false`. Specify `true` to
8
+ * [preload the query](/custom-storefronts/hydrogen/framework/preloaded-queries) for the URL
9
+ * or `'*'` to preload the query for all requests.
10
+ */
8
11
  preload: PreloadOptions;
9
12
  }
10
13
  /**
@@ -1,11 +1,11 @@
1
1
  import { ElementType } from 'react';
2
2
  import { Props } from '../types';
3
3
  import { ParsedMetafield } from '../../types';
4
- export interface MetafieldProps {
4
+ export interface MetafieldProps<TTag> {
5
5
  /** A [Metafield object](/api/storefront/reference/common-objects/metafield) from the Storefront API. */
6
6
  data: ParsedMetafield;
7
7
  /** An HTML tag to be rendered as the base element wrapper. The default value varies depending on [metafield.type](/apps/metafields/types). */
8
- as?: ElementType;
8
+ as?: TTag;
9
9
  }
10
10
  /**
11
11
  * The `Metafield` component renders the value of a Storefront
@@ -14,7 +14,7 @@ export interface MetafieldProps {
14
14
  * Renders a smart default of the
15
15
  * Metafield's `value`. For more information, refer to the [Default Output](#default-output) section.
16
16
  */
17
- export declare function Metafield<TTag extends ElementType>(props: Props<TTag> & MetafieldProps): JSX.Element | null;
17
+ export declare function Metafield<TTag extends ElementType>(props: Props<TTag> & MetafieldProps<TTag>): JSX.Element | null;
18
18
  export declare namespace Metafield {
19
19
  var Fragment: string;
20
20
  }
@@ -3,12 +3,12 @@ import { Props } from '../../../types';
3
3
  import { Rating } from '../../../../types';
4
4
  export declare const STAR_EMPTY = "\u2606";
5
5
  export declare const STAR_FILLED = "\u2605";
6
- export interface StarRatingProps {
6
+ export interface StarRatingProps<TTag> {
7
7
  rating: Rating;
8
8
  /** An HTML tag to be rendered as the base element wrapper. The default is `div`. */
9
- as?: ElementType;
9
+ as?: TTag;
10
10
  }
11
- export declare function StarRating<TTag extends ElementType>(props: Props<TTag> & StarRatingProps): JSX.Element;
11
+ export declare function StarRating<TTag extends ElementType>(props: Props<TTag> & StarRatingProps<TTag>): JSX.Element;
12
12
  export declare function Star({ percentFilled }: {
13
13
  percentFilled: number;
14
14
  }): JSX.Element;
@@ -1,9 +1,9 @@
1
1
  import { ElementType } from 'react';
2
2
  import { Props } from '../types';
3
3
  import { MoneyV2 } from '../../graphql/types/types';
4
- export interface MoneyProps {
4
+ export interface MoneyProps<TTag> {
5
5
  /** An HTML tag to be rendered as the base element wrapper. The default is `div`. */
6
- as?: ElementType;
6
+ as?: TTag;
7
7
  /** A [`MoneyV2` object](/api/storefront/reference/common-objects/moneyv2). */
8
8
  data: MoneyV2;
9
9
  }
@@ -12,7 +12,7 @@ export interface MoneyProps {
12
12
  * [`MoneyV2` object](/api/storefront/reference/common-objects/moneyv2) according to the
13
13
  * `defaultLocale` in the `shopify.config.js` file.
14
14
  */
15
- export declare function Money<TTag extends ElementType>(props: Props<TTag> & MoneyProps): JSX.Element;
15
+ export declare function Money<TTag extends ElementType>(props: Props<TTag> & MoneyProps<TTag>): JSX.Element;
16
16
  export declare namespace Money {
17
17
  var Fragment: string;
18
18
  }
@@ -1,7 +1,7 @@
1
1
  import { ElementType } from 'react';
2
2
  import { Props } from '../types';
3
3
  import { MetafieldProps } from '../Metafield/Metafield.client';
4
- export interface ProductMetafieldProps extends Omit<MetafieldProps, 'metafield'> {
4
+ export interface ProductMetafieldProps<TTag> extends Omit<MetafieldProps<TTag>, 'metafield'> {
5
5
  /** A string corresponding to the [key](/api/storefront/reference/common-objects/metafield) of the product's
6
6
  * metafield.
7
7
  */
@@ -18,4 +18,4 @@ export interface ProductMetafieldProps extends Omit<MetafieldProps, 'metafield'>
18
18
  * [`Metafield`](/api/hydrogen/components/primitive/metafield) component with the product metafield.
19
19
  * It must be a descendent of a `ProductProvider` component.
20
20
  */
21
- export declare function ProductMetafield<TTag extends ElementType>(props: Props<TTag> & Omit<ProductMetafieldProps, 'data'>): JSX.Element | null;
21
+ export declare function ProductMetafield<TTag extends ElementType>(props: Props<TTag> & Omit<ProductMetafieldProps<TTag>, 'data'>): JSX.Element | null;
@@ -1,7 +1,7 @@
1
1
  import { ElementType } from 'react';
2
2
  import { MoneyProps } from '../Money';
3
3
  import { Props } from '../types';
4
- export interface ProductPriceProps extends Omit<MoneyProps, 'data'> {
4
+ export interface ProductPriceProps<TTag> extends Omit<MoneyProps<TTag>, 'data'> {
5
5
  /** The type of price. Valid values: `regular` (default) or `compareAt`. */
6
6
  priceType?: 'regular' | 'compareAt';
7
7
  /** The type of value. Valid values: `min` (default), `max` or `unit`. */
@@ -13,4 +13,4 @@ export interface ProductPriceProps extends Omit<MoneyProps, 'data'> {
13
13
  * The `ProductPrice` component renders a `Money` component with the product
14
14
  * [`priceRange`](/api/storefront/reference/products/productpricerange)'s `maxVariantPrice` or `minVariantPrice`, for either the regular price or compare at price range. It must be a descendent of the `ProductProvider` component.
15
15
  */
16
- export declare function ProductPrice<TTag extends ElementType>(props: Props<TTag> & ProductPriceProps): JSX.Element | null;
16
+ export declare function ProductPrice<TTag extends ElementType>(props: Props<TTag> & ProductPriceProps<TTag>): JSX.Element | null;
@@ -9,5 +9,5 @@ export declare function ProductTitle<TTag extends ElementType = 'span'>(props: P
9
9
  /** An HTML tag to wrap the title. If not specified, then the
10
10
  * title is wrapped in a `span` element.
11
11
  */
12
- as?: ElementType;
12
+ as?: TTag;
13
13
  }): JSX.Element | null;
@@ -1,12 +1,12 @@
1
1
  import { ElementType } from 'react';
2
2
  import { Props } from '../types';
3
- export interface RawHtmlProps {
3
+ export interface RawHtmlProps<TTag> {
4
4
  /** An HTML string. */
5
5
  string: string;
6
6
  /** Whether the HTML string should be sanitized with `isomorphic-dompurify`. */
7
7
  unsanitized?: boolean;
8
8
  /** An HTML tag to be rendered as the base element wrapper. The default is `div`. */
9
- as?: ElementType;
9
+ as?: TTag;
10
10
  }
11
11
  /**
12
12
  * The `RawHtml` component renders an HTML string as HTML DOM elements. This should be used for
@@ -16,4 +16,4 @@ export interface RawHtmlProps {
16
16
  * [isomorphic-dompurify](https://github.com/kkomelin/isomorphic-dompurify) by default.
17
17
  * To keep the text unsanitized, set the `unsanitized` prop to `true`.
18
18
  */
19
- export declare function RawHtml<TTag extends ElementType>(props: Props<TTag> & RawHtmlProps): JSX.Element;
19
+ export declare function RawHtml<TTag extends ElementType>(props: Props<TTag> & RawHtmlProps<TTag>): JSX.Element;
@@ -20,7 +20,9 @@ export function ProductSeo({ url, title, description, seo, vendor, featuredImage
20
20
  },
21
21
  url,
22
22
  };
23
- productSchema.image = featuredImage.url;
23
+ if (featuredImage) {
24
+ productSchema.image = featuredImage.url;
25
+ }
24
26
  if (variants.edges.length > 0) {
25
27
  const firstVariant = variants.edges[0].node;
26
28
  firstVariantPrice = firstVariant.priceV2;
@@ -32,7 +32,7 @@ export interface Product {
32
32
  description?: Description;
33
33
  };
34
34
  vendor: string;
35
- featuredImage: Image;
35
+ featuredImage?: Image;
36
36
  variants: {
37
37
  edges: {
38
38
  node: {
@@ -1,19 +1,19 @@
1
1
  import { ElementType } from 'react';
2
2
  import { Props } from '../types';
3
3
  import { UnitPriceMeasurement, MoneyV2 } from '../../graphql/types/types';
4
- export interface UnitPriceProps {
4
+ export interface UnitPriceProps<TTag> {
5
5
  /** A [`MoneyV2` object](/api/storefront/reference/common-objects/moneyv2). */
6
6
  data: MoneyV2;
7
7
  /** A [`UnitPriceMeasurement` object](/api/storefront/reference/products/unitpricemeasurement). */
8
8
  measurement: UnitPriceMeasurement;
9
9
  /** An HTML tag to be rendered as the base element wrapper. The default is `div`. */
10
- as?: ElementType;
10
+ as?: TTag;
11
11
  }
12
12
  /**
13
13
  * The `UnitPrice` component renders a string with a [UnitPrice](/themes/pricing-payments/unit-pricing) as the
14
14
  * [Storefront API's `MoneyV2` object](/api/storefront/reference/common-objects/moneyv2) with a reference unit from the [Storefront API's `UnitPriceMeasurement` object](/api/storefront/reference/products/unitpricemeasurement).
15
15
  */
16
- export declare function UnitPrice<TTag extends ElementType>(props: Props<TTag> & UnitPriceProps): JSX.Element;
16
+ export declare function UnitPrice<TTag extends ElementType>(props: Props<TTag> & UnitPriceProps<TTag>): JSX.Element;
17
17
  export declare namespace UnitPrice {
18
18
  var Fragment: string;
19
19
  }
@@ -1,19 +1,22 @@
1
- import React, { Suspense, useState } from 'react';
2
- // @ts-ignore
1
+ import React, { Suspense, useState, StrictMode, Fragment, } from 'react';
2
+ // @ts-expect-error hydrateRoot isn't on the TS types yet, but we're using React 18 so it exists
3
3
  import { hydrateRoot } from 'react-dom';
4
4
  import { ErrorBoundary } from 'react-error-boundary';
5
5
  import { useServerResponse } from './framework/Hydration/rsc';
6
6
  import { ServerStateProvider } from './client';
7
7
  import { Router } from './foundation/Router/Router.client';
8
- const renderHydrogen = async (ClientWrapper) => {
8
+ const renderHydrogen = async (ClientWrapper, config) => {
9
9
  const root = document.getElementById('root');
10
10
  if (!root) {
11
11
  console.error(`Could not find a root element <div id="root"></div> to render.`);
12
12
  return;
13
13
  }
14
- hydrateRoot(root, React.createElement(ErrorBoundary, { FallbackComponent: Error },
15
- React.createElement(Suspense, { fallback: null },
16
- React.createElement(Content, { clientWrapper: ClientWrapper }))));
14
+ // default to StrictMode on, unless explicitly turned off
15
+ const RootComponent = (config === null || config === void 0 ? void 0 : config.strictMode) !== false ? StrictMode : Fragment;
16
+ hydrateRoot(root, React.createElement(RootComponent, null,
17
+ React.createElement(ErrorBoundary, { FallbackComponent: Error },
18
+ React.createElement(Suspense, { fallback: null },
19
+ React.createElement(Content, { clientWrapper: ClientWrapper })))));
17
20
  };
18
21
  export default renderHydrogen;
19
22
  function Content({ clientWrapper: ClientWrapper = ({ children }) => children, }) {
@@ -96,7 +96,14 @@ export function preloadRequestCacheData(request, preloadQueries) {
96
96
  promise = preloadQuery.fetcher().then((r) => {
97
97
  data = { data: r };
98
98
  collectQueryTimings(request, preloadQuery.key, 'resolved', getTime() - startApiTime);
99
- }, (e) => (data = { error: e }));
99
+ }, (e) => {
100
+ // The preload query failed for some reason:
101
+ // On Cloudfare, this happens when a Cache item has expired at max-age
102
+ //
103
+ // We need to remove this entry from cache so that render cycle will retry on its own
104
+ cache.delete(cacheKey);
105
+ collectQueryTimings(request, preloadQuery.key, 'expired', getTime() - startApiTime);
106
+ });
100
107
  }
101
108
  return promise;
102
109
  });
@@ -1,22 +1,32 @@
1
1
  import type { CachingStrategy, PreloadOptions, QueryKey } from '../../types';
2
2
  export interface HydrogenUseQueryOptions {
3
+ /** The [caching strategy](/custom-storefronts/hydrogen/framework/cache#caching-strategies) to help you
4
+ * determine which cache control header to set.
5
+ */
3
6
  cache?: CachingStrategy;
7
+ /** Whether to [preload the query](/custom-storefronts/hydrogen/framework/preloaded-queries).
8
+ * Defaults to `false`. Specify `true` to preload the query for the URL or `'*'`
9
+ * to preload the query for all requests.
10
+ */
4
11
  preload?: PreloadOptions;
5
12
  }
6
13
  /**
7
- * The `useQuery` hook is a wrapper around Suspense calls and
8
- * global runtime's Cache if it exists.
9
- * It supports Suspense calls on the server and on the client.
14
+ * The `useQuery` hook executes an asynchronous operation like `fetch` in a way that
15
+ * supports [Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html). It's based
16
+ * on [react-query](https://react-query.tanstack.com/reference/useQuery). You can use this
17
+ * hook to call any third-party APIs.
10
18
  */
11
19
  export declare function useQuery<T>(
12
20
  /** A string or array to uniquely identify the current query. */
13
21
  key: QueryKey,
14
22
  /** An asynchronous query function like `fetch` which returns data. */
15
23
  queryFn: () => Promise<T>,
16
- /** Options including `cache` to manage the cache behavior of the sub-request. */
24
+ /** The options to manage the cache behavior of the sub-request. */
17
25
  queryOptions?: HydrogenUseQueryOptions): {
18
26
  data?: undefined;
19
- error: Response;
27
+ error: Response; /**
28
+ * Attempt to read the query from cache. If it doesn't exist or if it's stale, regenerate it.
29
+ */
20
30
  } | {
21
31
  data: T;
22
32
  error?: undefined;
@@ -3,16 +3,17 @@ import { deleteItemFromCache, generateSubRequestCacheControlHeader, getItemFromC
3
3
  import { runDelayedFunction } from '../../framework/runtime';
4
4
  import { useRequestCacheData, useServerRequest } from '../ServerRequestProvider';
5
5
  /**
6
- * The `useQuery` hook is a wrapper around Suspense calls and
7
- * global runtime's Cache if it exists.
8
- * It supports Suspense calls on the server and on the client.
6
+ * The `useQuery` hook executes an asynchronous operation like `fetch` in a way that
7
+ * supports [Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html). It's based
8
+ * on [react-query](https://react-query.tanstack.com/reference/useQuery). You can use this
9
+ * hook to call any third-party APIs.
9
10
  */
10
11
  export function useQuery(
11
12
  /** A string or array to uniquely identify the current query. */
12
13
  key,
13
14
  /** An asynchronous query function like `fetch` which returns data. */
14
15
  queryFn,
15
- /** Options including `cache` to manage the cache behavior of the sub-request. */
16
+ /** The options to manage the cache behavior of the sub-request. */
16
17
  queryOptions) {
17
18
  const request = useServerRequest();
18
19
  const withCacheIdKey = ['__QUERY_CACHE_ID__', ...key];
@@ -100,7 +100,10 @@ function saveToPreloadAllPreload(query) {
100
100
  */
101
101
  function getUrlFromNodeRequest(request) {
102
102
  var _a;
103
+ const url = (_a = request.originalUrl) !== null && _a !== void 0 ? _a : request.url;
104
+ if (url && !url.startsWith('/'))
105
+ return url;
103
106
  // TODO: Find out how to determine https from `request` object without forwarded proto
104
107
  const secure = request.headers['x-forwarded-proto'] === 'https';
105
- return new URL(`${secure ? 'https' : 'http'}://${request.headers.host + ((_a = request.originalUrl) !== null && _a !== void 0 ? _a : request.url)}`).toString();
108
+ return new URL(`${secure ? 'https' : 'http'}://${request.headers.host + url}`).toString();
106
109
  }
@@ -43,7 +43,7 @@ export default () => {
43
43
  },
44
44
  generateBundle(options, bundle) {
45
45
  if (config.build.ssr) {
46
- const [[key, value]] = Object.entries(bundle);
46
+ const [key, value] = Object.entries(bundle).find(([, value]) => value.type === 'chunk' && value.isEntry);
47
47
  delete bundle[key];
48
48
  value.fileName = SSR_BUNDLE_NAME;
49
49
  bundle[SSR_BUNDLE_NAME] = value;
@@ -4,7 +4,7 @@ import { GraphQLConnection } from '../../types';
4
4
  * The `useProductOptions` hook returns an object that enables you to keep track of the
5
5
  * selected variant and/or selling plan state, as well as callbacks for modifying the state.
6
6
  */
7
- export declare function useProductOptions({ variants: variantsConnection, sellingPlanGroups: sellingPlanGroupsConnection, initialVariantId, }: {
7
+ export declare function useProductOptions({ variants: variantsConnection, sellingPlanGroups: sellingPlanGroupsConnection, initialVariantId: explicitVariantId, }: {
8
8
  /** The product's `VariantConnection`. */
9
9
  variants?: GraphQLConnection<Variant>;
10
10
  /** The product's `SellingPlanGroups`. */
@@ -5,18 +5,21 @@ import { getOptions, getSelectedVariant } from './helpers';
5
5
  * The `useProductOptions` hook returns an object that enables you to keep track of the
6
6
  * selected variant and/or selling plan state, as well as callbacks for modifying the state.
7
7
  */
8
- export function useProductOptions({ variants: variantsConnection, sellingPlanGroups: sellingPlanGroupsConnection, initialVariantId, }) {
8
+ export function useProductOptions({ variants: variantsConnection, sellingPlanGroups: sellingPlanGroupsConnection, initialVariantId: explicitVariantId, }) {
9
9
  // The flattened variants
10
10
  const variants = useMemo(() => (variantsConnection ? flattenConnection(variantsConnection) : []), [variantsConnection]);
11
11
  // All the options available for a product, based on all the variants
12
12
  const options = useMemo(() => getOptions(variants), [variants]);
13
+ const initialVariantId = explicitVariantId === null
14
+ ? explicitVariantId
15
+ : variants.find((variant) => variant.id === explicitVariantId) ||
16
+ variants.find((variant) => variant.availableForSale) ||
17
+ variants[0];
13
18
  /**
14
19
  * Track the selectedVariant within the hook. If `initialVariantId`
15
20
  * is passed, use that as an initial value.
16
21
  */
17
- const [selectedVariant, setSelectedVariant] = useState(initialVariantId == null
18
- ? initialVariantId
19
- : variants.find((variant) => variant.id === initialVariantId));
22
+ const [selectedVariant, setSelectedVariant] = useState(initialVariantId);
20
23
  /**
21
24
  * Track the selectedOptions within the hook. If a `initialVariantId`
22
25
  * is passed, use that to select initial options.
@@ -34,10 +37,7 @@ export function useProductOptions({ variants: variantsConnection, sellingPlanGro
34
37
  * values.
35
38
  */
36
39
  useEffect(() => {
37
- const selectedVariant = initialVariantId == null
38
- ? initialVariantId
39
- : variants.find((variant) => variant.id === initialVariantId);
40
- setSelectedVariant(selectedVariant);
40
+ setSelectedVariant(initialVariantId);
41
41
  const selectedOptions = (selectedVariant === null || selectedVariant === void 0 ? void 0 : selectedVariant.selectedOptions)
42
42
  ? selectedVariant.selectedOptions.reduce((memo, optionSet) => {
43
43
  memo[optionSet.name] = optionSet.value;
@@ -15,10 +15,15 @@ export declare function useShopQuery<T>({ query, variables, cache, locale, prelo
15
15
  query?: ASTNode | string;
16
16
  /** An object of the variables for the GraphQL query. */
17
17
  variables?: Record<string, any>;
18
- /** An object containing cache-control options for the sub-request. */
18
+ /** The [caching strategy](/custom-storefronts/hydrogen/framework/cache#caching-strategies) to
19
+ * help you determine which cache control header to set.
20
+ */
19
21
  cache?: CachingStrategy;
20
22
  /** A string corresponding to a valid locale identifier like `en-us` used to make the request. */
21
23
  locale?: string;
22
- /** Whether to preload this query */
24
+ /** Whether to[preload the query](/custom-storefronts/hydrogen/framework/preloaded-queries).
25
+ * Defaults to `false`. Specify `true` to preload the query for the URL or `'*'`
26
+ * to preload the query for all requests.
27
+ */
23
28
  preload?: PreloadOptions;
24
29
  }): UseShopQueryResponse<T>;
@@ -41,8 +41,10 @@ export declare type ServerHandlerConfig = {
41
41
  };
42
42
  export declare type ClientHandlerConfig = {
43
43
  shopifyConfig: ShopifyConfig;
44
+ /** React's StrictMode is on by default for your client side app; if you want to turn it off (not recommended), you can pass `false` */
45
+ strictMode?: boolean;
44
46
  };
45
- export declare type ClientHandler = (App: any, config: ClientHandlerConfig) => Promise<void>;
47
+ export declare type ClientHandler = (App: React.ElementType, config: ClientHandlerConfig) => Promise<void>;
46
48
  export interface GraphQLConnection<T> {
47
49
  edges?: {
48
50
  node: T;
@@ -1,7 +1,7 @@
1
1
  import { ServerComponentRequest } from '../../framework/Hydration/ServerComponentRequest.server';
2
2
  import { QueryKey } from '../../types';
3
3
  import type { RenderType } from './log';
4
- export declare type TimingType = 'requested' | 'resolved' | 'rendered' | 'preload';
4
+ export declare type TimingType = 'requested' | 'resolved' | 'rendered' | 'preload' | 'expired';
5
5
  export declare type QueryTiming = {
6
6
  name: string;
7
7
  timingType: TimingType;
@@ -9,6 +9,7 @@ const TIMING_MAPPING = {
9
9
  rendered: 'Rendered',
10
10
  resolved: 'Resolved',
11
11
  preload: 'Preload',
12
+ expired: 'Expired',
12
13
  };
13
14
  export function collectQueryTimings(request, queryKey, timingType, duration) {
14
15
  request.ctx.queryTimings.push({
@@ -31,7 +32,6 @@ export function logQueryTimings(type, request) {
31
32
  const detectMultipleDataLoad = {};
32
33
  let suspenseWaterfallDetectedCount = 0;
33
34
  queryList.forEach((query, index) => {
34
- var _a;
35
35
  if (query.timingType === 'requested' || query.timingType === 'preload') {
36
36
  detectSuspenseWaterfall[query.name] = true;
37
37
  }
@@ -44,8 +44,9 @@ export function logQueryTimings(type, request) {
44
44
  : 1;
45
45
  }
46
46
  const loadColor = query.timingType === 'preload' ? green : color;
47
- log.debug(color(`│ ${`${(query.timestamp - requestStartTime).toFixed(2)}ms`.padEnd(10)} ${loadColor(TIMING_MAPPING[query.timingType].padEnd(10))} ${query.name}${query.timingType === 'resolved'
48
- ? ` (Took ${(_a = query.duration) === null || _a === void 0 ? void 0 : _a.toFixed(2)}ms)`
47
+ const duration = query.duration;
48
+ log.debug(color(`│ ${`${(query.timestamp - requestStartTime).toFixed(2)}ms`.padEnd(10)} ${loadColor(TIMING_MAPPING[query.timingType].padEnd(10))} ${query.name}${query.timingType === 'resolved' || query.timingType === 'expired'
49
+ ? ` (Took ${duration === null || duration === void 0 ? void 0 : duration.toFixed(2)}ms)`
49
50
  : ''}`));
50
51
  // SSR + RSC render path generates 2 `load` and `render` for each query
51
52
  // We want to avoid falsely identifying a suspense waterfall near the end
@@ -1 +1 @@
1
- export declare const LIB_VERSION = "0.11.0";
1
+ export declare const LIB_VERSION = "0.11.1";
@@ -1 +1 @@
1
- export const LIB_VERSION = '0.11.0';
1
+ export const LIB_VERSION = '0.11.1';
@@ -121,7 +121,14 @@ function preloadRequestCacheData(request, preloadQueries) {
121
121
  promise = preloadQuery.fetcher().then((r) => {
122
122
  data = { data: r };
123
123
  (0, log_1.collectQueryTimings)(request, preloadQuery.key, 'resolved', (0, timing_1.getTime)() - startApiTime);
124
- }, (e) => (data = { error: e }));
124
+ }, (e) => {
125
+ // The preload query failed for some reason:
126
+ // On Cloudfare, this happens when a Cache item has expired at max-age
127
+ //
128
+ // We need to remove this entry from cache so that render cycle will retry on its own
129
+ cache.delete(cacheKey);
130
+ (0, log_1.collectQueryTimings)(request, preloadQuery.key, 'expired', (0, timing_1.getTime)() - startApiTime);
131
+ });
125
132
  }
126
133
  return promise;
127
134
  });
@@ -104,7 +104,10 @@ function saveToPreloadAllPreload(query) {
104
104
  */
105
105
  function getUrlFromNodeRequest(request) {
106
106
  var _a;
107
+ const url = (_a = request.originalUrl) !== null && _a !== void 0 ? _a : request.url;
108
+ if (url && !url.startsWith('/'))
109
+ return url;
107
110
  // TODO: Find out how to determine https from `request` object without forwarded proto
108
111
  const secure = request.headers['x-forwarded-proto'] === 'https';
109
- return new URL(`${secure ? 'https' : 'http'}://${request.headers.host + ((_a = request.originalUrl) !== null && _a !== void 0 ? _a : request.url)}`).toString();
112
+ return new URL(`${secure ? 'https' : 'http'}://${request.headers.host + url}`).toString();
110
113
  }
@@ -48,7 +48,7 @@ exports.default = () => {
48
48
  },
49
49
  generateBundle(options, bundle) {
50
50
  if (config.build.ssr) {
51
- const [[key, value]] = Object.entries(bundle);
51
+ const [key, value] = Object.entries(bundle).find(([, value]) => value.type === 'chunk' && value.isEntry);
52
52
  delete bundle[key];
53
53
  value.fileName = SSR_BUNDLE_NAME;
54
54
  bundle[SSR_BUNDLE_NAME] = value;
@@ -41,8 +41,10 @@ export declare type ServerHandlerConfig = {
41
41
  };
42
42
  export declare type ClientHandlerConfig = {
43
43
  shopifyConfig: ShopifyConfig;
44
+ /** React's StrictMode is on by default for your client side app; if you want to turn it off (not recommended), you can pass `false` */
45
+ strictMode?: boolean;
44
46
  };
45
- export declare type ClientHandler = (App: any, config: ClientHandlerConfig) => Promise<void>;
47
+ export declare type ClientHandler = (App: React.ElementType, config: ClientHandlerConfig) => Promise<void>;
46
48
  export interface GraphQLConnection<T> {
47
49
  edges?: {
48
50
  node: T;
@@ -1,7 +1,7 @@
1
1
  import { ServerComponentRequest } from '../../framework/Hydration/ServerComponentRequest.server';
2
2
  import { QueryKey } from '../../types';
3
3
  import type { RenderType } from './log';
4
- export declare type TimingType = 'requested' | 'resolved' | 'rendered' | 'preload';
4
+ export declare type TimingType = 'requested' | 'resolved' | 'rendered' | 'preload' | 'expired';
5
5
  export declare type QueryTiming = {
6
6
  name: string;
7
7
  timingType: TimingType;
@@ -12,6 +12,7 @@ const TIMING_MAPPING = {
12
12
  rendered: 'Rendered',
13
13
  resolved: 'Resolved',
14
14
  preload: 'Preload',
15
+ expired: 'Expired',
15
16
  };
16
17
  function collectQueryTimings(request, queryKey, timingType, duration) {
17
18
  request.ctx.queryTimings.push({
@@ -35,7 +36,6 @@ function logQueryTimings(type, request) {
35
36
  const detectMultipleDataLoad = {};
36
37
  let suspenseWaterfallDetectedCount = 0;
37
38
  queryList.forEach((query, index) => {
38
- var _a;
39
39
  if (query.timingType === 'requested' || query.timingType === 'preload') {
40
40
  detectSuspenseWaterfall[query.name] = true;
41
41
  }
@@ -48,8 +48,9 @@ function logQueryTimings(type, request) {
48
48
  : 1;
49
49
  }
50
50
  const loadColor = query.timingType === 'preload' ? kolorist_1.green : color;
51
- log.debug(color(`│ ${`${(query.timestamp - requestStartTime).toFixed(2)}ms`.padEnd(10)} ${loadColor(TIMING_MAPPING[query.timingType].padEnd(10))} ${query.name}${query.timingType === 'resolved'
52
- ? ` (Took ${(_a = query.duration) === null || _a === void 0 ? void 0 : _a.toFixed(2)}ms)`
51
+ const duration = query.duration;
52
+ log.debug(color(`│ ${`${(query.timestamp - requestStartTime).toFixed(2)}ms`.padEnd(10)} ${loadColor(TIMING_MAPPING[query.timingType].padEnd(10))} ${query.name}${query.timingType === 'resolved' || query.timingType === 'expired'
53
+ ? ` (Took ${duration === null || duration === void 0 ? void 0 : duration.toFixed(2)}ms)`
53
54
  : ''}`));
54
55
  // SSR + RSC render path generates 2 `load` and `render` for each query
55
56
  // We want to avoid falsely identifying a suspense waterfall near the end
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "engines": {
8
8
  "node": ">=14"
9
9
  },
10
- "version": "0.11.0",
10
+ "version": "0.11.1",
11
11
  "description": "Modern custom Shopify storefronts",
12
12
  "license": "MIT",
13
13
  "main": "dist/esnext/index.js",
@@ -115,6 +115,5 @@
115
115
  "react-helmet-async": "^1.2.3",
116
116
  "vite-plugin-inspect": "^0.3.6",
117
117
  "web-streams-polyfill": "^3.2.0"
118
- },
119
- "gitHead": "57d5e40c2193780639d765aa777cb8670bfbca40"
118
+ }
120
119
  }
package/LICENSE.md DELETED
@@ -1,7 +0,0 @@
1
- Copyright 2021-present, Shopify Inc.
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
-
5
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
-
7
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.