@nuskin/cs-product-lib 1.3.0 → 1.4.0-td-688.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/cs-product-lib",
3
- "version": "1.3.0",
3
+ "version": "1.4.0-td-688.2",
4
4
  "description": "Library for pulling and parsing product content (and applying business logic) retrieved from Contentstack",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -54,6 +54,8 @@
54
54
  "marked": "4.0.10",
55
55
  "semver": "7.5.2",
56
56
  "underscore": "1.13.1",
57
- "word-wrap": "1.2.4"
57
+ "word-wrap": "1.2.4",
58
+ "braces": "3.0.3",
59
+ "cross-spawn": "7.0.6"
58
60
  }
59
61
  }
package/src/csProduct.js CHANGED
@@ -10,6 +10,8 @@ const { transformBundle } = require('./transformBundle')
10
10
  const { formatCategoryTranslations } = require('./formatCategoryTranslations')
11
11
  const { isNullOrEmpty } = require('@nuskin/ns-common-lib')
12
12
  const { formatDiscounts } = require('./helpers/formatDiscounts');
13
+ const { formatCategory } = require('./formatCategory')
14
+ const { getAllTopCategories } = require('./getAllTopCategories')
13
15
 
14
16
  const validateConfig = (props) => {
15
17
  if (!props) {
@@ -55,6 +57,7 @@ const csProduct = (props) => {
55
57
  const PRODUCT_BRAND_STYLE = 'features.brand_style'
56
58
  const DEFAULT_LOCALE = 'en'
57
59
  const PRODUCT_TYPE = 'product'
60
+ const CATEGORY_TYPE = 'category'
58
61
  const INCLUDE_FALLBACK = '&include_fallback=true'
59
62
  const REQUIRED = 'required_products.product.'
60
63
  const OPTIONAL = 'optional_products.product.'
@@ -617,6 +620,25 @@ const csProduct = (props) => {
617
620
  }
618
621
  }
619
622
 
623
+ const getCategoryById = async (id, locale) => {
624
+ locale = badLocaleMap(locale)
625
+ try {
626
+ const categories = await getEntriesByQuery({
627
+ contentType: CATEGORY_TYPE,
628
+ query: `{"category_id": "${id}"}`,
629
+ locale,
630
+ includes: ['subcategories']
631
+ })
632
+ const { country, language } = helpers.parseLocale(locale)
633
+ const allTopCategories = await getAllTopCategories(locale, environment)
634
+ const category = categories[0]
635
+ category.localeData = { country, language }
636
+ return formatCategory(category, language, homeUrl, allTopCategories)
637
+ } catch (error) {
638
+ throw new Error('Failed to fetch category')
639
+ }
640
+ };
641
+
620
642
  return {
621
643
  asObject,
622
644
  getEntriesByQuery,
@@ -631,10 +653,11 @@ const csProduct = (props) => {
631
653
  getBundle,
632
654
  getBundles,
633
655
  getCategoryPageTranslations,
634
- formatProductWithSchema
656
+ formatProductWithSchema,
657
+ getCategoryById
635
658
  }
636
659
  }
637
660
 
638
661
  module.exports = {
639
662
  csProduct
640
- }
663
+ }
@@ -0,0 +1,32 @@
1
+ const helpers = require('./helpers');
2
+
3
+ const formatSubcategory = (subcategory, index) => ({
4
+ displayName: subcategory?.display_name || '',
5
+ categoryIdentifier: subcategory?.category_id || '',
6
+ sequence: index + 1
7
+ });
8
+
9
+ const formatProduct = (product) => ({
10
+ title: product?.title || '',
11
+ productID: product?.product_id || ''
12
+ });
13
+
14
+ const formatCategory = (parent, language = 'en', homeUrl, allTopCategories) => ({
15
+ displayName: parent?.display_name || '',
16
+ categoryIdentifier: parent?.category_id || '',
17
+ status: parent?.status || 'Inactive',
18
+ isHiddenFromNavigation: parent?.is_hidden_from_navigation || false,
19
+ startTime: parent?.start_time || '1994-01-03T08:00:01.000Z',
20
+ endTime: parent?.end_time || '2038-01-01T08:00:01.000Z',
21
+ isTopCategory: helpers.isTopCategory(parent, allTopCategories),
22
+ image: helpers.mapImage(parent?.image),
23
+ description: parent?.description?.[0] || '',
24
+ subcategories: parent?.subcategories?.map(formatSubcategory) || [],
25
+ seoInformation: helpers.mapSeoInformation(parent, homeUrl, 'nav-category'),
26
+ products: parent?.products?.map(formatProduct) || [],
27
+ language
28
+ });
29
+
30
+ module.exports = {
31
+ formatCategory
32
+ };
@@ -0,0 +1,48 @@
1
+ const axios = require("axios");
2
+ const helpers = require('./helpers');
3
+
4
+ const productApiMapping = {
5
+ 'public-dev': 'https://product.api.dev.nuskin.com/graphql',
6
+ 'public-prod': 'https://product.api.nuskin.com/graphql',
7
+ 'public-test': 'https://product.api.test.nuskin.com/graphql'
8
+ };
9
+
10
+ const query = `
11
+ query Categories($groupByCategory: Boolean, $language: String, $market: String) {
12
+ categories(groupByCategory: $groupByCategory, language: $language, market: $market) {
13
+ categories {
14
+ id
15
+ displayName
16
+ }
17
+ }
18
+ }
19
+ `;
20
+
21
+ const getAllTopCategories = async (locale, environment) => {
22
+ const productGraphqlUrl = productApiMapping[environment];
23
+ if (!productGraphqlUrl) {
24
+ throw new Error('Invalid environment');
25
+ }
26
+
27
+ const { country, language } = helpers.parseLocale(locale);
28
+
29
+ try {
30
+ const response = await axios.post(productGraphqlUrl, {
31
+ operationName: "Categories",
32
+ query,
33
+ variables: {
34
+ groupByCategory: true,
35
+ market: country,
36
+ language
37
+ }
38
+ });
39
+
40
+ return response?.data?.data?.categories?.categories;
41
+ } catch (error) {
42
+ throw new Error('Failed to fetch all categories');
43
+ }
44
+ };
45
+
46
+ module.exports = {
47
+ getAllTopCategories
48
+ };
package/src/helpers.js CHANGED
@@ -348,6 +348,15 @@ function mapSeoInformation(parent, homeUrl, type) {
348
348
  parent?.seo_information?.slug
349
349
  }`
350
350
  break
351
+ case 'nav-category':
352
+ seoData.canonicalURL = `${homeUrl}/${
353
+ parent?.localeData?.country
354
+ }/${parent?.localeData?.language}/catalog/${
355
+ parent?.category_id || parent?.seo_information?.slug
356
+ }`
357
+ seoData.metaTitle = seoData.metaTitle || parent?.display_name || '',
358
+ seoData.metaDescription = seoData.metaDescription || ''
359
+ break
351
360
  default:
352
361
  break
353
362
  }
@@ -1182,6 +1191,10 @@ function mapFaqs(product) {
1182
1191
  return []
1183
1192
  }
1184
1193
 
1194
+ function isTopCategory(category, allTopCategories){
1195
+ return Array.isArray(allTopCategories) && allTopCategories.some(cat => cat.id === category.category_id);
1196
+ }
1197
+
1185
1198
  function mapDiscontinuedSkuReplacement (product) {
1186
1199
  if (product?.discontinued_sku_replacement?.length > 0) {
1187
1200
  return getBestSkuData(product?.discontinued_sku_replacement[0])
@@ -1235,5 +1248,6 @@ module.exports = {
1235
1248
  createMarkdownFromRTE,
1236
1249
  benefitsToMarkdown,
1237
1250
  mapActiveEventDisclaimer,
1251
+ isTopCategory,
1238
1252
  mapDiscontinuedSkuReplacement
1239
1253
  }