@shopify/hydrogen-react 2024.7.6 → 2024.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/customer-account.schema.json +1 -1
- package/dist/browser-dev/AddToCartButton.mjs.map +1 -1
- package/dist/browser-dev/BuyNowButton.mjs.map +1 -1
- package/dist/browser-dev/CartCost.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/ExternalVideo.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/ProductPrice.mjs +7 -19
- package/dist/browser-dev/ProductPrice.mjs.map +1 -1
- package/dist/browser-dev/RichText.mjs.map +1 -1
- package/dist/browser-dev/Video.mjs.map +1 -1
- package/dist/browser-dev/codegen.helpers.mjs.map +1 -1
- package/dist/browser-dev/getProductOptions.mjs +239 -0
- package/dist/browser-dev/getProductOptions.mjs.map +1 -0
- package/dist/browser-dev/index.mjs +9 -0
- package/dist/browser-dev/index.mjs.map +1 -1
- package/dist/browser-dev/optionValueDecoder.mjs +91 -0
- package/dist/browser-dev/optionValueDecoder.mjs.map +1 -0
- package/dist/browser-dev/packages/hydrogen-react/package.json.mjs +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/useCartAPIStateMachine.mjs.map +1 -1
- package/dist/browser-dev/useCartActions.mjs.map +1 -1
- package/dist/browser-dev/useSelectedOptionInUrlParam.mjs +30 -0
- package/dist/browser-dev/useSelectedOptionInUrlParam.mjs.map +1 -0
- package/dist/browser-prod/AddToCartButton.mjs.map +1 -1
- package/dist/browser-prod/BuyNowButton.mjs.map +1 -1
- package/dist/browser-prod/CartCost.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/ExternalVideo.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/ProductPrice.mjs +7 -19
- package/dist/browser-prod/ProductPrice.mjs.map +1 -1
- package/dist/browser-prod/RichText.mjs.map +1 -1
- package/dist/browser-prod/Video.mjs.map +1 -1
- package/dist/browser-prod/codegen.helpers.mjs.map +1 -1
- package/dist/browser-prod/getProductOptions.mjs +239 -0
- package/dist/browser-prod/getProductOptions.mjs.map +1 -0
- package/dist/browser-prod/index.mjs +9 -0
- package/dist/browser-prod/index.mjs.map +1 -1
- package/dist/browser-prod/optionValueDecoder.mjs +91 -0
- package/dist/browser-prod/optionValueDecoder.mjs.map +1 -0
- package/dist/browser-prod/packages/hydrogen-react/package.json.mjs +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/useCartAPIStateMachine.mjs.map +1 -1
- package/dist/browser-prod/useCartActions.mjs.map +1 -1
- package/dist/browser-prod/useSelectedOptionInUrlParam.mjs +30 -0
- package/dist/browser-prod/useSelectedOptionInUrlParam.mjs.map +1 -0
- package/dist/node-dev/AddToCartButton.js.map +1 -1
- package/dist/node-dev/AddToCartButton.mjs.map +1 -1
- package/dist/node-dev/BuyNowButton.js.map +1 -1
- package/dist/node-dev/BuyNowButton.mjs.map +1 -1
- package/dist/node-dev/CartCost.js.map +1 -1
- package/dist/node-dev/CartCost.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/ExternalVideo.js.map +1 -1
- package/dist/node-dev/ExternalVideo.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/ProductPrice.js +7 -19
- package/dist/node-dev/ProductPrice.js.map +1 -1
- package/dist/node-dev/ProductPrice.mjs +7 -19
- package/dist/node-dev/ProductPrice.mjs.map +1 -1
- package/dist/node-dev/RichText.js.map +1 -1
- package/dist/node-dev/RichText.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/codegen.helpers.js.map +1 -1
- package/dist/node-dev/codegen.helpers.mjs.map +1 -1
- package/dist/node-dev/getProductOptions.js +239 -0
- package/dist/node-dev/getProductOptions.js.map +1 -0
- package/dist/node-dev/getProductOptions.mjs +239 -0
- package/dist/node-dev/getProductOptions.mjs.map +1 -0
- package/dist/node-dev/index.js +9 -0
- package/dist/node-dev/index.js.map +1 -1
- package/dist/node-dev/index.mjs +9 -0
- package/dist/node-dev/index.mjs.map +1 -1
- package/dist/node-dev/optionValueDecoder.js +91 -0
- package/dist/node-dev/optionValueDecoder.js.map +1 -0
- package/dist/node-dev/optionValueDecoder.mjs +91 -0
- package/dist/node-dev/optionValueDecoder.mjs.map +1 -0
- 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/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/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/useSelectedOptionInUrlParam.js +30 -0
- package/dist/node-dev/useSelectedOptionInUrlParam.js.map +1 -0
- package/dist/node-dev/useSelectedOptionInUrlParam.mjs +30 -0
- package/dist/node-dev/useSelectedOptionInUrlParam.mjs.map +1 -0
- package/dist/node-prod/AddToCartButton.js.map +1 -1
- package/dist/node-prod/AddToCartButton.mjs.map +1 -1
- package/dist/node-prod/BuyNowButton.js.map +1 -1
- package/dist/node-prod/BuyNowButton.mjs.map +1 -1
- package/dist/node-prod/CartCost.js.map +1 -1
- package/dist/node-prod/CartCost.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/ExternalVideo.js.map +1 -1
- package/dist/node-prod/ExternalVideo.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/ProductPrice.js +7 -19
- package/dist/node-prod/ProductPrice.js.map +1 -1
- package/dist/node-prod/ProductPrice.mjs +7 -19
- package/dist/node-prod/ProductPrice.mjs.map +1 -1
- package/dist/node-prod/RichText.js.map +1 -1
- package/dist/node-prod/RichText.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/codegen.helpers.js.map +1 -1
- package/dist/node-prod/codegen.helpers.mjs.map +1 -1
- package/dist/node-prod/getProductOptions.js +239 -0
- package/dist/node-prod/getProductOptions.js.map +1 -0
- package/dist/node-prod/getProductOptions.mjs +239 -0
- package/dist/node-prod/getProductOptions.mjs.map +1 -0
- package/dist/node-prod/index.js +9 -0
- package/dist/node-prod/index.js.map +1 -1
- package/dist/node-prod/index.mjs +9 -0
- package/dist/node-prod/index.mjs.map +1 -1
- package/dist/node-prod/optionValueDecoder.js +91 -0
- package/dist/node-prod/optionValueDecoder.js.map +1 -0
- package/dist/node-prod/optionValueDecoder.mjs +91 -0
- package/dist/node-prod/optionValueDecoder.mjs.map +1 -0
- 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/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/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/useSelectedOptionInUrlParam.js +30 -0
- package/dist/node-prod/useSelectedOptionInUrlParam.js.map +1 -0
- package/dist/node-prod/useSelectedOptionInUrlParam.mjs +30 -0
- package/dist/node-prod/useSelectedOptionInUrlParam.mjs.map +1 -0
- package/dist/types/CartLineProvider.d.ts +1 -1
- package/dist/types/CartProvider.d.ts +6 -5
- package/dist/types/Image.d.ts +1 -1
- package/dist/types/ModelViewer.d.ts +1 -1
- package/dist/types/Money.d.ts +1 -1
- package/dist/types/Video.d.ts +1 -1
- package/dist/types/codegen.helpers.d.ts +2 -2
- package/dist/types/getProductOptions.d.ts +49 -0
- package/dist/types/index.d.cts +3 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/optionValueDecoder.d.ts +29 -0
- package/dist/types/storefront-api-constants.d.ts +1 -1
- package/dist/types/storefront-api-response.types.d.ts +5 -5
- package/dist/types/storefront-api-types.d.ts +419 -26
- package/dist/types/useCartAPIStateMachine.d.ts +2 -2
- package/dist/types/useCartActions.d.ts +2 -2
- package/dist/types/useSelectedOptionInUrlParam.d.ts +2 -0
- package/dist/umd/hydrogen-react.dev.js +356 -21
- package/dist/umd/hydrogen-react.dev.js.map +1 -1
- package/dist/umd/hydrogen-react.prod.js +18 -18
- package/dist/umd/hydrogen-react.prod.js.map +1 -1
- package/package.json +2 -2
- package/storefront.schema.json +1 -1
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const optionValueDecoder = require("./optionValueDecoder.js");
|
|
4
|
+
function mapProductOptions(options) {
|
|
5
|
+
return options.map((option) => {
|
|
6
|
+
return Object.assign(
|
|
7
|
+
{},
|
|
8
|
+
...(option == null ? void 0 : option.optionValues) ? option.optionValues.map((value, index) => {
|
|
9
|
+
return { [value.name]: index };
|
|
10
|
+
}) : []
|
|
11
|
+
);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function mapSelectedProductOptionToObject(options) {
|
|
15
|
+
return Object.assign(
|
|
16
|
+
{},
|
|
17
|
+
...options.map((key) => {
|
|
18
|
+
return { [key.name]: key.value };
|
|
19
|
+
})
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
function mapSelectedProductOptionToObjectAsString(options) {
|
|
23
|
+
return JSON.stringify(mapSelectedProductOptionToObject(options));
|
|
24
|
+
}
|
|
25
|
+
function encodeSelectedProductOptionAsKey(selectedOption, productOptionMappings) {
|
|
26
|
+
if (Array.isArray(selectedOption)) {
|
|
27
|
+
return JSON.stringify(
|
|
28
|
+
selectedOption.map((key, index) => {
|
|
29
|
+
return productOptionMappings[index][key.value];
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
} else {
|
|
33
|
+
return JSON.stringify(
|
|
34
|
+
Object.keys(selectedOption).map((key, index) => {
|
|
35
|
+
return productOptionMappings[index][selectedOption[key]];
|
|
36
|
+
})
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function mapVariants(variants, productOptionMappings) {
|
|
41
|
+
return Object.assign(
|
|
42
|
+
{},
|
|
43
|
+
...variants.map((variant) => {
|
|
44
|
+
const variantKey = encodeSelectedProductOptionAsKey(
|
|
45
|
+
variant.selectedOptions || [],
|
|
46
|
+
productOptionMappings
|
|
47
|
+
);
|
|
48
|
+
return { [variantKey]: variant };
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
const PRODUCT_INPUTS = [
|
|
53
|
+
"options",
|
|
54
|
+
"selectedOrFirstAvailableVariant",
|
|
55
|
+
"adjacentVariants"
|
|
56
|
+
];
|
|
57
|
+
const PRODUCT_INPUTS_EXTRA = [
|
|
58
|
+
"handle",
|
|
59
|
+
"encodedVariantExistence",
|
|
60
|
+
"encodedVariantAvailability"
|
|
61
|
+
];
|
|
62
|
+
function logErrorAndReturnFalse(key) {
|
|
63
|
+
console.error(
|
|
64
|
+
`[h2:error:getProductOptions] product.${key} is missing. Make sure you query for this field from the Storefront API.`
|
|
65
|
+
);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
function checkProductParam(product, checkAll = false) {
|
|
69
|
+
var _a;
|
|
70
|
+
let validParam = true;
|
|
71
|
+
const productKeys = Object.keys(product);
|
|
72
|
+
(checkAll ? [...PRODUCT_INPUTS, ...PRODUCT_INPUTS_EXTRA] : PRODUCT_INPUTS).forEach((key) => {
|
|
73
|
+
if (!productKeys.includes(key)) {
|
|
74
|
+
validParam = logErrorAndReturnFalse(key);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
if (product.options) {
|
|
78
|
+
const firstOption = product == null ? void 0 : product.options[0];
|
|
79
|
+
if (checkAll && !(firstOption == null ? void 0 : firstOption.name)) {
|
|
80
|
+
validParam = logErrorAndReturnFalse("options.name");
|
|
81
|
+
}
|
|
82
|
+
if ((_a = product == null ? void 0 : product.options[0]) == null ? void 0 : _a.optionValues) {
|
|
83
|
+
const firstOptionValues = product.options[0].optionValues[0];
|
|
84
|
+
if (checkAll && !(firstOptionValues == null ? void 0 : firstOptionValues.name)) {
|
|
85
|
+
validParam = logErrorAndReturnFalse("options.optionValues.name");
|
|
86
|
+
}
|
|
87
|
+
if (firstOptionValues == null ? void 0 : firstOptionValues.firstSelectableVariant) {
|
|
88
|
+
validParam = checkProductVariantParam(
|
|
89
|
+
firstOptionValues.firstSelectableVariant,
|
|
90
|
+
"options.optionValues.firstSelectableVariant",
|
|
91
|
+
validParam,
|
|
92
|
+
checkAll
|
|
93
|
+
);
|
|
94
|
+
} else {
|
|
95
|
+
validParam = logErrorAndReturnFalse(
|
|
96
|
+
"options.optionValues.firstSelectableVariant"
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
validParam = logErrorAndReturnFalse("options.optionValues");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (product.selectedOrFirstAvailableVariant) {
|
|
104
|
+
validParam = checkProductVariantParam(
|
|
105
|
+
product.selectedOrFirstAvailableVariant,
|
|
106
|
+
"selectedOrFirstAvailableVariant",
|
|
107
|
+
validParam,
|
|
108
|
+
checkAll
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
if (!!product.adjacentVariants && product.adjacentVariants[0]) {
|
|
112
|
+
validParam = checkProductVariantParam(
|
|
113
|
+
product.adjacentVariants[0],
|
|
114
|
+
"adjacentVariants",
|
|
115
|
+
validParam,
|
|
116
|
+
checkAll
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
return validParam ? product : {};
|
|
120
|
+
}
|
|
121
|
+
function checkProductVariantParam(variant, key, currentValidParamState, checkAll) {
|
|
122
|
+
var _a;
|
|
123
|
+
let validParam = currentValidParamState;
|
|
124
|
+
if (checkAll && !((_a = variant.product) == null ? void 0 : _a.handle)) {
|
|
125
|
+
validParam = logErrorAndReturnFalse(`${key}.product.handle`);
|
|
126
|
+
}
|
|
127
|
+
if (variant.selectedOptions) {
|
|
128
|
+
const firstSelectedOption = variant.selectedOptions[0];
|
|
129
|
+
if (!(firstSelectedOption == null ? void 0 : firstSelectedOption.name)) {
|
|
130
|
+
validParam = logErrorAndReturnFalse(`${key}.selectedOptions.name`);
|
|
131
|
+
}
|
|
132
|
+
if (!(firstSelectedOption == null ? void 0 : firstSelectedOption.value)) {
|
|
133
|
+
validParam = logErrorAndReturnFalse(`${key}.selectedOptions.value`);
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
validParam = logErrorAndReturnFalse(`${key}.selectedOptions`);
|
|
137
|
+
}
|
|
138
|
+
return validParam;
|
|
139
|
+
}
|
|
140
|
+
function getAdjacentAndFirstAvailableVariants(product) {
|
|
141
|
+
const checkedProduct = checkProductParam(product);
|
|
142
|
+
if (!checkedProduct.options)
|
|
143
|
+
return [];
|
|
144
|
+
const availableVariants = {};
|
|
145
|
+
checkedProduct.options.map((option) => {
|
|
146
|
+
var _a;
|
|
147
|
+
(_a = option.optionValues) == null ? void 0 : _a.map((value) => {
|
|
148
|
+
if (value.firstSelectableVariant) {
|
|
149
|
+
const variantKey = mapSelectedProductOptionToObjectAsString(
|
|
150
|
+
value.firstSelectableVariant.selectedOptions
|
|
151
|
+
);
|
|
152
|
+
availableVariants[variantKey] = value.firstSelectableVariant;
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
checkedProduct.adjacentVariants.map((variant) => {
|
|
157
|
+
const variantKey = mapSelectedProductOptionToObjectAsString(
|
|
158
|
+
variant.selectedOptions
|
|
159
|
+
);
|
|
160
|
+
availableVariants[variantKey] = variant;
|
|
161
|
+
});
|
|
162
|
+
const selectedVariant = checkedProduct.selectedOrFirstAvailableVariant;
|
|
163
|
+
if (selectedVariant) {
|
|
164
|
+
const variantKey = mapSelectedProductOptionToObjectAsString(
|
|
165
|
+
selectedVariant.selectedOptions
|
|
166
|
+
);
|
|
167
|
+
availableVariants[variantKey] = selectedVariant;
|
|
168
|
+
}
|
|
169
|
+
return Object.values(availableVariants);
|
|
170
|
+
}
|
|
171
|
+
function getProductOptions(product) {
|
|
172
|
+
const checkedProduct = checkProductParam(product, true);
|
|
173
|
+
if (!checkedProduct.options)
|
|
174
|
+
return [];
|
|
175
|
+
const {
|
|
176
|
+
options,
|
|
177
|
+
selectedOrFirstAvailableVariant: selectedVariant,
|
|
178
|
+
adjacentVariants,
|
|
179
|
+
encodedVariantExistence,
|
|
180
|
+
encodedVariantAvailability,
|
|
181
|
+
handle: productHandle
|
|
182
|
+
} = checkedProduct;
|
|
183
|
+
const productOptionMappings = mapProductOptions(options);
|
|
184
|
+
const variants = mapVariants(
|
|
185
|
+
selectedVariant ? [selectedVariant, ...adjacentVariants] : adjacentVariants,
|
|
186
|
+
productOptionMappings
|
|
187
|
+
);
|
|
188
|
+
const selectedOptions = mapSelectedProductOptionToObject(
|
|
189
|
+
selectedVariant ? selectedVariant.selectedOptions : []
|
|
190
|
+
);
|
|
191
|
+
const productOptions = options.map((option, optionIndex) => {
|
|
192
|
+
return {
|
|
193
|
+
...option,
|
|
194
|
+
optionValues: option.optionValues.map((value) => {
|
|
195
|
+
var _a;
|
|
196
|
+
const targetOptionParams = { ...selectedOptions };
|
|
197
|
+
targetOptionParams[option.name] = value.name;
|
|
198
|
+
const targetKey = encodeSelectedProductOptionAsKey(
|
|
199
|
+
targetOptionParams || [],
|
|
200
|
+
productOptionMappings
|
|
201
|
+
);
|
|
202
|
+
const topDownKey = JSON.parse(targetKey).slice(
|
|
203
|
+
0,
|
|
204
|
+
optionIndex + 1
|
|
205
|
+
);
|
|
206
|
+
const exists = optionValueDecoder.isOptionValueCombinationInEncodedVariant(
|
|
207
|
+
topDownKey,
|
|
208
|
+
encodedVariantExistence || ""
|
|
209
|
+
);
|
|
210
|
+
const available = optionValueDecoder.isOptionValueCombinationInEncodedVariant(
|
|
211
|
+
topDownKey,
|
|
212
|
+
encodedVariantAvailability || ""
|
|
213
|
+
);
|
|
214
|
+
const variant = variants[targetKey] || value.firstSelectableVariant;
|
|
215
|
+
const variantOptionParam = mapSelectedProductOptionToObject(
|
|
216
|
+
variant.selectedOptions || []
|
|
217
|
+
);
|
|
218
|
+
const searchParams = new URLSearchParams(variantOptionParam);
|
|
219
|
+
const handle = (_a = variant == null ? void 0 : variant.product) == null ? void 0 : _a.handle;
|
|
220
|
+
return {
|
|
221
|
+
...value,
|
|
222
|
+
variant,
|
|
223
|
+
handle,
|
|
224
|
+
variantUriQuery: searchParams.toString(),
|
|
225
|
+
selected: selectedOptions[option.name] === value.name,
|
|
226
|
+
exists,
|
|
227
|
+
available,
|
|
228
|
+
isDifferentProduct: handle !== productHandle
|
|
229
|
+
};
|
|
230
|
+
})
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
return productOptions;
|
|
234
|
+
}
|
|
235
|
+
exports.checkProductParam = checkProductParam;
|
|
236
|
+
exports.getAdjacentAndFirstAvailableVariants = getAdjacentAndFirstAvailableVariants;
|
|
237
|
+
exports.getProductOptions = getProductOptions;
|
|
238
|
+
exports.mapSelectedProductOptionToObject = mapSelectedProductOptionToObject;
|
|
239
|
+
//# sourceMappingURL=getProductOptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getProductOptions.js","sources":["../../src/getProductOptions.ts"],"sourcesContent":["import {isOptionValueCombinationInEncodedVariant} from './optionValueDecoder.js';\nimport type {\n Product,\n ProductOption,\n ProductOptionValue,\n ProductVariant,\n SelectedOption,\n} from './storefront-api-types';\n\nexport type RecursivePartial<T> = {\n [P in keyof T]?: RecursivePartial<T[P]>;\n};\ntype ProductOptionsMapping = Record<string, number>;\ntype ProductOptionValueState = {\n variant: ProductVariant;\n handle: string;\n variantUriQuery: string;\n selected: boolean;\n exists: boolean;\n available: boolean;\n isDifferentProduct: boolean;\n};\ntype MappedProductOptionValue = ProductOptionValue & ProductOptionValueState;\n\n/**\n * Creates a mapping of product options to their index for matching encoded values\n * For example, a product option of\n * [\n * \\{\n * name: 'Color',\n * optionValues: [\\{name: 'Red'\\}, \\{name: 'Blue'\\}]\n * \\},\n * \\{\n * name: 'Size',\n * optionValues: [\\{name: 'Small'\\}, \\{name: 'Medium'\\}, \\{name: 'Large'\\}]\n * \\}\n * ]\n * Would return\n * [\n * \\{Red: 0, Blue: 1\\},\n * \\{Small: 0, Medium: 1, Large: 2\\}\n * ]\n */\nfunction mapProductOptions(options: ProductOption[]): ProductOptionsMapping[] {\n return options.map((option: ProductOption) => {\n return Object.assign(\n {},\n ...(option?.optionValues\n ? option.optionValues.map((value, index) => {\n return {[value.name]: index};\n })\n : []),\n ) as ProductOptionsMapping;\n });\n}\n\n/**\n * Converts the product option into an Object\\<key, value\\> for building query params\n * For example, a selected product option of\n * [\n * \\{\n * name: 'Color',\n * value: 'Red',\n * \\},\n * \\{\n * name: 'Size',\n * value: 'Medium',\n * \\}\n * ]\n * Would return\n * \\{\n * Color: 'Red',\n * Size: 'Medium',\n * \\}\n */\nexport function mapSelectedProductOptionToObject(\n options: Pick<SelectedOption, 'name' | 'value'>[],\n): Record<string, string> {\n return Object.assign(\n {},\n ...options.map((key) => {\n return {[key.name]: key.value};\n }),\n ) as Record<string, string>;\n}\n\n/**\n * Returns the JSON stringify result of mapSelectedProductOptionToObject\n */\nfunction mapSelectedProductOptionToObjectAsString(\n options: Pick<SelectedOption, 'name' | 'value'>[],\n): string {\n return JSON.stringify(mapSelectedProductOptionToObject(options));\n}\n\n/**\n * Encode the selected product option as a key for mapping to the encoded variants\n * For example, a selected product option of\n * [\n * \\{\n * name: 'Color',\n * value: 'Red',\n * \\},\n * \\{\n * name: 'Size',\n * value: 'Medium',\n * \\}\n * ]\n * Would return\n * [0,1]\n *\n * Also works with the result of mapSelectedProductOption. For example:\n * \\{\n * Color: 'Red',\n * Size: 'Medium',\n * \\}\n * Would return\n * [0,1]\n *\n * @param selectedOption - The selected product option\n * @param productOptionMappings - The result of product option mapping from mapProductOptions\n * @returns\n */\nfunction encodeSelectedProductOptionAsKey(\n selectedOption:\n | Pick<SelectedOption, 'name' | 'value'>[]\n | Record<string, string>,\n productOptionMappings: ProductOptionsMapping[],\n): string {\n if (Array.isArray(selectedOption)) {\n return JSON.stringify(\n selectedOption.map((key, index) => {\n return productOptionMappings[index][key.value];\n }),\n );\n } else {\n return JSON.stringify(\n Object.keys(selectedOption).map((key, index) => {\n return productOptionMappings[index][selectedOption[key]];\n }),\n );\n }\n}\n\n/**\n * Takes an array of product variants and maps them to an object with the encoded selected option values as the key.\n * For example, a product variant of\n * [\n * \\{\n * id: 1,\n * selectedOptions: [\n * \\{name: 'Color', value: 'Red'\\},\n * \\{name: 'Size', value: 'Small'\\},\n * ],\n * \\},\n * \\{\n * id: 2,\n * selectedOptions: [\n * \\{name: 'Color', value: 'Red'\\},\n * \\{name: 'Size', value: 'Medium'\\},\n * ],\n * \\}\n * ]\n * Would return\n * \\{\n * '[0,0]': \\{id: 1, selectedOptions: [\\{name: 'Color', value: 'Red'\\}, \\{name: 'Size', value: 'Small'\\}]\\},\n * '[0,1]': \\{id: 2, selectedOptions: [\\{name: 'Color', value: 'Red'\\}, \\{name: 'Size', value: 'Medium'\\}]\\},\n * \\}\n */\nfunction mapVariants(\n variants: ProductVariant[],\n productOptionMappings: ProductOptionsMapping[],\n): Record<string, ProductVariant> {\n return Object.assign(\n {},\n ...variants.map((variant) => {\n const variantKey = encodeSelectedProductOptionAsKey(\n variant.selectedOptions || [],\n productOptionMappings,\n );\n return {[variantKey]: variant};\n }),\n ) as Record<string, ProductVariant>;\n}\n\nexport type MappedProductOptions = Omit<ProductOption, 'optionValues'> & {\n optionValues: MappedProductOptionValue[];\n};\n\nconst PRODUCT_INPUTS = [\n 'options',\n 'selectedOrFirstAvailableVariant',\n 'adjacentVariants',\n];\n\nconst PRODUCT_INPUTS_EXTRA = [\n 'handle',\n 'encodedVariantExistence',\n 'encodedVariantAvailability',\n];\n\nfunction logErrorAndReturnFalse(key: string): boolean {\n console.error(\n `[h2:error:getProductOptions] product.${key} is missing. Make sure you query for this field from the Storefront API.`,\n );\n return false;\n}\n\nexport function checkProductParam(\n product: RecursivePartial<Product>,\n checkAll = false,\n): Product {\n let validParam = true;\n const productKeys = Object.keys(product);\n\n // Check product input\n (checkAll\n ? [...PRODUCT_INPUTS, ...PRODUCT_INPUTS_EXTRA]\n : PRODUCT_INPUTS\n ).forEach((key) => {\n if (!productKeys.includes(key)) {\n validParam = logErrorAndReturnFalse(key);\n }\n });\n\n // Check for nested options requirements\n if (product.options) {\n const firstOption = product?.options[0];\n\n if (checkAll && !firstOption?.name) {\n validParam = logErrorAndReturnFalse('options.name');\n }\n\n // Check for options.optionValues\n if (product?.options[0]?.optionValues) {\n const firstOptionValues = product.options[0].optionValues[0];\n\n // Check for options.optionValues.name\n if (checkAll && !firstOptionValues?.name) {\n validParam = logErrorAndReturnFalse('options.optionValues.name');\n }\n\n // Check for options.optionValues.firstSelectableVariant\n if (firstOptionValues?.firstSelectableVariant) {\n // check product variant\n validParam = checkProductVariantParam(\n firstOptionValues.firstSelectableVariant,\n 'options.optionValues.firstSelectableVariant',\n validParam,\n checkAll,\n );\n } else {\n validParam = logErrorAndReturnFalse(\n 'options.optionValues.firstSelectableVariant',\n );\n }\n } else {\n validParam = logErrorAndReturnFalse('options.optionValues');\n }\n }\n\n // Check for nested selectedOrFirstAvailableVariant requirements\n if (product.selectedOrFirstAvailableVariant) {\n validParam = checkProductVariantParam(\n product.selectedOrFirstAvailableVariant,\n 'selectedOrFirstAvailableVariant',\n validParam,\n checkAll,\n );\n }\n\n // Check for nested adjacentVariants requirements\n if (!!product.adjacentVariants && product.adjacentVariants[0]) {\n validParam = checkProductVariantParam(\n product.adjacentVariants[0],\n 'adjacentVariants',\n validParam,\n checkAll,\n );\n }\n\n return (validParam ? product : {}) as Product;\n}\n\nfunction checkProductVariantParam(\n variant: RecursivePartial<ProductVariant>,\n key: string,\n currentValidParamState: boolean,\n checkAll: boolean,\n): boolean {\n let validParam = currentValidParamState;\n\n if (checkAll && !variant.product?.handle) {\n validParam = logErrorAndReturnFalse(`${key}.product.handle`);\n }\n if (variant.selectedOptions) {\n const firstSelectedOption = variant.selectedOptions[0];\n if (!firstSelectedOption?.name) {\n validParam = logErrorAndReturnFalse(`${key}.selectedOptions.name`);\n }\n if (!firstSelectedOption?.value) {\n validParam = logErrorAndReturnFalse(`${key}.selectedOptions.value`);\n }\n } else {\n validParam = logErrorAndReturnFalse(`${key}.selectedOptions`);\n }\n\n return validParam;\n}\n\n/**\n * Finds all the variants provided by adjacentVariants, options.optionValues.firstAvailableVariant,\n * and selectedOrFirstAvailableVariant and return them in a single array\n */\nexport function getAdjacentAndFirstAvailableVariants(\n product: RecursivePartial<Product>,\n): ProductVariant[] {\n // Checks for valid product input\n const checkedProduct = checkProductParam(product);\n\n if (!checkedProduct.options) return [];\n\n const availableVariants: Record<string, ProductVariant> = {};\n checkedProduct.options.map((option) => {\n option.optionValues?.map((value) => {\n if (value.firstSelectableVariant) {\n const variantKey = mapSelectedProductOptionToObjectAsString(\n value.firstSelectableVariant.selectedOptions,\n );\n availableVariants[variantKey] = value.firstSelectableVariant;\n }\n });\n });\n\n checkedProduct.adjacentVariants.map((variant) => {\n const variantKey = mapSelectedProductOptionToObjectAsString(\n variant.selectedOptions,\n );\n availableVariants[variantKey] = variant;\n });\n\n const selectedVariant = checkedProduct.selectedOrFirstAvailableVariant;\n if (selectedVariant) {\n const variantKey = mapSelectedProductOptionToObjectAsString(\n selectedVariant.selectedOptions,\n );\n availableVariants[variantKey] = selectedVariant;\n }\n\n return Object.values(availableVariants);\n}\n\n/**\n * Returns a product options array with its relevant information\n * about the variant\n */\nexport function getProductOptions(\n product: RecursivePartial<Product>,\n): MappedProductOptions[] {\n // Checks for valid product input\n const checkedProduct = checkProductParam(product, true);\n\n if (!checkedProduct.options) return [];\n\n const {\n options,\n selectedOrFirstAvailableVariant: selectedVariant,\n adjacentVariants,\n encodedVariantExistence,\n encodedVariantAvailability,\n handle: productHandle,\n } = checkedProduct;\n // Get a mapping of product option names to their index for matching encoded values\n const productOptionMappings = mapProductOptions(options);\n\n // Get the adjacent variants mapped to the encoded selected option values\n const variants = mapVariants(\n selectedVariant ? [selectedVariant, ...adjacentVariants] : adjacentVariants,\n productOptionMappings,\n );\n\n // Get the key:value version of selected options for building url query params\n const selectedOptions = mapSelectedProductOptionToObject(\n selectedVariant ? selectedVariant.selectedOptions : [],\n );\n\n const productOptions = options.map((option, optionIndex) => {\n return {\n ...option,\n optionValues: option.optionValues.map((value) => {\n const targetOptionParams = {...selectedOptions}; // Clones the selected options\n\n // Modify the selected option value to the current option value\n targetOptionParams[option.name] = value.name;\n\n // Encode the new selected option values as a key for mapping to the product variants\n const targetKey = encodeSelectedProductOptionAsKey(\n targetOptionParams || [],\n productOptionMappings,\n );\n\n // Top-down option check for existence and availability\n const topDownKey = (JSON.parse(targetKey) as number[]).slice(\n 0,\n optionIndex + 1,\n );\n const exists = isOptionValueCombinationInEncodedVariant(\n topDownKey,\n encodedVariantExistence || '',\n );\n const available = isOptionValueCombinationInEncodedVariant(\n topDownKey,\n encodedVariantAvailability || '',\n );\n\n // Get the variant for the current option value if exists, else use the first selectable variant\n const variant: ProductVariant =\n variants[targetKey] || value.firstSelectableVariant;\n\n // Build the query params for this option value\n const variantOptionParam = mapSelectedProductOptionToObject(\n variant.selectedOptions || [],\n );\n const searchParams = new URLSearchParams(variantOptionParam);\n const handle = variant?.product?.handle;\n\n return {\n ...value,\n variant,\n handle,\n variantUriQuery: searchParams.toString(),\n selected: selectedOptions[option.name] === value.name,\n exists,\n available,\n isDifferentProduct: handle !== productHandle,\n };\n }),\n };\n });\n\n return productOptions;\n}\n"],"names":["isOptionValueCombinationInEncodedVariant"],"mappings":"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"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { isOptionValueCombinationInEncodedVariant } from "./optionValueDecoder.mjs";
|
|
2
|
+
function mapProductOptions(options) {
|
|
3
|
+
return options.map((option) => {
|
|
4
|
+
return Object.assign(
|
|
5
|
+
{},
|
|
6
|
+
...(option == null ? void 0 : option.optionValues) ? option.optionValues.map((value, index) => {
|
|
7
|
+
return { [value.name]: index };
|
|
8
|
+
}) : []
|
|
9
|
+
);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function mapSelectedProductOptionToObject(options) {
|
|
13
|
+
return Object.assign(
|
|
14
|
+
{},
|
|
15
|
+
...options.map((key) => {
|
|
16
|
+
return { [key.name]: key.value };
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
function mapSelectedProductOptionToObjectAsString(options) {
|
|
21
|
+
return JSON.stringify(mapSelectedProductOptionToObject(options));
|
|
22
|
+
}
|
|
23
|
+
function encodeSelectedProductOptionAsKey(selectedOption, productOptionMappings) {
|
|
24
|
+
if (Array.isArray(selectedOption)) {
|
|
25
|
+
return JSON.stringify(
|
|
26
|
+
selectedOption.map((key, index) => {
|
|
27
|
+
return productOptionMappings[index][key.value];
|
|
28
|
+
})
|
|
29
|
+
);
|
|
30
|
+
} else {
|
|
31
|
+
return JSON.stringify(
|
|
32
|
+
Object.keys(selectedOption).map((key, index) => {
|
|
33
|
+
return productOptionMappings[index][selectedOption[key]];
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function mapVariants(variants, productOptionMappings) {
|
|
39
|
+
return Object.assign(
|
|
40
|
+
{},
|
|
41
|
+
...variants.map((variant) => {
|
|
42
|
+
const variantKey = encodeSelectedProductOptionAsKey(
|
|
43
|
+
variant.selectedOptions || [],
|
|
44
|
+
productOptionMappings
|
|
45
|
+
);
|
|
46
|
+
return { [variantKey]: variant };
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
const PRODUCT_INPUTS = [
|
|
51
|
+
"options",
|
|
52
|
+
"selectedOrFirstAvailableVariant",
|
|
53
|
+
"adjacentVariants"
|
|
54
|
+
];
|
|
55
|
+
const PRODUCT_INPUTS_EXTRA = [
|
|
56
|
+
"handle",
|
|
57
|
+
"encodedVariantExistence",
|
|
58
|
+
"encodedVariantAvailability"
|
|
59
|
+
];
|
|
60
|
+
function logErrorAndReturnFalse(key) {
|
|
61
|
+
console.error(
|
|
62
|
+
`[h2:error:getProductOptions] product.${key} is missing. Make sure you query for this field from the Storefront API.`
|
|
63
|
+
);
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
function checkProductParam(product, checkAll = false) {
|
|
67
|
+
var _a;
|
|
68
|
+
let validParam = true;
|
|
69
|
+
const productKeys = Object.keys(product);
|
|
70
|
+
(checkAll ? [...PRODUCT_INPUTS, ...PRODUCT_INPUTS_EXTRA] : PRODUCT_INPUTS).forEach((key) => {
|
|
71
|
+
if (!productKeys.includes(key)) {
|
|
72
|
+
validParam = logErrorAndReturnFalse(key);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
if (product.options) {
|
|
76
|
+
const firstOption = product == null ? void 0 : product.options[0];
|
|
77
|
+
if (checkAll && !(firstOption == null ? void 0 : firstOption.name)) {
|
|
78
|
+
validParam = logErrorAndReturnFalse("options.name");
|
|
79
|
+
}
|
|
80
|
+
if ((_a = product == null ? void 0 : product.options[0]) == null ? void 0 : _a.optionValues) {
|
|
81
|
+
const firstOptionValues = product.options[0].optionValues[0];
|
|
82
|
+
if (checkAll && !(firstOptionValues == null ? void 0 : firstOptionValues.name)) {
|
|
83
|
+
validParam = logErrorAndReturnFalse("options.optionValues.name");
|
|
84
|
+
}
|
|
85
|
+
if (firstOptionValues == null ? void 0 : firstOptionValues.firstSelectableVariant) {
|
|
86
|
+
validParam = checkProductVariantParam(
|
|
87
|
+
firstOptionValues.firstSelectableVariant,
|
|
88
|
+
"options.optionValues.firstSelectableVariant",
|
|
89
|
+
validParam,
|
|
90
|
+
checkAll
|
|
91
|
+
);
|
|
92
|
+
} else {
|
|
93
|
+
validParam = logErrorAndReturnFalse(
|
|
94
|
+
"options.optionValues.firstSelectableVariant"
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
validParam = logErrorAndReturnFalse("options.optionValues");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (product.selectedOrFirstAvailableVariant) {
|
|
102
|
+
validParam = checkProductVariantParam(
|
|
103
|
+
product.selectedOrFirstAvailableVariant,
|
|
104
|
+
"selectedOrFirstAvailableVariant",
|
|
105
|
+
validParam,
|
|
106
|
+
checkAll
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
if (!!product.adjacentVariants && product.adjacentVariants[0]) {
|
|
110
|
+
validParam = checkProductVariantParam(
|
|
111
|
+
product.adjacentVariants[0],
|
|
112
|
+
"adjacentVariants",
|
|
113
|
+
validParam,
|
|
114
|
+
checkAll
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
return validParam ? product : {};
|
|
118
|
+
}
|
|
119
|
+
function checkProductVariantParam(variant, key, currentValidParamState, checkAll) {
|
|
120
|
+
var _a;
|
|
121
|
+
let validParam = currentValidParamState;
|
|
122
|
+
if (checkAll && !((_a = variant.product) == null ? void 0 : _a.handle)) {
|
|
123
|
+
validParam = logErrorAndReturnFalse(`${key}.product.handle`);
|
|
124
|
+
}
|
|
125
|
+
if (variant.selectedOptions) {
|
|
126
|
+
const firstSelectedOption = variant.selectedOptions[0];
|
|
127
|
+
if (!(firstSelectedOption == null ? void 0 : firstSelectedOption.name)) {
|
|
128
|
+
validParam = logErrorAndReturnFalse(`${key}.selectedOptions.name`);
|
|
129
|
+
}
|
|
130
|
+
if (!(firstSelectedOption == null ? void 0 : firstSelectedOption.value)) {
|
|
131
|
+
validParam = logErrorAndReturnFalse(`${key}.selectedOptions.value`);
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
validParam = logErrorAndReturnFalse(`${key}.selectedOptions`);
|
|
135
|
+
}
|
|
136
|
+
return validParam;
|
|
137
|
+
}
|
|
138
|
+
function getAdjacentAndFirstAvailableVariants(product) {
|
|
139
|
+
const checkedProduct = checkProductParam(product);
|
|
140
|
+
if (!checkedProduct.options)
|
|
141
|
+
return [];
|
|
142
|
+
const availableVariants = {};
|
|
143
|
+
checkedProduct.options.map((option) => {
|
|
144
|
+
var _a;
|
|
145
|
+
(_a = option.optionValues) == null ? void 0 : _a.map((value) => {
|
|
146
|
+
if (value.firstSelectableVariant) {
|
|
147
|
+
const variantKey = mapSelectedProductOptionToObjectAsString(
|
|
148
|
+
value.firstSelectableVariant.selectedOptions
|
|
149
|
+
);
|
|
150
|
+
availableVariants[variantKey] = value.firstSelectableVariant;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
checkedProduct.adjacentVariants.map((variant) => {
|
|
155
|
+
const variantKey = mapSelectedProductOptionToObjectAsString(
|
|
156
|
+
variant.selectedOptions
|
|
157
|
+
);
|
|
158
|
+
availableVariants[variantKey] = variant;
|
|
159
|
+
});
|
|
160
|
+
const selectedVariant = checkedProduct.selectedOrFirstAvailableVariant;
|
|
161
|
+
if (selectedVariant) {
|
|
162
|
+
const variantKey = mapSelectedProductOptionToObjectAsString(
|
|
163
|
+
selectedVariant.selectedOptions
|
|
164
|
+
);
|
|
165
|
+
availableVariants[variantKey] = selectedVariant;
|
|
166
|
+
}
|
|
167
|
+
return Object.values(availableVariants);
|
|
168
|
+
}
|
|
169
|
+
function getProductOptions(product) {
|
|
170
|
+
const checkedProduct = checkProductParam(product, true);
|
|
171
|
+
if (!checkedProduct.options)
|
|
172
|
+
return [];
|
|
173
|
+
const {
|
|
174
|
+
options,
|
|
175
|
+
selectedOrFirstAvailableVariant: selectedVariant,
|
|
176
|
+
adjacentVariants,
|
|
177
|
+
encodedVariantExistence,
|
|
178
|
+
encodedVariantAvailability,
|
|
179
|
+
handle: productHandle
|
|
180
|
+
} = checkedProduct;
|
|
181
|
+
const productOptionMappings = mapProductOptions(options);
|
|
182
|
+
const variants = mapVariants(
|
|
183
|
+
selectedVariant ? [selectedVariant, ...adjacentVariants] : adjacentVariants,
|
|
184
|
+
productOptionMappings
|
|
185
|
+
);
|
|
186
|
+
const selectedOptions = mapSelectedProductOptionToObject(
|
|
187
|
+
selectedVariant ? selectedVariant.selectedOptions : []
|
|
188
|
+
);
|
|
189
|
+
const productOptions = options.map((option, optionIndex) => {
|
|
190
|
+
return {
|
|
191
|
+
...option,
|
|
192
|
+
optionValues: option.optionValues.map((value) => {
|
|
193
|
+
var _a;
|
|
194
|
+
const targetOptionParams = { ...selectedOptions };
|
|
195
|
+
targetOptionParams[option.name] = value.name;
|
|
196
|
+
const targetKey = encodeSelectedProductOptionAsKey(
|
|
197
|
+
targetOptionParams || [],
|
|
198
|
+
productOptionMappings
|
|
199
|
+
);
|
|
200
|
+
const topDownKey = JSON.parse(targetKey).slice(
|
|
201
|
+
0,
|
|
202
|
+
optionIndex + 1
|
|
203
|
+
);
|
|
204
|
+
const exists = isOptionValueCombinationInEncodedVariant(
|
|
205
|
+
topDownKey,
|
|
206
|
+
encodedVariantExistence || ""
|
|
207
|
+
);
|
|
208
|
+
const available = isOptionValueCombinationInEncodedVariant(
|
|
209
|
+
topDownKey,
|
|
210
|
+
encodedVariantAvailability || ""
|
|
211
|
+
);
|
|
212
|
+
const variant = variants[targetKey] || value.firstSelectableVariant;
|
|
213
|
+
const variantOptionParam = mapSelectedProductOptionToObject(
|
|
214
|
+
variant.selectedOptions || []
|
|
215
|
+
);
|
|
216
|
+
const searchParams = new URLSearchParams(variantOptionParam);
|
|
217
|
+
const handle = (_a = variant == null ? void 0 : variant.product) == null ? void 0 : _a.handle;
|
|
218
|
+
return {
|
|
219
|
+
...value,
|
|
220
|
+
variant,
|
|
221
|
+
handle,
|
|
222
|
+
variantUriQuery: searchParams.toString(),
|
|
223
|
+
selected: selectedOptions[option.name] === value.name,
|
|
224
|
+
exists,
|
|
225
|
+
available,
|
|
226
|
+
isDifferentProduct: handle !== productHandle
|
|
227
|
+
};
|
|
228
|
+
})
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
return productOptions;
|
|
232
|
+
}
|
|
233
|
+
export {
|
|
234
|
+
checkProductParam,
|
|
235
|
+
getAdjacentAndFirstAvailableVariants,
|
|
236
|
+
getProductOptions,
|
|
237
|
+
mapSelectedProductOptionToObject
|
|
238
|
+
};
|
|
239
|
+
//# sourceMappingURL=getProductOptions.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getProductOptions.mjs","sources":["../../src/getProductOptions.ts"],"sourcesContent":["import {isOptionValueCombinationInEncodedVariant} from './optionValueDecoder.js';\nimport type {\n Product,\n ProductOption,\n ProductOptionValue,\n ProductVariant,\n SelectedOption,\n} from './storefront-api-types';\n\nexport type RecursivePartial<T> = {\n [P in keyof T]?: RecursivePartial<T[P]>;\n};\ntype ProductOptionsMapping = Record<string, number>;\ntype ProductOptionValueState = {\n variant: ProductVariant;\n handle: string;\n variantUriQuery: string;\n selected: boolean;\n exists: boolean;\n available: boolean;\n isDifferentProduct: boolean;\n};\ntype MappedProductOptionValue = ProductOptionValue & ProductOptionValueState;\n\n/**\n * Creates a mapping of product options to their index for matching encoded values\n * For example, a product option of\n * [\n * \\{\n * name: 'Color',\n * optionValues: [\\{name: 'Red'\\}, \\{name: 'Blue'\\}]\n * \\},\n * \\{\n * name: 'Size',\n * optionValues: [\\{name: 'Small'\\}, \\{name: 'Medium'\\}, \\{name: 'Large'\\}]\n * \\}\n * ]\n * Would return\n * [\n * \\{Red: 0, Blue: 1\\},\n * \\{Small: 0, Medium: 1, Large: 2\\}\n * ]\n */\nfunction mapProductOptions(options: ProductOption[]): ProductOptionsMapping[] {\n return options.map((option: ProductOption) => {\n return Object.assign(\n {},\n ...(option?.optionValues\n ? option.optionValues.map((value, index) => {\n return {[value.name]: index};\n })\n : []),\n ) as ProductOptionsMapping;\n });\n}\n\n/**\n * Converts the product option into an Object\\<key, value\\> for building query params\n * For example, a selected product option of\n * [\n * \\{\n * name: 'Color',\n * value: 'Red',\n * \\},\n * \\{\n * name: 'Size',\n * value: 'Medium',\n * \\}\n * ]\n * Would return\n * \\{\n * Color: 'Red',\n * Size: 'Medium',\n * \\}\n */\nexport function mapSelectedProductOptionToObject(\n options: Pick<SelectedOption, 'name' | 'value'>[],\n): Record<string, string> {\n return Object.assign(\n {},\n ...options.map((key) => {\n return {[key.name]: key.value};\n }),\n ) as Record<string, string>;\n}\n\n/**\n * Returns the JSON stringify result of mapSelectedProductOptionToObject\n */\nfunction mapSelectedProductOptionToObjectAsString(\n options: Pick<SelectedOption, 'name' | 'value'>[],\n): string {\n return JSON.stringify(mapSelectedProductOptionToObject(options));\n}\n\n/**\n * Encode the selected product option as a key for mapping to the encoded variants\n * For example, a selected product option of\n * [\n * \\{\n * name: 'Color',\n * value: 'Red',\n * \\},\n * \\{\n * name: 'Size',\n * value: 'Medium',\n * \\}\n * ]\n * Would return\n * [0,1]\n *\n * Also works with the result of mapSelectedProductOption. For example:\n * \\{\n * Color: 'Red',\n * Size: 'Medium',\n * \\}\n * Would return\n * [0,1]\n *\n * @param selectedOption - The selected product option\n * @param productOptionMappings - The result of product option mapping from mapProductOptions\n * @returns\n */\nfunction encodeSelectedProductOptionAsKey(\n selectedOption:\n | Pick<SelectedOption, 'name' | 'value'>[]\n | Record<string, string>,\n productOptionMappings: ProductOptionsMapping[],\n): string {\n if (Array.isArray(selectedOption)) {\n return JSON.stringify(\n selectedOption.map((key, index) => {\n return productOptionMappings[index][key.value];\n }),\n );\n } else {\n return JSON.stringify(\n Object.keys(selectedOption).map((key, index) => {\n return productOptionMappings[index][selectedOption[key]];\n }),\n );\n }\n}\n\n/**\n * Takes an array of product variants and maps them to an object with the encoded selected option values as the key.\n * For example, a product variant of\n * [\n * \\{\n * id: 1,\n * selectedOptions: [\n * \\{name: 'Color', value: 'Red'\\},\n * \\{name: 'Size', value: 'Small'\\},\n * ],\n * \\},\n * \\{\n * id: 2,\n * selectedOptions: [\n * \\{name: 'Color', value: 'Red'\\},\n * \\{name: 'Size', value: 'Medium'\\},\n * ],\n * \\}\n * ]\n * Would return\n * \\{\n * '[0,0]': \\{id: 1, selectedOptions: [\\{name: 'Color', value: 'Red'\\}, \\{name: 'Size', value: 'Small'\\}]\\},\n * '[0,1]': \\{id: 2, selectedOptions: [\\{name: 'Color', value: 'Red'\\}, \\{name: 'Size', value: 'Medium'\\}]\\},\n * \\}\n */\nfunction mapVariants(\n variants: ProductVariant[],\n productOptionMappings: ProductOptionsMapping[],\n): Record<string, ProductVariant> {\n return Object.assign(\n {},\n ...variants.map((variant) => {\n const variantKey = encodeSelectedProductOptionAsKey(\n variant.selectedOptions || [],\n productOptionMappings,\n );\n return {[variantKey]: variant};\n }),\n ) as Record<string, ProductVariant>;\n}\n\nexport type MappedProductOptions = Omit<ProductOption, 'optionValues'> & {\n optionValues: MappedProductOptionValue[];\n};\n\nconst PRODUCT_INPUTS = [\n 'options',\n 'selectedOrFirstAvailableVariant',\n 'adjacentVariants',\n];\n\nconst PRODUCT_INPUTS_EXTRA = [\n 'handle',\n 'encodedVariantExistence',\n 'encodedVariantAvailability',\n];\n\nfunction logErrorAndReturnFalse(key: string): boolean {\n console.error(\n `[h2:error:getProductOptions] product.${key} is missing. Make sure you query for this field from the Storefront API.`,\n );\n return false;\n}\n\nexport function checkProductParam(\n product: RecursivePartial<Product>,\n checkAll = false,\n): Product {\n let validParam = true;\n const productKeys = Object.keys(product);\n\n // Check product input\n (checkAll\n ? [...PRODUCT_INPUTS, ...PRODUCT_INPUTS_EXTRA]\n : PRODUCT_INPUTS\n ).forEach((key) => {\n if (!productKeys.includes(key)) {\n validParam = logErrorAndReturnFalse(key);\n }\n });\n\n // Check for nested options requirements\n if (product.options) {\n const firstOption = product?.options[0];\n\n if (checkAll && !firstOption?.name) {\n validParam = logErrorAndReturnFalse('options.name');\n }\n\n // Check for options.optionValues\n if (product?.options[0]?.optionValues) {\n const firstOptionValues = product.options[0].optionValues[0];\n\n // Check for options.optionValues.name\n if (checkAll && !firstOptionValues?.name) {\n validParam = logErrorAndReturnFalse('options.optionValues.name');\n }\n\n // Check for options.optionValues.firstSelectableVariant\n if (firstOptionValues?.firstSelectableVariant) {\n // check product variant\n validParam = checkProductVariantParam(\n firstOptionValues.firstSelectableVariant,\n 'options.optionValues.firstSelectableVariant',\n validParam,\n checkAll,\n );\n } else {\n validParam = logErrorAndReturnFalse(\n 'options.optionValues.firstSelectableVariant',\n );\n }\n } else {\n validParam = logErrorAndReturnFalse('options.optionValues');\n }\n }\n\n // Check for nested selectedOrFirstAvailableVariant requirements\n if (product.selectedOrFirstAvailableVariant) {\n validParam = checkProductVariantParam(\n product.selectedOrFirstAvailableVariant,\n 'selectedOrFirstAvailableVariant',\n validParam,\n checkAll,\n );\n }\n\n // Check for nested adjacentVariants requirements\n if (!!product.adjacentVariants && product.adjacentVariants[0]) {\n validParam = checkProductVariantParam(\n product.adjacentVariants[0],\n 'adjacentVariants',\n validParam,\n checkAll,\n );\n }\n\n return (validParam ? product : {}) as Product;\n}\n\nfunction checkProductVariantParam(\n variant: RecursivePartial<ProductVariant>,\n key: string,\n currentValidParamState: boolean,\n checkAll: boolean,\n): boolean {\n let validParam = currentValidParamState;\n\n if (checkAll && !variant.product?.handle) {\n validParam = logErrorAndReturnFalse(`${key}.product.handle`);\n }\n if (variant.selectedOptions) {\n const firstSelectedOption = variant.selectedOptions[0];\n if (!firstSelectedOption?.name) {\n validParam = logErrorAndReturnFalse(`${key}.selectedOptions.name`);\n }\n if (!firstSelectedOption?.value) {\n validParam = logErrorAndReturnFalse(`${key}.selectedOptions.value`);\n }\n } else {\n validParam = logErrorAndReturnFalse(`${key}.selectedOptions`);\n }\n\n return validParam;\n}\n\n/**\n * Finds all the variants provided by adjacentVariants, options.optionValues.firstAvailableVariant,\n * and selectedOrFirstAvailableVariant and return them in a single array\n */\nexport function getAdjacentAndFirstAvailableVariants(\n product: RecursivePartial<Product>,\n): ProductVariant[] {\n // Checks for valid product input\n const checkedProduct = checkProductParam(product);\n\n if (!checkedProduct.options) return [];\n\n const availableVariants: Record<string, ProductVariant> = {};\n checkedProduct.options.map((option) => {\n option.optionValues?.map((value) => {\n if (value.firstSelectableVariant) {\n const variantKey = mapSelectedProductOptionToObjectAsString(\n value.firstSelectableVariant.selectedOptions,\n );\n availableVariants[variantKey] = value.firstSelectableVariant;\n }\n });\n });\n\n checkedProduct.adjacentVariants.map((variant) => {\n const variantKey = mapSelectedProductOptionToObjectAsString(\n variant.selectedOptions,\n );\n availableVariants[variantKey] = variant;\n });\n\n const selectedVariant = checkedProduct.selectedOrFirstAvailableVariant;\n if (selectedVariant) {\n const variantKey = mapSelectedProductOptionToObjectAsString(\n selectedVariant.selectedOptions,\n );\n availableVariants[variantKey] = selectedVariant;\n }\n\n return Object.values(availableVariants);\n}\n\n/**\n * Returns a product options array with its relevant information\n * about the variant\n */\nexport function getProductOptions(\n product: RecursivePartial<Product>,\n): MappedProductOptions[] {\n // Checks for valid product input\n const checkedProduct = checkProductParam(product, true);\n\n if (!checkedProduct.options) return [];\n\n const {\n options,\n selectedOrFirstAvailableVariant: selectedVariant,\n adjacentVariants,\n encodedVariantExistence,\n encodedVariantAvailability,\n handle: productHandle,\n } = checkedProduct;\n // Get a mapping of product option names to their index for matching encoded values\n const productOptionMappings = mapProductOptions(options);\n\n // Get the adjacent variants mapped to the encoded selected option values\n const variants = mapVariants(\n selectedVariant ? [selectedVariant, ...adjacentVariants] : adjacentVariants,\n productOptionMappings,\n );\n\n // Get the key:value version of selected options for building url query params\n const selectedOptions = mapSelectedProductOptionToObject(\n selectedVariant ? selectedVariant.selectedOptions : [],\n );\n\n const productOptions = options.map((option, optionIndex) => {\n return {\n ...option,\n optionValues: option.optionValues.map((value) => {\n const targetOptionParams = {...selectedOptions}; // Clones the selected options\n\n // Modify the selected option value to the current option value\n targetOptionParams[option.name] = value.name;\n\n // Encode the new selected option values as a key for mapping to the product variants\n const targetKey = encodeSelectedProductOptionAsKey(\n targetOptionParams || [],\n productOptionMappings,\n );\n\n // Top-down option check for existence and availability\n const topDownKey = (JSON.parse(targetKey) as number[]).slice(\n 0,\n optionIndex + 1,\n );\n const exists = isOptionValueCombinationInEncodedVariant(\n topDownKey,\n encodedVariantExistence || '',\n );\n const available = isOptionValueCombinationInEncodedVariant(\n topDownKey,\n encodedVariantAvailability || '',\n );\n\n // Get the variant for the current option value if exists, else use the first selectable variant\n const variant: ProductVariant =\n variants[targetKey] || value.firstSelectableVariant;\n\n // Build the query params for this option value\n const variantOptionParam = mapSelectedProductOptionToObject(\n variant.selectedOptions || [],\n );\n const searchParams = new URLSearchParams(variantOptionParam);\n const handle = variant?.product?.handle;\n\n return {\n ...value,\n variant,\n handle,\n variantUriQuery: searchParams.toString(),\n selected: selectedOptions[option.name] === value.name,\n exists,\n available,\n isDifferentProduct: handle !== productHandle,\n };\n }),\n };\n });\n\n return productOptions;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/node-prod/index.js
CHANGED
|
@@ -16,11 +16,13 @@ const codegen_helpers = require("./codegen.helpers.js");
|
|
|
16
16
|
const cookiesUtils = require("./cookies-utils.js");
|
|
17
17
|
const ExternalVideo = require("./ExternalVideo.js");
|
|
18
18
|
const flattenConnection = require("./flatten-connection.js");
|
|
19
|
+
const getProductOptions = require("./getProductOptions.js");
|
|
19
20
|
const Image = require("./Image.js");
|
|
20
21
|
const loadScript = require("./load-script.js");
|
|
21
22
|
const MediaFile = require("./MediaFile.js");
|
|
22
23
|
const ModelViewer = require("./ModelViewer.js");
|
|
23
24
|
const Money = require("./Money.js");
|
|
25
|
+
const optionValueDecoder = require("./optionValueDecoder.js");
|
|
24
26
|
const parseMetafield = require("./parse-metafield.js");
|
|
25
27
|
const ProductPrice = require("./ProductPrice.js");
|
|
26
28
|
const ProductProvider = require("./ProductProvider.js");
|
|
@@ -29,6 +31,7 @@ const ShopifyProvider = require("./ShopifyProvider.js");
|
|
|
29
31
|
const ShopPayButton = require("./ShopPayButton.js");
|
|
30
32
|
const storefrontClient = require("./storefront-client.js");
|
|
31
33
|
const useMoney = require("./useMoney.js");
|
|
34
|
+
const useSelectedOptionInUrlParam = require("./useSelectedOptionInUrlParam.js");
|
|
32
35
|
const useShopifyCookies = require("./useShopifyCookies.js");
|
|
33
36
|
const Video = require("./Video.js");
|
|
34
37
|
exports.AddToCartButton = AddToCartButton.AddToCartButton;
|
|
@@ -57,12 +60,17 @@ exports.storefrontApiCustomScalars = codegen_helpers.storefrontApiCustomScalars;
|
|
|
57
60
|
exports.getShopifyCookies = cookiesUtils.getShopifyCookies;
|
|
58
61
|
exports.ExternalVideo = ExternalVideo.ExternalVideo;
|
|
59
62
|
exports.flattenConnection = flattenConnection.flattenConnection;
|
|
63
|
+
exports.getAdjacentAndFirstAvailableVariants = getProductOptions.getAdjacentAndFirstAvailableVariants;
|
|
64
|
+
exports.getProductOptions = getProductOptions.getProductOptions;
|
|
65
|
+
exports.mapSelectedProductOptionToObject = getProductOptions.mapSelectedProductOptionToObject;
|
|
60
66
|
exports.IMAGE_FRAGMENT = Image.IMAGE_FRAGMENT;
|
|
61
67
|
exports.Image = Image.Image;
|
|
62
68
|
exports.useLoadScript = loadScript.useLoadScript;
|
|
63
69
|
exports.MediaFile = MediaFile.MediaFile;
|
|
64
70
|
exports.ModelViewer = ModelViewer.ModelViewer;
|
|
65
71
|
exports.Money = Money.Money;
|
|
72
|
+
exports.decodeEncodedVariant = optionValueDecoder.decodeEncodedVariant;
|
|
73
|
+
exports.isOptionValueCombinationInEncodedVariant = optionValueDecoder.isOptionValueCombinationInEncodedVariant;
|
|
66
74
|
exports.parseMetafield = parseMetafield.parseMetafield;
|
|
67
75
|
exports.ProductPrice = ProductPrice.ProductPrice;
|
|
68
76
|
exports.ProductProvider = ProductProvider.ProductProvider;
|
|
@@ -73,6 +81,7 @@ exports.useShop = ShopifyProvider.useShop;
|
|
|
73
81
|
exports.ShopPayButton = ShopPayButton.ShopPayButton;
|
|
74
82
|
exports.createStorefrontClient = storefrontClient.createStorefrontClient;
|
|
75
83
|
exports.useMoney = useMoney.useMoney;
|
|
84
|
+
exports.useSelectedOptionInUrlParam = useSelectedOptionInUrlParam.useSelectedOptionInUrlParam;
|
|
76
85
|
exports.useShopifyCookies = useShopifyCookies.useShopifyCookies;
|
|
77
86
|
exports.Video = Video.Video;
|
|
78
87
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/node-prod/index.mjs
CHANGED
|
@@ -14,11 +14,13 @@ import { customerAccountApiCustomScalars, storefrontApiCustomScalars } from "./c
|
|
|
14
14
|
import { getShopifyCookies } from "./cookies-utils.mjs";
|
|
15
15
|
import { ExternalVideo } from "./ExternalVideo.mjs";
|
|
16
16
|
import { flattenConnection } from "./flatten-connection.mjs";
|
|
17
|
+
import { getAdjacentAndFirstAvailableVariants, getProductOptions, mapSelectedProductOptionToObject } from "./getProductOptions.mjs";
|
|
17
18
|
import { IMAGE_FRAGMENT, Image } from "./Image.mjs";
|
|
18
19
|
import { useLoadScript } from "./load-script.mjs";
|
|
19
20
|
import { MediaFile } from "./MediaFile.mjs";
|
|
20
21
|
import { ModelViewer } from "./ModelViewer.mjs";
|
|
21
22
|
import { Money } from "./Money.mjs";
|
|
23
|
+
import { decodeEncodedVariant, isOptionValueCombinationInEncodedVariant } from "./optionValueDecoder.mjs";
|
|
22
24
|
import { parseMetafield } from "./parse-metafield.mjs";
|
|
23
25
|
import { ProductPrice } from "./ProductPrice.mjs";
|
|
24
26
|
import { ProductProvider, useProduct } from "./ProductProvider.mjs";
|
|
@@ -27,6 +29,7 @@ import { ShopifyProvider, useShop } from "./ShopifyProvider.mjs";
|
|
|
27
29
|
import { ShopPayButton } from "./ShopPayButton.mjs";
|
|
28
30
|
import { createStorefrontClient } from "./storefront-client.mjs";
|
|
29
31
|
import { useMoney } from "./useMoney.mjs";
|
|
32
|
+
import { useSelectedOptionInUrlParam } from "./useSelectedOptionInUrlParam.mjs";
|
|
30
33
|
import { useShopifyCookies } from "./useShopifyCookies.mjs";
|
|
31
34
|
import { Video } from "./Video.mjs";
|
|
32
35
|
export {
|
|
@@ -60,9 +63,14 @@ export {
|
|
|
60
63
|
Video,
|
|
61
64
|
createStorefrontClient,
|
|
62
65
|
customerAccountApiCustomScalars,
|
|
66
|
+
decodeEncodedVariant,
|
|
63
67
|
flattenConnection,
|
|
68
|
+
getAdjacentAndFirstAvailableVariants,
|
|
64
69
|
getClientBrowserParameters,
|
|
70
|
+
getProductOptions,
|
|
65
71
|
getShopifyCookies,
|
|
72
|
+
isOptionValueCombinationInEncodedVariant,
|
|
73
|
+
mapSelectedProductOptionToObject,
|
|
66
74
|
parseGid,
|
|
67
75
|
parseMetafield,
|
|
68
76
|
sendShopifyAnalytics,
|
|
@@ -72,6 +80,7 @@ export {
|
|
|
72
80
|
useLoadScript,
|
|
73
81
|
useMoney,
|
|
74
82
|
useProduct,
|
|
83
|
+
useSelectedOptionInUrlParam,
|
|
75
84
|
useShop,
|
|
76
85
|
useShopifyCookies
|
|
77
86
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|