@shopify/hydrogen 1.6.3 → 1.6.5

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.
@@ -47,4 +47,3 @@ export declare function CartProvider({ children, numCartLines, onCreate, onLineA
47
47
  /** The ISO country code for i18n. */
48
48
  countryCode?: CountryCode;
49
49
  }): JSX.Element;
50
- export declare const defaultCartFragment = "\nfragment CartFragment on Cart {\n id\n checkoutUrl\n totalQuantity\n buyerIdentity {\n countryCode\n customer {\n id\n email\n firstName\n lastName\n displayName\n }\n email\n phone\n }\n lines(first: $numCartLines) {\n edges {\n node {\n id\n quantity\n attributes {\n key\n value\n }\n cost {\n totalAmount {\n amount\n currencyCode\n }\n compareAtAmountPerQuantity {\n amount\n currencyCode\n }\n }\n merchandise {\n ... on ProductVariant {\n id\n availableForSale\n compareAtPriceV2 {\n ...MoneyFragment\n }\n priceV2 {\n ...MoneyFragment\n }\n requiresShipping\n title\n image {\n ...ImageFragment\n }\n product {\n handle\n title\n }\n selectedOptions {\n name\n value\n }\n }\n }\n }\n }\n }\n cost {\n subtotalAmount {\n ...MoneyFragment\n }\n totalAmount {\n ...MoneyFragment\n }\n totalDutyAmount {\n ...MoneyFragment\n }\n totalTaxAmount {\n ...MoneyFragment\n }\n }\n note\n attributes {\n key\n value\n }\n discountCodes {\n code\n }\n}\n\nfragment MoneyFragment on MoneyV2 {\n currencyCode\n amount\n}\nfragment ImageFragment on Image {\n id\n url\n altText\n width\n height\n}\n";
@@ -1,5 +1,6 @@
1
1
  import React, { useCallback, useEffect, useMemo, useRef, useState, useTransition, } from 'react';
2
2
  import { CountryCode, } from '../../storefront-api-types.js';
3
+ import { defaultCartFragment } from './cart-queries.js';
3
4
  import { CartContext } from './context.js';
4
5
  import { useCartAPIStateMachine } from './useCartAPIStateMachine.client.js';
5
6
  import { CART_ID_STORAGE_KEY } from './constants.js';
@@ -51,25 +52,23 @@ export function CartProvider({ children, numCartLines, onCreate, onLineAdd, onLi
51
52
  onNoteUpdate,
52
53
  ]);
