@nuskin/contentstack-lib 2.1.0-pa-1117.1 → 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/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.1.0-pa-1117.1](https://code.tls.nuskin.io/ns-am/utility/npm/contentstack-lib/compare/v2.0.0...v2.1.0-pa-1117.1) (2026-04-06)
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.1.0-pa-1117.1",
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
@@ -179,13 +179,13 @@ async function getSingletonEntries(options) {
179
179
  * @param {string[]} values
180
180
  * @return {Promise<{Object}>} config
181
181
  */
182
- const _getMultiEntries = async (contentType, values) => {
182
+ const _getMultiEntries = async (contentType, includeRefs, values) => {
183
183
  try {
184
184
  const [results] = await Stack
185
185
  .ContentType(contentType)
186
186
  .Query()
187
187
  .containedIn('title', values)
188
- .includeReference(['pre_address_fields', 'address_form', 'post_address_fields'])
188
+ .includeReference(includeRefs)
189
189
  .toJSON()
190
190
  .find();
191
191
 
@@ -195,11 +195,47 @@ const _getMultiEntries = async (contentType, values) => {
195
195
  }
196
196
  }
197
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
+ }
198
215
 
199
- const getShippingAddressForms = async (countries) => {
200
- const results = await _getMultiEntries(countries);
201
- console.log(results);
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
+ }));
202
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;
203
239
  }
204
240
 
205
241
  /**
@@ -227,7 +263,10 @@ function getStack(envrnmnt) {
227
263
  // extend the Stack with a custom function to get translations
228
264
  Stack.getSingletonEntries = getSingletonEntries;
229
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
230
268
  Stack.getShippingAddressForms = getShippingAddressForms;
269
+ Stack.extractAddressFormFields = _extractAddressFormFields;
231
270
 
232
271
  return Stack;
233
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
  };