@nuskin/contentstack-lib 2.1.0-pa-1117.6 → 2.1.0-pa-1117.8

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/README.md CHANGED
@@ -11,13 +11,13 @@ FOR COMMON SPANISH AND MX-es FOR EXAMPLE.
11
11
 
12
12
  ## Installing
13
13
 
14
- Usng npm:
14
+ Using npm:
15
15
 
16
16
  ```bash
17
17
  npm install @nuskin/contentstack-lib
18
18
  ```
19
19
 
20
- Usng yarn:
20
+ Using yarn:
21
21
 
22
22
  ```bash
23
23
  yarn add @nuskin/contentstack-lib
@@ -28,8 +28,9 @@ yarn add @nuskin/contentstack-lib
28
28
  ```js
29
29
  const { getStack } = require('@nuskin/contentstack-lib')
30
30
 
31
- // Call getStack to get the stack object
32
- const Stack = getStack()
31
+ // Pass an environment explicitly outside the browser.
32
+ // In the browser, getStack() can infer the env from the hostname.
33
+ const Stack = getStack('prod')
33
34
 
34
35
  // get all languages
35
36
  const languages = await Stack.ContentType('supported_language').Query().toJSON().find();
@@ -37,16 +38,6 @@ const languages = await Stack.ContentType('supported_language').Query().toJSON()
37
38
  // get all markets
38
39
  const markets = await Stack.ContentType('market').Query().toJSON().find();
39
40
 
40
- // Use the extended getStrings function to get translations
41
- // ==================== Deprecated - Dont use this function ==========================
42
- const translations = Stack.getStrings({
43
- contentTypes: ['checkout_adr_strings', 'checkout_cart_strings'], // List of content types you want to get translations for
44
- language: 'en',
45
- country: 'US',
46
- merge: true // Will combine checkout_adr_strings and checkout_cart_strings object with single list of strings
47
- });
48
-
49
- // Use this function instead to get your translations
50
41
  // The entries are returned in the order they were requested so you can destructure the array accordingly
51
42
  // To get the result in camelcase instead of snake case you can pass in the option.camelcase: true
52
43
  // Contentstack does not merge common english strings with en_US strings. This function allows you to merge the two with mergeWithFallback: true
@@ -76,10 +67,13 @@ const addressForms = await Stack.getAddressForms(['United States']);
76
67
  // field: 'address1',
77
68
  // width: 'full',
78
69
  // editable: true,
79
- // max_length: 40
70
+ // max_length: 40,
71
+ // required: true
80
72
  // }
81
73
  // ],
82
- // postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$'
74
+ // postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$',
75
+ // verify_after_autocomplete: true,
76
+ // wrap_address1_to_address2: false
83
77
  // }
84
78
  // ]
85
79
 
@@ -87,8 +81,54 @@ const addressForms = await Stack.getAddressForms(['United States']);
87
81
  const camelizedAddressForms = await Stack.getAddressForms(['United States'], true);
88
82
 
89
83
  // Get shipping address forms with referenced address form fields expanded.
90
- // The second parameter works the same way here.
84
+ // countries is normalized to a list of { code, name } objects.
91
85
  const shippingAddressForms = await Stack.getShippingAddressForms(['United States']);
86
+
87
+ // Example result:
88
+ // [
89
+ // {
90
+ // countries: [
91
+ // {
92
+ // code: 'US',
93
+ // name: 'United States'
94
+ // }
95
+ // ],
96
+ // pre_address_fields: [
97
+ // {
98
+ // field: 'givenName',
99
+ // width: 'half',
100
+ // editable: true,
101
+ // max_length: 30,
102
+ // required: true
103
+ // }
104
+ // ],
105
+ // address_form: {
106
+ // address_elements: [
107
+ // {
108
+ // field: 'address1',
109
+ // width: 'full',
110
+ // editable: true,
111
+ // max_length: 40,
112
+ // required: true
113
+ // }
114
+ // ],
115
+ // postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$',
116
+ // verify_after_autocomplete: true,
117
+ // wrap_address1_to_address2: false
118
+ // },
119
+ // post_address_fields: [
120
+ // {
121
+ // field: 'mobilePhone',
122
+ // width: 'full',
123
+ // editable: true,
124
+ // max_length: 20,
125
+ // required: true
126
+ // }
127
+ // ]
128
+ // }
129
+ // ]
130
+
131
+ // Pass true as the second parameter to camelCase the returned keys.
92
132
  const camelizedShippingAddressForms = await Stack.getShippingAddressForms(['United States'], true);
