@nuskin/ns-product-lib 2.2.0-cx24-2467.2 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +3 -9
- package/package.json +2 -2
- package/src/contentstack/contentstack.js +35 -3
- package/src/productData.js +21 -147
package/CHANGELOG.md
CHANGED
@@ -1,16 +1,10 @@
|
|
1
|
-
# [2.2.0
|
1
|
+
# [2.2.0](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.1.0...v2.2.0) (2022-10-13)
|
2
2
|
|
3
3
|
|
4
4
|
### Update
|
5
5
|
|
6
|
-
*
|
7
|
-
|
8
|
-
# [2.2.0-cx24-2467.1](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.1.0...v2.2.0-cx24-2467.1) (2022-10-11)
|
9
|
-
|
10
|
-
|
11
|
-
### New
|
12
|
-
|
13
|
-
* add variants (#CX24-2467) ([04b0632](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/04b0632d3f10758852f815cf2d06dd1f04aa7188)), closes [#CX24-2467](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX24-2467)
|
6
|
+
* Get Kong URL from contentstack (CX24-2447) ([272b35a](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/272b35a63908267e3c004ef43cbc2ecf0452a907))
|
7
|
+
* redirect to equinox sign-in if the market is equinox-enabled (CX24-2092) ([ffff6e2](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/ffff6e21c0c6e72e0e3e42583dd443d7a0227bea))
|
14
8
|
|
15
9
|
# [2.1.0](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.0.1...v2.1.0) (2022-10-04)
|
16
10
|
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@nuskin/ns-product-lib",
|
3
|
-
"version": "2.2.0
|
3
|
+
"version": "2.2.0",
|
4
4
|
"description": "This project contains shared Product models and code between the backend and frontend.",
|
5
5
|
"main": "src/index.js",
|
6
6
|
"scripts": {
|
@@ -29,7 +29,7 @@
|
|
29
29
|
"prettier": "1.19.1"
|
30
30
|
},
|
31
31
|
"dependencies": {
|
32
|
-
"@nuskin/ns-common-lib": "1.
|
32
|
+
"@nuskin/ns-common-lib": "1.4.5",
|
33
33
|
"@nuskin/ns-util": "3.107.0",
|
34
34
|
"axios": "0.27.2",
|
35
35
|
"qs": "6.11.0"
|
@@ -14,11 +14,12 @@ const headers = {
|
|
14
14
|
const http = axios.create({ baseURL, headers });
|
15
15
|
|
16
16
|
// in-memory caching
|
17
|
-
const cacheKeys = { aemConfig: 'aemConfig', equinoxMarkets: 'equinoxMarkets' };
|
17
|
+
const cacheKeys = { aemConfig: 'aemConfig', equinoxMarkets: 'equinoxMarkets', kongUrl: 'kongUrl' };
|
18
18
|
const cacheTTLInSeconds = 30 * 1000;
|
19
19
|
const cache = {
|
20
20
|
[cacheKeys.aemConfig]: { data: null, ttl: Date.now() + cacheTTLInSeconds },
|
21
|
-
[cacheKeys.equinoxMarkets]: { data: null, ttl: Date.now() + cacheTTLInSeconds }
|
21
|
+
[cacheKeys.equinoxMarkets]: { data: null, ttl: Date.now() + cacheTTLInSeconds },
|
22
|
+
[cacheKeys.kongUrl]: { data: null, ttl: Date.now() + cacheTTLInSeconds}
|
22
23
|
};
|
23
24
|
|
24
25
|
/**
|
@@ -139,6 +140,36 @@ async function getEquinoxMarkets() {
|
|
139
140
|
}
|
140
141
|
}
|
141
142
|
|
143
|
+
/**getKongUrl gets the URL for Kong in contentstack
|
144
|
+
*
|
145
|
+
* @returns {string}
|
146
|
+
*/
|
147
|
+
async function getKongUrl() {
|
148
|
+
try {
|
149
|
+
if (isCacheExpired(cacheKeys.kongUrl)) {
|
150
|
+
const variables = { uid: 'blt5633ff9e560f14ef' };
|
151
|
+
const query = `query KongUrlByUid($uid: String!) {
|
152
|
+
equinox_markets(uid: $uid) {
|
153
|
+
kong_urls {
|
154
|
+
${env}
|
155
|
+
}
|
156
|
+
}
|
157
|
+
}`;
|
158
|
+
|
159
|
+
const { data } = await contentstackService({
|
160
|
+
data: { variables, query }
|
161
|
+
});
|
162
|
+
|
163
|
+
setCachedData(cacheKeys.kongUrl, data.equinox_markets.kong_urls[env]);
|
164
|
+
}
|
165
|
+
|
166
|
+
return getCachedData(cacheKeys.kongUrl);
|
167
|
+
} catch (error) {
|
168
|
+
console.error(error);
|
169
|
+
return [];
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
142
173
|
/**
|
143
174
|
* isMarketEnabled checks is the given market is in the list
|
144
175
|
* of equinox-enabled markets.
|
@@ -177,5 +208,6 @@ async function contentstackService(config) {
|
|
177
208
|
module.exports = {
|
178
209
|
getAEMConfig,
|
179
210
|
getEquinoxMarkets,
|
180
|
-
isMarketEnabled
|
211
|
+
isMarketEnabled,
|
212
|
+
getKongUrl
|
181
213
|
}
|
package/src/productData.js
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
"use strict";
|
2
2
|
const axios = require("axios");
|
3
3
|
const contentstack = require('./contentstack/contentstack');
|
4
|
-
const
|
4
|
+
const product = require("./product");
|
5
5
|
|
6
6
|
/** @type {*} */
|
7
7
|
const ProductData = {
|
8
8
|
/**
|
9
|
-
* @param {string[]} skus
|
10
|
-
* @param {string} locale
|
11
|
-
* @param {string} market
|
12
|
-
* @param {boolean} isEquinoxEnabled
|
9
|
+
* @param {string[]} skus
|
10
|
+
* @param {string} locale
|
11
|
+
* @param {string} market
|
12
|
+
* @param {boolean} isEquinoxEnabled
|
13
13
|
*/
|
14
14
|
getProductData: async function (skus, locale, market, isEquinoxEnabled = false) {
|
15
15
|
const localeMarket = `${locale}_${market}`;
|
@@ -28,7 +28,9 @@ const ProductData = {
|
|
28
28
|
getProductFromEquinox: async function (skus, locale, storeID) {
|
29
29
|
const filter = '{"filters":[{"field":"index_key_skuId","operation":"IN","value":"' + skus.toString() + '"}]}';
|
30
30
|
axios.defaults.withCredentials = true;
|
31
|
-
|
31
|
+
|
32
|
+
const url = await contentstack.getKongUrl() + `/orchestrationservices/storefront/catalogs/search/`;
|
33
|
+
console.log("Dynamic URL", url)
|
32
34
|
const href = `${url}?filter=${encodeURI(filter)}`;
|
33
35
|
const response = await axios.request({
|
34
36
|
method: 'get',
|
@@ -76,7 +78,7 @@ const ProductData = {
|
|
76
78
|
responseType: 'json'
|
77
79
|
});
|
78
80
|
},
|
79
|
-
|
81
|
+
|
80
82
|
/**
|
81
83
|
* @param {contentstack.MarketConfig} marketConfig
|
82
84
|
*/
|
@@ -88,149 +90,20 @@ const ProductData = {
|
|
88
90
|
};
|
89
91
|
},
|
90
92
|
|
91
|
-
/**
|
92
|
-
* Map product variant
|
93
|
-
* @todo remove unnecessary fields
|
94
|
-
* @param {*} eqVariant
|
95
|
-
* @returns Array<Product>
|
96
|
-
*/
|
97
|
-
eqProductVariantMapper : function (eqVariant) {
|
98
|
-
|
99
|
-
let imageURL = eqVariant.properties.imageURL;
|
100
|
-
const regex = /\d+.\d+/
|
101
|
-
let thumbnailImage = ''
|
102
|
-
|
103
|
-
if (imageURL.includes('contentstack')) {
|
104
|
-
thumbnailImage = imageURL + '?width=40'
|
105
|
-
} else {
|
106
|
-
thumbnailImage = imageURL.replace(regex,'40.40')
|
107
|
-
}
|
108
|
-
|
109
|
-
return {
|
110
|
-
"sku": eqVariant.identifier,
|
111
|
-
"globalProductID": eqVariant.identifier,
|
112
|
-
"title": eqVariant.properties.name,
|
113
|
-
"country": eqVariant.properties.market,
|
114
|
-
"language": "en",
|
115
|
-
"shortDescr": eqVariant.properties.description,
|
116
|
-
"longDescr": eqVariant.properties.productDetailsDescription,
|
117
|
-
"fullImage": imageURL,
|
118
|
-
"imageAltText": eqVariant.properties.name,
|
119
|
-
"productCarouselImages": [
|
120
|
-
{
|
121
|
-
"contentType": "img",
|
122
|
-
"src": "/content/products/24/00/35/24003529/jcr:content/fullImage.imgw.1280.1280.png",
|
123
|
-
"alt": ""
|
124
|
-
}
|
125
|
-
],
|
126
|
-
"thumbnail": thumbnailImage,
|
127
|
-
"ingredients": eqVariant.properties.ingredients,
|
128
|
-
"benefits": eqVariant.properties.benefits,
|
129
|
-
"usage": eqVariant.properties.usage,
|
130
|
-
"resources": eqVariant.properties.resources,
|
131
|
-
"videos": "",
|
132
|
-
"movie": "",
|
133
|
-
"youtube": "",
|
134
|
-
"salesEventText": "",
|
135
|
-
"contentSection": [
|
136
|
-
{
|
137
|
-
"sectionContent": "<div class=\"contentSections\"><div class=\"contentSection section\"><div>\n<h3>BENEFITS</h3>\n<div>\n<div class=\"sectionContent parsys\"><div class=\"text parbase section\">\n<p>Green tea has been used in China for thousands of years for its health-preserving and revitalizing power. Modern science has identified powerful antioxidants in green tea called polyphenols. One group of polyphenols called catechins is particularly potent and is highly effective at neutralizing free radicals at the cellular level. Catechins support healthy cell function while providing antioxidant protection to critical cell structures such as DNA. Clinical studies show catechins interfere with the production of certain enzymes involved in cell damage. Additionally, catechins have been demonstrated to cause a thermogenic effect that enhances the body s metabolic rate. Tegreen 97<sup>®</sup> from Pharmanex is a proprietary, highly concentrated extract of the catechins found in green tea. Tegreen 97<sup>®</sup> is one of the most potent antioxidant supplements on the market with a 97 percent polyphenol content, 65% catechins. Each Tegreen 97<sup>®</sup> capsule contains the catechin equivalent of approximately seven cups of green tea and is 99.5 percent caffeine free.</p>\r\n\n</div>\n\n</div>\n\n</div>\n</div>\n</div>\n<div class=\"contentSection section\"><div>\n<h3>USAGE</h3>\n<div>\n<div class=\"sectionContent parsys\"><div class=\"text parbase section\">\n<p>As a dietary supplement, take one (1) to four (4) capsules daily; preferably one (1) to two (2) each morning and evening with food. Store in a cool, dry place.</p>\r\n\n</div>\n\n</div>\n\n</div>\n</div>\n</div>\n<div class=\"contentSection section\"><div>\n<h3>INGREDIENTS</h3>\n<div>\n<div class=\"sectionContent parsys\"><div class=\"text parbase section\">\n<table border=\"1\" cellspacing=\"1\" cellpadding=\"0\" width=\"360\"><tbody>\r\n<tr>\r\n<td><b>Nutritional Facts</b></td>\r\n<td><b>Amount</b></td>\r\n<td><b>% Daily Value</b></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"3\"><b>Serving Size: 1 Capsule<br>\r\nServings Per Container: 120</b></td>\r\n</tr>\r\n<tr>\r\n<td width=\"55%\">Green tea leaf (20:1) Extract (<i>Camellia sinensis</i></td>\r\n<td width=\"20%\">250 mg</td>\r\n<td width=\"25%\"> </td>\r\n</tr>\r\n<tr>\r\n<td width=\"55%\" colspan=\"3\">* Daily Value not established</td>\r\n</tr>\r\n<tr>\r\n<td width=\"55%\" colspan=\"3\"><b>Other Ingredients: Gelatin, Silicon Dioxide, Microcrystalline Cellulose, Magnesium Stearate.</b></td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n<p> </p>\r\n\n</div>\n\n</div>\n\n</div>\n</div>\n</div>\n</div>\n"
|
138
|
-
}
|
139
|
-
],
|
140
|
-
"scanQualified": eqVariant.properties.scanQualifiedCount,
|
141
|
-
"availableQuantity": 999,
|
142
|
-
"maxQuantity": 999,
|
143
|
-
"points": "",
|
144
|
-
"cv": (eqVariant.priceFacets.CV) ? eqVariant.priceFacets.CV : '',
|
145
|
-
"pv":eqVariant.priceFacets.PV,
|
146
|
-
"priceType": "WRTL",
|
147
|
-
"price": eqVariant.priceFacets["Regular Price"],
|
148
|
-
"priceMap": {
|
149
|
-
"WRTL": eqVariant.priceFacets["Regular Price"],
|
150
|
-
"WADW-WRTL": eqVariant.priceFacets["Regular Price"],
|
151
|
-
"WADR": 9999.01,
|
152
|
-
"RTL": eqVariant.priceFacets["Regular Price"],
|
153
|
-
"WWHL": 9998.01,
|
154
|
-
"WADW": 9998.01,
|
155
|
-
"WHL": 9998.01
|
156
|
-
},
|
157
|
-
"cvMap": {
|
158
|
-
"WWHL": (eqVariant.priceFacets.CV) ? eqVariant.priceFacets.CV : '',
|
159
|
-
"WADW": (eqVariant.priceFacets.CV) ? eqVariant.priceFacets.CV : '',
|
160
|
-
"WHL": (eqVariant.priceFacets.CV) ? eqVariant.priceFacets.CV : ''
|
161
|
-
},
|
162
|
-
"pvMap": {
|
163
|
-
"WWHL": eqVariant.priceFacets.PV,
|
164
|
-
"WADW": eqVariant.priceFacets.PV,
|
165
|
-
"WHL": eqVariant.priceFacets.PV
|
166
|
-
},
|
167
|
-
"orderTypes": {
|
168
|
-
"adr": true,
|
169
|
-
"order": true,
|
170
|
-
"zpfc": false,
|
171
|
-
"zadp": true,
|
172
|
-
"ars": true,
|
173
|
-
"kiosk": true,
|
174
|
-
"mobile": true,
|
175
|
-
"preferred customer": true,
|
176
|
-
"retail": true,
|
177
|
-
"web": true,
|
178
|
-
"web display": true
|
179
|
-
},
|
180
|
-
"division": eqVariant.properties.division,
|
181
|
-
"backOrderDate": null,
|
182
|
-
"locallyProduced": false,
|
183
|
-
"agelocme": null,
|
184
|
-
"count": "",
|
185
|
-
"flavor": "",
|
186
|
-
"size": eqVariant.properties.size,
|
187
|
-
"shade": "",
|
188
|
-
"status": this.switchStatusFromEquinox(eqVariant.properties.status),
|
189
|
-
"variantType": "Other",
|
190
|
-
"variantDropdownLabel": "Select Type",
|
191
|
-
"variantDropdownPlaceholder": "Select Type",
|
192
|
-
"variantsLabel": "Select Type",
|
193
|
-
"groupOffer": false,
|
194
|
-
"personalOffer": false,
|
195
|
-
"savedEventName": null,
|
196
|
-
"salesLabel": "",
|
197
|
-
"eventName": null,
|
198
|
-
"sizeWeight": '',
|
199
|
-
"nettoWeight": "",
|
200
|
-
"searchScore": 0,
|
201
|
-
"isExclusive": false,
|
202
|
-
"marketAttributes": {
|
203
|
-
"discount": true,
|
204
|
-
"redeem": true,
|
205
|
-
"earn": true
|
206
|
-
},
|
207
|
-
"restrictedMarkets": [],
|
208
|
-
"addOns": []
|
209
|
-
};
|
210
|
-
},
|
211
|
-
|
212
93
|
eqProductMapper: function (productDataResponse) {
|
213
94
|
let prod = [];
|
214
|
-
let
|
95
|
+
let count = 0;
|
215
96
|
|
216
|
-
let prodArr = productDataResponse.map((data
|
97
|
+
let prodArr = productDataResponse.map((data) => {
|
217
98
|
let imageURL = data.sku[count].properties.imageURL;
|
218
99
|
const regex = /\d+.\d+/
|
219
100
|
let thumbnailImage = ''
|
220
|
-
|
101
|
+
|
221
102
|
if (imageURL.includes('contentstack')) {
|
222
103
|
thumbnailImage = imageURL + '?width=40'
|
223
104
|
} else {
|
224
105
|
thumbnailImage = imageURL.replace(regex,'40.40')
|
225
106
|
}
|
226
|
-
|
227
|
-
if (data.sku && data.sku.length > 1) {
|
228
|
-
data.sku.map(variant => {
|
229
|
-
variants[variant.identifier] = this.eqProductVariantMapper(variant);
|
230
|
-
return variant;
|
231
|
-
});
|
232
|
-
}
|
233
|
-
|
234
107
|
prod = {
|
235
108
|
"sku": data.sku[count].identifier,
|
236
109
|
"globalProductID": data.identifier,
|
@@ -324,9 +197,10 @@ const ProductData = {
|
|
324
197
|
"eventName": null,
|
325
198
|
"sizeWeight": '',
|
326
199
|
"nettoWeight": "",
|
327
|
-
"variants":
|
200
|
+
"variants": {
|
201
|
+
},
|
328
202
|
"searchScore": 0,
|
329
|
-
"isExclusive":
|
203
|
+
"isExclusive": data.sku[count].properties.isExclusive,
|
330
204
|
"marketAttributes": {
|
331
205
|
"discount": true,
|
332
206
|
"redeem": true,
|
@@ -335,7 +209,7 @@ const ProductData = {
|
|
335
209
|
"restrictedMarkets": [],
|
336
210
|
"addOns": []
|
337
211
|
};
|
338
|
-
let newProduct = new
|
212
|
+
let newProduct = new product(prod);
|
339
213
|
return newProduct
|
340
214
|
})
|
341
215
|
|
@@ -371,20 +245,20 @@ const ProductData = {
|
|
371
245
|
newStatus = 'NOT_RELEASED_FOR_SALE';
|
372
246
|
break;
|
373
247
|
default:
|
374
|
-
newStatus = '
|
248
|
+
newStatus = 'NOT_RELEASED_FOR_SALE'
|
375
249
|
break;
|
376
250
|
}
|
377
251
|
return newStatus;
|
378
252
|
},
|
379
253
|
|
380
254
|
/**
|
381
|
-
*
|
382
|
-
* @param {*} custType
|
383
|
-
*
|
255
|
+
*
|
256
|
+
* @param {*} custType
|
257
|
+
*
|
384
258
|
*/
|
385
259
|
switchCustType: function (custType) {
|
386
260
|
let newCustType = [];
|
387
|
-
if (custType.includes('Brand Affiliate - Business Entity') || custType.includes('Brand Affiliate - Individual'))
|
261
|
+
if (custType.includes('Brand Affiliate - Business Entity') || custType.includes('Brand Affiliate - Individual'))
|
388
262
|
newCustType.push(10)
|
389
263
|
if (custType.includes('Retail Customer'))
|
390
264
|
newCustType.push(20)
|