some-common-functions-js 1.0.9 → 1.1.0

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/CHANGELOG.md CHANGED
@@ -28,8 +28,12 @@ Improve README.md documentation.
28
28
  - Corrected README documentation.
29
29
 
30
30
  ## Version 1.0.8 - 2025/11/21 - ITA
31
- - Corrected test code and README documentation
31
+ - Corrected test code and README documentation.
32
32
 
33
33
  ## Version 1.0.9 - 2025/11/28 - ITA
34
34
  - Provided more documentation in test.js to remind a developer how to symbolic-link (mimick as installed) the package and running the test code.
35
35
  - Added new function, hasOnlyAll(), and updated the README.md documentation accordingly.
36
+
37
+ ## Version 1.1.0 - 2025/12/22 - ITA
38
+ - Improved documentation.
39
+ - Moved in more functions to the package: `deepClone(anObject)`, `getSortedObject(anObject)`, `timeStampYyyyMmDd(dateInstance)` and `timeStampString(dateInstance)`.
package/README.md CHANGED
@@ -1,13 +1,17 @@
1
- # JavaScript Object Utilities & Field Validation Functions
1
+ # JavaScript Object Utilities, Field Validation Functions, Array Binary Search, and Date timestamp Functions.
2
2
 
3
3
  Common functions used for working with JavaScript objects and validating field values.
4
4
 
5
5
  ---
6
6
  ## Installation
7
- **npm install some-common-functions-js**
8
-
7
+ ```
8
+ npm install some-common-functions-js
9
+ ```
9
10
  ## 1. JavaScript Object Utilities
10
11
 
12
+ ### `deepClone(anObject)`
13
+ Returns a deep clone of a plain Javascript object. The clone, while it has field equal to that of the original object, is separate from the original object.
14
+
11
15
  ### `getPaths(anObject)`
12
16
  Returns a string array of path/field names inside a JavaScript object.
13
17
  ***Example***
@@ -30,8 +34,47 @@ let client = {
30
34
 
31
35
  let paths = getPaths(client);
32
36
  // ["name", "surname", "address.streetNum", "address.streetName", "address.suburb",
33
- // "address.town", "address.country.name", "address.country.code"]
37
+ // "address.town", "address.country.name", "address.country.code"]
34
38
  ```
39
+ ### `getSortedObject(anObject)`
40
+ Returns an object with sorted fields, by ordered by field name ascending.
41
+ ***Examples***
42
+ ```
43
+ const client = {
44
+ firstName: "Isaiah",
45
+ lastName: "Tshabalala",
46
+ address: {
47
+ houseNum: "5520",
48
+ streetName: "Main Road",
49
+ mainPlace: "Evaton",
50
+ subPlace: "Evaton Small Farms",
51
+ city: "Vereeniging",
52
+ country: {
53
+ name: "South Africa",
54
+ code: "ZA"
55
+ }
56
+ }
57
+ };
58
+
59
+ const sortedObject = getSortedObject(client);
60
+ /*
61
+ {
62
+ address: {
63
+ city: 'Vereeniging',
64
+ country: {
65
+ code: 'ZA',
66
+ name: 'South Africa'
67
+ },
68
+ houseNum: '5520',
69
+ mainPlace: 'Evaton',
70
+ streetName: 'Main Road',
71
+ subPlace: 'Evaton Small Farms'
72
+ },
73
+ firstName: 'Isaiah',
74
+ lastName: 'Tshabalala'
75
+ }
76
+ */
77
+ ```
35
78
  ### `hasOnly(anObject, ...fields)`
36
79
  Returns `true` if the object contains **only** some or all of the specified fields and no others.
37
80
  ***Examples***
@@ -344,7 +387,7 @@ let anIndex = binarySearchObj(teamsArray, searchObj, 0, "score desc", "numGames
344
387
 
345
388
  let result = objCompare(searchObj, teamsArray[anIndex], "score desc", "numGames asc"); // 0 -- an object with value { score: 85, numGames: 8} exists at teamsArray[anIndex];
346
389
  ```
347
- ## 4. `getObjArrayWithNoDuplicates(objArray, firstOfDuplicates, ...comparisonFields)`
390
+ ### `getObjArrayWithNoDuplicates(objArray, firstOfDuplicates, ...comparisonFields)`
348
391
  Create an array of objects with duplicates eliminated. Taking only the first or last object from each duplicate set. The input array must be sorted according to the values of comparisonFields.
349
392
  * If firstOfDuplicates === true, then the first element in each set of duplicates is taken.
350
393
  * if firstOfDuplicates === false, then the last element is taken from each set of duplicates.
@@ -382,7 +425,13 @@ console.log(noDuplicatesArray); // Should contain only unique objects according
382
425
  ]