93
133
 
94
134
  // We could possibly add functionality to return the list of regions markets and languages in a single object structure
@@ -86,14 +86,16 @@ const addressFormFieldEntries = [
86
86
  width: 'full',
87
87
  editable: true,
88
88
  max_length: '40',
89
- required: true
89
+ required: true,
90
+ api_mappings: ['address1']
90
91
  },
91
92
  {
92
93
  field: 'postalCode',
93
94
  width: 'half',
94
95
  editable: false,
95
96
  max_length: '10',
96
- required: false
97
+ required: false,
98
+ api_mappings: ['postalCode']
97
99
  }
98
100
  ];
99
101
 
@@ -157,9 +159,9 @@ describe("ContentstackApi", () => {
157
159
  global.window = Object.create(window);
158
160
  global.window.location = { hostname };
159
161
  const {getStack} = require('../src/api');
160
- getStack(env[index]);
162
+ getStack();
161
163
  expect(mockStack).toHaveBeenCalledWith({api_key: csCfg.apiKey, delivery_token: csCfg.deliveryToken, environment: csCfg.environment});
162
- })
164
+ });
163
165
  });
164
166
 
165
167
  test('extractAddressFormFields maps address form field entries', () => {
@@ -171,14 +173,16 @@ describe("ContentstackApi", () => {
171
173
  width: 'full',
172
174
  editable: true,
173
175
  max_length: 40,
174
- required: true
176
+ required: true,
177
+ api_mappings: ['address1']
175
178
  },
176
179
  {
177
180
  field: 'postalCode',
178
181
  width: 'half',
179
182
  editable: false,
180
183
  max_length: 10,
181
- required: false
184
+ required: false,
185
+ api_mappings: ['postalCode']
182
186
  }
183
187
  ]);
184
188
  });
@@ -192,18 +196,26 @@ describe("ContentstackApi", () => {
192
196
  width: 'full',
193
197
  editable: true,
194
198
  maxLength: 40,
195
- required: true
199
+ required: true,
200
+ apiMappings: ['address1']
196
201
  },
197
202
  {
198
203
  field: 'postalCode',
199
204
  width: 'half',
200
205
  editable: false,
201
206
  maxLength: 10,
202
- required: false
207
+ required: false,
208
+ apiMappings: ['postalCode']
203
209
  }
204
210
  ]);
205
211
  });
206
212
 
