@nuskin/contentstack-lib 2.0.0 → 2.1.0-pa-1117.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/.releaserc CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "branches": [
3
- "master"
3
+ "master", {"name":"PA-1117", "channel":"prerelease", "prerelease":"pa-1117"}
4
4
  ],
5
5
  "plugins": [
6
6
  "@semantic-release/release-notes-generator",
package/README.md CHANGED
@@ -7,6 +7,7 @@ This project extends the Contentstack delivery sdk, to be shared between the bac
7
7
  getSingletonEntries TAKES AN OPTION CALLED mergeWithFallback. IF THAT IS SET TO TRUE THEN IT WILL MERGE THE RESULTS
8
8
  FOR COMMON SPANISH AND MX-es FOR EXAMPLE.
9
9
  4. getSingletonEntries also allows you to convert the keys from snake case to camel case.
10
+ 5. It extends the stack with getAddressForms and getShippingAddressForms for address form content types.
10
11
 
11
12
  ## Installing
12
13
 
@@ -63,6 +64,33 @@ const [
63
64
  mergeWithFallback: true
64
65
  });
65
66
 
67
+ // Get address forms for a list of countries.
68
+ // By default the returned keys are snake_case.
69
+ const addressForms = await Stack.getAddressForms(['United States']);
70
+
71
+ // Example result:
72
+ // [
73
+ // {
74
+ // address_elements: [
75
+ // {
76
+ // field: 'address1',
77
+ // width: 'full',
78
+ // editable: true,
79
+ // max_length: 40
80
+ // }
81
+ // ],
82
+ // postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$'
83
+ // }
84
+ // ]
85
+
86
+ // Pass true as the second parameter to camelCase the returned keys.
87
+ const camelizedAddressForms = await Stack.getAddressForms(['United States'], true);
88
+
89
+ // Get shipping address forms with referenced address form fields expanded.
90
+ // The second parameter works the same way here.
91
+ const shippingAddressForms = await Stack.getShippingAddressForms(['United States']);
92
+ const camelizedShippingAddressForms = await Stack.getShippingAddressForms(['United States'], true);
93
+
66
94
  // We could possibly add functionality to return the list of regions markets and languages in a single object structure