383
426
  */
384
427
  ```
428
+ ## 4. Date Timestamp Functions
429
+ ### `timeStampYyyyMmDd(dateInstance)`
430
+ Converts the date object to a string of the form CCYY-MM-DD
431
+
432
+ ### `timeStampString(dateInstance)`
433
+ Converts a date object to a string of the form CCYY-MM-DDThh:mm:ss.ccc, e.g. '2024-02-25T15:00:25.251'
434
+
385
435
  ---
386
436
  ## License
387
437
  MIT
388
-
package/index.js CHANGED
@@ -3,9 +3,14 @@
3
3
  * Date Dev Version Description
4
4
  * 2025/11/19 ITA 1.00 Genesis.
5
5
  * 2025/11/28 ITA 1.01 Added function hasOnlyAll().
6
+ * 2025/12/22 ITA 1.02 Improved documentation of the functions and moved in more functions.
6
7
  */
7
8
  const loDash = require('lodash');
8
9
 
10
+ /**Return true if userName is valid
11
+ * @param {string} userName
12
+ * @returns {boolean} true if a userName is valid, otherwise false.
13
+ */
9
14
  function isValidUserName(userName) {
10
15
  if (!userName) // The username must be provided.
11
16
  return false;
@@ -15,6 +20,10 @@ function isValidUserName(userName) {
15
20
  }
16
21
  module.exports.isValidUserName = isValidUserName;
17
22
 
23
+ /**Return true if a name is valid
24
+ * @param {string} name
25
+ * @returns {boolean} true if a name is valid, otherwise false.
26
+ */
18
27
  function isValidName(name) {
19
28
  if (!name) // The name must be provided.
20
29
  return false;
@@ -24,6 +33,10 @@ function isValidName(name) {
24
33
  }
25
34
  module.exports.isValidName = isValidName;
26
35
 
36
+ /**Return true if userName is valid
37
+ * @param {string} email
38
+ * @returns {boolean} true if an email is valid, otherwise false.
39
+ */
27
40
  function isValidEmail(email) {
28
41
  if (!email)
29
42
  return false;
@@ -33,6 +46,10 @@ function isValidEmail(email) {
33
46
  }
34
47
  module.exports.isValidEmail = isValidEmail;
35
48
 
49
+ /**Return true if userName is valid
50
+ * @param {string} num phone number
51
+ * @returns {boolean} true if phone number is valid, otherwise false.
52
+ */
36
53
  function isValidPhoneNum(num) {
37
54
  if (!num) // The number must be provided.
38
55
  return false;
@@ -42,6 +59,10 @@ function isValidPhoneNum(num) {
42
59
  }
43
60
  module.exports.isValidPhoneNum = isValidPhoneNum;
44
61
 
62
+ /**Return true if the name of an organisation is valid
63
+ * @param {string} name an organisation name
64
+ * @returns {boolean} true if an organisation name is valid, otherwise false.
65
+ */
45
66
  function isValidOrganisationName(name) {
46
67
  if (!name) // The name must be provided.
47
68
  return false;
@@ -51,6 +72,10 @@ function isValidOrganisationName(name) {
51
72
  }
52
73
  module.exports.isValidOrganisationName = isValidOrganisationName;
53
74
 
75
+ /**Return true if a password is valid
76
+ * @param {string} password
77
+ * @returns {boolean} true if a password is valid, otherwise false.
78
+ */
54
79
  function isValidPassword(password) {
55
80
  if (!password)
56
81
  return false;
@@ -83,9 +108,79 @@ function isValidPassword(password) {
83
108
  }
84
109
  module.exports.isValidPassword = isValidPassword;
85
110
 
111
+ /** Converts the date object to a string of the form CCYY-MM-DD
112
+ * @param {Date} dateObj
113
+ * @returns {string} string of the form CCYY-MM-DD
114
+ */
115
+ function timeStampYyyyMmDd(dateObj) {
116
+ // Convert the date to string form yyyy-mm-dd
117
+ let year = dateObj.getFullYear();
118
+ let month = dateObj.getMonth() + 1;
119
+ month = addLeadingZeros(month, 2);
120
+ let day = dateObj.getDate();
121
+ day = addLeadingZeros(day, 2);
122
+ return `${year}-${month}-${day}`;
123
+ } // function timeStampYYYYMMDd(dateObj) {
124
+ module.exports.timeStampYyyyMmDd = timeStampYyyyMmDd;
125
+
126
+ /** Converts a date object to a string of the form CCYY-MM-DDThh:mm:ss.ccc, e.g. '2024-02-25T15:00:25.251'
127
+ * @param {Date} dateObj
128
+ * @returns {string} a string of the form CCYY-MM-DDThh:mm:ss.ccc.
129
+ */
130
+ function timeStampString(dateObj) {
131
+ let hours = addLeadingZeros(dateObj.getHours(), 2);
132
+ let minutes = addLeadingZeros(dateObj.getMinutes(), 2);
133
+ let seconds = addLeadingZeros(dateObj.getSeconds(), 2);
134
+ let milliSec = addLeadingZeros(dateObj.getMilliseconds(), 3);
135
+ return `${timeStampYyyyMmDd(dateObj)}T${hours}:${minutes}:${seconds}.${milliSec}`;
136
+ } // function timeStampString(dateObj) {
137
+ module.exports.timeStampString = timeStampString;
138
+
139
+
140
+ /** Return a numeric string with trailing zeros.
141
+ * E.g. addLeadingZeros(9, 3) = '009'
142
+ * Inputs:
143
+ * @param {Number} aNumber an integer or integer string.
144
+ * @param {Number} newLength the new length of the resulting string.
145
+ * @returns a string of a number with the specified number of leading zeros.
146
+ */
147
+ function addLeadingZeros(aNumber, newLength) {
148
+
149
+ let newString = aNumber + '';
150
+ const howManyZeros = newLength - newString.length;
151
+ for (let count = 1; count <= howManyZeros; count++)
152
+ newString = '0' + newString;
153
+
154
+ return newString;
155
+ } // function addLeadingZeros(aString, newLength) {
156
+ module.exports.addLeadingZeros = addLeadingZeros;
157
+
158
+ /**Convert numeric input to ZAR currency format string.
159
+ * @param {Number} a number
160
+ * @returns a string of the form R 256,534.00
161
+ */
162
+ function toZarCurrencyFormat(number) {
163
+ const zarCurrencyFormat = new Intl.NumberFormat('en-US', {style: 'currency', currency: 'ZAR'});
164
+ return zarCurrencyFormat.format(number).replace(/ZAR/gi, 'R');
165
+ }
166
+ module.exports.toZarCurrencyFormat = toZarCurrencyFormat;
167
+
168
+ /**Return a deep clone of a document object.
169
+ * By using deep cloning, you create a new object that is entirely separate from the original original.
170
+ * So that whatever you do to that clone, such as deletion of fields, does not affect the original.
171
+ * NB. Class instance types will be converted to plain object types due to stringification.
172
+ * @param {object} obj a plain Javascript object.
173
+ * @returns a Javascript object that is separate from the original object.
174
+ */
175
+ function deepClone(obj) {
176
+ return JSON.parse(JSON.stringify(obj));
177
+ } // function deepClone(obj) { // Return a deep clone of an object.
178
+ module.exports.deepClone = deepClone;
179
+
180
+
86
181
  /**
87
182
  * Get the paths (fields) of the plain Javascript object.
88
- * @param {object} anObject
183
+ * @param {object} anObject a plain Javascript object.
89
184
  * @returns a sorted string array of paths.
90
185
  */
91
186
  function getPaths(anObject) {
@@ -108,11 +203,32 @@ function getPaths(anObject) {
108
203
  } // function getPaths()
109
204
  module.exports.getPaths = getPaths;
110
205
 
206
+ /** Return an object with sorted fields, by ordered by field name ascending.
207
+ * This is desirable when equality comparison is done to ensure two objects sharing equal field values
208
+ * the pass the equality test stringify(object1) === stringify(object2)
209
+ * @param {object} pObject
210
+ * @returns {object} an object with fields sorted in ascending order of field names.
211
+ */
212
+ function getSortedObject(pObject) {
213
+
214
+ const paths = getPaths(pObject);
215
+ paths.sort();
216
+ const sortedObject = {};
217
+
218
+ for (let index in paths) {
219
+ const path = paths[index];
220
+ const value = loDash.get(pObject, path);
221
+ loDash.set(sortedObject, path, value);
222
+ } // for (index in paths) {
223
+ return sortedObject;
224
+ } // function getSortedObject(pObject) {
225
+ module.exports.getSortedObject = getSortedObject;
226
+
111
227
  /**
112
- * Determine whether an object contains only some or all of the specified fields, and not any other fields.
113
- * @param {*} anObject a Javascript object.
228
+ * Determine whether an object contains only 1, some or all of the specified fields, and not any other fields.
229
+ * @param {object} anObject a Javascript object.
114
230
  * @param {...string} fields one or more field names.
115
- * @returns boolean.
231
+ * @returns boolean true or false.
116
232
  */
117
233
  function hasOnly(anObject, ...fields) {
118
234
  if (!fields || !fields.length)
@@ -134,10 +250,10 @@ function hasOnly(anObject, ...fields) {
134
250
  module.exports.hasOnly = hasOnly;
135
251
 
136
252
  /**
137
- * Determine whether an object contains all of the specified fields. It may have additional fields.
138
- * @param {*} anObject a Javascript object.
253
+ * Determine whether an object contains all of the specified fields in addition to other fields.
254
+ * @param {object} anObject a Javascript object.
139
255
  * @param {...string} fields one or field names.
140
- * @returns boolean.
256
+ * @returns boolean true or false.
141
257
  */
142
258
  function hasAll(anObject, ...fields) {
143
259
  if (!fields || !fields.length)
@@ -160,9 +276,9 @@ module.exports.hasAll = hasAll;
160
276
 
161
277
  /**
162
278
  * Determine whether an object contains only all of the specified fields. Nothing more, nothing less.
163
- * @param {*} anObject a Javascript object.
279
+ * @param {object} anObject a Javascript object.
164
280
  * @param {...string} fields one or field names.
165
- * @returns boolean.
281
+ * @returns boolean true or false.
166
282
  */
167
283
  function hasOnlyAll(anObject, ...fields) {
168
284
  return hasOnly(anObject, ...fields) && hasAll(anObject, ...fields);
@@ -175,6 +291,11 @@ module.exports.hasOnlyAll = hasOnlyAll;
175
291
  * otherwise, the index is of closest value in the array that is before or after the search value in terms of sort order.
176
292
  * Return -1 for an empty array.
177
293
  * This function is to be used also in cases where values are to be inserted into the array while maintaining sort order.
294
+ * @param {Array} anArray an array of primitve type. All element must be the same type.
295
+ * @param {*} searchVal search value
296
+ * @param {number} [startFrom=0] index from which to start. Default: 0.
297
+ * @param {string} [arraySortDir='asc'] sort direction. Must be 'asc' or 'desc'. Default: 'asc'
298
+ * @returns {number} an index
178
299
  */
179
300
  function binarySearch(anArray, searchVal, startFrom = 0, arraySortDir = 'asc') {
180
301
 
@@ -212,7 +333,10 @@ module.exports.binarySearch = binarySearch;
212
333
  * A return value of -1 means that value1 is before value2 in terms of sort order.
213
334
  * A return value of 1 means that value1 is after value2 in terms of sort order.
214
335
  * A return value of 0 means that value1 is equal to value2.
215
- * Sort directions: 'asc', 'desc'. Default is 'asc'.
336
+ * @param {*} value1
337
+ * @param {*} value2
338
+ * @param {string} [sortDir='asc']
339
+ * @returns {number} integer (-1, 0 or 1)
216
340
  */
217
341
  function compare(value1, value2, sortDir = 'asc') {
218
342
  if (!['asc', 'desc'].includes(sortDir))
@@ -236,8 +360,13 @@ module.exports.compare = compare;
236
360
  * Return -1 for an empty array.
237
361
  * Assumed field data types are Number, String and Date.
238
362
  * This function is to be used also in cases where objects are to be inserted into the array while maintaining sort order.
363
+ * @param {Array<object} objArray an array of Javascript objects.
364
+ * @param {object} searchObj an object to search for.
365
+ * @@param {number} [startFrom=0] index from which to start searching.
366
+ * @param {...string} sortFields one or more search fields.
367
+ * @returns {number} an index.
239
368
  */
240
- function binarySearchObj(objArray, searchObj, startFrom, ...sortFields) {
369
+ function binarySearchObj(objArray, searchObj, startFrom = 0, ...sortFields) {
241
370
  if (objArray.length === 0)
242
371
  return -1;
243
372
 
@@ -264,7 +393,7 @@ function binarySearchObj(objArray, searchObj, startFrom, ...sortFields) {
264
393
  } // function binarySearchObj(objArray, searchObj, ...comparisonFields) {
265
394
  module.exports.binarySearchObj = binarySearchObj;
266
395
 
267
- /**Create an array with duplicates eliminated. Taking only the first or last object from each duplicate set.
396
+ /**Create an array with duplicates eliminated, according to certain fields. Taking only the first or last object from each duplicate set.
268
397
  * If firstOfDuplicates === true, then the first element in each set of duplicates is taken.
269
398
  * if firstOfDuplicates === false, then the last element is taken from each set of duplicates.
270
399
  * Assumed field data types are Number, String and Date.
@@ -272,6 +401,10 @@ module.exports.binarySearchObj = binarySearchObj;
272
401
  * The value of the comparison field must include both the field name and sort direction.
273
402
  * Sort direction assumed to be "asc" if not provided.
274
403
  * Examples of comparison fields: "firstName", "lastName desc", "address.province asc", "address.townOrCity".
404
+ * @param {Array<object>} objArray an input array of objects
405
+ * @param {boolean} firstOfDuplicates specify whether to take the first or last object in each a duplicate set.
406
+ * @param {...string} comparisonFields comparison fieds plus sort order.
407
+ * @returns {Array<object>} an array with no duplicates.
275
408
  */
276
409
  function getObjArrayWithNoDuplicates(objArray, firstOfDuplicates, ...comparisonFields) {
277
410
  function getNextSearchObj(pNext) {
@@ -367,6 +500,9 @@ module.exports.getObjArrayWithNoDuplicates = getObjArrayWithNoDuplicates;
367
500
  * Sort directions: 'asc', 'desc'.
368
501
  * Examples: 'lastName desc', 'firstName', 'firstName asc', 'address.provinceName asc'.
369
502
  * If sort direction is not provided, then it is assumed to be ascending.
503
+ * @param {object} obj1 first object to compare
504
+ * @param {object} obj2 second object to compare
505
+ * @returns {number} a comparison value of 1, 0 or -1
370
506
  */
371
507
  function objCompare(obj1, obj2, ...comparisonFields) {
372
508
  if (comparisonFields.length === 0)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "some-common-functions-js",
3
- "version": "1.0.9",
3
+ "version": "1.1.0",
4
4
  "description": "Common functions used with Javascript objects, and field validation functions.",
5
5
  "keywords": [
6
6
  "validation",