213
+ test('extractAddressFormFields returns an empty list when no entries are provided', () => {
214
+ const {getStack} = require('../src/api');
215
+ const Stack = getStack('dev');
216
+ expect(Stack.extractAddressFormFields()).toStrictEqual([]);
217
+ });
218
+
207
219
  test('getAddressForms maps address_elements', async () => {
208
220
  mockPromiseResult.mockResolvedValueOnce([[
209
221
  {
@@ -224,14 +236,16 @@ describe("ContentstackApi", () => {
224
236
  width: 'full',
225
237
  editable: true,
226
238
  max_length: 40,
227
- required: true
239
+ required: true,
240
+ api_mappings: ['address1']
228
241
  },
229
242
  {
230
243
  field: 'postalCode',
231
244
  width: 'half',
232
245
  editable: false,
233
246
  max_length: 10,
234
- required: false
247
+ required: false,
248
+ api_mappings: ['postalCode']
235
249
  }
236
250
  ],
237
251
  postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$',
@@ -260,14 +274,16 @@ describe("ContentstackApi", () => {
260
274
  width: 'full',
261
275
  editable: true,
262
276
  maxLength: 40,
263
- required: true
277
+ required: true,
278
+ apiMappings: ['address1']
264
279
  },
265
280
  {
266
281
  field: 'postalCode',
267
282
  width: 'half',
268
283
  editable: false,
269
284
  maxLength: 10,
270
- required: false
285
+ required: false,
286
+ apiMappings: ['postalCode']
271
287
  }
272
288
  ],
273
289
  postalCodeRegex: '^[0-9]{5}(?:-[0-9]{4})?$',
@@ -277,6 +293,21 @@ describe("ContentstackApi", () => {
277
293
  ]);
278
294
  });
279
295
 
296
+ test('getAddressForms returns an empty list when no forms are found', async () => {
297
+ mockPromiseResult.mockResolvedValueOnce([undefined]);
298
+ const {getStack} = require('../src/api');
299
+ const Stack = getStack('dev');
300
+ await expect(Stack.getAddressForms(['Unknown'])).resolves.toStrictEqual([]);
301
+ });
302
+
303
+ test('getSingletonEntries maps language code in to id', async () => {
304
+ mockSinglePromiseResult.mockResolvedValueOnce(singleCheckoutAdrStrings);
305
+ const {getStack} = require('../src/api');
306
+ const Stack = getStack('dev');
307
+ await Stack.getSingletonEntries({contentTypeUIDs: ['checkout_adr_strings'], language: 'in'});
308
+ expect(mockSinglePromiseResult).toHaveBeenCalled();
309
+ });
310
+
280
311
  test('getShippingAddressForms maps nested address form fields', async () => {
281
312
  mockPromiseResult.mockResolvedValueOnce([[
282
313
  {
@@ -296,13 +327,15 @@ describe("ContentstackApi", () => {
296
327
  }
297
328
  ],
298
329
  pre_address_fields: [addressFormFieldEntries[0]],
299
- address_form: {
300
- title: 'default',
301
- address_elements: addressFormFieldEntries,
302
- postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$',
303
- verify_after_autocomplete: true,
304
- wrap_address1_to_address2: false
305
- },
330
+ address_form: [
331
+ {
332
+ title: 'default',
333
+ address_elements: addressFormFieldEntries,
334
+ postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$',
335
+ verify_after_autocomplete: true,
336
+ wrap_address1_to_address2: false
337
+ }
338
+ ],
306
339
  post_address_fields: [addressFormFieldEntries[1]]
307
340
  }
308
341
  ]]);
@@ -326,7 +359,8 @@ describe("ContentstackApi", () => {
326
359
  width: 'full',
327
360
  editable: true,
328
361
  max_length: 40,
329
- required: true
362
+ required: true,
363
+ api_mappings: ['address1']
330
364
  }
331
365
  ],
332
366
  address_form: {
@@ -336,14 +370,16 @@ describe("ContentstackApi", () => {
336
370
  width: 'full',
337
371
  editable: true,
338
372
  max_length: 40,
339
- required: true
373
+ required: true,
374
+ api_mappings: ['address1']
340
375
  },
341
376
  {
342
377
  field: 'postalCode',
343
378
  width: 'half',
344
379
  editable: false,
345
380
  max_length: 10,
346
- required: false
381
+ required: false,
382
+ api_mappings: ['postalCode']
347
383
  }
348
384
  ],
349
385
  postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$',
@@ -356,7 +392,8 @@ describe("ContentstackApi", () => {
356
392
  width: 'half',
357
393
  editable: false,
358
394
  max_length: 10,
359
- required: false
395
+ required: false,
396
+ api_mappings: ['postalCode']
360
397
  }
361
398
  ]
362
399
  }
@@ -382,13 +419,15 @@ describe("ContentstackApi", () => {
382
419
  }
383
420
  ],
384
421
  pre_address_fields: [addressFormFieldEntries[0]],
385
- address_form: {
386
- title: 'default',
387
- address_elements: addressFormFieldEntries,
388
- postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$',
389
- verify_after_autocomplete: true,
390
- wrap_address1_to_address2: false
391
- },
422
+ address_form: [
423
+ {
424
+ title: 'default',
425
+ address_elements: addressFormFieldEntries,
426
+ postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$',
427
+ verify_after_autocomplete: true,
428
+ wrap_address1_to_address2: false
429
+ }
430
+ ],
392
431
  post_address_fields: [addressFormFieldEntries[1]]
393
432
  }
394
433
  ]]);
@@ -412,7 +451,8 @@ describe("ContentstackApi", () => {
412
451
  width: 'full',
413
452
  editable: true,
414
453
  maxLength: 40,
415
- required: true
454
+ required: true,
455
+ apiMappings: ['address1']
416
456
  }
417
457
  ],
418
458
  addressForm: {
@@ -422,14 +462,16 @@ describe("ContentstackApi", () => {
422
462
  width: 'full',
423
463
  editable: true,
424
464
  maxLength: 40,
425
- required: true
465
+ required: true,
466
+ apiMappings: ['address1']
426
467
  },
427
468
  {
428
469
  field: 'postalCode',
429
470
  width: 'half',
430
471
  editable: false,
431
472
  maxLength: 10,
432
- required: false
473
+ required: false,
474
+ apiMappings: ['postalCode']
433
475
  }
434
476
  ],
435
477
  postalCodeRegex: '^[0-9]{5}(?:-[0-9]{4})?$',
@@ -442,10 +484,32 @@ describe("ContentstackApi", () => {
442
484
  width: 'half',
443
485
  editable: false,
444
486
  maxLength: 10,
445
- required: false
487
+ required: false,
488
+ apiMappings: ['postalCode']
446
489
  }
447
490
  ]
448
491
  }
449
492
  ]);
