@cocreate/utils 1.31.0 → 1.32.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/package.json +1 -1
  3. package/src/index.js +185 -143
package/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ # [1.32.0](https://github.com/CoCreate-app/CoCreate-utils/compare/v1.31.0...v1.32.0) (2024-01-17)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * getValueFromObject conditions and param names ([2fd7387](https://github.com/CoCreate-app/CoCreate-utils/commit/2fd73873cc42d0a22e43e04fee35f31227790f7b))
7
+ * getValueFromObject param trowError boolean will trow erro if property does not exist vs returning undefined ([39a9cab](https://github.com/CoCreate-app/CoCreate-utils/commit/39a9cabb9e109d1aae6a695ba47d76c95c8581f6))
8
+ * renamed isMatch to queryMatch ([b3c9429](https://github.com/CoCreate-app/CoCreate-utils/commit/b3c942950661b1d906c9f8a77a3bbd2f5693fd47))
9
+ * update to support new query system ([a267b52](https://github.com/CoCreate-app/CoCreate-utils/commit/a267b5260955a631330a2b22bd9fb316a00004c6))
10
+
11
+
12
+ ### Features
13
+
14
+ * query() function to handle queries similar to mongodb ([164bf45](https://github.com/CoCreate-app/CoCreate-utils/commit/164bf45d44f620fe8e6a4cf75fe744be68277d6c))
15
+ * sort by multiple keys ([7872a53](https://github.com/CoCreate-app/CoCreate-utils/commit/7872a5308bcf510e40385c57b45c0d899a40295a))
16
+
1
17
  # [1.31.0](https://github.com/CoCreate-app/CoCreate-utils/compare/v1.30.0...v1.31.0) (2024-01-08)
2
18
 
3
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/utils",
3
- "version": "1.31.0",
3
+ "version": "1.32.0",
4
4
  "description": "A simple utils component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "utils",
package/src/index.js CHANGED
@@ -142,32 +142,36 @@
142
142
  }
143
143
  }
144
144
 
145
- function getValueFromObject(json, path) {
145
+ function getValueFromObject(object = {}, path = '', throwError = false) {
146
146
  try {
147
- if (typeof json == 'undefined' || !path)
148
- return;
147
+ if (!Object.keys(object).length || !path) {
148
+ if (throwError)
149
+ throw new Error("Invalid input to getValueFromObject");
150
+ return
151
+
152
+ }
149
153
 
150
154
  path = path.replace(/\[(\d+)\]/g, '.$1');
151
155
 
152
- let jsonData = json, subpath = path.split('.');
156
+ let data = object, subpath = path.split('.');
153
157
 
154
158
  for (let i = 0; i < subpath.length; i++) {
155
- jsonData = jsonData[subpath[i]];
156
- if (!jsonData)
157
- return jsonData;
159
+ if (throwError && !(subpath[i] in data))
160
+ throw new Error("Key not found in object: " + subpath[i]);
161
+
162
+ data = data[subpath[i]];
163
+ if (!data)
164
+ return;
158
165
  }
159
- return jsonData;
166
+
167
+ return data;
160
168
  } catch (error) {
161
- console.log("Error in getValueFromObject", error);
162
- return;
169
+ // console.error("Error in getValueFromObject:", error);
170
+ if (throwError)
171
+ throw error;
163
172
  }
164
173
  }
165
174
 
166
- function isObjectEmpty(obj) {
167
- for (var x in obj) { return false }
168
- return true;
169
- }
170
-
171
175
  function domParser(str) {
172
176
  try {
173
177
  var mainTag = str.match(/\<(?<tag>[a-z0-9]+)(.*?)?\>/).groups.tag;
@@ -298,6 +302,7 @@
298
302
  }
299
303
 
300
304
  if (Selector) {
305
+ // let selectors = Selector.split(/,(?![^()]*\))/g);
301
306
 
302
307
  let selectors = Selector.split(',');
303
308
  for (let j = 0; j < selectors.length; j++) {
@@ -418,146 +423,153 @@
418
423
  return selector
419
424
  }
420
425
 
421
-
422
426
  function queryData(data, query) {
423
- if (!data)
424
- return false;
425
-
426
- if (!Array.isArray(data))
427
- data = [data]
427
+ if (query.$and) {
428
+ for (let i = 0; i < query.$and.length; i++) {
429
+ if (!queryData(data, query.$and[i]))
430
+ return false
431
+ }
432
+ }
428
433
 
429
- if (!query)
430
- return true
434
+ if (query.$nor) {
435
+ for (let i = 0; i < query.$nor.length; i++) {
436
+ if (queryData(data, query.$nor[i]))
437
+ return false;
438
+ }
439
+ }
431
440
 
432
- if (!Array.isArray(query))
433
- query = [query]
434
- if (!query.length)
435
- return true
441
+ for (let key of Object.keys(query)) {
442
+ if (key === '$and' || key === '$or')
443
+ continue
444
+ if (!queryMatch(data, { [key]: query[key] }))
445
+ return false
446
+ }
436
447
 
437
- let queryResult = false
438
- for (let n = 0; n < data.length; n++) {
439
- for (let i = 0; i < query.length; i++) {
440
- let dataValue
441
- if (query[i].key.includes('.') || /\[([0-9]*)\]/g.test(query[i].key))
442
- dataValue = getValueFromObject(data[n], query[i].key)
443
- else
444
- dataValue = data[n][query[i].key]
445
- if (dataValue == undefined)
446
- dataValue = ''
447
- let logicalOperator = query[i].logicalOperator || 'and'
448
- let queryValues = query[i].value
449
-
450
- let queryIsArray = false
451
- if (!Array.isArray(queryValues))
452
- queryValues = [queryValues]
453
- else
454
- queryIsArray = true
448
+ if (query.$or) {
449
+ for (let i = 0; i < query.$or.length; i++) {
450
+ if (queryData(data, query.$or[i]))
451
+ return true
452
+ }
453
+ }
455
454
 
455
+ return true;
456
+ }
456
457
 
457
- let queryStatus = false
458
- for (let queryValue of queryValues) {
459
- if (query[i].caseSensitive != 'true' || query[i].caseSensitive != true) {
460
- if (typeof dataValue == 'string')
461
- dataValue = dataValue.toLowerCase()
462
- if (typeof queryValue == 'string')
463
- queryValue = queryValue.toLowerCase()
464
- }
458
+ function queryMatch(data, query) {
459
+ for (let key of Object.keys(query)) {
460
+ // if (!data.hasOwnProperty(key))
461
+ // return false
465
462
 
466
- if (isValidDate(dataValue) && isValidDate(queryValue)) {
467
- dataValue = new Date(dataValue)
468
- queryValue = new Date(queryValue)
469
- }
470
- switch (query[i].operator) {
471
- case '$includes':
472
- case 'includes':
473
- if (dataValue.includes(queryValue))
474
- queryStatus = true
475
- // if (queryValue === "" && logicalOperator === 'and') {
476
- // if (dataValue !== "")
477
- // queryStatus = false
478
- // }
479
- break;
480
- case '$eq':
481
- if (dataValue == queryValue)
482
- queryStatus = true
483
- break;
484
- case '$ne':
485
- if (Array.isArray(dataValue)) {
486
- // Check if the entire array is different from queryValue
487
- queryStatus = !isEqualArray(dataValue, queryValue);
488
- } else if (Array.isArray(queryValue)) {
489
- // If queryValue is an array, check if dataValue is different from this array
490
- queryStatus = !isEqualArray(queryValue, dataValue);
491
- } else {
492
- // If neither is an array, simple comparison
493
- queryStatus = (dataValue != queryValue);
494
- }
495
- break;
496
- case '$lt':
497
- if (dataValue < queryValue)
498
- queryStatus = true
499
- break;
500
- case '$lte':
501
- if (dataValue <= queryValue)
502
- queryStatus = true
503
- break;
504
- case '$gt':
505
- if (dataValue > queryValue)
506
- queryStatus = true
507
- break;
508
- case '$gte':
509
- if (dataValue >= queryValue)
510
- queryStatus = true
511
- break;
512
- case '$in':
513
- if (Array.isArray(dataValue)) {
514
- queryStatus = dataValue.some(element => queryValue.includes(element));
515
- } else {
516
- queryStatus = queryValue.includes(dataValue);
517
- }
518
- break;
519
- case '$nin':
520
- if (Array.isArray(dataValue)) {
521
- queryStatus = !dataValue.some(element => queryValue.includes(element));
522
- } else {
523
- queryStatus = !queryValue.includes(dataValue);
524
- }
525
- break;
526
- case '$range':
527
- if (queryValue[0] !== null && queryValue[1] !== null) {
528
- if (dataValue >= queryValue[0] && dataValue <= queryValue[1])
529
- queryStatus = true
530
- } else if (queryValue[0] == null && dataValue <= queryValue[1]) {
531
- queryStatus = true
532
- } else if (queryValue[1] == null && dataValue >= queryValue[0]) {
533
- queryStatus = true
534
- }
535
- break;
463
+ let dataValue
464
+ try {
465
+ dataValue = getValueFromObject(data, key, true)
466
+ } catch (error) {
467
+ return false
468
+ }
536
469
 
537
- default:
538
- if (dataValue.includes(queryValue))
539
- queryStatus = true
540
- break;
541
- }
542
- if (!queryIsArray || query[i].operator === "$nin") {
543
- switch (logicalOperator) {
544
- case 'and':
545
- if (queryStatus == false)
546
- return false
470
+ if (typeof query[key] === 'string' || typeof query[key] === 'number' || typeof query[key] === 'boolean') {
471
+ if (Array.isArray(dataValue))
472
+ return dataValue.includes(query[key])
473
+ else
474
+ return dataValue === query[key]
475
+ } else if (Array.isArray(query[key])) {
476
+ if (Array.isArray(dataValue)) {
477
+ return isEqualArray(dataValue, query[key]);
478
+ } else {
479
+ return false;
480
+ }
481
+ } else {
482
+ for (let property of Object.keys(query[key])) {
483
+ if (!property.startsWith('$')) {
484
+ if (typeof dataValue !== 'object') {
485
+ return false;
486
+ } else
487
+ return queryMatch({ [property]: getValueFromObject(dataValue, property) }, { [property]: query[key][property] })
488
+ } else {
489
+ let queryValue = query[key][property]
490
+ let queryStatus = false
491
+ switch (property) {
492
+ case '$eq':
493
+ if (Array.isArray(dataValue) && Array.isArray(queryValue)) {
494
+ queryStatus = isEqualArray(dataValue, queryValue);
495
+ } else {
496
+ queryStatus = (dataValue === queryValue);
497
+ }
498
+ break;
499
+ case '$ne':
500
+ if (Array.isArray(dataValue) && Array.isArray(queryValue)) {
501
+ queryStatus = !isEqualArray(dataValue, queryValue);
502
+ } else {
503
+ queryStatus = (dataValue !== queryValue);
504
+ }
505
+ break;
506
+ case '$not':
507
+ queryStatus = !queryMatch(data, { [key]: query[key]['$not'] });
508
+ break;
509
+ case '$lt':
510
+ queryStatus = (dataValue < queryValue)
511
+ break;
512
+ case '$lte':
513
+ queryStatus = (dataValue <= queryValue)
514
+ break;
515
+ case '$gt':
516
+ queryStatus = (dataValue > queryValue)
517
+ break;
518
+ case '$gte':
519
+ queryStatus = (dataValue >= queryValue)
520
+ break;
521
+ case '$in':
522
+ if (Array.isArray(dataValue)) {
523
+ queryStatus = dataValue.some(element => queryValue.includes(element));
524
+ } else {
525
+ queryStatus = queryValue.includes(dataValue);
526
+ }
527
+ break;
528
+ case '$nin':
529
+ if (Array.isArray(dataValue)) {
530
+ queryStatus = !dataValue.some(element => queryValue.includes(element));
531
+ } else {
532
+ queryStatus = !queryValue.includes(dataValue);
533
+ }
534
+ break;
535
+ case '$all':
536
+ if (Array.isArray(dataValue) && Array.isArray(queryValue)) {
537
+ queryStatus = queryValue.every(element => dataValue.includes(element));
538
+ }
539
+ break;
540
+ case '$elemMatch':
541
+ if (Array.isArray(data[key])) {
542
+ queryStatus = data[key].some(element => queryMatch(element, query[key][property]));
543
+ }
544
+ break;
545
+ case '$size':
546
+ if (Array.isArray(dataValue)) {
547
+ queryStatus = (dataValue.length === queryValue);
548
+ }
549
+ break;
550
+ case '$exists':
551
+ queryStatus = (queryValue ? data.hasOwnProperty(key) : !data.hasOwnProperty(key));
547
552
  break;
548
- // case 'or':
549
- // if (queryStatus == true)
550
- // queryResult = queryStatus
551
- // break;
553
+ case '$regex':
554
+ if (typeof dataValue === 'string') {
555
+ let regex = new RegExp(queryValue);
556
+ queryStatus = regex.test(dataValue);
557
+ }
558
+ break;
559
+ default:
560
+ console.log('unknown operator')
561
+ break;
562
+
552
563
  }
553
- } else if (queryStatus && query[i].operator === "$in")
554
- return true
555
- queryResult = queryStatus
564
+ if (!queryStatus)
565
+ return false
566
+
567
+ }
556
568
  }
569
+ return true
557
570
  }
558
- }
559
571
 
560
- return queryResult;
572
+ }
561
573
  }
562
574
 
563
575
  function isEqualArray(arr1, arr2) {
@@ -643,7 +655,38 @@
643
655
  return true
644
656
  }
645
657
 
658
+
646
659
  function sortData(data, sort) {
660
+ return data.sort((a, b) => {
661
+ for (let i = 0; i < sort.length; i++) {
662
+ let key = sort[i].key;
663
+ if (a[key] == null && b[key] == null) continue;
664
+ if (a[key] == null)
665
+ return sort[i].direction === 'desc' ? -1 : 1;
666
+ if (b[key] == null)
667
+ return sort[i].direction === 'desc' ? 1 : -1;
668
+
669
+ if (typeof a[key] !== typeof b[key]) {
670
+ return typeof a[key] < typeof b[key] ? -1 : 1;
671
+ }
672
+
673
+ if (a[key] !== b[key]) {
674
+ if (typeof a[key] === 'string') {
675
+ return sort[i].direction === 'desc' ?
676
+ b[key].localeCompare(a[key]) :
677
+ a[key].localeCompare(b[key]);
678
+ } else { // Assuming numeric or other comparable types
679
+ return sort[i].direction === 'desc' ?
680
+ (b[key] - a[key]) :
681
+ (a[key] - b[key]);
682
+ }
683
+ }
684
+ }
685
+ return 0;
686
+ });
687
+ }
688
+
689
+ function sortDataOld(data, sort) {
647
690
  if (!Array.isArray(sort))
648
691
  sort = [sort]
649
692
  for (let i = 0; i < sort.length; i++) {
@@ -748,7 +791,6 @@
748
791
  isValidDate,
749
792
  dotNotationToObject,
750
793
  getValueFromObject,
751
- isObjectEmpty,
752
794
  domParser,
753
795
  parseTextToHtml,
754
796
  escapeHtml,