53
54
  const onCartActionOptimisticUI = useCallback((context, event) => {
54
- if (!context?.cart)
55
- return { cart: undefined };
55
+ if (!context.cart)
56
+ return { ...context };
56
57
  switch (event.type) {
57
58
  case 'CARTLINE_REMOVE':
58
59
  return {
59
60
  ...context,
60
- lastValidCart: context.cart,
61
61
  cart: {
62
62
  ...context.cart,
63
- lines: context?.cart?.lines.filter(({ id }) => !event.payload.lines.includes(id)),
63
+ lines: context.cart.lines.filter(({ id }) => !event.payload.lines.includes(id)),
64
64
  },
65
65
  };
66
66
  case 'CARTLINE_UPDATE':
67
67
  return {
68
68
  ...context,
69
- lastValidCart: context.cart,
70
69
  cart: {
71
70
  ...context.cart,
72
- lines: context.cart.lines.map((line) => {
71
+ lines: context?.cart?.lines.map((line) => {
73
72
  const updatedLine = event.payload.lines.find(({ id }) => id === line.id);
74
73
  if (updatedLine && updatedLine.quantity) {
75
74
  return {
@@ -82,7 +81,7 @@ export function CartProvider({ children, numCartLines, onCreate, onLineAdd, onLi
82
81
  },
83
82
  };
84
83
  }
85
- return { cart: context.cart ? { ...context.cart } : undefined };
84
+ return { ...context };
86
85
  }, []);
87
86
  const onCartActionComplete = useCallback((context, event) => {
88
87
  const cartActionEvent = event.payload.cartActionEvent;
@@ -432,103 +431,3 @@ function publishDiscountCodesUpdateAnalytics(context, event) {
432
431
  prevCart: context.prevCart,
433
432
  });
434
433
  }
435
- export const defaultCartFragment = `
436
- fragment CartFragment on Cart {
437
- id
438
- checkoutUrl
439
- totalQuantity
440
- buyerIdentity {
441
- countryCode
442
- customer {
443
- id
444
- email
445
- firstName
446
- lastName
447
- displayName
448
- }
449
- email
450
- phone
451
- }
452
- lines(first: $numCartLines) {
453
- edges {
454
- node {
455
- id
456
- quantity
457
- attributes {
458
- key
459
- value
460
- }
461
- cost {
462
- totalAmount {
463
- amount
464
- currencyCode
465
- }
466
- compareAtAmountPerQuantity {
467
- amount
468
- currencyCode
469
- }
470
- }
471
- merchandise {
472
- ... on ProductVariant {
473
- id
474
- availableForSale
475
- compareAtPriceV2 {
476
- ...MoneyFragment
477
- }
478
- priceV2 {
479
- ...MoneyFragment
480
- }
481
- requiresShipping
482
- title
483
- image {
484
- ...ImageFragment
485
- }
486
- product {
487
- handle
488
- title
489
- }
490
- selectedOptions {
491
- name
492
- value
493
- }
494
- }
495
- }
496
- }
497
- }
498
- }
499
- cost {
500
- subtotalAmount {
501
- ...MoneyFragment
502
- }
503
- totalAmount {
504
- ...MoneyFragment
505
- }
506
- totalDutyAmount {
507
- ...MoneyFragment
508
- }
509
- totalTaxAmount {
510
- ...MoneyFragment
511
- }
512
- }
513
- note
514
- attributes {
515
- key
516
- value
517
- }
518
- discountCodes {
519
- code
520
- }
521
- }
522
-
523
- fragment MoneyFragment on MoneyV2 {
524
- currencyCode
525
- amount
526
- }
527
- fragment ImageFragment on Image {
528
- id
529
- url
530
- altText
531
- width
532
- height
533
- }
534
- `;
@@ -7,6 +7,9 @@ function invokeCart(action, options) {
7
7
  return {
8
8
  entry: [
9
9
  ...(options?.entryActions || []),
10
+ assign({
11
+ lastValidCart: (context) => context?.cart,
12
+ }),
10
13
  'onCartActionEntry',
11
14
  'onCartActionOptimisticUI',
12
15
  action,
@@ -16,7 +19,7 @@ function invokeCart(action, options) {
16
19
  target: options?.resolveTarget || 'idle',
17
20
  actions: [
18
21
  assign({
19
- prevCart: (context) => context?.cart,
22
+ prevCart: (context) => context?.lastValidCart,
20
23
  cart: (_, event) => event?.payload?.cart,
21
24
  rawCartResult: (_, event) => event?.payload?.rawCartResult,
22
25
  errors: (_) => undefined,
@@ -27,7 +30,7 @@ function invokeCart(action, options) {
27
30
  target: options?.errorTarget || 'error',
28
31
  actions: [
29
32
  assign({
30
- prevCart: (context) => context?.cart,
33
+ prevCart: (context) => context?.lastValidCart,
31
34
  cart: (context, _) => context?.lastValidCart,
32
35
  errors: (_, event) => event?.payload?.errors,
33
36
  }),
@@ -39,6 +42,7 @@ function invokeCart(action, options) {
39
42
  prevCart: (_) => undefined,
40
43
  cart: (_) => undefined,
41
44
  lastValidCart: (_) => undefined,
45
+ rawCartResult: (_) => undefined,
42
46
  errors: (_) => undefined,
43
47
  }),
44
48
  },
@@ -573,7 +573,7 @@ function tagOnWrite(response) {
573
573
  const savedChunks = [];
574
574
  response.write = (arg) => {
575
575
  if (arg instanceof Uint8Array) {
576
- savedChunks.push(decoder.decode(arg));
576
+ savedChunks.push(decoder.decode(arg, { stream: true }));
577
577
  }
578
578
  else {
579
579
  savedChunks.push(arg);
@@ -2,7 +2,10 @@ import React, { FormEvent } from 'react';
2
2
  interface FormProps {
3
3
  action: string;
4
4
  method?: string;
5
- children?: Array<React.ReactNode>;
5
+ children?: Array<React.ReactNode> | ((props: {
6
+ loading: boolean;
7
+ error: Error | null;
8
+ }) => React.ReactNode);
6
9
  onSubmit?: (e: FormEvent<HTMLFormElement>) => void;
7
10
  encType?: string;
8
11
  noValidate?: boolean;
@@ -14,7 +14,7 @@ export async function bufferReadableStream(reader, cb) {
14
14
  const { done, value } = await reader.read();
15
15
  if (done)
16
16
  break;
17
- const stringValue = typeof value === 'string' ? value : decoder.decode(value);
17
+ const stringValue = typeof value === 'string' ? value : decoder.decode(value, { stream: true });
18
18
  result += stringValue;
19
19
  if (cb) {
20
20
  cb(stringValue);
@@ -1,4 +1,2 @@
1
1
  export declare function parseJSON(json: any): any;
2
- export declare function parseState(url: URL): {
3
- [k: string]: string;
4
- } | undefined;
2
+ export declare function parseState(url: URL): Record<string, any> | undefined;
@@ -11,13 +11,16 @@ function noproto(k, v) {
11
11
  export function parseState(url) {
12
12
  try {
13
13
  const { pathname, search } = url;
14
+ const stateParam = url.searchParams.get('state');
14
15
  const state = pathname === RSC_PATHNAME
15
- ? parseJSON(url.searchParams.get('state') ?? '{}')
16
- : { pathname, search };
17
- return Object.fromEntries(Object.entries(state).map(([key, value]) => [
18
- decodeURIComponent(key ?? ''),
19
- decodeURIComponent(value ?? ''),
20
- ]));
16
+ ? stateParam
17
+ ? parseJSON(decodeURIComponent(stateParam))
18
+ : {}
19
+ : {
20
+ pathname: decodeURIComponent(pathname),
21
+ search: decodeURIComponent(search),
22
+ };
23
+ return state;
21
24
  }
22
25
  catch {
23
26
  // Do not throw to prevent unhandled errors
@@ -1 +1 @@
1
- export declare const LIB_VERSION = "1.6.3";
1
+ export declare const LIB_VERSION = "1.6.5";
@@ -1 +1 @@
1
- export const LIB_VERSION = '1.6.3';
1
+ export const LIB_VERSION = '1.6.5';
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "engines": {
8
8
  "node": ">=14"
9
9
  },
10
- "version": "1.6.3",
10
+ "version": "1.6.5",
11
11
  "description": "Modern custom Shopify storefronts",
12
12
  "license": "MIT",
13
13
  "main": "dist/esnext/index.js",