450
493
  });
494
+
495
+ test('getShippingAddressForms returns empty nested data when optional references are missing', async () => {
496
+ mockPromiseResult.mockResolvedValueOnce([[
497
+ {
498
+ countries: [],
499
+ pre_address_fields: undefined,
500
+ address_form: [],
501
+ post_address_fields: undefined
502
+ }
503
+ ]]);
504
+ const {getStack} = require('../src/api');
505
+ const Stack = getStack('dev');
506
+ await expect(Stack.getShippingAddressForms(['Unknown'])).resolves.toStrictEqual([
507
+ {
508
+ countries: [],
509
+ pre_address_fields: [],
510
+ address_form: undefined,
511
+ post_address_fields: []
512
+ }
513
+ ]);
514
+ });
451
515
  });
package/docs/CHANGELOG.md CHANGED
@@ -1 +1 @@
1
- # [2.1.0-pa-1117.6](https://code.tls.nuskin.io/ns-am/utility/npm/contentstack-lib/compare/v2.1.0-pa-1117.5...v2.1.0-pa-1117.6) (2026-04-08)
1
+ # [2.1.0-pa-1117.8](https://code.tls.nuskin.io/ns-am/utility/npm/contentstack-lib/compare/v2.1.0-pa-1117.7...v2.1.0-pa-1117.8) (2026-05-08)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/contentstack-lib",
3
- "version": "2.1.0-pa-1117.6",
3
+ "version": "2.1.0-pa-1117.8",
4
4
  "description": "This project contains configuration and api code to access Contentstack, to be shared between the backend (AWS Lambda) and frontend (Vue, etc).",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/api.js CHANGED
@@ -202,12 +202,13 @@ const _getMultiEntries = async (contentType, includeRefs, values) => {
202
202
  * @private
203
203
  */
204
204
  const _extractAddressFormFields = (addressFormFields = [], camelcase = false) => {
205
- const mappedFields = addressFormFields.map(({field, width, editable, max_length, required}) => ({
205
+ const mappedFields = addressFormFields.map(({field, width, editable, max_length, required, api_mappings}) => ({
206
206
  field,
207
207
  width,
208
208
  editable,
209
209
  max_length: Number(max_length),
210
- required
210
+ required,
211
+ api_mappings
211
212
  }));
212
213
 
213
214
  return camelcase ? _snakeObjectToCamel(mappedFields) : mappedFields;
@@ -237,24 +238,24 @@ const _extractShippingCountries = (countries = []) => {
237
238
  }));
238
239
  }
239
240
 
240
- const getShippingAddressForms = async (countries, camelcase = false) => {
241
+ const getShippingAddressForms = async (forms, camelcase = false) => {
241
242
  const results = await _getMultiEntries(
242
243
  'shipping_address_form',
243
244
  ['countries', 'pre_address_fields', 'address_form', 'address_form.address_elements', 'post_address_fields'],
244
- countries
245
+ forms
245
246
  );
246
247
  const mappedResults = (results || []).map((result) => ({
247
248
  countries: _extractShippingCountries(result.countries),
248
249
  pre_address_fields: _extractAddressFormFields(result.pre_address_fields, camelcase),
249
- address_form: _extractAddressForm(result.address_form, camelcase),
250
+ address_form: _extractAddressForm(result.address_form[0], camelcase),
250
251
  post_address_fields: _extractAddressFormFields(result.post_address_fields, camelcase)
251
252
  }));
252
253
 
253
254
  return camelcase ? _snakeObjectToCamel(mappedResults) : mappedResults;
254
255
  }
255
256
 
256
- const getAddressForms = async (countries, camelcase = false) => {
257
- const results = await _getMultiEntries('address_form', 'address_elements', countries);
257
+ const getAddressForms = async (forms, camelcase = false) => {
258
+ const results = await _getMultiEntries('address_form', 'address_elements', forms);
258
259
  const mappedResults = (results || []).map((result) => _extractAddressForm(result, camelcase));
259
260
 
260
261
  return camelcase ? _snakeObjectToCamel(mappedResults) : mappedResults;