67
95
  ```
68
96
 
@@ -52,6 +52,13 @@ beforeEach(() => {
52
52
  findOne: mockSinglePromiseResult
53
53
  })
54
54
  })
55
+ }),
56
+ containedIn: () => ({
57
+ includeReference: () => ({
58
+ toJSON: () => ({
59
+ find: mockPromiseResult
60
+ })
61
+ })
55
62
  })
56
63
  })
57
64
  })
@@ -73,6 +80,23 @@ const mockResults = () => {
73
80
  mockSinglePromiseResult.mockResolvedValueOnce(singleCheckoutCartStrings);
74
81
  }
75
82
 
83
+ const addressFormFieldEntries = [
84
+ {
85
+ field: 'address1',
86
+ width: 'full',
87
+ editable: true,
88
+ max_length: '40',
89
+ required: true
90
+ },
91
+ {
92
+ field: 'postalCode',
93
+ width: 'half',
94
+ editable: false,
95
+ max_length: '10',
96
+ required: false
97
+ }
98
+ ];
99
+
76
100
  describe("ContentstackApi", () => {
77
101
  test("getSingletonEntries", async () => {
78
102
  mockResults();
@@ -136,5 +160,228 @@ describe("ContentstackApi", () => {
136
160
  getStack(env[index]);
137
161
  expect(mockStack).toHaveBeenCalledWith({api_key: csCfg.apiKey, delivery_token: csCfg.deliveryToken, environment: csCfg.environment});
138
162
  })
139
- })
163
+ });
164
+
165
+ test('extractAddressFormFields maps address form field entries', () => {
166
+ const {getStack} = require('../src/api');
167
+ const Stack = getStack('dev');
168
+ expect(Stack.extractAddressFormFields(addressFormFieldEntries)).toStrictEqual([
169
+ {
170
+ field: 'address1',
171
+ width: 'full',
172
+ editable: true,
173
+ max_length: 40,
174
+ required: true
175
+ },
176
+ {
177
+ field: 'postalCode',
178
+ width: 'half',
179
+ editable: false,
180
+ max_length: 10,
181
+ required: false
182
+ }
183
+ ]);
184
+ });
185
+
186
+ test('extractAddressFormFields camelcases address form field entries', () => {
187
+ const {getStack} = require('../src/api');
188
+ const Stack = getStack('dev');
189
+ expect(Stack.extractAddressFormFields(addressFormFieldEntries, true)).toStrictEqual([
190
+ {
191
+ field: 'address1',
192
+ width: 'full',
193
+ editable: true,
194
+ maxLength: 40,
195
+ required: true
196
+ },
197
+ {
198
+ field: 'postalCode',
199
+ width: 'half',
200
+ editable: false,
201
+ maxLength: 10,
202
+ required: false
203
+ }
204
+ ]);
205
+ });
206
+
207
+ test('getAddressForms maps address_elements', async () => {
208
+ mockPromiseResult.mockResolvedValueOnce([[
209
+ {
210
+ title: 'United States',
211
+ address_elements: addressFormFieldEntries,
212
+ postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$'
213
+ }
214
+ ]]);
215
+ const {getStack} = require('../src/api');
216
+ const Stack = getStack('dev');
217
+ await expect(Stack.getAddressForms(['United States'])).resolves.toStrictEqual([
218
+ {
219
+ address_elements: [
220
+ {
221
+ field: 'address1',
222
+ width: 'full',
223
+ editable: true,
224
+ max_length: 40,
225
+ required: true
226
+ },
227
+ {
228
+ field: 'postalCode',
229
+ width: 'half',
230
+ editable: false,
231
+ max_length: 10,
232
+ required: false
233
+ }
234
+ ],
235
+ postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$'
236
+ }
237
+ ]);
238
+ });
239
+
240
+ test('getAddressForms camelcases returned field names', async () => {
241
+ mockPromiseResult.mockResolvedValueOnce([[
242
+ {
243
+ address_elements: addressFormFieldEntries,
244
+ postal_code_regex: '^[0-9]{5}(?:-[0-9]{4})?$'
245
+ }
246
+ ]]);
247
+ const {getStack} = require('../src/api');
248
+ const Stack = getStack('dev');
249
+ await expect(Stack.getAddressForms(['United States'], true)).resolves.toStrictEqual([
250
+ {
251
+ addressElements: [
252
+ {
253
+ field: 'address1',
254
+ width: 'full',
255
+ editable: true,
256
+ maxLength: 40,
257
+ required: true
258
+ },
259
+ {
260
+ field: 'postalCode',
261
+ width: 'half',
262
+ editable: false,
263
+ maxLength: 10,
264
+ required: false
265
+ }
266
+ ],
267
+ postalCodeRegex: '^[0-9]{5}(?:-[0-9]{4})?$'
268
+ }
269
+ ]);
270
+ });
271
+
272
+ test('getShippingAddressForms maps nested address form fields', async () => {
273
+ mockPromiseResult.mockResolvedValueOnce([[
274
+ {
275
+ title: 'United States',
276
+ pre_address_fields: [addressFormFieldEntries[0]],
277
+ address_form: {
278
+ title: 'default',
279
+ address_elements: addressFormFieldEntries
280
+ },
281
+ post_address_fields: [addressFormFieldEntries[1]]
282
+ }
283
+ ]]);
284
+ const {getStack} = require('../src/api');
285
+ const Stack = getStack('dev');
286
+ await expect(Stack.getShippingAddressForms(['United States'])).resolves.toStrictEqual([
287
+ {
288
+ title: 'United States',
289
+ pre_address_fields: [
290
+ {
291
+ field: 'address1',
292
+ width: 'full',
293
+ editable: true,
294
+ max_length: 40,
295
+ required: true
296
+ }
297
+ ],
298
+ address_form: {
299
+ title: 'default',
300
+ address_elements: [
301
+ {
302
+ field: 'address1',
303
+ width: 'full',
304
+ editable: true,
305
+ max_length: 40,
306
+ required: true
307
+ },
308
+ {
309
+ field: 'postalCode',
310
+ width: 'half',
311
+ editable: false,
312
+ max_length: 10,
313
+ required: false
314
+ }
315
+ ]
316
+ },
317
+ post_address_fields: [
318
+ {
319
+ field: 'postalCode',
320
+ width: 'half',
321
+ editable: false,
322
+ max_length: 10,
323
+ required: false
324
+ }
325
+ ]
326
+ }
327
+ ]);
328
+ });
329
+
330
+ test('getShippingAddressForms camelcases returned field names', async () => {
331
+ mockPromiseResult.mockResolvedValueOnce([[
332
+ {
333
+ title: 'United States',
334
+ pre_address_fields: [addressFormFieldEntries[0]],
335
+ address_form: {
336
+ title: 'default',
337
+ address_elements: addressFormFieldEntries
338
+ },
339
+ post_address_fields: [addressFormFieldEntries[1]]
340
+ }
341
+ ]]);
342
+ const {getStack} = require('../src/api');
343
+ const Stack = getStack('dev');
344
+ await expect(Stack.getShippingAddressForms(['United States'], true)).resolves.toStrictEqual([
345
+ {
346
+ title: 'United States',
347
+ preAddressFields: [
348
+ {
349
+ field: 'address1',
350
+ width: 'full',
351
+ editable: true,
352
+ maxLength: 40,
353
+ required: true
354
+ }
355
+ ],
356
+ addressForm: {
357
+ title: 'default',
358
+ addressElements: [
359
+ {
360
+ field: 'address1',
361
+ width: 'full',
362
+ editable: true,
363
+ maxLength: 40,
364
+ required: true
365
+ },
366
+ {
367
+ field: 'postalCode',
368
+ width: 'half',
369
+ editable: false,
370
+ maxLength: 10,
371
+ required: false
372
+ }
373
+ ]
374
+ },
375
+ postAddressFields: [
376
+ {
377
+ field: 'postalCode',
378
+ width: 'half',
379
+ editable: false,
380
+ maxLength: 10,
381
+ required: false
382
+ }
383
+ ]
384
+ }
385
+ ]);
386
+ });
140
387
  });
package/docs/CHANGELOG.md CHANGED
@@ -1 +1 @@
1
- # [2.0.0](https://code.tls.nuskin.io/ns-am/utility/npm/contentstack-lib/compare/v1.0.0...v2.0.0) (2026-03-24)
1
+ # [2.1.0-pa-1117.2](https://code.tls.nuskin.io/ns-am/utility/npm/contentstack-lib/compare/v2.1.0-pa-1117.1...v2.1.0-pa-1117.2) (2026-04-06)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/contentstack-lib",
3
- "version": "2.0.0",
3
+ "version": "2.1.0-pa-1117.2",
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
@@ -173,6 +173,71 @@ async function getSingletonEntries(options) {
173
173
  }
174
174
  }
175
175
 
176
+ /**
177
+ * Gets all the specified entries for a multiple content type
178
+ * @param {string} contentType
179
+ * @param {string[]} values
180
+ * @return {Promise<{Object}>} config
181
+ */
182
+ const _getMultiEntries = async (contentType, includeRefs, values) => {
183
+ try {
184
+ const [results] = await Stack
185
+ .ContentType(contentType)
186
+ .Query()
187
+ .containedIn('title', values)
188
+ .includeReference(includeRefs)
189
+ .toJSON()
190
+ .find();
191
+
192
+ return results;
193
+ } catch(err) {
194
+ console.error(err);
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Maps address form field entries into a small normalized dataset.
200
+ * @param {Object[]} addressFormFields
201
+ * @return {Object[]}
202
+ * @private
203
+ */
204
+ const _extractAddressFormFields = (addressFormFields = [], camelcase = false) => {
205
+ const mappedFields = addressFormFields.map(({field, width, editable, max_length, required}) => ({
206
+ field,
207
+ width,
208
+ editable,
209
+ max_length: Number(max_length),
210
+ required
211
+ }));
212
+
213
+ return camelcase ? _snakeObjectToCamel(mappedFields) : mappedFields;
214
+ }
215
+
216
+ const getShippingAddressForms = async (countries, camelcase = false) => {
217
+ const results = await _getMultiEntries('shipping_address_form', ['pre_address_fields', 'address_form', 'address_form.address_elements', 'post_address_fields'], countries);
218
+ const mappedResults = (results || []).map(result => ({
219
+ ...result,
220
+ pre_address_fields: _extractAddressFormFields(result.pre_address_fields, camelcase),
221
+ address_form: result.address_form ? {
222
+ ...result.address_form,
223
+ address_elements: _extractAddressFormFields(result.address_form.address_elements, camelcase)
224
+ } : result.address_form,
225
+ post_address_fields: _extractAddressFormFields(result.post_address_fields, camelcase)
226
+ }));
227
+
228
+ return camelcase ? _snakeObjectToCamel(mappedResults) : mappedResults;
229
+ }
230
+
231
+ const getAddressForms = async (countries, camelcase = false) => {
232
+ const results = await _getMultiEntries('address_form', 'address_elements', countries);
233
+ const mappedResults = (results || []).map(({address_elements, postal_code_regex}) => ({
234
+ address_elements: _extractAddressFormFields(address_elements, camelcase),
235
+ postal_code_regex
236
+ }));
237
+
238
+ return camelcase ? _snakeObjectToCamel(mappedResults) : mappedResults;
239
+ }
240
+
176
241
  /**
177
242
  * Returns contentstack Stack object initialized with the api key, deliveryToken, and extended with custom functionality
178
243
  * @param {'dev' | 'test' | 'stage' | 'prod'} envrnmnt
@@ -197,6 +262,11 @@ function getStack(envrnmnt) {
197
262
 
198
263
  // extend the Stack with a custom function to get translations
199
264
  Stack.getSingletonEntries = getSingletonEntries;
265
+ // extend the Stack with a custom function to get ShippingAddressForms
266
+ Stack.getAddressForms = getAddressForms;
267
+ // extend the Stack with a custom function to get ShippingAddressForms
268
+ Stack.getShippingAddressForms = getShippingAddressForms;
269
+ Stack.extractAddressFormFields = _extractAddressFormFields;
200
270
 
201
271
  return Stack;
202
272
  }
package/src/index.js CHANGED
@@ -5,9 +5,8 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const {getStack, init} = require("./api.js");
8
+ const {getStack} = require("./api.js");
9
9
 
10
10
  module.exports = {
11
- init,
12
11
  getStack
13
12
  };