@shopify/hydrogen-react 2025.7.2 → 2026.1.0
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/customer-account.schema.json +1 -1
- package/dist/browser-dev/AddToCartButton.mjs +3 -1
- package/dist/browser-dev/AddToCartButton.mjs.map +1 -1
- package/dist/browser-dev/CartLineProvider.mjs.map +1 -1
- package/dist/browser-dev/CartProvider.mjs.map +1 -1
- package/dist/browser-dev/Image.mjs.map +1 -1
- package/dist/browser-dev/ModelViewer.mjs.map +1 -1
- package/dist/browser-dev/Money.mjs.map +1 -1
- package/dist/browser-dev/Video.mjs.map +1 -1
- package/dist/browser-dev/cart-queries.mjs +64 -10
- package/dist/browser-dev/cart-queries.mjs.map +1 -1
- package/dist/browser-dev/codegen.helpers.mjs.map +1 -1
- package/dist/browser-dev/optionValueDecoder.mjs.map +1 -1
- package/dist/browser-dev/packages/hydrogen-react/package.json.mjs +1 -1
- package/dist/browser-dev/parse-metafield.mjs +2 -0
- package/dist/browser-dev/parse-metafield.mjs.map +1 -1
- package/dist/browser-dev/storefront-api-constants.mjs +1 -1
- package/dist/browser-dev/storefront-api-constants.mjs.map +1 -1
- package/dist/browser-dev/storefront-client.mjs +0 -1
- package/dist/browser-dev/storefront-client.mjs.map +1 -1
- package/dist/browser-dev/useCartAPIStateMachine.mjs.map +1 -1
- package/dist/browser-dev/useCartActions.mjs.map +1 -1
- package/dist/browser-dev/useMoney.mjs.map +1 -1
- package/dist/browser-prod/AddToCartButton.mjs +3 -1
- package/dist/browser-prod/AddToCartButton.mjs.map +1 -1
- package/dist/browser-prod/CartLineProvider.mjs.map +1 -1
- package/dist/browser-prod/CartProvider.mjs.map +1 -1
- package/dist/browser-prod/Image.mjs.map +1 -1
- package/dist/browser-prod/ModelViewer.mjs.map +1 -1
- package/dist/browser-prod/Money.mjs.map +1 -1
- package/dist/browser-prod/Video.mjs.map +1 -1
- package/dist/browser-prod/cart-queries.mjs +64 -10
- package/dist/browser-prod/cart-queries.mjs.map +1 -1
- package/dist/browser-prod/codegen.helpers.mjs.map +1 -1
- package/dist/browser-prod/optionValueDecoder.mjs.map +1 -1
- package/dist/browser-prod/packages/hydrogen-react/package.json.mjs +1 -1
- package/dist/browser-prod/parse-metafield.mjs +2 -0
- package/dist/browser-prod/parse-metafield.mjs.map +1 -1
- package/dist/browser-prod/storefront-api-constants.mjs +1 -1
- package/dist/browser-prod/storefront-api-constants.mjs.map +1 -1
- package/dist/browser-prod/storefront-client.mjs +0 -1
- package/dist/browser-prod/storefront-client.mjs.map +1 -1
- package/dist/browser-prod/useCartAPIStateMachine.mjs.map +1 -1
- package/dist/browser-prod/useCartActions.mjs.map +1 -1
- package/dist/browser-prod/useMoney.mjs.map +1 -1
- package/dist/node-dev/AddToCartButton.js +3 -1
- package/dist/node-dev/AddToCartButton.js.map +1 -1
- package/dist/node-dev/AddToCartButton.mjs +3 -1
- package/dist/node-dev/AddToCartButton.mjs.map +1 -1
- package/dist/node-dev/CartLineProvider.js.map +1 -1
- package/dist/node-dev/CartLineProvider.mjs.map +1 -1
- package/dist/node-dev/CartProvider.js.map +1 -1
- package/dist/node-dev/CartProvider.mjs.map +1 -1
- package/dist/node-dev/Image.js.map +1 -1
- package/dist/node-dev/Image.mjs.map +1 -1
- package/dist/node-dev/ModelViewer.js.map +1 -1
- package/dist/node-dev/ModelViewer.mjs.map +1 -1
- package/dist/node-dev/Money.js.map +1 -1
- package/dist/node-dev/Money.mjs.map +1 -1
- package/dist/node-dev/Video.js.map +1 -1
- package/dist/node-dev/Video.mjs.map +1 -1
- package/dist/node-dev/cart-queries.js +64 -10
- package/dist/node-dev/cart-queries.js.map +1 -1
- package/dist/node-dev/cart-queries.mjs +64 -10
- package/dist/node-dev/cart-queries.mjs.map +1 -1
- package/dist/node-dev/codegen.helpers.js.map +1 -1
- package/dist/node-dev/codegen.helpers.mjs.map +1 -1
- package/dist/node-dev/optionValueDecoder.js.map +1 -1
- package/dist/node-dev/optionValueDecoder.mjs.map +1 -1
- package/dist/node-dev/packages/hydrogen-react/package.json.js +1 -1
- package/dist/node-dev/packages/hydrogen-react/package.json.mjs +1 -1
- package/dist/node-dev/parse-metafield.js +2 -0
- package/dist/node-dev/parse-metafield.js.map +1 -1
- package/dist/node-dev/parse-metafield.mjs +2 -0
- package/dist/node-dev/parse-metafield.mjs.map +1 -1
- package/dist/node-dev/storefront-api-constants.js +1 -1
- package/dist/node-dev/storefront-api-constants.js.map +1 -1
- package/dist/node-dev/storefront-api-constants.mjs +1 -1
- package/dist/node-dev/storefront-api-constants.mjs.map +1 -1
- package/dist/node-dev/storefront-client.js +0 -1
- package/dist/node-dev/storefront-client.js.map +1 -1
- package/dist/node-dev/storefront-client.mjs +0 -1
- package/dist/node-dev/storefront-client.mjs.map +1 -1
- package/dist/node-dev/useCartAPIStateMachine.js.map +1 -1
- package/dist/node-dev/useCartAPIStateMachine.mjs.map +1 -1
- package/dist/node-dev/useCartActions.js.map +1 -1
- package/dist/node-dev/useCartActions.mjs.map +1 -1
- package/dist/node-dev/useMoney.js.map +1 -1
- package/dist/node-dev/useMoney.mjs.map +1 -1
- package/dist/node-prod/AddToCartButton.js +3 -1
- package/dist/node-prod/AddToCartButton.js.map +1 -1
- package/dist/node-prod/AddToCartButton.mjs +3 -1
- package/dist/node-prod/AddToCartButton.mjs.map +1 -1
- package/dist/node-prod/CartLineProvider.js.map +1 -1
- package/dist/node-prod/CartLineProvider.mjs.map +1 -1
- package/dist/node-prod/CartProvider.js.map +1 -1
- package/dist/node-prod/CartProvider.mjs.map +1 -1
- package/dist/node-prod/Image.js.map +1 -1
- package/dist/node-prod/Image.mjs.map +1 -1
- package/dist/node-prod/ModelViewer.js.map +1 -1
- package/dist/node-prod/ModelViewer.mjs.map +1 -1
- package/dist/node-prod/Money.js.map +1 -1
- package/dist/node-prod/Money.mjs.map +1 -1
- package/dist/node-prod/Video.js.map +1 -1
- package/dist/node-prod/Video.mjs.map +1 -1
- package/dist/node-prod/cart-queries.js +64 -10
- package/dist/node-prod/cart-queries.js.map +1 -1
- package/dist/node-prod/cart-queries.mjs +64 -10
- package/dist/node-prod/cart-queries.mjs.map +1 -1
- package/dist/node-prod/codegen.helpers.js.map +1 -1
- package/dist/node-prod/codegen.helpers.mjs.map +1 -1
- package/dist/node-prod/optionValueDecoder.js.map +1 -1
- package/dist/node-prod/optionValueDecoder.mjs.map +1 -1
- package/dist/node-prod/packages/hydrogen-react/package.json.js +1 -1
- package/dist/node-prod/packages/hydrogen-react/package.json.mjs +1 -1
- package/dist/node-prod/parse-metafield.js +2 -0
- package/dist/node-prod/parse-metafield.js.map +1 -1
- package/dist/node-prod/parse-metafield.mjs +2 -0
- package/dist/node-prod/parse-metafield.mjs.map +1 -1
- package/dist/node-prod/storefront-api-constants.js +1 -1
- package/dist/node-prod/storefront-api-constants.js.map +1 -1
- package/dist/node-prod/storefront-api-constants.mjs +1 -1
- package/dist/node-prod/storefront-api-constants.mjs.map +1 -1
- package/dist/node-prod/storefront-client.js +0 -1
- package/dist/node-prod/storefront-client.js.map +1 -1
- package/dist/node-prod/storefront-client.mjs +0 -1
- package/dist/node-prod/storefront-client.mjs.map +1 -1
- package/dist/node-prod/useCartAPIStateMachine.js.map +1 -1
- package/dist/node-prod/useCartAPIStateMachine.mjs.map +1 -1
- package/dist/node-prod/useCartActions.js.map +1 -1
- package/dist/node-prod/useCartActions.mjs.map +1 -1
- package/dist/node-prod/useMoney.js.map +1 -1
- package/dist/node-prod/useMoney.mjs.map +1 -1
- package/dist/types/AddToCartButton.d.ts +3 -0
- package/dist/types/CartLineProvider.d.ts +1 -1
- package/dist/types/CartProvider.d.ts +2 -2
- package/dist/types/Image.d.ts +1 -1
- package/dist/types/ModelViewer.d.ts +1 -1
- package/dist/types/Money.d.ts +5 -5
- package/dist/types/Video.d.ts +1 -1
- package/dist/types/codegen.helpers.d.ts +2 -2
- package/dist/types/customer-account-api-types.d.ts +669 -20
- package/dist/types/optionValueDecoder.d.ts +2 -2
- package/dist/types/parse-metafield.d.ts +14 -2
- package/dist/types/storefront-api-constants.d.ts +1 -1
- package/dist/types/storefront-api-types.d.ts +165 -7
- package/dist/types/useCartAPIStateMachine.d.ts +2 -2
- package/dist/types/useCartActions.d.ts +2 -2
- package/dist/types/useMoney.d.ts +4 -4
- package/dist/umd/hydrogen-react.dev.js +71 -14
- package/dist/umd/hydrogen-react.dev.js.map +1 -1
- package/dist/umd/hydrogen-react.prod.js +78 -24
- package/dist/umd/hydrogen-react.prod.js.map +1 -1
- package/package.json +1 -1
- package/storefront.schema.json +1 -1
|
@@ -7,7 +7,13 @@ const CartLineAdd = (cartFragment) => (
|
|
|
7
7
|
$numCartLines: Int = 250
|
|
8
8
|
$country: CountryCode = ZZ
|
|
9
9
|
$language: LanguageCode
|
|
10
|
-
|
|
10
|
+
$visitorConsent: VisitorConsent
|
|
11
|
+
)
|
|
12
|
+
@inContext(
|
|
13
|
+
country: $country
|
|
14
|
+
language: $language
|
|
15
|
+
visitorConsent: $visitorConsent
|
|
16
|
+
) {
|
|
11
17
|
cartLinesAdd(cartId: $cartId, lines: $lines) {
|
|
12
18
|
cart {
|
|
13
19
|
...CartFragment
|
|
@@ -26,7 +32,13 @@ const CartCreate = (cartFragment) => (
|
|
|
26
32
|
$numCartLines: Int = 250
|
|
27
33
|
$country: CountryCode = ZZ
|
|
28
34
|
$language: LanguageCode
|
|
29
|
-
|
|
35
|
+
$visitorConsent: VisitorConsent
|
|
36
|
+
)
|
|
37
|
+
@inContext(
|
|
38
|
+
country: $country
|
|
39
|
+
language: $language
|
|
40
|
+
visitorConsent: $visitorConsent
|
|
41
|
+
) {
|
|
30
42
|
cartCreate(input: $input) {
|
|
31
43
|
cart {
|
|
32
44
|
...CartFragment
|
|
@@ -46,7 +58,13 @@ const CartLineRemove = (cartFragment) => (
|
|
|
46
58
|
$numCartLines: Int = 250
|
|
47
59
|
$country: CountryCode = ZZ
|
|
48
60
|
$language: LanguageCode
|
|
49
|
-
|
|
61
|
+
$visitorConsent: VisitorConsent
|
|
62
|
+
)
|
|
63
|
+
@inContext(
|
|
64
|
+
country: $country
|
|
65
|
+
language: $language
|
|
66
|
+
visitorConsent: $visitorConsent
|
|
67
|
+
) {
|
|
50
68
|
cartLinesRemove(cartId: $cartId, lineIds: $lines) {
|
|
51
69
|
cart {
|
|
52
70
|
...CartFragment
|
|
@@ -66,7 +84,13 @@ const CartLineUpdate = (cartFragment) => (
|
|
|
66
84
|
$numCartLines: Int = 250
|
|
67
85
|
$country: CountryCode = ZZ
|
|
68
86
|
$language: LanguageCode
|
|
69
|
-
|
|
87
|
+
$visitorConsent: VisitorConsent
|
|
88
|
+
)
|
|
89
|
+
@inContext(
|
|
90
|
+
country: $country
|
|
91
|
+
language: $language
|
|
92
|
+
visitorConsent: $visitorConsent
|
|
93
|
+
) {
|
|
70
94
|
cartLinesUpdate(cartId: $cartId, lines: $lines) {
|
|
71
95
|
cart {
|
|
72
96
|
...CartFragment
|
|
@@ -86,7 +110,13 @@ const CartNoteUpdate = (cartFragment) => (
|
|
|
86
110
|
$numCartLines: Int = 250
|
|
87
111
|
$country: CountryCode = ZZ
|
|
88
112
|
$language: LanguageCode
|
|
89
|
-
|
|
113
|
+
$visitorConsent: VisitorConsent
|
|
114
|
+
)
|
|
115
|
+
@inContext(
|
|
116
|
+
country: $country
|
|
117
|
+
language: $language
|
|
118
|
+
visitorConsent: $visitorConsent
|
|
119
|
+
) {
|
|
90
120
|
cartNoteUpdate(cartId: $cartId, note: $note) {
|
|
91
121
|
cart {
|
|
92
122
|
...CartFragment
|
|
@@ -106,7 +136,13 @@ const CartBuyerIdentityUpdate = (cartFragment) => (
|
|
|
106
136
|
$numCartLines: Int = 250
|
|
107
137
|
$country: CountryCode = ZZ
|
|
108
138
|
$language: LanguageCode
|
|
109
|
-
|
|
139
|
+
$visitorConsent: VisitorConsent
|
|
140
|
+
)
|
|
141
|
+
@inContext(
|
|
142
|
+
country: $country
|
|
143
|
+
language: $language
|
|
144
|
+
visitorConsent: $visitorConsent
|
|
145
|
+
) {
|
|
110
146
|
cartBuyerIdentityUpdate(cartId: $cartId, buyerIdentity: $buyerIdentity) {
|
|
111
147
|
cart {
|
|
112
148
|
...CartFragment
|
|
@@ -126,7 +162,13 @@ const CartAttributesUpdate = (cartFragment) => (
|
|
|
126
162
|
$numCartLines: Int = 250
|
|
127
163
|
$country: CountryCode = ZZ
|
|
128
164
|
$language: LanguageCode
|
|
129
|
-
|
|
165
|
+
$visitorConsent: VisitorConsent
|
|
166
|
+
)
|
|
167
|
+
@inContext(
|
|
168
|
+
country: $country
|
|
169
|
+
language: $language
|
|
170
|
+
visitorConsent: $visitorConsent
|
|
171
|
+
) {
|
|
130
172
|
cartAttributesUpdate(attributes: $attributes, cartId: $cartId) {
|
|
131
173
|
cart {
|
|
132
174
|
...CartFragment
|
|
@@ -142,11 +184,17 @@ const CartDiscountCodesUpdate = (cartFragment) => (
|
|
|
142
184
|
`
|
|
143
185
|
mutation CartDiscountCodesUpdate(
|
|
144
186
|
$cartId: ID!
|
|
145
|
-
$discountCodes: [String!]
|
|
187
|
+
$discountCodes: [String!]!
|
|
146
188
|
$numCartLines: Int = 250
|
|
147
189
|
$country: CountryCode = ZZ
|
|
148
190
|
$language: LanguageCode
|
|
149
|
-
|
|
191
|
+
$visitorConsent: VisitorConsent
|
|
192
|
+
)
|
|
193
|
+
@inContext(
|
|
194
|
+
country: $country
|
|
195
|
+
language: $language
|
|
196
|
+
visitorConsent: $visitorConsent
|
|
197
|
+
) {
|
|
150
198
|
cartDiscountCodesUpdate(cartId: $cartId, discountCodes: $discountCodes) {
|
|
151
199
|
cart {
|
|
152
200
|
...CartFragment
|
|
@@ -165,7 +213,13 @@ const CartQuery = (cartFragment) => (
|
|
|
165
213
|
$numCartLines: Int = 250
|
|
166
214
|
$country: CountryCode = ZZ
|
|
167
215
|
$language: LanguageCode
|
|
168
|
-
|
|
216
|
+
$visitorConsent: VisitorConsent
|
|
217
|
+
)
|
|
218
|
+
@inContext(
|
|
219
|
+
country: $country
|
|
220
|
+
language: $language
|
|
221
|
+
visitorConsent: $visitorConsent
|
|
222
|
+
) {
|
|
169
223
|
cart(id: $id) {
|
|
170
224
|
...CartFragment
|
|
171
225
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cart-queries.mjs","sources":["../../src/cart-queries.ts"],"sourcesContent":["export const CartLineAdd = (cartFragment: string): string => /* GraphQL */ `\n mutation CartLineAdd(\n $cartId: ID!\n $lines: [CartLineInput!]!\n $numCartLines: Int = 250\n $country: CountryCode = ZZ\n $language: LanguageCode\n )
|
|
1
|
+
{"version":3,"file":"cart-queries.mjs","sources":["../../src/cart-queries.ts"],"sourcesContent":["export const CartLineAdd = (cartFragment: string): string => /* GraphQL */ `\n mutation CartLineAdd(\n $cartId: ID!\n $lines: [CartLineInput!]!\n $numCartLines: Int = 250\n $country: CountryCode = ZZ\n $language: LanguageCode\n $visitorConsent: VisitorConsent\n )\n @inContext(\n country: $country\n language: $language\n visitorConsent: $visitorConsent\n ) {\n cartLinesAdd(cartId: $cartId, lines: $lines) {\n cart {\n ...CartFragment\n }\n }\n }\n\n ${cartFragment}\n`;\n\nexport const CartCreate = (cartFragment: string): string => /* GraphQL */ `\n mutation CartCreate(\n $input: CartInput!\n $numCartLines: Int = 250\n $country: CountryCode = ZZ\n $language: LanguageCode\n $visitorConsent: VisitorConsent\n )\n @inContext(\n country: $country\n language: $language\n visitorConsent: $visitorConsent\n ) {\n cartCreate(input: $input) {\n cart {\n ...CartFragment\n }\n }\n }\n\n ${cartFragment}\n`;\n\nexport const CartLineRemove = (cartFragment: string): string => /* GraphQL */ `\n mutation CartLineRemove(\n $cartId: ID!\n $lines: [ID!]!\n $numCartLines: Int = 250\n $country: CountryCode = ZZ\n $language: LanguageCode\n $visitorConsent: VisitorConsent\n )\n @inContext(\n country: $country\n language: $language\n visitorConsent: $visitorConsent\n ) {\n cartLinesRemove(cartId: $cartId, lineIds: $lines) {\n cart {\n ...CartFragment\n }\n }\n }\n\n ${cartFragment}\n`;\n\nexport const CartLineUpdate = (cartFragment: string): string => /* GraphQL */ `\n mutation CartLineUpdate(\n $cartId: ID!\n $lines: [CartLineUpdateInput!]!\n $numCartLines: Int = 250\n $country: CountryCode = ZZ\n $language: LanguageCode\n $visitorConsent: VisitorConsent\n )\n @inContext(\n country: $country\n language: $language\n visitorConsent: $visitorConsent\n ) {\n cartLinesUpdate(cartId: $cartId, lines: $lines) {\n cart {\n ...CartFragment\n }\n }\n }\n\n ${cartFragment}\n`;\n\nexport const CartNoteUpdate = (cartFragment: string): string => /* GraphQL */ `\n mutation CartNoteUpdate(\n $cartId: ID!\n $note: String!\n $numCartLines: Int = 250\n $country: CountryCode = ZZ\n $language: LanguageCode\n $visitorConsent: VisitorConsent\n )\n @inContext(\n country: $country\n language: $language\n visitorConsent: $visitorConsent\n ) {\n cartNoteUpdate(cartId: $cartId, note: $note) {\n cart {\n ...CartFragment\n }\n }\n }\n\n ${cartFragment}\n`;\n\nexport const CartBuyerIdentityUpdate = (\n cartFragment: string,\n): string => /* GraphQL */ `\n mutation CartBuyerIdentityUpdate(\n $cartId: ID!\n $buyerIdentity: CartBuyerIdentityInput!\n $numCartLines: Int = 250\n $country: CountryCode = ZZ\n $language: LanguageCode\n $visitorConsent: VisitorConsent\n )\n @inContext(\n country: $country\n language: $language\n visitorConsent: $visitorConsent\n ) {\n cartBuyerIdentityUpdate(cartId: $cartId, buyerIdentity: $buyerIdentity) {\n cart {\n ...CartFragment\n }\n }\n }\n\n ${cartFragment}\n`;\n\nexport const CartAttributesUpdate = (\n cartFragment: string,\n): string => /* GraphQL */ `\n mutation CartAttributesUpdate(\n $attributes: [AttributeInput!]!\n $cartId: ID!\n $numCartLines: Int = 250\n $country: CountryCode = ZZ\n $language: LanguageCode\n $visitorConsent: VisitorConsent\n )\n @inContext(\n country: $country\n language: $language\n visitorConsent: $visitorConsent\n ) {\n cartAttributesUpdate(attributes: $attributes, cartId: $cartId) {\n cart {\n ...CartFragment\n }\n }\n }\n\n ${cartFragment}\n`;\n\nexport const CartDiscountCodesUpdate = (\n cartFragment: string,\n): string => /* GraphQL */ `\n mutation CartDiscountCodesUpdate(\n $cartId: ID!\n $discountCodes: [String!]!\n $numCartLines: Int = 250\n $country: CountryCode = ZZ\n $language: LanguageCode\n $visitorConsent: VisitorConsent\n )\n @inContext(\n country: $country\n language: $language\n visitorConsent: $visitorConsent\n ) {\n cartDiscountCodesUpdate(cartId: $cartId, discountCodes: $discountCodes) {\n cart {\n ...CartFragment\n }\n }\n }\n\n ${cartFragment}\n`;\n\nexport const CartQuery = (cartFragment: string): string => /* GraphQL */ `\n query CartQuery(\n $id: ID!\n $numCartLines: Int = 250\n $country: CountryCode = ZZ\n $language: LanguageCode\n $visitorConsent: VisitorConsent\n )\n @inContext(\n country: $country\n language: $language\n visitorConsent: $visitorConsent\n ) {\n cart(id: $id) {\n ...CartFragment\n }\n }\n\n ${cartFragment}\n`;\n\nexport const defaultCartFragment = /* GraphQL */ `\n fragment 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 compareAtPrice {\n ...MoneyFragment\n }\n price {\n ...MoneyFragment\n }\n requiresShipping\n title\n image {\n ...ImageFragment\n }\n product {\n handle\n title\n id\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 applicable\n }\n }\n\n fragment MoneyFragment on MoneyV2 {\n currencyCode\n amount\n }\n fragment ImageFragment on Image {\n id\n url\n altText\n width\n height\n }\n`;\n"],"names":[],"mappings":"AAAO,MAAM,cAAc,CAAC;AAAA;AAAA,EAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqBvE,YAAY;AAAA;AAAA;AAGT,MAAM,aAAa,CAAC;AAAA;AAAA,EAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAoBtE,YAAY;AAAA;AAAA;AAGT,MAAM,iBAAiB,CAAC;AAAA;AAAA,EAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqB1E,YAAY;AAAA;AAAA;AAGT,MAAM,iBAAiB,CAAC;AAAA;AAAA,EAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqB1E,YAAY;AAAA;AAAA;AAGT,MAAM,iBAAiB,CAAC;AAAA;AAAA,EAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqB1E,YAAY;AAAA;AAAA;AAGT,MAAM,0BAA0B,CACrC;AAAA;AAAA,EACyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqBvB,YAAY;AAAA;AAAA;AAGT,MAAM,uBAAuB,CAClC;AAAA;AAAA,EACyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqBvB,YAAY;AAAA;AAAA;AAGT,MAAM,0BAA0B,CACrC;AAAA;AAAA,EACyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqBvB,YAAY;AAAA;AAAA;AAGT,MAAM,YAAY,CAAC;AAAA;AAAA,EAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAkBrE,YAAY;AAAA;AAAA;AAGT,MAAM;AAAA;AAAA,EAAoC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.helpers.js","sources":["../../src/codegen.helpers.ts"],"sourcesContent":["/**\n * Meant to be used with GraphQL CodeGen to type the Storefront API's custom scalars correctly.\n * Reference for the GraphQL types: https://shopify.dev/docs/api/storefront/
|
|
1
|
+
{"version":3,"file":"codegen.helpers.js","sources":["../../src/codegen.helpers.ts"],"sourcesContent":["/**\n * Meant to be used with GraphQL CodeGen to type the Storefront API's custom scalars correctly.\n * Reference for the GraphQL types: https://shopify.dev/docs/api/storefront/2026-01/scalars/HTML\n * Note: JSON is generated as 'unknown' by default.\n */\nexport const storefrontApiCustomScalars = {\n // Keep in sync with the definitions in the app/nextjs/codegen.ts!\n DateTime: 'string',\n Decimal: 'string',\n HTML: 'string',\n URL: 'string',\n Color: 'string',\n UnsignedInt64: 'string',\n};\n\n/**\n * Meant to be used with GraphQL CodeGen to type the Storefront API's custom scalars correctly.\n * Reference for the GraphQL types: https://shopify.dev/docs/api/customer/2026-01/scalars/HTML\n * Note: JSON is generated as 'unknown' by default.\n */\nexport const customerAccountApiCustomScalars = {\n DateTime: 'string',\n Decimal: 'string',\n HTML: 'string',\n ISO8601DateTime: 'string',\n URL: 'string',\n UnsignedInt64: 'string',\n};\n"],"names":[],"mappings":";;AAKO,MAAM,6BAA6B;AAAA;AAAA,EAExC,UAAU;AAAA,EACV,SAAS;AAAA,EACT,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,eAAe;AACjB;AAOO,MAAM,kCAAkC;AAAA,EAC7C,UAAU;AAAA,EACV,SAAS;AAAA,EACT,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,KAAK;AAAA,EACL,eAAe;AACjB;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.helpers.mjs","sources":["../../src/codegen.helpers.ts"],"sourcesContent":["/**\n * Meant to be used with GraphQL CodeGen to type the Storefront API's custom scalars correctly.\n * Reference for the GraphQL types: https://shopify.dev/docs/api/storefront/
|
|
1
|
+
{"version":3,"file":"codegen.helpers.mjs","sources":["../../src/codegen.helpers.ts"],"sourcesContent":["/**\n * Meant to be used with GraphQL CodeGen to type the Storefront API's custom scalars correctly.\n * Reference for the GraphQL types: https://shopify.dev/docs/api/storefront/2026-01/scalars/HTML\n * Note: JSON is generated as 'unknown' by default.\n */\nexport const storefrontApiCustomScalars = {\n // Keep in sync with the definitions in the app/nextjs/codegen.ts!\n DateTime: 'string',\n Decimal: 'string',\n HTML: 'string',\n URL: 'string',\n Color: 'string',\n UnsignedInt64: 'string',\n};\n\n/**\n * Meant to be used with GraphQL CodeGen to type the Storefront API's custom scalars correctly.\n * Reference for the GraphQL types: https://shopify.dev/docs/api/customer/2026-01/scalars/HTML\n * Note: JSON is generated as 'unknown' by default.\n */\nexport const customerAccountApiCustomScalars = {\n DateTime: 'string',\n Decimal: 'string',\n HTML: 'string',\n ISO8601DateTime: 'string',\n URL: 'string',\n UnsignedInt64: 'string',\n};\n"],"names":[],"mappings":"AAKO,MAAM,6BAA6B;AAAA;AAAA,EAExC,UAAU;AAAA,EACV,SAAS;AAAA,EACT,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,eAAe;AACjB;AAOO,MAAM,kCAAkC;AAAA,EAC7C,UAAU;AAAA,EACV,SAAS;AAAA,EACT,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,KAAK;AAAA,EACL,eAAe;AACjB;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optionValueDecoder.js","sources":["../../src/optionValueDecoder.ts"],"sourcesContent":["/**\n * This file provides utility functions for determining whether or not an option value combination is present in an encoded option value string.\n *\n * In V1 of the encoding strategy, option value arrays are encoded as a trie with the following rules:\n * - `:` `,` ` ` and `-` are control characters.\n * - `:` indicates a new option. ex: 0:1 indicates value 0 for the option in position 1, value 1 for the option in position 2.\n * - `,` indicates the end of a repeated prefix, mulitple consecutive commas indicate the end of multiple repeated prefixes.\n * - ` ` indicates a gap in the sequence of option values. ex: `0 4` indicates option values in position 0 and 4 are present.\n * - `-` indicates a continuous range of option values. ex: `0 1-3 4`. Ranges are only present encoded in the final option value position, so for example the trie for the set [[0,0,0],[0,0,1], ..., [0,2,2]] will be structured as `0:0:0-2,1:0-2,2:0-2`, not `0:0-2:0-2`.\n */\n\nimport {Product} from './storefront-api-types.js';\n\nconst OPTION_VALUE_SEPARATOR = ',';\n\nconst V1_CONTROL_CHARS = {\n OPTION: ':',\n END_OF_PREFIX: ',',\n SEQUENCE_GAP: ' ',\n RANGE: '-',\n};\n\nexport type IsOptionValueCombinationInEncodedVariant = (\n targetOptionValueCombination: number[],\n encodedVariantField: string,\n) => boolean;\n\n/**\n * Determine whether an option value combination is present in an encoded option value string. Function is memoized by encodedVariantField.\n *\n * @param targetOptionValueCombination - Indices of option values to look up in the encoded option value string. A partial set of indices may be passed to determine whether a node or any children is present. For example, if a product has 3 options, passing [0] will return true if any option value combination for the first option's option value is present in the encoded string.\n * @param encodedVariantField - Encoded option value string from the Storefront API, e.g. [product.encodedVariantExistence](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantexistence) or [product.encodedVariantAvailability](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantavailability)\n * @returns - True if a full or partial targetOptionValueIndices is present in the encoded option value string, false otherwise.\n */\nexport const isOptionValueCombinationInEncodedVariant: IsOptionValueCombinationInEncodedVariant =\n ((): IsOptionValueCombinationInEncodedVariant => {\n const decodedOptionValues = new Map<string, Set<string>>();\n\n return function (\n targetOptionValueCombination: number[],\n encodedVariantField: string,\n ): boolean {\n if (targetOptionValueCombination.length === 0) {\n return false;\n }\n\n if (!decodedOptionValues.has(encodedVariantField)) {\n const decodedOptionValuesSet = new Set<string>();\n\n for (const optionValue of decodeEncodedVariant(encodedVariantField)) {\n // add the complete option value to the decoded option values set\n decodedOptionValuesSet.add(optionValue.join(OPTION_VALUE_SEPARATOR));\n\n // add all composite parts of the option value to the decoded option values set. e.g. if the option value is [0,1,2], add \"0\", \"0,1\", \"0,1,2\"\n for (let i = 0; i < optionValue.length; i++) {\n decodedOptionValuesSet.add(\n optionValue.slice(0, i + 1).join(OPTION_VALUE_SEPARATOR),\n );\n }\n }\n\n decodedOptionValues.set(encodedVariantField, decodedOptionValuesSet);\n }\n\n return Boolean(\n decodedOptionValues\n .get(encodedVariantField)\n ?.has(targetOptionValueCombination.join(OPTION_VALUE_SEPARATOR)),\n );\n };\n })();\n\ntype EncodedVariantField =\n | Product['encodedVariantAvailability']\n // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents\n | Product['encodedVariantExistence'];\ntype DecodedOptionValues = number[][];\n\n/**\n * For an encoded option value string, decode into option value combinations. Entries represent a valid combination formatted as an array of option value positions.\n * @param encodedVariantField - Encoded option value string from the Storefront API, e.g. [product.encodedVariantExistence](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantexistence) or [product.encodedVariantAvailability](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantavailability)\n * @returns Decoded option value combinations\n */\nexport function decodeEncodedVariant(\n encodedVariantField: EncodedVariantField,\n): DecodedOptionValues {\n if (!encodedVariantField) return [];\n\n if (encodedVariantField.startsWith('v1_')) {\n return v1Decoder(stripVersion(encodedVariantField));\n }\n\n throw new Error('Unsupported option value encoding');\n}\n\nconst stripVersion: (encodedVariantField: string) => string = (\n encodedVariantField: string,\n) => encodedVariantField.replace(/^v1_/, '');\n\n/**\n * We encode an array of arrays representing variants, expressed in terms of options and option values, as a trie.\n *\n * This encoding strategy allows extremely large numbers of variants to be expressed in an extremely compact data structure.\n *\n * Integers represent option and values, so [0,0,0] represents option_value at array index 0 for the options at array indexes 0, 1 and 2\n *\n * `:`, `,`, ` ` and `-` are control characters.\n * `:` indicates a new option\n * `,` indicates the end of a repeated prefix, mulitple consecutive commas indicate the end of multiple repeated prefixes.\n * ` ` indicates a gap in the sequence of option values\n * `-` indicates a continuous range of option values\n *\n * Encoding process:\n *\n * example input array: [[0,0,0], [0,1,0], [0,1,1], [1,0,0], [1,0,1], [1,1,1], [2,0,1], [2,1,0]]\n *\n * step 1: encode as string: \"0:0:0,0:1:0,0:1:1,1:0:0,1:0:1,1:1:1,2:0:1,2:1:0,\"\n * step 2: combine nodes that share a prefix: \"0:0:0,0:1:0 1,1:0:0 1,1:1:1,2:0:1,2:1:0,\"\n * step 3: encode data as a trie so no prefixes need to be repeated: \"0:0:0,1:0 1,,1:0:0 1,1:1,,2:0:1,1:0,,\"\n * step 4: since the options are sorted, use a dash to express ranges: \"0:0:0,1:0-1,,1:0:0-1,1:1,,2:0:1,1:0,,\"\n */\nfunction v1Decoder(encodedVariantField: string): number[][] {\n const tokenizer = /[ :,-]/g;\n let index = 0;\n let token: RegExpExecArray | null;\n const options: number[][] = [];\n const currentOptionValue: number[] = [];\n let depth = 0;\n let rangeStart: number | null = null;\n\n // iterate over control characters\n while ((token = tokenizer.exec(encodedVariantField))) {\n const operation = token[0];\n const optionValueIndex =\n Number.parseInt(encodedVariantField.slice(index, token.index)) || 0;\n\n if (rangeStart !== null) {\n // If a range has been started, iterate over the range and add each option value to the list of options\n // - `rangeStart` is set if the last control char was a dash, e.g. `0` for 0-2. It represents the numeric option value position for the start of the range.\n // - `optionValueIndex` is the numeric option value position for the end of the range\n for (; rangeStart < optionValueIndex; rangeStart++) {\n currentOptionValue[depth] = rangeStart;\n options.push([...currentOptionValue]);\n }\n // indicates the range has been processed\n rangeStart = null;\n }\n\n currentOptionValue[depth] = optionValueIndex;\n\n if (operation === V1_CONTROL_CHARS.RANGE) {\n // dash operation indicates we are in a range. e.g. 0-2 means option values 0, 1, 2\n rangeStart = optionValueIndex;\n } else if (operation === V1_CONTROL_CHARS.OPTION) {\n // colon operation indicates that we are moving down to the next layer of option values. e.g. 0:0:0-2 means we traverse down from option1 to option3 and represents [[0,0,0], [0,0,1], [0,0,2]]\n depth++;\n } else {\n if (\n operation === V1_CONTROL_CHARS.SEQUENCE_GAP ||\n (operation === V1_CONTROL_CHARS.END_OF_PREFIX &&\n encodedVariantField[token.index - 1] !==\n V1_CONTROL_CHARS.END_OF_PREFIX)\n ) {\n // add the current option value to the list of options if we hit a gap in our sequence or we are at the end of our depth and need to move back up\n options.push([...currentOptionValue]);\n }\n if (operation === V1_CONTROL_CHARS.END_OF_PREFIX) {\n // go up an option level, trash the last item in currentOptionValue\n currentOptionValue.pop();\n depth--;\n }\n }\n index = tokenizer.lastIndex;\n }\n\n // The while loop only iterates control characters, meaning if an encoded string ends with an index it will not be processed.\n const encodingEndsWithIndex = encodedVariantField.match(/\\d+$/g);\n if (encodingEndsWithIndex) {\n const finalValueIndex = parseInt(encodingEndsWithIndex[0]);\n if (rangeStart != null) {\n // process final range\n for (; rangeStart <= finalValueIndex; rangeStart++) {\n currentOptionValue[depth] = rangeStart;\n options.push([...currentOptionValue]);\n }\n } else {\n // process final index\n options.push([finalValueIndex]);\n }\n }\n\n return options;\n}\n"],"names":[],"mappings":";;AAaA,MAAM,yBAAyB;AAE/B,MAAM,mBAAmB;AAAA,EACvB,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,cAAc;AAAA,EACd,OAAO;AACT;AAcO,MAAM,2CACV,uBAAgD;AAC/C,QAAM,0CAA0B,IAAA;AAEhC,SAAO,SACL,8BACA,qBACS;;AACT,QAAI,6BAA6B,WAAW,GAAG;AAC7C,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,oBAAoB,IAAI,mBAAmB,GAAG;AACjD,YAAM,6CAA6B,IAAA;AAEnC,iBAAW,eAAe,qBAAqB,mBAAmB,GAAG;AAEnE,+BAAuB,IAAI,YAAY,KAAK,sBAAsB,CAAC;AAGnE,iBAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,iCAAuB;AAAA,YACrB,YAAY,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,sBAAsB;AAAA,UAAA;AAAA,QAE3D;AAAA,MACF;AAEA,0BAAoB,IAAI,qBAAqB,sBAAsB;AAAA,IACrE;AAEA,WAAO;AAAA,OACL,yBACG,IAAI,mBAAmB,MAD1B,mBAEI,IAAI,6BAA6B,KAAK,sBAAsB;AAAA,IAAC;AAAA,EAErE;AACF,GAAA;AAaK,SAAS,qBACd,qBACqB;AACrB,MAAI,CAAC,oBAAqB,QAAO,CAAA;AAEjC,MAAI,oBAAoB,WAAW,KAAK,GAAG;AACzC,WAAO,UAAU,aAAa,mBAAmB,CAAC;AAAA,EACpD;AAEA,QAAM,IAAI,MAAM,mCAAmC;AACrD;AAEA,MAAM,eAAwD,CAC5D,wBACG,oBAAoB,QAAQ,QAAQ,EAAE;AAwB3C,SAAS,UAAU,qBAAyC;AAC1D,QAAM,YAAY;AAClB,MAAI,QAAQ;AACZ,MAAI;AACJ,QAAM,UAAsB,CAAA;AAC5B,QAAM,qBAA+B,CAAA;AACrC,MAAI,QAAQ;AACZ,MAAI,aAA4B;AAGhC,SAAQ,QAAQ,UAAU,KAAK,mBAAmB,GAAI;AACpD,UAAM,YAAY,MAAM,CAAC;AACzB,UAAM,mBACJ,OAAO,SAAS,oBAAoB,MAAM,OAAO,MAAM,KAAK,CAAC,KAAK;AAEpE,QAAI,eAAe,MAAM;AAIvB,aAAO,aAAa,kBAAkB,cAAc;AAClD,2BAAmB,KAAK,IAAI;AAC5B,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AAEA,mBAAa;AAAA,IACf;AAEA,uBAAmB,KAAK,IAAI;AAE5B,QAAI,cAAc,iBAAiB,OAAO;AAExC,mBAAa;AAAA,IACf,WAAW,cAAc,iBAAiB,QAAQ;AAEhD;AAAA,IACF,OAAO;AACL,UACE,cAAc,iBAAiB,gBAC9B,cAAc,iBAAiB,iBAC9B,oBAAoB,MAAM,QAAQ,CAAC,MACjC,iBAAiB,eACrB;AAEA,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AACA,UAAI,cAAc,iBAAiB,eAAe;AAEhD,2BAAmB,IAAA;AACnB;AAAA,MACF;AAAA,IACF;AACA,YAAQ,UAAU;AAAA,EACpB;AAGA,QAAM,wBAAwB,oBAAoB,MAAM,OAAO;AAC/D,MAAI,uBAAuB;AACzB,UAAM,kBAAkB,SAAS,sBAAsB,CAAC,CAAC;AACzD,QAAI,cAAc,MAAM;AAEtB,aAAO,cAAc,iBAAiB,cAAc;AAClD,2BAAmB,KAAK,IAAI;AAC5B,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AAAA,IACF,OAAO;AAEL,cAAQ,KAAK,CAAC,eAAe,CAAC;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AACT;;;"}
|
|
1
|
+
{"version":3,"file":"optionValueDecoder.js","sources":["../../src/optionValueDecoder.ts"],"sourcesContent":["/**\n * This file provides utility functions for determining whether or not an option value combination is present in an encoded option value string.\n *\n * In V1 of the encoding strategy, option value arrays are encoded as a trie with the following rules:\n * - `:` `,` ` ` and `-` are control characters.\n * - `:` indicates a new option. ex: 0:1 indicates value 0 for the option in position 1, value 1 for the option in position 2.\n * - `,` indicates the end of a repeated prefix, mulitple consecutive commas indicate the end of multiple repeated prefixes.\n * - ` ` indicates a gap in the sequence of option values. ex: `0 4` indicates option values in position 0 and 4 are present.\n * - `-` indicates a continuous range of option values. ex: `0 1-3 4`. Ranges are only present encoded in the final option value position, so for example the trie for the set [[0,0,0],[0,0,1], ..., [0,2,2]] will be structured as `0:0:0-2,1:0-2,2:0-2`, not `0:0-2:0-2`.\n */\n\nimport {Product} from './storefront-api-types.js';\n\nconst OPTION_VALUE_SEPARATOR = ',';\n\nconst V1_CONTROL_CHARS = {\n OPTION: ':',\n END_OF_PREFIX: ',',\n SEQUENCE_GAP: ' ',\n RANGE: '-',\n};\n\nexport type IsOptionValueCombinationInEncodedVariant = (\n targetOptionValueCombination: number[],\n encodedVariantField: string,\n) => boolean;\n\n/**\n * Determine whether an option value combination is present in an encoded option value string. Function is memoized by encodedVariantField.\n *\n * @param targetOptionValueCombination - Indices of option values to look up in the encoded option value string. A partial set of indices may be passed to determine whether a node or any children is present. For example, if a product has 3 options, passing [0] will return true if any option value combination for the first option's option value is present in the encoded string.\n * @param encodedVariantField - Encoded option value string from the Storefront API, e.g. [product.encodedVariantExistence](/docs/api/storefront/2026-01/objects/Product#field-encodedvariantexistence) or [product.encodedVariantAvailability](/docs/api/storefront/2026-01/objects/Product#field-encodedvariantavailability)\n * @returns - True if a full or partial targetOptionValueIndices is present in the encoded option value string, false otherwise.\n */\nexport const isOptionValueCombinationInEncodedVariant: IsOptionValueCombinationInEncodedVariant =\n ((): IsOptionValueCombinationInEncodedVariant => {\n const decodedOptionValues = new Map<string, Set<string>>();\n\n return function (\n targetOptionValueCombination: number[],\n encodedVariantField: string,\n ): boolean {\n if (targetOptionValueCombination.length === 0) {\n return false;\n }\n\n if (!decodedOptionValues.has(encodedVariantField)) {\n const decodedOptionValuesSet = new Set<string>();\n\n for (const optionValue of decodeEncodedVariant(encodedVariantField)) {\n // add the complete option value to the decoded option values set\n decodedOptionValuesSet.add(optionValue.join(OPTION_VALUE_SEPARATOR));\n\n // add all composite parts of the option value to the decoded option values set. e.g. if the option value is [0,1,2], add \"0\", \"0,1\", \"0,1,2\"\n for (let i = 0; i < optionValue.length; i++) {\n decodedOptionValuesSet.add(\n optionValue.slice(0, i + 1).join(OPTION_VALUE_SEPARATOR),\n );\n }\n }\n\n decodedOptionValues.set(encodedVariantField, decodedOptionValuesSet);\n }\n\n return Boolean(\n decodedOptionValues\n .get(encodedVariantField)\n ?.has(targetOptionValueCombination.join(OPTION_VALUE_SEPARATOR)),\n );\n };\n })();\n\ntype EncodedVariantField =\n | Product['encodedVariantAvailability']\n // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents\n | Product['encodedVariantExistence'];\ntype DecodedOptionValues = number[][];\n\n/**\n * For an encoded option value string, decode into option value combinations. Entries represent a valid combination formatted as an array of option value positions.\n * @param encodedVariantField - Encoded option value string from the Storefront API, e.g. [product.encodedVariantExistence](/docs/api/storefront/2026-01/objects/Product#field-encodedvariantexistence) or [product.encodedVariantAvailability](/docs/api/storefront/2026-01/objects/Product#field-encodedvariantavailability)\n * @returns Decoded option value combinations\n */\nexport function decodeEncodedVariant(\n encodedVariantField: EncodedVariantField,\n): DecodedOptionValues {\n if (!encodedVariantField) return [];\n\n if (encodedVariantField.startsWith('v1_')) {\n return v1Decoder(stripVersion(encodedVariantField));\n }\n\n throw new Error('Unsupported option value encoding');\n}\n\nconst stripVersion: (encodedVariantField: string) => string = (\n encodedVariantField: string,\n) => encodedVariantField.replace(/^v1_/, '');\n\n/**\n * We encode an array of arrays representing variants, expressed in terms of options and option values, as a trie.\n *\n * This encoding strategy allows extremely large numbers of variants to be expressed in an extremely compact data structure.\n *\n * Integers represent option and values, so [0,0,0] represents option_value at array index 0 for the options at array indexes 0, 1 and 2\n *\n * `:`, `,`, ` ` and `-` are control characters.\n * `:` indicates a new option\n * `,` indicates the end of a repeated prefix, mulitple consecutive commas indicate the end of multiple repeated prefixes.\n * ` ` indicates a gap in the sequence of option values\n * `-` indicates a continuous range of option values\n *\n * Encoding process:\n *\n * example input array: [[0,0,0], [0,1,0], [0,1,1], [1,0,0], [1,0,1], [1,1,1], [2,0,1], [2,1,0]]\n *\n * step 1: encode as string: \"0:0:0,0:1:0,0:1:1,1:0:0,1:0:1,1:1:1,2:0:1,2:1:0,\"\n * step 2: combine nodes that share a prefix: \"0:0:0,0:1:0 1,1:0:0 1,1:1:1,2:0:1,2:1:0,\"\n * step 3: encode data as a trie so no prefixes need to be repeated: \"0:0:0,1:0 1,,1:0:0 1,1:1,,2:0:1,1:0,,\"\n * step 4: since the options are sorted, use a dash to express ranges: \"0:0:0,1:0-1,,1:0:0-1,1:1,,2:0:1,1:0,,\"\n */\nfunction v1Decoder(encodedVariantField: string): number[][] {\n const tokenizer = /[ :,-]/g;\n let index = 0;\n let token: RegExpExecArray | null;\n const options: number[][] = [];\n const currentOptionValue: number[] = [];\n let depth = 0;\n let rangeStart: number | null = null;\n\n // iterate over control characters\n while ((token = tokenizer.exec(encodedVariantField))) {\n const operation = token[0];\n const optionValueIndex =\n Number.parseInt(encodedVariantField.slice(index, token.index)) || 0;\n\n if (rangeStart !== null) {\n // If a range has been started, iterate over the range and add each option value to the list of options\n // - `rangeStart` is set if the last control char was a dash, e.g. `0` for 0-2. It represents the numeric option value position for the start of the range.\n // - `optionValueIndex` is the numeric option value position for the end of the range\n for (; rangeStart < optionValueIndex; rangeStart++) {\n currentOptionValue[depth] = rangeStart;\n options.push([...currentOptionValue]);\n }\n // indicates the range has been processed\n rangeStart = null;\n }\n\n currentOptionValue[depth] = optionValueIndex;\n\n if (operation === V1_CONTROL_CHARS.RANGE) {\n // dash operation indicates we are in a range. e.g. 0-2 means option values 0, 1, 2\n rangeStart = optionValueIndex;\n } else if (operation === V1_CONTROL_CHARS.OPTION) {\n // colon operation indicates that we are moving down to the next layer of option values. e.g. 0:0:0-2 means we traverse down from option1 to option3 and represents [[0,0,0], [0,0,1], [0,0,2]]\n depth++;\n } else {\n if (\n operation === V1_CONTROL_CHARS.SEQUENCE_GAP ||\n (operation === V1_CONTROL_CHARS.END_OF_PREFIX &&\n encodedVariantField[token.index - 1] !==\n V1_CONTROL_CHARS.END_OF_PREFIX)\n ) {\n // add the current option value to the list of options if we hit a gap in our sequence or we are at the end of our depth and need to move back up\n options.push([...currentOptionValue]);\n }\n if (operation === V1_CONTROL_CHARS.END_OF_PREFIX) {\n // go up an option level, trash the last item in currentOptionValue\n currentOptionValue.pop();\n depth--;\n }\n }\n index = tokenizer.lastIndex;\n }\n\n // The while loop only iterates control characters, meaning if an encoded string ends with an index it will not be processed.\n const encodingEndsWithIndex = encodedVariantField.match(/\\d+$/g);\n if (encodingEndsWithIndex) {\n const finalValueIndex = parseInt(encodingEndsWithIndex[0]);\n if (rangeStart != null) {\n // process final range\n for (; rangeStart <= finalValueIndex; rangeStart++) {\n currentOptionValue[depth] = rangeStart;\n options.push([...currentOptionValue]);\n }\n } else {\n // process final index\n options.push([finalValueIndex]);\n }\n }\n\n return options;\n}\n"],"names":[],"mappings":";;AAaA,MAAM,yBAAyB;AAE/B,MAAM,mBAAmB;AAAA,EACvB,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,cAAc;AAAA,EACd,OAAO;AACT;AAcO,MAAM,2CACV,uBAAgD;AAC/C,QAAM,0CAA0B,IAAA;AAEhC,SAAO,SACL,8BACA,qBACS;;AACT,QAAI,6BAA6B,WAAW,GAAG;AAC7C,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,oBAAoB,IAAI,mBAAmB,GAAG;AACjD,YAAM,6CAA6B,IAAA;AAEnC,iBAAW,eAAe,qBAAqB,mBAAmB,GAAG;AAEnE,+BAAuB,IAAI,YAAY,KAAK,sBAAsB,CAAC;AAGnE,iBAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,iCAAuB;AAAA,YACrB,YAAY,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,sBAAsB;AAAA,UAAA;AAAA,QAE3D;AAAA,MACF;AAEA,0BAAoB,IAAI,qBAAqB,sBAAsB;AAAA,IACrE;AAEA,WAAO;AAAA,OACL,yBACG,IAAI,mBAAmB,MAD1B,mBAEI,IAAI,6BAA6B,KAAK,sBAAsB;AAAA,IAAC;AAAA,EAErE;AACF,GAAA;AAaK,SAAS,qBACd,qBACqB;AACrB,MAAI,CAAC,oBAAqB,QAAO,CAAA;AAEjC,MAAI,oBAAoB,WAAW,KAAK,GAAG;AACzC,WAAO,UAAU,aAAa,mBAAmB,CAAC;AAAA,EACpD;AAEA,QAAM,IAAI,MAAM,mCAAmC;AACrD;AAEA,MAAM,eAAwD,CAC5D,wBACG,oBAAoB,QAAQ,QAAQ,EAAE;AAwB3C,SAAS,UAAU,qBAAyC;AAC1D,QAAM,YAAY;AAClB,MAAI,QAAQ;AACZ,MAAI;AACJ,QAAM,UAAsB,CAAA;AAC5B,QAAM,qBAA+B,CAAA;AACrC,MAAI,QAAQ;AACZ,MAAI,aAA4B;AAGhC,SAAQ,QAAQ,UAAU,KAAK,mBAAmB,GAAI;AACpD,UAAM,YAAY,MAAM,CAAC;AACzB,UAAM,mBACJ,OAAO,SAAS,oBAAoB,MAAM,OAAO,MAAM,KAAK,CAAC,KAAK;AAEpE,QAAI,eAAe,MAAM;AAIvB,aAAO,aAAa,kBAAkB,cAAc;AAClD,2BAAmB,KAAK,IAAI;AAC5B,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AAEA,mBAAa;AAAA,IACf;AAEA,uBAAmB,KAAK,IAAI;AAE5B,QAAI,cAAc,iBAAiB,OAAO;AAExC,mBAAa;AAAA,IACf,WAAW,cAAc,iBAAiB,QAAQ;AAEhD;AAAA,IACF,OAAO;AACL,UACE,cAAc,iBAAiB,gBAC9B,cAAc,iBAAiB,iBAC9B,oBAAoB,MAAM,QAAQ,CAAC,MACjC,iBAAiB,eACrB;AAEA,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AACA,UAAI,cAAc,iBAAiB,eAAe;AAEhD,2BAAmB,IAAA;AACnB;AAAA,MACF;AAAA,IACF;AACA,YAAQ,UAAU;AAAA,EACpB;AAGA,QAAM,wBAAwB,oBAAoB,MAAM,OAAO;AAC/D,MAAI,uBAAuB;AACzB,UAAM,kBAAkB,SAAS,sBAAsB,CAAC,CAAC;AACzD,QAAI,cAAc,MAAM;AAEtB,aAAO,cAAc,iBAAiB,cAAc;AAClD,2BAAmB,KAAK,IAAI;AAC5B,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AAAA,IACF,OAAO;AAEL,cAAQ,KAAK,CAAC,eAAe,CAAC;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AACT;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optionValueDecoder.mjs","sources":["../../src/optionValueDecoder.ts"],"sourcesContent":["/**\n * This file provides utility functions for determining whether or not an option value combination is present in an encoded option value string.\n *\n * In V1 of the encoding strategy, option value arrays are encoded as a trie with the following rules:\n * - `:` `,` ` ` and `-` are control characters.\n * - `:` indicates a new option. ex: 0:1 indicates value 0 for the option in position 1, value 1 for the option in position 2.\n * - `,` indicates the end of a repeated prefix, mulitple consecutive commas indicate the end of multiple repeated prefixes.\n * - ` ` indicates a gap in the sequence of option values. ex: `0 4` indicates option values in position 0 and 4 are present.\n * - `-` indicates a continuous range of option values. ex: `0 1-3 4`. Ranges are only present encoded in the final option value position, so for example the trie for the set [[0,0,0],[0,0,1], ..., [0,2,2]] will be structured as `0:0:0-2,1:0-2,2:0-2`, not `0:0-2:0-2`.\n */\n\nimport {Product} from './storefront-api-types.js';\n\nconst OPTION_VALUE_SEPARATOR = ',';\n\nconst V1_CONTROL_CHARS = {\n OPTION: ':',\n END_OF_PREFIX: ',',\n SEQUENCE_GAP: ' ',\n RANGE: '-',\n};\n\nexport type IsOptionValueCombinationInEncodedVariant = (\n targetOptionValueCombination: number[],\n encodedVariantField: string,\n) => boolean;\n\n/**\n * Determine whether an option value combination is present in an encoded option value string. Function is memoized by encodedVariantField.\n *\n * @param targetOptionValueCombination - Indices of option values to look up in the encoded option value string. A partial set of indices may be passed to determine whether a node or any children is present. For example, if a product has 3 options, passing [0] will return true if any option value combination for the first option's option value is present in the encoded string.\n * @param encodedVariantField - Encoded option value string from the Storefront API, e.g. [product.encodedVariantExistence](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantexistence) or [product.encodedVariantAvailability](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantavailability)\n * @returns - True if a full or partial targetOptionValueIndices is present in the encoded option value string, false otherwise.\n */\nexport const isOptionValueCombinationInEncodedVariant: IsOptionValueCombinationInEncodedVariant =\n ((): IsOptionValueCombinationInEncodedVariant => {\n const decodedOptionValues = new Map<string, Set<string>>();\n\n return function (\n targetOptionValueCombination: number[],\n encodedVariantField: string,\n ): boolean {\n if (targetOptionValueCombination.length === 0) {\n return false;\n }\n\n if (!decodedOptionValues.has(encodedVariantField)) {\n const decodedOptionValuesSet = new Set<string>();\n\n for (const optionValue of decodeEncodedVariant(encodedVariantField)) {\n // add the complete option value to the decoded option values set\n decodedOptionValuesSet.add(optionValue.join(OPTION_VALUE_SEPARATOR));\n\n // add all composite parts of the option value to the decoded option values set. e.g. if the option value is [0,1,2], add \"0\", \"0,1\", \"0,1,2\"\n for (let i = 0; i < optionValue.length; i++) {\n decodedOptionValuesSet.add(\n optionValue.slice(0, i + 1).join(OPTION_VALUE_SEPARATOR),\n );\n }\n }\n\n decodedOptionValues.set(encodedVariantField, decodedOptionValuesSet);\n }\n\n return Boolean(\n decodedOptionValues\n .get(encodedVariantField)\n ?.has(targetOptionValueCombination.join(OPTION_VALUE_SEPARATOR)),\n );\n };\n })();\n\ntype EncodedVariantField =\n | Product['encodedVariantAvailability']\n // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents\n | Product['encodedVariantExistence'];\ntype DecodedOptionValues = number[][];\n\n/**\n * For an encoded option value string, decode into option value combinations. Entries represent a valid combination formatted as an array of option value positions.\n * @param encodedVariantField - Encoded option value string from the Storefront API, e.g. [product.encodedVariantExistence](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantexistence) or [product.encodedVariantAvailability](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantavailability)\n * @returns Decoded option value combinations\n */\nexport function decodeEncodedVariant(\n encodedVariantField: EncodedVariantField,\n): DecodedOptionValues {\n if (!encodedVariantField) return [];\n\n if (encodedVariantField.startsWith('v1_')) {\n return v1Decoder(stripVersion(encodedVariantField));\n }\n\n throw new Error('Unsupported option value encoding');\n}\n\nconst stripVersion: (encodedVariantField: string) => string = (\n encodedVariantField: string,\n) => encodedVariantField.replace(/^v1_/, '');\n\n/**\n * We encode an array of arrays representing variants, expressed in terms of options and option values, as a trie.\n *\n * This encoding strategy allows extremely large numbers of variants to be expressed in an extremely compact data structure.\n *\n * Integers represent option and values, so [0,0,0] represents option_value at array index 0 for the options at array indexes 0, 1 and 2\n *\n * `:`, `,`, ` ` and `-` are control characters.\n * `:` indicates a new option\n * `,` indicates the end of a repeated prefix, mulitple consecutive commas indicate the end of multiple repeated prefixes.\n * ` ` indicates a gap in the sequence of option values\n * `-` indicates a continuous range of option values\n *\n * Encoding process:\n *\n * example input array: [[0,0,0], [0,1,0], [0,1,1], [1,0,0], [1,0,1], [1,1,1], [2,0,1], [2,1,0]]\n *\n * step 1: encode as string: \"0:0:0,0:1:0,0:1:1,1:0:0,1:0:1,1:1:1,2:0:1,2:1:0,\"\n * step 2: combine nodes that share a prefix: \"0:0:0,0:1:0 1,1:0:0 1,1:1:1,2:0:1,2:1:0,\"\n * step 3: encode data as a trie so no prefixes need to be repeated: \"0:0:0,1:0 1,,1:0:0 1,1:1,,2:0:1,1:0,,\"\n * step 4: since the options are sorted, use a dash to express ranges: \"0:0:0,1:0-1,,1:0:0-1,1:1,,2:0:1,1:0,,\"\n */\nfunction v1Decoder(encodedVariantField: string): number[][] {\n const tokenizer = /[ :,-]/g;\n let index = 0;\n let token: RegExpExecArray | null;\n const options: number[][] = [];\n const currentOptionValue: number[] = [];\n let depth = 0;\n let rangeStart: number | null = null;\n\n // iterate over control characters\n while ((token = tokenizer.exec(encodedVariantField))) {\n const operation = token[0];\n const optionValueIndex =\n Number.parseInt(encodedVariantField.slice(index, token.index)) || 0;\n\n if (rangeStart !== null) {\n // If a range has been started, iterate over the range and add each option value to the list of options\n // - `rangeStart` is set if the last control char was a dash, e.g. `0` for 0-2. It represents the numeric option value position for the start of the range.\n // - `optionValueIndex` is the numeric option value position for the end of the range\n for (; rangeStart < optionValueIndex; rangeStart++) {\n currentOptionValue[depth] = rangeStart;\n options.push([...currentOptionValue]);\n }\n // indicates the range has been processed\n rangeStart = null;\n }\n\n currentOptionValue[depth] = optionValueIndex;\n\n if (operation === V1_CONTROL_CHARS.RANGE) {\n // dash operation indicates we are in a range. e.g. 0-2 means option values 0, 1, 2\n rangeStart = optionValueIndex;\n } else if (operation === V1_CONTROL_CHARS.OPTION) {\n // colon operation indicates that we are moving down to the next layer of option values. e.g. 0:0:0-2 means we traverse down from option1 to option3 and represents [[0,0,0], [0,0,1], [0,0,2]]\n depth++;\n } else {\n if (\n operation === V1_CONTROL_CHARS.SEQUENCE_GAP ||\n (operation === V1_CONTROL_CHARS.END_OF_PREFIX &&\n encodedVariantField[token.index - 1] !==\n V1_CONTROL_CHARS.END_OF_PREFIX)\n ) {\n // add the current option value to the list of options if we hit a gap in our sequence or we are at the end of our depth and need to move back up\n options.push([...currentOptionValue]);\n }\n if (operation === V1_CONTROL_CHARS.END_OF_PREFIX) {\n // go up an option level, trash the last item in currentOptionValue\n currentOptionValue.pop();\n depth--;\n }\n }\n index = tokenizer.lastIndex;\n }\n\n // The while loop only iterates control characters, meaning if an encoded string ends with an index it will not be processed.\n const encodingEndsWithIndex = encodedVariantField.match(/\\d+$/g);\n if (encodingEndsWithIndex) {\n const finalValueIndex = parseInt(encodingEndsWithIndex[0]);\n if (rangeStart != null) {\n // process final range\n for (; rangeStart <= finalValueIndex; rangeStart++) {\n currentOptionValue[depth] = rangeStart;\n options.push([...currentOptionValue]);\n }\n } else {\n // process final index\n options.push([finalValueIndex]);\n }\n }\n\n return options;\n}\n"],"names":[],"mappings":"AAaA,MAAM,yBAAyB;AAE/B,MAAM,mBAAmB;AAAA,EACvB,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,cAAc;AAAA,EACd,OAAO;AACT;AAcO,MAAM,2CACV,uBAAgD;AAC/C,QAAM,0CAA0B,IAAA;AAEhC,SAAO,SACL,8BACA,qBACS;AA5Bf;AA6BM,QAAI,6BAA6B,WAAW,GAAG;AAC7C,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,oBAAoB,IAAI,mBAAmB,GAAG;AACjD,YAAM,6CAA6B,IAAA;AAEnC,iBAAW,eAAe,qBAAqB,mBAAmB,GAAG;AAEnE,+BAAuB,IAAI,YAAY,KAAK,sBAAsB,CAAC;AAGnE,iBAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,iCAAuB;AAAA,YACrB,YAAY,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,sBAAsB;AAAA,UAAA;AAAA,QAE3D;AAAA,MACF;AAEA,0BAAoB,IAAI,qBAAqB,sBAAsB;AAAA,IACrE;AAEA,WAAO;AAAA,OACL,yBACG,IAAI,mBAAmB,MAD1B,mBAEI,IAAI,6BAA6B,KAAK,sBAAsB;AAAA,IAAC;AAAA,EAErE;AACF,GAAA;AAaK,SAAS,qBACd,qBACqB;AACrB,MAAI,CAAC,oBAAqB,QAAO,CAAA;AAEjC,MAAI,oBAAoB,WAAW,KAAK,GAAG;AACzC,WAAO,UAAU,aAAa,mBAAmB,CAAC;AAAA,EACpD;AAEA,QAAM,IAAI,MAAM,mCAAmC;AACrD;AAEA,MAAM,eAAwD,CAC5D,wBACG,oBAAoB,QAAQ,QAAQ,EAAE;AAwB3C,SAAS,UAAU,qBAAyC;AAC1D,QAAM,YAAY;AAClB,MAAI,QAAQ;AACZ,MAAI;AACJ,QAAM,UAAsB,CAAA;AAC5B,QAAM,qBAA+B,CAAA;AACrC,MAAI,QAAQ;AACZ,MAAI,aAA4B;AAGhC,SAAQ,QAAQ,UAAU,KAAK,mBAAmB,GAAI;AACpD,UAAM,YAAY,MAAM,CAAC;AACzB,UAAM,mBACJ,OAAO,SAAS,oBAAoB,MAAM,OAAO,MAAM,KAAK,CAAC,KAAK;AAEpE,QAAI,eAAe,MAAM;AAIvB,aAAO,aAAa,kBAAkB,cAAc;AAClD,2BAAmB,KAAK,IAAI;AAC5B,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AAEA,mBAAa;AAAA,IACf;AAEA,uBAAmB,KAAK,IAAI;AAE5B,QAAI,cAAc,iBAAiB,OAAO;AAExC,mBAAa;AAAA,IACf,WAAW,cAAc,iBAAiB,QAAQ;AAEhD;AAAA,IACF,OAAO;AACL,UACE,cAAc,iBAAiB,gBAC9B,cAAc,iBAAiB,iBAC9B,oBAAoB,MAAM,QAAQ,CAAC,MACjC,iBAAiB,eACrB;AAEA,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AACA,UAAI,cAAc,iBAAiB,eAAe;AAEhD,2BAAmB,IAAA;AACnB;AAAA,MACF;AAAA,IACF;AACA,YAAQ,UAAU;AAAA,EACpB;AAGA,QAAM,wBAAwB,oBAAoB,MAAM,OAAO;AAC/D,MAAI,uBAAuB;AACzB,UAAM,kBAAkB,SAAS,sBAAsB,CAAC,CAAC;AACzD,QAAI,cAAc,MAAM;AAEtB,aAAO,cAAc,iBAAiB,cAAc;AAClD,2BAAmB,KAAK,IAAI;AAC5B,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AAAA,IACF,OAAO;AAEL,cAAQ,KAAK,CAAC,eAAe,CAAC;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AACT;"}
|
|
1
|
+
{"version":3,"file":"optionValueDecoder.mjs","sources":["../../src/optionValueDecoder.ts"],"sourcesContent":["/**\n * This file provides utility functions for determining whether or not an option value combination is present in an encoded option value string.\n *\n * In V1 of the encoding strategy, option value arrays are encoded as a trie with the following rules:\n * - `:` `,` ` ` and `-` are control characters.\n * - `:` indicates a new option. ex: 0:1 indicates value 0 for the option in position 1, value 1 for the option in position 2.\n * - `,` indicates the end of a repeated prefix, mulitple consecutive commas indicate the end of multiple repeated prefixes.\n * - ` ` indicates a gap in the sequence of option values. ex: `0 4` indicates option values in position 0 and 4 are present.\n * - `-` indicates a continuous range of option values. ex: `0 1-3 4`. Ranges are only present encoded in the final option value position, so for example the trie for the set [[0,0,0],[0,0,1], ..., [0,2,2]] will be structured as `0:0:0-2,1:0-2,2:0-2`, not `0:0-2:0-2`.\n */\n\nimport {Product} from './storefront-api-types.js';\n\nconst OPTION_VALUE_SEPARATOR = ',';\n\nconst V1_CONTROL_CHARS = {\n OPTION: ':',\n END_OF_PREFIX: ',',\n SEQUENCE_GAP: ' ',\n RANGE: '-',\n};\n\nexport type IsOptionValueCombinationInEncodedVariant = (\n targetOptionValueCombination: number[],\n encodedVariantField: string,\n) => boolean;\n\n/**\n * Determine whether an option value combination is present in an encoded option value string. Function is memoized by encodedVariantField.\n *\n * @param targetOptionValueCombination - Indices of option values to look up in the encoded option value string. A partial set of indices may be passed to determine whether a node or any children is present. For example, if a product has 3 options, passing [0] will return true if any option value combination for the first option's option value is present in the encoded string.\n * @param encodedVariantField - Encoded option value string from the Storefront API, e.g. [product.encodedVariantExistence](/docs/api/storefront/2026-01/objects/Product#field-encodedvariantexistence) or [product.encodedVariantAvailability](/docs/api/storefront/2026-01/objects/Product#field-encodedvariantavailability)\n * @returns - True if a full or partial targetOptionValueIndices is present in the encoded option value string, false otherwise.\n */\nexport const isOptionValueCombinationInEncodedVariant: IsOptionValueCombinationInEncodedVariant =\n ((): IsOptionValueCombinationInEncodedVariant => {\n const decodedOptionValues = new Map<string, Set<string>>();\n\n return function (\n targetOptionValueCombination: number[],\n encodedVariantField: string,\n ): boolean {\n if (targetOptionValueCombination.length === 0) {\n return false;\n }\n\n if (!decodedOptionValues.has(encodedVariantField)) {\n const decodedOptionValuesSet = new Set<string>();\n\n for (const optionValue of decodeEncodedVariant(encodedVariantField)) {\n // add the complete option value to the decoded option values set\n decodedOptionValuesSet.add(optionValue.join(OPTION_VALUE_SEPARATOR));\n\n // add all composite parts of the option value to the decoded option values set. e.g. if the option value is [0,1,2], add \"0\", \"0,1\", \"0,1,2\"\n for (let i = 0; i < optionValue.length; i++) {\n decodedOptionValuesSet.add(\n optionValue.slice(0, i + 1).join(OPTION_VALUE_SEPARATOR),\n );\n }\n }\n\n decodedOptionValues.set(encodedVariantField, decodedOptionValuesSet);\n }\n\n return Boolean(\n decodedOptionValues\n .get(encodedVariantField)\n ?.has(targetOptionValueCombination.join(OPTION_VALUE_SEPARATOR)),\n );\n };\n })();\n\ntype EncodedVariantField =\n | Product['encodedVariantAvailability']\n // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents\n | Product['encodedVariantExistence'];\ntype DecodedOptionValues = number[][];\n\n/**\n * For an encoded option value string, decode into option value combinations. Entries represent a valid combination formatted as an array of option value positions.\n * @param encodedVariantField - Encoded option value string from the Storefront API, e.g. [product.encodedVariantExistence](/docs/api/storefront/2026-01/objects/Product#field-encodedvariantexistence) or [product.encodedVariantAvailability](/docs/api/storefront/2026-01/objects/Product#field-encodedvariantavailability)\n * @returns Decoded option value combinations\n */\nexport function decodeEncodedVariant(\n encodedVariantField: EncodedVariantField,\n): DecodedOptionValues {\n if (!encodedVariantField) return [];\n\n if (encodedVariantField.startsWith('v1_')) {\n return v1Decoder(stripVersion(encodedVariantField));\n }\n\n throw new Error('Unsupported option value encoding');\n}\n\nconst stripVersion: (encodedVariantField: string) => string = (\n encodedVariantField: string,\n) => encodedVariantField.replace(/^v1_/, '');\n\n/**\n * We encode an array of arrays representing variants, expressed in terms of options and option values, as a trie.\n *\n * This encoding strategy allows extremely large numbers of variants to be expressed in an extremely compact data structure.\n *\n * Integers represent option and values, so [0,0,0] represents option_value at array index 0 for the options at array indexes 0, 1 and 2\n *\n * `:`, `,`, ` ` and `-` are control characters.\n * `:` indicates a new option\n * `,` indicates the end of a repeated prefix, mulitple consecutive commas indicate the end of multiple repeated prefixes.\n * ` ` indicates a gap in the sequence of option values\n * `-` indicates a continuous range of option values\n *\n * Encoding process:\n *\n * example input array: [[0,0,0], [0,1,0], [0,1,1], [1,0,0], [1,0,1], [1,1,1], [2,0,1], [2,1,0]]\n *\n * step 1: encode as string: \"0:0:0,0:1:0,0:1:1,1:0:0,1:0:1,1:1:1,2:0:1,2:1:0,\"\n * step 2: combine nodes that share a prefix: \"0:0:0,0:1:0 1,1:0:0 1,1:1:1,2:0:1,2:1:0,\"\n * step 3: encode data as a trie so no prefixes need to be repeated: \"0:0:0,1:0 1,,1:0:0 1,1:1,,2:0:1,1:0,,\"\n * step 4: since the options are sorted, use a dash to express ranges: \"0:0:0,1:0-1,,1:0:0-1,1:1,,2:0:1,1:0,,\"\n */\nfunction v1Decoder(encodedVariantField: string): number[][] {\n const tokenizer = /[ :,-]/g;\n let index = 0;\n let token: RegExpExecArray | null;\n const options: number[][] = [];\n const currentOptionValue: number[] = [];\n let depth = 0;\n let rangeStart: number | null = null;\n\n // iterate over control characters\n while ((token = tokenizer.exec(encodedVariantField))) {\n const operation = token[0];\n const optionValueIndex =\n Number.parseInt(encodedVariantField.slice(index, token.index)) || 0;\n\n if (rangeStart !== null) {\n // If a range has been started, iterate over the range and add each option value to the list of options\n // - `rangeStart` is set if the last control char was a dash, e.g. `0` for 0-2. It represents the numeric option value position for the start of the range.\n // - `optionValueIndex` is the numeric option value position for the end of the range\n for (; rangeStart < optionValueIndex; rangeStart++) {\n currentOptionValue[depth] = rangeStart;\n options.push([...currentOptionValue]);\n }\n // indicates the range has been processed\n rangeStart = null;\n }\n\n currentOptionValue[depth] = optionValueIndex;\n\n if (operation === V1_CONTROL_CHARS.RANGE) {\n // dash operation indicates we are in a range. e.g. 0-2 means option values 0, 1, 2\n rangeStart = optionValueIndex;\n } else if (operation === V1_CONTROL_CHARS.OPTION) {\n // colon operation indicates that we are moving down to the next layer of option values. e.g. 0:0:0-2 means we traverse down from option1 to option3 and represents [[0,0,0], [0,0,1], [0,0,2]]\n depth++;\n } else {\n if (\n operation === V1_CONTROL_CHARS.SEQUENCE_GAP ||\n (operation === V1_CONTROL_CHARS.END_OF_PREFIX &&\n encodedVariantField[token.index - 1] !==\n V1_CONTROL_CHARS.END_OF_PREFIX)\n ) {\n // add the current option value to the list of options if we hit a gap in our sequence or we are at the end of our depth and need to move back up\n options.push([...currentOptionValue]);\n }\n if (operation === V1_CONTROL_CHARS.END_OF_PREFIX) {\n // go up an option level, trash the last item in currentOptionValue\n currentOptionValue.pop();\n depth--;\n }\n }\n index = tokenizer.lastIndex;\n }\n\n // The while loop only iterates control characters, meaning if an encoded string ends with an index it will not be processed.\n const encodingEndsWithIndex = encodedVariantField.match(/\\d+$/g);\n if (encodingEndsWithIndex) {\n const finalValueIndex = parseInt(encodingEndsWithIndex[0]);\n if (rangeStart != null) {\n // process final range\n for (; rangeStart <= finalValueIndex; rangeStart++) {\n currentOptionValue[depth] = rangeStart;\n options.push([...currentOptionValue]);\n }\n } else {\n // process final index\n options.push([finalValueIndex]);\n }\n }\n\n return options;\n}\n"],"names":[],"mappings":"AAaA,MAAM,yBAAyB;AAE/B,MAAM,mBAAmB;AAAA,EACvB,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,cAAc;AAAA,EACd,OAAO;AACT;AAcO,MAAM,2CACV,uBAAgD;AAC/C,QAAM,0CAA0B,IAAA;AAEhC,SAAO,SACL,8BACA,qBACS;AA5Bf;AA6BM,QAAI,6BAA6B,WAAW,GAAG;AAC7C,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,oBAAoB,IAAI,mBAAmB,GAAG;AACjD,YAAM,6CAA6B,IAAA;AAEnC,iBAAW,eAAe,qBAAqB,mBAAmB,GAAG;AAEnE,+BAAuB,IAAI,YAAY,KAAK,sBAAsB,CAAC;AAGnE,iBAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,iCAAuB;AAAA,YACrB,YAAY,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,sBAAsB;AAAA,UAAA;AAAA,QAE3D;AAAA,MACF;AAEA,0BAAoB,IAAI,qBAAqB,sBAAsB;AAAA,IACrE;AAEA,WAAO;AAAA,OACL,yBACG,IAAI,mBAAmB,MAD1B,mBAEI,IAAI,6BAA6B,KAAK,sBAAsB;AAAA,IAAC;AAAA,EAErE;AACF,GAAA;AAaK,SAAS,qBACd,qBACqB;AACrB,MAAI,CAAC,oBAAqB,QAAO,CAAA;AAEjC,MAAI,oBAAoB,WAAW,KAAK,GAAG;AACzC,WAAO,UAAU,aAAa,mBAAmB,CAAC;AAAA,EACpD;AAEA,QAAM,IAAI,MAAM,mCAAmC;AACrD;AAEA,MAAM,eAAwD,CAC5D,wBACG,oBAAoB,QAAQ,QAAQ,EAAE;AAwB3C,SAAS,UAAU,qBAAyC;AAC1D,QAAM,YAAY;AAClB,MAAI,QAAQ;AACZ,MAAI;AACJ,QAAM,UAAsB,CAAA;AAC5B,QAAM,qBAA+B,CAAA;AACrC,MAAI,QAAQ;AACZ,MAAI,aAA4B;AAGhC,SAAQ,QAAQ,UAAU,KAAK,mBAAmB,GAAI;AACpD,UAAM,YAAY,MAAM,CAAC;AACzB,UAAM,mBACJ,OAAO,SAAS,oBAAoB,MAAM,OAAO,MAAM,KAAK,CAAC,KAAK;AAEpE,QAAI,eAAe,MAAM;AAIvB,aAAO,aAAa,kBAAkB,cAAc;AAClD,2BAAmB,KAAK,IAAI;AAC5B,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AAEA,mBAAa;AAAA,IACf;AAEA,uBAAmB,KAAK,IAAI;AAE5B,QAAI,cAAc,iBAAiB,OAAO;AAExC,mBAAa;AAAA,IACf,WAAW,cAAc,iBAAiB,QAAQ;AAEhD;AAAA,IACF,OAAO;AACL,UACE,cAAc,iBAAiB,gBAC9B,cAAc,iBAAiB,iBAC9B,oBAAoB,MAAM,QAAQ,CAAC,MACjC,iBAAiB,eACrB;AAEA,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AACA,UAAI,cAAc,iBAAiB,eAAe;AAEhD,2BAAmB,IAAA;AACnB;AAAA,MACF;AAAA,IACF;AACA,YAAQ,UAAU;AAAA,EACpB;AAGA,QAAM,wBAAwB,oBAAoB,MAAM,OAAO;AAC/D,MAAI,uBAAuB;AACzB,UAAM,kBAAkB,SAAS,sBAAsB,CAAC,CAAC;AACzD,QAAI,cAAc,MAAM;AAEtB,aAAO,cAAc,iBAAiB,cAAc;AAClD,2BAAmB,KAAK,IAAI;AAC5B,gBAAQ,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAAA,MACtC;AAAA,IACF,OAAO;AAEL,cAAQ,KAAK,CAAC,eAAe,CAAC;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AACT;"}
|
|
@@ -14,6 +14,7 @@ function parseMetafield(metafield) {
|
|
|
14
14
|
...metafield,
|
|
15
15
|
parsedValue: metafield.value === "true"
|
|
16
16
|
};
|
|
17
|
+
case "article_reference":
|
|
17
18
|
case "collection_reference":
|
|
18
19
|
case "file_reference":
|
|
19
20
|
case "page_reference":
|
|
@@ -107,6 +108,7 @@ function parseMetafield(metafield) {
|
|
|
107
108
|
...metafield,
|
|
108
109
|
parsedValue: Number(metafield.value)
|
|
109
110
|
};
|
|
111
|
+
case "list.article_reference":
|
|
110
112
|
case "list.collection_reference":
|
|
111
113
|
case "list.file_reference":
|
|
112
114
|
case "list.page_reference":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-metafield.js","sources":["../../src/parse-metafield.ts"],"sourcesContent":["import type {\n Collection,\n CurrencyCode,\n GenericFile,\n Metafield as MetafieldBaseType,\n MoneyV2,\n Page,\n Product,\n ProductVariant,\n} from './storefront-api-types.js';\nimport type {PartialDeep, Simplify} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\nimport {RootASTNode as RichTextRootASTNode} from './RichText.types.js';\n\n/**\n * A function that uses `metafield.type` to parse the Metafield's `value` or `reference` or `references` (depending on the `metafield.type`) and places the result in `metafield.parsedValue`\n *\n * TypeScript developers can use the type `ParsedMetafields` from this package to get the returned object's type correct. For example:\n *\n * ```\n * parseMetafield<ParsedMetafields['boolean']>({type: 'boolean', value: 'false'}\n * ```\n */\nexport function parseMetafield<ReturnGeneric>(\n metafield: PartialDeep<MetafieldBaseType, {recurseIntoArrays: true}>,\n): ReturnGeneric {\n if (!metafield.type) {\n const noTypeError = `parseMetafield(): The 'type' field is required in order to parse the Metafield.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(noTypeError);\n } else {\n console.error(`${noTypeError} Returning 'parsedValue' of 'null'`);\n return {\n ...metafield,\n parsedValue: null,\n } as ReturnGeneric;\n }\n }\n\n switch (metafield.type) {\n case 'boolean':\n return {\n ...metafield,\n parsedValue: metafield.value === 'true',\n } as ReturnGeneric;\n\n case 'collection_reference':\n case 'file_reference':\n case 'page_reference':\n case 'product_reference':\n case 'variant_reference':\n return {\n ...metafield,\n parsedValue: metafield.reference,\n } as ReturnGeneric;\n\n case 'color':\n case 'multi_line_text_field':\n case 'single_line_text_field':\n case 'url':\n return {\n ...metafield,\n parsedValue: metafield.value,\n } as ReturnGeneric;\n\n // TODO: 'money' should probably be parsed even further to like `useMoney()`, but that logic needs to be extracted first so it's not a hook\n case 'money': {\n let parsedValue: MoneyV2 | null = null;\n try {\n const parsed = parseJSON(metafield.value ?? '');\n // Transform currency_code from Storefront API to currencyCode to match MoneyV2 type\n if (parsed && typeof parsed === 'object' && 'currency_code' in parsed) {\n const moneyData = parsed as {amount: string; currency_code: string};\n parsedValue = {\n amount: moneyData.amount,\n currencyCode: moneyData.currency_code as CurrencyCode,\n };\n } else if (\n parsed &&\n typeof parsed === 'object' &&\n 'currencyCode' in parsed\n ) {\n // Already in correct format (for backward compatibility)\n parsedValue = parsed as MoneyV2;\n } else {\n parsedValue = parsed as MoneyV2 | null;\n }\n } catch (err) {\n const parseError = `parseMetafield(): attempted to JSON.parse the 'metafield.value' property, but failed.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(parseError);\n } else {\n console.error(`${parseError} Returning 'null' for 'parsedValue'`);\n }\n parsedValue = null;\n }\n return {\n ...metafield,\n parsedValue,\n } as ReturnGeneric;\n }\n\n case 'dimension':\n case 'json':\n case 'rating':\n case 'volume':\n case 'weight':\n case 'rich_text_field':\n case 'list.color':\n case 'list.dimension':\n case 'list.number_integer':\n case 'list.number_decimal':\n case 'list.rating':\n case 'list.single_line_text_field':\n case 'list.url':\n case 'list.volume':\n case 'list.weight': {\n let parsedValue = null;\n try {\n parsedValue = parseJSON(metafield.value ?? '');\n } catch (err) {\n const parseError = `parseMetafield(): attempted to JSON.parse the 'metafield.value' property, but failed.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(parseError);\n } else {\n console.error(`${parseError} Returning 'null' for 'parsedValue'`);\n }\n parsedValue = null;\n }\n return {\n ...metafield,\n parsedValue,\n } as ReturnGeneric;\n }\n\n case 'date':\n case 'date_time':\n return {\n ...metafield,\n parsedValue: new Date(metafield.value ?? ''),\n } as ReturnGeneric;\n\n case 'list.date':\n case 'list.date_time': {\n const jsonParseValue = parseJSON(metafield?.value ?? '') as string[];\n return {\n ...metafield,\n parsedValue: jsonParseValue.map((dateString) => new Date(dateString)),\n } as ReturnGeneric;\n }\n\n case 'number_decimal':\n case 'number_integer':\n return {\n ...metafield,\n parsedValue: Number(metafield.value),\n } as ReturnGeneric;\n\n case 'list.collection_reference':\n case 'list.file_reference':\n case 'list.page_reference':\n case 'list.product_reference':\n case 'list.variant_reference':\n return {\n ...metafield,\n parsedValue: flattenConnection(metafield.references ?? undefined),\n } as ReturnGeneric;\n\n default: {\n const typeNotFoundError = `parseMetafield(): the 'metafield.type' you passed in is not supported. Your type: \"${metafield.type}\". If you believe this is an error, please open an issue on GitHub.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(typeNotFoundError);\n } else {\n console.error(\n `${typeNotFoundError} Returning 'parsedValue' of 'null'`,\n );\n return {\n ...metafield,\n parsedValue: null,\n } as ReturnGeneric;\n }\n }\n }\n}\n\n/**\n * Parses a JSON string while preventing prototype injection attacks.\n */\nexport function parseJSON(json: string): unknown {\n if (String(json).includes('__proto__')) {\n return JSON.parse(json, (k, v) => {\n if (k !== '__proto__') return v as unknown;\n }) as unknown;\n }\n return JSON.parse(json) as unknown;\n}\n\n// taken from https://shopify.dev/apps/metafields/types\nexport const allMetafieldTypesArray = [\n 'boolean',\n 'collection_reference',\n 'color',\n 'date',\n 'date_time',\n 'dimension',\n 'file_reference',\n 'json',\n 'money',\n 'rich_text_field',\n 'multi_line_text_field',\n 'number_decimal',\n 'number_integer',\n 'page_reference',\n 'product_reference',\n 'rating',\n 'single_line_text_field',\n 'url',\n 'variant_reference',\n 'volume',\n 'weight',\n // list metafields\n 'list.collection_reference',\n 'list.color',\n 'list.date',\n 'list.date_time',\n 'list.dimension',\n 'list.file_reference',\n 'list.number_integer',\n 'list.number_decimal',\n 'list.page_reference',\n 'list.product_reference',\n 'list.rating',\n 'list.single_line_text_field',\n 'list.url',\n 'list.variant_reference',\n 'list.volume',\n 'list.weight',\n] as const;\n\n/** A union of all the supported `metafield.type`s */\nexport type MetafieldTypeTypes = (typeof allMetafieldTypesArray)[number];\n\n/**\n * A mapping of a Metafield's `type` to the TypeScript type that is returned from `parseMetafield()`\n * For example, when using `parseMetafield()`, the type will be correctly returned when used like the following:\n *\n * ```\n * const parsedMetafield = parseMetafield<ParsedMetafields['boolean']>(metafield);`\n * ```\n * `parsedMetafield.parsedValue`'s type is now `boolean`\n */\nexport type ParsedMetafields<ExtraTypeGeneric = void> = {\n /** A Metafield that's been parsed, with a `parsedValue` of `boolean` */\n boolean: Simplify<BooleanParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Collection` object (as defined by the Storefront API) */\n collection_reference: Simplify<CollectionParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n color: Simplify<ColorParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Date` */\n date: Simplify<DatesParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Date` */\n date_time: Simplify<DatesParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n dimension: Simplify<MeasurementParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `GenericFile` object (as defined by the Storefront API) */\n file_reference: Simplify<FileRefParsedMetafield>;\n /**\n * A Metafield that's been parsed, with a `parsedValue` of type `unknown`, unless you pass in the type as a generic. For example:\n *\n * ```\n * ParsedMetafields<MyJsonType>['json']\n * ```\n */\n json: Simplify<JsonParsedMetafield<ExtraTypeGeneric>>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Money` */\n money: Simplify<MoneyParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n multi_line_text_field: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `number` */\n number_decimal: Simplify<NumberParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `number` */\n number_integer: Simplify<NumberParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Page` object (as defined by the Storefront API) */\n page_reference: Simplify<PageParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Product` object (as defined by the Storefront API) */\n product_reference: Simplify<ProductParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Rating` */\n rating: Simplify<RatingParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Rating` */\n rich_text_field: Simplify<RichTextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n single_line_text_field: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n url: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `ProductVariant` object (as defined by the Storefront API) */\n variant_reference: Simplify<VariantParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n volume: Simplify<MeasurementParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n weight: Simplify<MeasurementParsedMetafield>;\n // list metafields\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Collection` objects (as defined by the Storefront API) */\n 'list.collection_reference': Simplify<CollectionListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.color': Simplify<ColorListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of Date objects */\n 'list.date': Simplify<DatesListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of Date objects */\n 'list.date_time': Simplify<DatesListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement` objects */\n 'list.dimension': Simplify<MeasurementListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `GenericFile` objects (as defined by the Storefront API) */\n 'list.file_reference': Simplify<FileListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of numbers */\n 'list.number_integer': Simplify<NumberListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of numbers */\n 'list.number_decimal': Simplify<NumberListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Page` objects (as defined by the Storefront API) */\n 'list.page_reference': Simplify<PageListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Product` objects (as defined by the Storefront API) */\n 'list.product_reference': Simplify<ProductListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Rating`s */\n 'list.rating': Simplify<RatingListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.single_line_text_field': Simplify<TextListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.url': Simplify<TextListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `ProductVariant` objects (as defined by the Storefront API) */\n 'list.variant_reference': Simplify<VariantListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement`s */\n 'list.volume': Simplify<MeasurementListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement`s */\n 'list.weight': Simplify<MeasurementListParsedMetafield>;\n};\n\ninterface ParsedBase extends MetafieldBaseType {\n type: MetafieldTypeTypes;\n parsedValue: unknown;\n}\n\ninterface BooleanParsedMetafield extends ParsedBase {\n type: 'boolean';\n parsedValue: boolean | null;\n}\ntype CollectionParsedRefMetafield = MetafieldBaseType & {\n type: 'collection_reference';\n parsedValue: Collection | null;\n};\ntype ColorParsedMetafield = MetafieldBaseType & {\n type: 'color';\n parsedValue: string | null;\n};\ntype DatesParsedMetafield = MetafieldBaseType & {\n type: 'date' | 'date_time';\n parsedValue: Date | null;\n};\n\ntype MeasurementParsedMetafield = MetafieldBaseType & {\n type: 'dimension' | 'weight' | 'volume';\n parsedValue: Measurement | null;\n};\n\ntype FileRefParsedMetafield = MetafieldBaseType & {\n type: 'file_reference';\n parsedValue: GenericFile | null;\n};\n\ntype JsonParsedMetafield<JsonTypeGeneric = void> = MetafieldBaseType & {\n type: 'json';\n parsedValue: JsonTypeGeneric extends void ? unknown : JsonTypeGeneric | null;\n};\n\ntype MoneyParsedMetafield = MetafieldBaseType & {\n type: 'money';\n parsedValue: MoneyV2 | null;\n};\n\ntype TextParsedMetafield = MetafieldBaseType & {\n type: 'single_line_text_field' | 'multi_line_text_field' | 'url';\n parsedValue: string | null;\n};\n\ntype NumberParsedMetafield = MetafieldBaseType & {\n type: 'number_decimal' | 'number_integer';\n parsedValue: number | null;\n};\n\ntype PageParsedRefMetafield = MetafieldBaseType & {\n type: 'page_reference';\n parsedValue: Page | null;\n};\n\ntype ProductParsedRefMetafield = MetafieldBaseType & {\n type: 'product_reference';\n parsedValue: Product | null;\n};\n\ntype RatingParsedMetafield = MetafieldBaseType & {\n type: 'rating';\n parsedValue: Rating | null;\n};\n\ntype RichTextParsedMetafield = MetafieldBaseType & {\n type: 'rich_text_field';\n parsedValue: RichTextRootASTNode | null;\n};\n\ntype VariantParsedRefMetafield = MetafieldBaseType & {\n type: 'variant_reference';\n parsedValue: ProductVariant | null;\n};\n\ntype CollectionListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.collection_reference';\n parsedValue: Array<Collection> | null;\n};\n\ntype ColorListParsedMetafield = MetafieldBaseType & {\n type: 'list.color';\n parsedValue: Array<string> | null;\n};\n\ntype DatesListParsedMetafield = MetafieldBaseType & {\n type: 'list.date' | 'list.date_time';\n parsedValue: Array<Date> | null;\n};\n\ntype MeasurementListParsedMetafield = MetafieldBaseType & {\n type: 'list.dimension' | 'list.weight' | 'list.volume';\n parsedValue: Array<Measurement> | null;\n};\n\ntype FileListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.file_reference';\n parsedValue: Array<GenericFile> | null;\n};\n\ntype TextListParsedMetafield = MetafieldBaseType & {\n type: 'list.single_line_text_field' | 'list.url';\n parsedValue: Array<string> | null;\n};\n\ntype NumberListParsedMetafield = MetafieldBaseType & {\n type: 'list.number_decimal' | 'list.number_integer';\n parsedValue: Array<number> | null;\n};\n\ntype PageListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.page_reference';\n parsedValue: Array<Page> | null;\n};\n\ntype ProductListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.product_reference';\n parsedValue: Array<Product> | null;\n};\n\ntype RatingListParsedMetafield = MetafieldBaseType & {\n type: 'list.rating';\n parsedValue: Array<Rating> | null;\n};\n\ntype VariantListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.variant_reference';\n parsedValue: Array<ProductVariant> | null;\n};\n\nexport type Measurement = {\n unit: string;\n value: number;\n};\n\nexport interface Rating {\n value: number;\n scale_min: number;\n scale_max: number;\n}\n"],"names":["flattenConnection"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parse-metafield.js","sources":["../../src/parse-metafield.ts"],"sourcesContent":["import type {\n Article,\n Collection,\n CurrencyCode,\n GenericFile,\n Metafield as MetafieldBaseType,\n MoneyV2,\n Page,\n Product,\n ProductVariant,\n} from './storefront-api-types.js';\nimport type {PartialDeep, Simplify} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\nimport {RootASTNode as RichTextRootASTNode} from './RichText.types.js';\n\n/**\n * A function that uses `metafield.type` to parse the Metafield's `value` or `reference` or `references` (depending on the `metafield.type`) and places the result in `metafield.parsedValue`\n *\n * TypeScript developers can use the type `ParsedMetafields` from this package to get the returned object's type correct. For example:\n *\n * ```\n * parseMetafield<ParsedMetafields['boolean']>({type: 'boolean', value: 'false'}\n * ```\n */\nexport function parseMetafield<ReturnGeneric>(\n metafield: PartialDeep<MetafieldBaseType, {recurseIntoArrays: true}>,\n): ReturnGeneric {\n if (!metafield.type) {\n const noTypeError = `parseMetafield(): The 'type' field is required in order to parse the Metafield.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(noTypeError);\n } else {\n console.error(`${noTypeError} Returning 'parsedValue' of 'null'`);\n return {\n ...metafield,\n parsedValue: null,\n } as ReturnGeneric;\n }\n }\n\n switch (metafield.type) {\n case 'boolean':\n return {\n ...metafield,\n parsedValue: metafield.value === 'true',\n } as ReturnGeneric;\n\n case 'article_reference':\n case 'collection_reference':\n case 'file_reference':\n case 'page_reference':\n case 'product_reference':\n case 'variant_reference':\n return {\n ...metafield,\n parsedValue: metafield.reference,\n } as ReturnGeneric;\n\n case 'color':\n case 'multi_line_text_field':\n case 'single_line_text_field':\n case 'url':\n return {\n ...metafield,\n parsedValue: metafield.value,\n } as ReturnGeneric;\n\n // TODO: 'money' should probably be parsed even further to like `useMoney()`, but that logic needs to be extracted first so it's not a hook\n case 'money': {\n let parsedValue: MoneyV2 | null = null;\n try {\n const parsed = parseJSON(metafield.value ?? '');\n // Transform currency_code from Storefront API to currencyCode to match MoneyV2 type\n if (parsed && typeof parsed === 'object' && 'currency_code' in parsed) {\n const moneyData = parsed as {amount: string; currency_code: string};\n parsedValue = {\n amount: moneyData.amount,\n currencyCode: moneyData.currency_code as CurrencyCode,\n };\n } else if (\n parsed &&\n typeof parsed === 'object' &&\n 'currencyCode' in parsed\n ) {\n // Already in correct format (for backward compatibility)\n parsedValue = parsed as MoneyV2;\n } else {\n parsedValue = parsed as MoneyV2 | null;\n }\n } catch (err) {\n const parseError = `parseMetafield(): attempted to JSON.parse the 'metafield.value' property, but failed.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(parseError);\n } else {\n console.error(`${parseError} Returning 'null' for 'parsedValue'`);\n }\n parsedValue = null;\n }\n return {\n ...metafield,\n parsedValue,\n } as ReturnGeneric;\n }\n\n case 'dimension':\n case 'json':\n case 'rating':\n case 'volume':\n case 'weight':\n case 'rich_text_field':\n case 'list.color':\n case 'list.dimension':\n case 'list.number_integer':\n case 'list.number_decimal':\n case 'list.rating':\n case 'list.single_line_text_field':\n case 'list.url':\n case 'list.volume':\n case 'list.weight': {\n let parsedValue = null;\n try {\n parsedValue = parseJSON(metafield.value ?? '');\n } catch (err) {\n const parseError = `parseMetafield(): attempted to JSON.parse the 'metafield.value' property, but failed.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(parseError);\n } else {\n console.error(`${parseError} Returning 'null' for 'parsedValue'`);\n }\n parsedValue = null;\n }\n return {\n ...metafield,\n parsedValue,\n } as ReturnGeneric;\n }\n\n case 'date':\n case 'date_time':\n return {\n ...metafield,\n parsedValue: new Date(metafield.value ?? ''),\n } as ReturnGeneric;\n\n case 'list.date':\n case 'list.date_time': {\n const jsonParseValue = parseJSON(metafield?.value ?? '') as string[];\n return {\n ...metafield,\n parsedValue: jsonParseValue.map((dateString) => new Date(dateString)),\n } as ReturnGeneric;\n }\n\n case 'number_decimal':\n case 'number_integer':\n return {\n ...metafield,\n parsedValue: Number(metafield.value),\n } as ReturnGeneric;\n\n case 'list.article_reference':\n case 'list.collection_reference':\n case 'list.file_reference':\n case 'list.page_reference':\n case 'list.product_reference':\n case 'list.variant_reference':\n return {\n ...metafield,\n parsedValue: flattenConnection(metafield.references ?? undefined),\n } as ReturnGeneric;\n\n default: {\n const typeNotFoundError = `parseMetafield(): the 'metafield.type' you passed in is not supported. Your type: \"${metafield.type}\". If you believe this is an error, please open an issue on GitHub.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(typeNotFoundError);\n } else {\n console.error(\n `${typeNotFoundError} Returning 'parsedValue' of 'null'`,\n );\n return {\n ...metafield,\n parsedValue: null,\n } as ReturnGeneric;\n }\n }\n }\n}\n\n/**\n * Parses a JSON string while preventing prototype injection attacks.\n */\nexport function parseJSON(json: string): unknown {\n if (String(json).includes('__proto__')) {\n return JSON.parse(json, (k, v) => {\n if (k !== '__proto__') return v as unknown;\n }) as unknown;\n }\n return JSON.parse(json) as unknown;\n}\n\n// taken from https://shopify.dev/apps/metafields/types\nexport const allMetafieldTypesArray = [\n 'article_reference',\n 'boolean',\n 'collection_reference',\n 'color',\n 'date',\n 'date_time',\n 'dimension',\n 'file_reference',\n 'json',\n 'money',\n 'rich_text_field',\n 'multi_line_text_field',\n 'number_decimal',\n 'number_integer',\n 'page_reference',\n 'product_reference',\n 'rating',\n 'single_line_text_field',\n 'url',\n 'variant_reference',\n 'volume',\n 'weight',\n // list metafields\n 'list.article_reference',\n 'list.collection_reference',\n 'list.color',\n 'list.date',\n 'list.date_time',\n 'list.dimension',\n 'list.file_reference',\n 'list.number_integer',\n 'list.number_decimal',\n 'list.page_reference',\n 'list.product_reference',\n 'list.rating',\n 'list.single_line_text_field',\n 'list.url',\n 'list.variant_reference',\n 'list.volume',\n 'list.weight',\n] as const;\n\n/** A union of all the supported `metafield.type`s */\nexport type MetafieldTypeTypes = (typeof allMetafieldTypesArray)[number];\n\n/**\n * A mapping of a Metafield's `type` to the TypeScript type that is returned from `parseMetafield()`\n * For example, when using `parseMetafield()`, the type will be correctly returned when used like the following:\n *\n * ```\n * const parsedMetafield = parseMetafield<ParsedMetafields['boolean']>(metafield);`\n * ```\n * `parsedMetafield.parsedValue`'s type is now `boolean`\n */\nexport type ParsedMetafields<ExtraTypeGeneric = void> = {\n /** A Metafield that's been parsed, with a `parsedValue` of an `Article` object (as defined by the Storefront API) */\n article_reference: Simplify<ArticleParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of `boolean` */\n boolean: Simplify<BooleanParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Collection` object (as defined by the Storefront API) */\n collection_reference: Simplify<CollectionParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n color: Simplify<ColorParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Date` */\n date: Simplify<DatesParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Date` */\n date_time: Simplify<DatesParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n dimension: Simplify<MeasurementParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `GenericFile` object (as defined by the Storefront API) */\n file_reference: Simplify<FileRefParsedMetafield>;\n /**\n * A Metafield that's been parsed, with a `parsedValue` of type `unknown`, unless you pass in the type as a generic. For example:\n *\n * ```\n * ParsedMetafields<MyJsonType>['json']\n * ```\n */\n json: Simplify<JsonParsedMetafield<ExtraTypeGeneric>>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Money` */\n money: Simplify<MoneyParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n multi_line_text_field: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `number` */\n number_decimal: Simplify<NumberParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `number` */\n number_integer: Simplify<NumberParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Page` object (as defined by the Storefront API) */\n page_reference: Simplify<PageParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Product` object (as defined by the Storefront API) */\n product_reference: Simplify<ProductParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Rating` */\n rating: Simplify<RatingParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Rating` */\n rich_text_field: Simplify<RichTextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n single_line_text_field: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n url: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `ProductVariant` object (as defined by the Storefront API) */\n variant_reference: Simplify<VariantParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n volume: Simplify<MeasurementParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n weight: Simplify<MeasurementParsedMetafield>;\n // list metafields\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Article` objects (as defined by the Storefront API) */\n 'list.article_reference': Simplify<ArticleListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Collection` objects (as defined by the Storefront API) */\n 'list.collection_reference': Simplify<CollectionListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.color': Simplify<ColorListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of Date objects */\n 'list.date': Simplify<DatesListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of Date objects */\n 'list.date_time': Simplify<DatesListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement` objects */\n 'list.dimension': Simplify<MeasurementListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `GenericFile` objects (as defined by the Storefront API) */\n 'list.file_reference': Simplify<FileListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of numbers */\n 'list.number_integer': Simplify<NumberListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of numbers */\n 'list.number_decimal': Simplify<NumberListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Page` objects (as defined by the Storefront API) */\n 'list.page_reference': Simplify<PageListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Product` objects (as defined by the Storefront API) */\n 'list.product_reference': Simplify<ProductListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Rating`s */\n 'list.rating': Simplify<RatingListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.single_line_text_field': Simplify<TextListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.url': Simplify<TextListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `ProductVariant` objects (as defined by the Storefront API) */\n 'list.variant_reference': Simplify<VariantListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement`s */\n 'list.volume': Simplify<MeasurementListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement`s */\n 'list.weight': Simplify<MeasurementListParsedMetafield>;\n};\n\ninterface ParsedBase extends MetafieldBaseType {\n type: MetafieldTypeTypes;\n parsedValue: unknown;\n}\n\ninterface BooleanParsedMetafield extends ParsedBase {\n type: 'boolean';\n parsedValue: boolean | null;\n}\ntype CollectionParsedRefMetafield = MetafieldBaseType & {\n type: 'collection_reference';\n parsedValue: Collection | null;\n};\ntype ColorParsedMetafield = MetafieldBaseType & {\n type: 'color';\n parsedValue: string | null;\n};\ntype DatesParsedMetafield = MetafieldBaseType & {\n type: 'date' | 'date_time';\n parsedValue: Date | null;\n};\n\ntype MeasurementParsedMetafield = MetafieldBaseType & {\n type: 'dimension' | 'weight' | 'volume';\n parsedValue: Measurement | null;\n};\n\ntype FileRefParsedMetafield = MetafieldBaseType & {\n type: 'file_reference';\n parsedValue: GenericFile | null;\n};\n\ntype JsonParsedMetafield<JsonTypeGeneric = void> = MetafieldBaseType & {\n type: 'json';\n parsedValue: JsonTypeGeneric extends void ? unknown : JsonTypeGeneric | null;\n};\n\ntype MoneyParsedMetafield = MetafieldBaseType & {\n type: 'money';\n parsedValue: MoneyV2 | null;\n};\n\ntype TextParsedMetafield = MetafieldBaseType & {\n type: 'single_line_text_field' | 'multi_line_text_field' | 'url';\n parsedValue: string | null;\n};\n\ntype NumberParsedMetafield = MetafieldBaseType & {\n type: 'number_decimal' | 'number_integer';\n parsedValue: number | null;\n};\n\ntype ArticleParsedRefMetafield = MetafieldBaseType & {\n type: 'article_reference';\n parsedValue: Article | null;\n};\n\ntype PageParsedRefMetafield = MetafieldBaseType & {\n type: 'page_reference';\n parsedValue: Page | null;\n};\n\ntype ProductParsedRefMetafield = MetafieldBaseType & {\n type: 'product_reference';\n parsedValue: Product | null;\n};\n\ntype RatingParsedMetafield = MetafieldBaseType & {\n type: 'rating';\n parsedValue: Rating | null;\n};\n\ntype RichTextParsedMetafield = MetafieldBaseType & {\n type: 'rich_text_field';\n parsedValue: RichTextRootASTNode | null;\n};\n\ntype VariantParsedRefMetafield = MetafieldBaseType & {\n type: 'variant_reference';\n parsedValue: ProductVariant | null;\n};\n\ntype ArticleListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.article_reference';\n parsedValue: Array<Article> | null;\n};\n\ntype CollectionListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.collection_reference';\n parsedValue: Array<Collection> | null;\n};\n\ntype ColorListParsedMetafield = MetafieldBaseType & {\n type: 'list.color';\n parsedValue: Array<string> | null;\n};\n\ntype DatesListParsedMetafield = MetafieldBaseType & {\n type: 'list.date' | 'list.date_time';\n parsedValue: Array<Date> | null;\n};\n\ntype MeasurementListParsedMetafield = MetafieldBaseType & {\n type: 'list.dimension' | 'list.weight' | 'list.volume';\n parsedValue: Array<Measurement> | null;\n};\n\ntype FileListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.file_reference';\n parsedValue: Array<GenericFile> | null;\n};\n\ntype TextListParsedMetafield = MetafieldBaseType & {\n type: 'list.single_line_text_field' | 'list.url';\n parsedValue: Array<string> | null;\n};\n\ntype NumberListParsedMetafield = MetafieldBaseType & {\n type: 'list.number_decimal' | 'list.number_integer';\n parsedValue: Array<number> | null;\n};\n\ntype PageListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.page_reference';\n parsedValue: Array<Page> | null;\n};\n\ntype ProductListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.product_reference';\n parsedValue: Array<Product> | null;\n};\n\ntype RatingListParsedMetafield = MetafieldBaseType & {\n type: 'list.rating';\n parsedValue: Array<Rating> | null;\n};\n\ntype VariantListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.variant_reference';\n parsedValue: Array<ProductVariant> | null;\n};\n\nexport type Measurement = {\n unit: string;\n value: number;\n};\n\nexport interface Rating {\n value: number;\n scale_min: number;\n scale_max: number;\n}\n"],"names":["flattenConnection"],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@ function parseMetafield(metafield) {
|
|
|
12
12
|
...metafield,
|
|
13
13
|
parsedValue: metafield.value === "true"
|
|
14
14
|
};
|
|
15
|
+
case "article_reference":
|
|
15
16
|
case "collection_reference":
|
|
16
17
|
case "file_reference":
|
|
17
18
|
case "page_reference":
|
|
@@ -105,6 +106,7 @@ function parseMetafield(metafield) {
|
|
|
105
106
|
...metafield,
|
|
106
107
|
parsedValue: Number(metafield.value)
|
|
107
108
|
};
|
|
109
|
+
case "list.article_reference":
|
|
108
110
|
case "list.collection_reference":
|
|
109
111
|
case "list.file_reference":
|
|
110
112
|
case "list.page_reference":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-metafield.mjs","sources":["../../src/parse-metafield.ts"],"sourcesContent":["import type {\n Collection,\n CurrencyCode,\n GenericFile,\n Metafield as MetafieldBaseType,\n MoneyV2,\n Page,\n Product,\n ProductVariant,\n} from './storefront-api-types.js';\nimport type {PartialDeep, Simplify} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\nimport {RootASTNode as RichTextRootASTNode} from './RichText.types.js';\n\n/**\n * A function that uses `metafield.type` to parse the Metafield's `value` or `reference` or `references` (depending on the `metafield.type`) and places the result in `metafield.parsedValue`\n *\n * TypeScript developers can use the type `ParsedMetafields` from this package to get the returned object's type correct. For example:\n *\n * ```\n * parseMetafield<ParsedMetafields['boolean']>({type: 'boolean', value: 'false'}\n * ```\n */\nexport function parseMetafield<ReturnGeneric>(\n metafield: PartialDeep<MetafieldBaseType, {recurseIntoArrays: true}>,\n): ReturnGeneric {\n if (!metafield.type) {\n const noTypeError = `parseMetafield(): The 'type' field is required in order to parse the Metafield.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(noTypeError);\n } else {\n console.error(`${noTypeError} Returning 'parsedValue' of 'null'`);\n return {\n ...metafield,\n parsedValue: null,\n } as ReturnGeneric;\n }\n }\n\n switch (metafield.type) {\n case 'boolean':\n return {\n ...metafield,\n parsedValue: metafield.value === 'true',\n } as ReturnGeneric;\n\n case 'collection_reference':\n case 'file_reference':\n case 'page_reference':\n case 'product_reference':\n case 'variant_reference':\n return {\n ...metafield,\n parsedValue: metafield.reference,\n } as ReturnGeneric;\n\n case 'color':\n case 'multi_line_text_field':\n case 'single_line_text_field':\n case 'url':\n return {\n ...metafield,\n parsedValue: metafield.value,\n } as ReturnGeneric;\n\n // TODO: 'money' should probably be parsed even further to like `useMoney()`, but that logic needs to be extracted first so it's not a hook\n case 'money': {\n let parsedValue: MoneyV2 | null = null;\n try {\n const parsed = parseJSON(metafield.value ?? '');\n // Transform currency_code from Storefront API to currencyCode to match MoneyV2 type\n if (parsed && typeof parsed === 'object' && 'currency_code' in parsed) {\n const moneyData = parsed as {amount: string; currency_code: string};\n parsedValue = {\n amount: moneyData.amount,\n currencyCode: moneyData.currency_code as CurrencyCode,\n };\n } else if (\n parsed &&\n typeof parsed === 'object' &&\n 'currencyCode' in parsed\n ) {\n // Already in correct format (for backward compatibility)\n parsedValue = parsed as MoneyV2;\n } else {\n parsedValue = parsed as MoneyV2 | null;\n }\n } catch (err) {\n const parseError = `parseMetafield(): attempted to JSON.parse the 'metafield.value' property, but failed.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(parseError);\n } else {\n console.error(`${parseError} Returning 'null' for 'parsedValue'`);\n }\n parsedValue = null;\n }\n return {\n ...metafield,\n parsedValue,\n } as ReturnGeneric;\n }\n\n case 'dimension':\n case 'json':\n case 'rating':\n case 'volume':\n case 'weight':\n case 'rich_text_field':\n case 'list.color':\n case 'list.dimension':\n case 'list.number_integer':\n case 'list.number_decimal':\n case 'list.rating':\n case 'list.single_line_text_field':\n case 'list.url':\n case 'list.volume':\n case 'list.weight': {\n let parsedValue = null;\n try {\n parsedValue = parseJSON(metafield.value ?? '');\n } catch (err) {\n const parseError = `parseMetafield(): attempted to JSON.parse the 'metafield.value' property, but failed.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(parseError);\n } else {\n console.error(`${parseError} Returning 'null' for 'parsedValue'`);\n }\n parsedValue = null;\n }\n return {\n ...metafield,\n parsedValue,\n } as ReturnGeneric;\n }\n\n case 'date':\n case 'date_time':\n return {\n ...metafield,\n parsedValue: new Date(metafield.value ?? ''),\n } as ReturnGeneric;\n\n case 'list.date':\n case 'list.date_time': {\n const jsonParseValue = parseJSON(metafield?.value ?? '') as string[];\n return {\n ...metafield,\n parsedValue: jsonParseValue.map((dateString) => new Date(dateString)),\n } as ReturnGeneric;\n }\n\n case 'number_decimal':\n case 'number_integer':\n return {\n ...metafield,\n parsedValue: Number(metafield.value),\n } as ReturnGeneric;\n\n case 'list.collection_reference':\n case 'list.file_reference':\n case 'list.page_reference':\n case 'list.product_reference':\n case 'list.variant_reference':\n return {\n ...metafield,\n parsedValue: flattenConnection(metafield.references ?? undefined),\n } as ReturnGeneric;\n\n default: {\n const typeNotFoundError = `parseMetafield(): the 'metafield.type' you passed in is not supported. Your type: \"${metafield.type}\". If you believe this is an error, please open an issue on GitHub.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(typeNotFoundError);\n } else {\n console.error(\n `${typeNotFoundError} Returning 'parsedValue' of 'null'`,\n );\n return {\n ...metafield,\n parsedValue: null,\n } as ReturnGeneric;\n }\n }\n }\n}\n\n/**\n * Parses a JSON string while preventing prototype injection attacks.\n */\nexport function parseJSON(json: string): unknown {\n if (String(json).includes('__proto__')) {\n return JSON.parse(json, (k, v) => {\n if (k !== '__proto__') return v as unknown;\n }) as unknown;\n }\n return JSON.parse(json) as unknown;\n}\n\n// taken from https://shopify.dev/apps/metafields/types\nexport const allMetafieldTypesArray = [\n 'boolean',\n 'collection_reference',\n 'color',\n 'date',\n 'date_time',\n 'dimension',\n 'file_reference',\n 'json',\n 'money',\n 'rich_text_field',\n 'multi_line_text_field',\n 'number_decimal',\n 'number_integer',\n 'page_reference',\n 'product_reference',\n 'rating',\n 'single_line_text_field',\n 'url',\n 'variant_reference',\n 'volume',\n 'weight',\n // list metafields\n 'list.collection_reference',\n 'list.color',\n 'list.date',\n 'list.date_time',\n 'list.dimension',\n 'list.file_reference',\n 'list.number_integer',\n 'list.number_decimal',\n 'list.page_reference',\n 'list.product_reference',\n 'list.rating',\n 'list.single_line_text_field',\n 'list.url',\n 'list.variant_reference',\n 'list.volume',\n 'list.weight',\n] as const;\n\n/** A union of all the supported `metafield.type`s */\nexport type MetafieldTypeTypes = (typeof allMetafieldTypesArray)[number];\n\n/**\n * A mapping of a Metafield's `type` to the TypeScript type that is returned from `parseMetafield()`\n * For example, when using `parseMetafield()`, the type will be correctly returned when used like the following:\n *\n * ```\n * const parsedMetafield = parseMetafield<ParsedMetafields['boolean']>(metafield);`\n * ```\n * `parsedMetafield.parsedValue`'s type is now `boolean`\n */\nexport type ParsedMetafields<ExtraTypeGeneric = void> = {\n /** A Metafield that's been parsed, with a `parsedValue` of `boolean` */\n boolean: Simplify<BooleanParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Collection` object (as defined by the Storefront API) */\n collection_reference: Simplify<CollectionParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n color: Simplify<ColorParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Date` */\n date: Simplify<DatesParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Date` */\n date_time: Simplify<DatesParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n dimension: Simplify<MeasurementParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `GenericFile` object (as defined by the Storefront API) */\n file_reference: Simplify<FileRefParsedMetafield>;\n /**\n * A Metafield that's been parsed, with a `parsedValue` of type `unknown`, unless you pass in the type as a generic. For example:\n *\n * ```\n * ParsedMetafields<MyJsonType>['json']\n * ```\n */\n json: Simplify<JsonParsedMetafield<ExtraTypeGeneric>>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Money` */\n money: Simplify<MoneyParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n multi_line_text_field: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `number` */\n number_decimal: Simplify<NumberParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `number` */\n number_integer: Simplify<NumberParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Page` object (as defined by the Storefront API) */\n page_reference: Simplify<PageParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Product` object (as defined by the Storefront API) */\n product_reference: Simplify<ProductParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Rating` */\n rating: Simplify<RatingParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Rating` */\n rich_text_field: Simplify<RichTextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n single_line_text_field: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n url: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `ProductVariant` object (as defined by the Storefront API) */\n variant_reference: Simplify<VariantParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n volume: Simplify<MeasurementParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n weight: Simplify<MeasurementParsedMetafield>;\n // list metafields\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Collection` objects (as defined by the Storefront API) */\n 'list.collection_reference': Simplify<CollectionListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.color': Simplify<ColorListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of Date objects */\n 'list.date': Simplify<DatesListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of Date objects */\n 'list.date_time': Simplify<DatesListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement` objects */\n 'list.dimension': Simplify<MeasurementListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `GenericFile` objects (as defined by the Storefront API) */\n 'list.file_reference': Simplify<FileListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of numbers */\n 'list.number_integer': Simplify<NumberListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of numbers */\n 'list.number_decimal': Simplify<NumberListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Page` objects (as defined by the Storefront API) */\n 'list.page_reference': Simplify<PageListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Product` objects (as defined by the Storefront API) */\n 'list.product_reference': Simplify<ProductListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Rating`s */\n 'list.rating': Simplify<RatingListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.single_line_text_field': Simplify<TextListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.url': Simplify<TextListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `ProductVariant` objects (as defined by the Storefront API) */\n 'list.variant_reference': Simplify<VariantListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement`s */\n 'list.volume': Simplify<MeasurementListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement`s */\n 'list.weight': Simplify<MeasurementListParsedMetafield>;\n};\n\ninterface ParsedBase extends MetafieldBaseType {\n type: MetafieldTypeTypes;\n parsedValue: unknown;\n}\n\ninterface BooleanParsedMetafield extends ParsedBase {\n type: 'boolean';\n parsedValue: boolean | null;\n}\ntype CollectionParsedRefMetafield = MetafieldBaseType & {\n type: 'collection_reference';\n parsedValue: Collection | null;\n};\ntype ColorParsedMetafield = MetafieldBaseType & {\n type: 'color';\n parsedValue: string | null;\n};\ntype DatesParsedMetafield = MetafieldBaseType & {\n type: 'date' | 'date_time';\n parsedValue: Date | null;\n};\n\ntype MeasurementParsedMetafield = MetafieldBaseType & {\n type: 'dimension' | 'weight' | 'volume';\n parsedValue: Measurement | null;\n};\n\ntype FileRefParsedMetafield = MetafieldBaseType & {\n type: 'file_reference';\n parsedValue: GenericFile | null;\n};\n\ntype JsonParsedMetafield<JsonTypeGeneric = void> = MetafieldBaseType & {\n type: 'json';\n parsedValue: JsonTypeGeneric extends void ? unknown : JsonTypeGeneric | null;\n};\n\ntype MoneyParsedMetafield = MetafieldBaseType & {\n type: 'money';\n parsedValue: MoneyV2 | null;\n};\n\ntype TextParsedMetafield = MetafieldBaseType & {\n type: 'single_line_text_field' | 'multi_line_text_field' | 'url';\n parsedValue: string | null;\n};\n\ntype NumberParsedMetafield = MetafieldBaseType & {\n type: 'number_decimal' | 'number_integer';\n parsedValue: number | null;\n};\n\ntype PageParsedRefMetafield = MetafieldBaseType & {\n type: 'page_reference';\n parsedValue: Page | null;\n};\n\ntype ProductParsedRefMetafield = MetafieldBaseType & {\n type: 'product_reference';\n parsedValue: Product | null;\n};\n\ntype RatingParsedMetafield = MetafieldBaseType & {\n type: 'rating';\n parsedValue: Rating | null;\n};\n\ntype RichTextParsedMetafield = MetafieldBaseType & {\n type: 'rich_text_field';\n parsedValue: RichTextRootASTNode | null;\n};\n\ntype VariantParsedRefMetafield = MetafieldBaseType & {\n type: 'variant_reference';\n parsedValue: ProductVariant | null;\n};\n\ntype CollectionListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.collection_reference';\n parsedValue: Array<Collection> | null;\n};\n\ntype ColorListParsedMetafield = MetafieldBaseType & {\n type: 'list.color';\n parsedValue: Array<string> | null;\n};\n\ntype DatesListParsedMetafield = MetafieldBaseType & {\n type: 'list.date' | 'list.date_time';\n parsedValue: Array<Date> | null;\n};\n\ntype MeasurementListParsedMetafield = MetafieldBaseType & {\n type: 'list.dimension' | 'list.weight' | 'list.volume';\n parsedValue: Array<Measurement> | null;\n};\n\ntype FileListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.file_reference';\n parsedValue: Array<GenericFile> | null;\n};\n\ntype TextListParsedMetafield = MetafieldBaseType & {\n type: 'list.single_line_text_field' | 'list.url';\n parsedValue: Array<string> | null;\n};\n\ntype NumberListParsedMetafield = MetafieldBaseType & {\n type: 'list.number_decimal' | 'list.number_integer';\n parsedValue: Array<number> | null;\n};\n\ntype PageListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.page_reference';\n parsedValue: Array<Page> | null;\n};\n\ntype ProductListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.product_reference';\n parsedValue: Array<Product> | null;\n};\n\ntype RatingListParsedMetafield = MetafieldBaseType & {\n type: 'list.rating';\n parsedValue: Array<Rating> | null;\n};\n\ntype VariantListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.variant_reference';\n parsedValue: Array<ProductVariant> | null;\n};\n\nexport type Measurement = {\n unit: string;\n value: number;\n};\n\nexport interface Rating {\n value: number;\n scale_min: number;\n scale_max: number;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parse-metafield.mjs","sources":["../../src/parse-metafield.ts"],"sourcesContent":["import type {\n Article,\n Collection,\n CurrencyCode,\n GenericFile,\n Metafield as MetafieldBaseType,\n MoneyV2,\n Page,\n Product,\n ProductVariant,\n} from './storefront-api-types.js';\nimport type {PartialDeep, Simplify} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\nimport {RootASTNode as RichTextRootASTNode} from './RichText.types.js';\n\n/**\n * A function that uses `metafield.type` to parse the Metafield's `value` or `reference` or `references` (depending on the `metafield.type`) and places the result in `metafield.parsedValue`\n *\n * TypeScript developers can use the type `ParsedMetafields` from this package to get the returned object's type correct. For example:\n *\n * ```\n * parseMetafield<ParsedMetafields['boolean']>({type: 'boolean', value: 'false'}\n * ```\n */\nexport function parseMetafield<ReturnGeneric>(\n metafield: PartialDeep<MetafieldBaseType, {recurseIntoArrays: true}>,\n): ReturnGeneric {\n if (!metafield.type) {\n const noTypeError = `parseMetafield(): The 'type' field is required in order to parse the Metafield.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(noTypeError);\n } else {\n console.error(`${noTypeError} Returning 'parsedValue' of 'null'`);\n return {\n ...metafield,\n parsedValue: null,\n } as ReturnGeneric;\n }\n }\n\n switch (metafield.type) {\n case 'boolean':\n return {\n ...metafield,\n parsedValue: metafield.value === 'true',\n } as ReturnGeneric;\n\n case 'article_reference':\n case 'collection_reference':\n case 'file_reference':\n case 'page_reference':\n case 'product_reference':\n case 'variant_reference':\n return {\n ...metafield,\n parsedValue: metafield.reference,\n } as ReturnGeneric;\n\n case 'color':\n case 'multi_line_text_field':\n case 'single_line_text_field':\n case 'url':\n return {\n ...metafield,\n parsedValue: metafield.value,\n } as ReturnGeneric;\n\n // TODO: 'money' should probably be parsed even further to like `useMoney()`, but that logic needs to be extracted first so it's not a hook\n case 'money': {\n let parsedValue: MoneyV2 | null = null;\n try {\n const parsed = parseJSON(metafield.value ?? '');\n // Transform currency_code from Storefront API to currencyCode to match MoneyV2 type\n if (parsed && typeof parsed === 'object' && 'currency_code' in parsed) {\n const moneyData = parsed as {amount: string; currency_code: string};\n parsedValue = {\n amount: moneyData.amount,\n currencyCode: moneyData.currency_code as CurrencyCode,\n };\n } else if (\n parsed &&\n typeof parsed === 'object' &&\n 'currencyCode' in parsed\n ) {\n // Already in correct format (for backward compatibility)\n parsedValue = parsed as MoneyV2;\n } else {\n parsedValue = parsed as MoneyV2 | null;\n }\n } catch (err) {\n const parseError = `parseMetafield(): attempted to JSON.parse the 'metafield.value' property, but failed.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(parseError);\n } else {\n console.error(`${parseError} Returning 'null' for 'parsedValue'`);\n }\n parsedValue = null;\n }\n return {\n ...metafield,\n parsedValue,\n } as ReturnGeneric;\n }\n\n case 'dimension':\n case 'json':\n case 'rating':\n case 'volume':\n case 'weight':\n case 'rich_text_field':\n case 'list.color':\n case 'list.dimension':\n case 'list.number_integer':\n case 'list.number_decimal':\n case 'list.rating':\n case 'list.single_line_text_field':\n case 'list.url':\n case 'list.volume':\n case 'list.weight': {\n let parsedValue = null;\n try {\n parsedValue = parseJSON(metafield.value ?? '');\n } catch (err) {\n const parseError = `parseMetafield(): attempted to JSON.parse the 'metafield.value' property, but failed.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(parseError);\n } else {\n console.error(`${parseError} Returning 'null' for 'parsedValue'`);\n }\n parsedValue = null;\n }\n return {\n ...metafield,\n parsedValue,\n } as ReturnGeneric;\n }\n\n case 'date':\n case 'date_time':\n return {\n ...metafield,\n parsedValue: new Date(metafield.value ?? ''),\n } as ReturnGeneric;\n\n case 'list.date':\n case 'list.date_time': {\n const jsonParseValue = parseJSON(metafield?.value ?? '') as string[];\n return {\n ...metafield,\n parsedValue: jsonParseValue.map((dateString) => new Date(dateString)),\n } as ReturnGeneric;\n }\n\n case 'number_decimal':\n case 'number_integer':\n return {\n ...metafield,\n parsedValue: Number(metafield.value),\n } as ReturnGeneric;\n\n case 'list.article_reference':\n case 'list.collection_reference':\n case 'list.file_reference':\n case 'list.page_reference':\n case 'list.product_reference':\n case 'list.variant_reference':\n return {\n ...metafield,\n parsedValue: flattenConnection(metafield.references ?? undefined),\n } as ReturnGeneric;\n\n default: {\n const typeNotFoundError = `parseMetafield(): the 'metafield.type' you passed in is not supported. Your type: \"${metafield.type}\". If you believe this is an error, please open an issue on GitHub.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(typeNotFoundError);\n } else {\n console.error(\n `${typeNotFoundError} Returning 'parsedValue' of 'null'`,\n );\n return {\n ...metafield,\n parsedValue: null,\n } as ReturnGeneric;\n }\n }\n }\n}\n\n/**\n * Parses a JSON string while preventing prototype injection attacks.\n */\nexport function parseJSON(json: string): unknown {\n if (String(json).includes('__proto__')) {\n return JSON.parse(json, (k, v) => {\n if (k !== '__proto__') return v as unknown;\n }) as unknown;\n }\n return JSON.parse(json) as unknown;\n}\n\n// taken from https://shopify.dev/apps/metafields/types\nexport const allMetafieldTypesArray = [\n 'article_reference',\n 'boolean',\n 'collection_reference',\n 'color',\n 'date',\n 'date_time',\n 'dimension',\n 'file_reference',\n 'json',\n 'money',\n 'rich_text_field',\n 'multi_line_text_field',\n 'number_decimal',\n 'number_integer',\n 'page_reference',\n 'product_reference',\n 'rating',\n 'single_line_text_field',\n 'url',\n 'variant_reference',\n 'volume',\n 'weight',\n // list metafields\n 'list.article_reference',\n 'list.collection_reference',\n 'list.color',\n 'list.date',\n 'list.date_time',\n 'list.dimension',\n 'list.file_reference',\n 'list.number_integer',\n 'list.number_decimal',\n 'list.page_reference',\n 'list.product_reference',\n 'list.rating',\n 'list.single_line_text_field',\n 'list.url',\n 'list.variant_reference',\n 'list.volume',\n 'list.weight',\n] as const;\n\n/** A union of all the supported `metafield.type`s */\nexport type MetafieldTypeTypes = (typeof allMetafieldTypesArray)[number];\n\n/**\n * A mapping of a Metafield's `type` to the TypeScript type that is returned from `parseMetafield()`\n * For example, when using `parseMetafield()`, the type will be correctly returned when used like the following:\n *\n * ```\n * const parsedMetafield = parseMetafield<ParsedMetafields['boolean']>(metafield);`\n * ```\n * `parsedMetafield.parsedValue`'s type is now `boolean`\n */\nexport type ParsedMetafields<ExtraTypeGeneric = void> = {\n /** A Metafield that's been parsed, with a `parsedValue` of an `Article` object (as defined by the Storefront API) */\n article_reference: Simplify<ArticleParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of `boolean` */\n boolean: Simplify<BooleanParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Collection` object (as defined by the Storefront API) */\n collection_reference: Simplify<CollectionParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n color: Simplify<ColorParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Date` */\n date: Simplify<DatesParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Date` */\n date_time: Simplify<DatesParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n dimension: Simplify<MeasurementParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `GenericFile` object (as defined by the Storefront API) */\n file_reference: Simplify<FileRefParsedMetafield>;\n /**\n * A Metafield that's been parsed, with a `parsedValue` of type `unknown`, unless you pass in the type as a generic. For example:\n *\n * ```\n * ParsedMetafields<MyJsonType>['json']\n * ```\n */\n json: Simplify<JsonParsedMetafield<ExtraTypeGeneric>>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Money` */\n money: Simplify<MoneyParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n multi_line_text_field: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `number` */\n number_decimal: Simplify<NumberParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `number` */\n number_integer: Simplify<NumberParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Page` object (as defined by the Storefront API) */\n page_reference: Simplify<PageParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `Product` object (as defined by the Storefront API) */\n product_reference: Simplify<ProductParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Rating` */\n rating: Simplify<RatingParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Rating` */\n rich_text_field: Simplify<RichTextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n single_line_text_field: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n url: Simplify<TextParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of a `ProductVariant` object (as defined by the Storefront API) */\n variant_reference: Simplify<VariantParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n volume: Simplify<MeasurementParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n weight: Simplify<MeasurementParsedMetafield>;\n // list metafields\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Article` objects (as defined by the Storefront API) */\n 'list.article_reference': Simplify<ArticleListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Collection` objects (as defined by the Storefront API) */\n 'list.collection_reference': Simplify<CollectionListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.color': Simplify<ColorListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of Date objects */\n 'list.date': Simplify<DatesListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of Date objects */\n 'list.date_time': Simplify<DatesListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement` objects */\n 'list.dimension': Simplify<MeasurementListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `GenericFile` objects (as defined by the Storefront API) */\n 'list.file_reference': Simplify<FileListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of numbers */\n 'list.number_integer': Simplify<NumberListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of numbers */\n 'list.number_decimal': Simplify<NumberListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Page` objects (as defined by the Storefront API) */\n 'list.page_reference': Simplify<PageListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Product` objects (as defined by the Storefront API) */\n 'list.product_reference': Simplify<ProductListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Rating`s */\n 'list.rating': Simplify<RatingListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.single_line_text_field': Simplify<TextListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n 'list.url': Simplify<TextListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `ProductVariant` objects (as defined by the Storefront API) */\n 'list.variant_reference': Simplify<VariantListParsedRefMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement`s */\n 'list.volume': Simplify<MeasurementListParsedMetafield>;\n /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement`s */\n 'list.weight': Simplify<MeasurementListParsedMetafield>;\n};\n\ninterface ParsedBase extends MetafieldBaseType {\n type: MetafieldTypeTypes;\n parsedValue: unknown;\n}\n\ninterface BooleanParsedMetafield extends ParsedBase {\n type: 'boolean';\n parsedValue: boolean | null;\n}\ntype CollectionParsedRefMetafield = MetafieldBaseType & {\n type: 'collection_reference';\n parsedValue: Collection | null;\n};\ntype ColorParsedMetafield = MetafieldBaseType & {\n type: 'color';\n parsedValue: string | null;\n};\ntype DatesParsedMetafield = MetafieldBaseType & {\n type: 'date' | 'date_time';\n parsedValue: Date | null;\n};\n\ntype MeasurementParsedMetafield = MetafieldBaseType & {\n type: 'dimension' | 'weight' | 'volume';\n parsedValue: Measurement | null;\n};\n\ntype FileRefParsedMetafield = MetafieldBaseType & {\n type: 'file_reference';\n parsedValue: GenericFile | null;\n};\n\ntype JsonParsedMetafield<JsonTypeGeneric = void> = MetafieldBaseType & {\n type: 'json';\n parsedValue: JsonTypeGeneric extends void ? unknown : JsonTypeGeneric | null;\n};\n\ntype MoneyParsedMetafield = MetafieldBaseType & {\n type: 'money';\n parsedValue: MoneyV2 | null;\n};\n\ntype TextParsedMetafield = MetafieldBaseType & {\n type: 'single_line_text_field' | 'multi_line_text_field' | 'url';\n parsedValue: string | null;\n};\n\ntype NumberParsedMetafield = MetafieldBaseType & {\n type: 'number_decimal' | 'number_integer';\n parsedValue: number | null;\n};\n\ntype ArticleParsedRefMetafield = MetafieldBaseType & {\n type: 'article_reference';\n parsedValue: Article | null;\n};\n\ntype PageParsedRefMetafield = MetafieldBaseType & {\n type: 'page_reference';\n parsedValue: Page | null;\n};\n\ntype ProductParsedRefMetafield = MetafieldBaseType & {\n type: 'product_reference';\n parsedValue: Product | null;\n};\n\ntype RatingParsedMetafield = MetafieldBaseType & {\n type: 'rating';\n parsedValue: Rating | null;\n};\n\ntype RichTextParsedMetafield = MetafieldBaseType & {\n type: 'rich_text_field';\n parsedValue: RichTextRootASTNode | null;\n};\n\ntype VariantParsedRefMetafield = MetafieldBaseType & {\n type: 'variant_reference';\n parsedValue: ProductVariant | null;\n};\n\ntype ArticleListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.article_reference';\n parsedValue: Array<Article> | null;\n};\n\ntype CollectionListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.collection_reference';\n parsedValue: Array<Collection> | null;\n};\n\ntype ColorListParsedMetafield = MetafieldBaseType & {\n type: 'list.color';\n parsedValue: Array<string> | null;\n};\n\ntype DatesListParsedMetafield = MetafieldBaseType & {\n type: 'list.date' | 'list.date_time';\n parsedValue: Array<Date> | null;\n};\n\ntype MeasurementListParsedMetafield = MetafieldBaseType & {\n type: 'list.dimension' | 'list.weight' | 'list.volume';\n parsedValue: Array<Measurement> | null;\n};\n\ntype FileListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.file_reference';\n parsedValue: Array<GenericFile> | null;\n};\n\ntype TextListParsedMetafield = MetafieldBaseType & {\n type: 'list.single_line_text_field' | 'list.url';\n parsedValue: Array<string> | null;\n};\n\ntype NumberListParsedMetafield = MetafieldBaseType & {\n type: 'list.number_decimal' | 'list.number_integer';\n parsedValue: Array<number> | null;\n};\n\ntype PageListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.page_reference';\n parsedValue: Array<Page> | null;\n};\n\ntype ProductListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.product_reference';\n parsedValue: Array<Product> | null;\n};\n\ntype RatingListParsedMetafield = MetafieldBaseType & {\n type: 'list.rating';\n parsedValue: Array<Rating> | null;\n};\n\ntype VariantListParsedRefMetafield = MetafieldBaseType & {\n type: 'list.variant_reference';\n parsedValue: Array<ProductVariant> | null;\n};\n\nexport type Measurement = {\n unit: string;\n value: number;\n};\n\nexport interface Rating {\n value: number;\n scale_min: number;\n scale_max: number;\n}\n"],"names":[],"mappings":";AAwBO,SAAS,eACd,WACe;AACf,MAAI,CAAC,UAAU,MAAM;AACnB,UAAM,cAAc;AACE;AACpB,YAAM,IAAI,MAAM,WAAW;AAAA,IAC7B;AAAA,EAOF;AAEA,UAAQ,UAAU,MAAA;AAAA,IAChB,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,aAAa,UAAU,UAAU;AAAA,MAAA;AAAA,IAGrC,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,aAAa,UAAU;AAAA,MAAA;AAAA,IAG3B,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,aAAa,UAAU;AAAA,MAAA;AAAA;AAAA,IAI3B,KAAK,SAAS;AACZ,UAAI,cAA8B;AAClC,UAAI;AACF,cAAM,SAAS,UAAU,UAAU,SAAS,EAAE;AAE9C,YAAI,UAAU,OAAO,WAAW,YAAY,mBAAmB,QAAQ;AACrE,gBAAM,YAAY;AAClB,wBAAc;AAAA,YACZ,QAAQ,UAAU;AAAA,YAClB,cAAc,UAAU;AAAA,UAAA;AAAA,QAE5B,WACE,UACA,OAAO,WAAW,YAClB,kBAAkB,QAClB;AAEA,wBAAc;AAAA,QAChB,OAAO;AACL,wBAAc;AAAA,QAChB;AAAA,MACF,SAAS,KAAK;AACZ,cAAM,aAAa;AACG;AACpB,gBAAM,IAAI,MAAM,UAAU;AAAA,QAC5B;AAAA,MAIF;AACA,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,IAEA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,eAAe;AAClB,UAAI,cAAc;AAClB,UAAI;AACF,sBAAc,UAAU,UAAU,SAAS,EAAE;AAAA,MAC/C,SAAS,KAAK;AACZ,cAAM,aAAa;AACG;AACpB,gBAAM,IAAI,MAAM,UAAU;AAAA,QAC5B;AAAA,MAIF;AACA,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,IAEA,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,aAAa,IAAI,KAAK,UAAU,SAAS,EAAE;AAAA,MAAA;AAAA,IAG/C,KAAK;AAAA,IACL,KAAK,kBAAkB;AACrB,YAAM,iBAAiB,WAAU,uCAAW,UAAS,EAAE;AACvD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,aAAa,eAAe,IAAI,CAAC,eAAe,IAAI,KAAK,UAAU,CAAC;AAAA,MAAA;AAAA,IAExE;AAAA,IAEA,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,aAAa,OAAO,UAAU,KAAK;AAAA,MAAA;AAAA,IAGvC,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,aAAa,kBAAkB,UAAU,cAAc,MAAS;AAAA,MAAA;AAAA,IAGpE,SAAS;AACP,YAAM,oBAAoB,sFAAsF,UAAU,IAAI;AACxG;AACpB,cAAM,IAAI,MAAM,iBAAiB;AAAA,MACnC;AAAA,IASF;AAAA,EAAA;AAEJ;AAKO,SAAS,UAAU,MAAuB;AAC/C,MAAI,OAAO,IAAI,EAAE,SAAS,WAAW,GAAG;AACtC,WAAO,KAAK,MAAM,MAAM,CAAC,GAAG,MAAM;AAChC,UAAI,MAAM,YAAa,QAAO;AAAA,IAChC,CAAC;AAAA,EACH;AACA,SAAO,KAAK,MAAM,IAAI;AACxB;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storefront-api-constants.js","sources":["../../src/storefront-api-constants.ts"],"sourcesContent":["export const SFAPI_VERSION = '
|
|
1
|
+
{"version":3,"file":"storefront-api-constants.js","sources":["../../src/storefront-api-constants.ts"],"sourcesContent":["export const SFAPI_VERSION = '2026-01';\n"],"names":[],"mappings":";;AAAO,MAAM,gBAAgB;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storefront-api-constants.mjs","sources":["../../src/storefront-api-constants.ts"],"sourcesContent":["export const SFAPI_VERSION = '
|
|
1
|
+
{"version":3,"file":"storefront-api-constants.mjs","sources":["../../src/storefront-api-constants.ts"],"sourcesContent":["export const SFAPI_VERSION = '2026-01';\n"],"names":[],"mappings":"AAAO,MAAM,gBAAgB;"}
|