@cocreate/indexeddb 1.13.5 → 1.14.1
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/.github/workflows/automated.yml +0 -26
- package/CHANGELOG.md +22 -0
- package/package.json +2 -2
- package/src/index.js +233 -71
- package/test/index.html +3 -2
- package/test/operators.js +105 -0
|
@@ -41,30 +41,4 @@ jobs:
|
|
|
41
41
|
outputs:
|
|
42
42
|
new_release_published: "${{ steps.semantic.outputs.new_release_published }}"
|
|
43
43
|
new_release_version: "${{ steps.semantic.outputs.new_release_version }}"
|
|
44
|
-
upload:
|
|
45
|
-
runs-on: ubuntu-latest
|
|
46
|
-
needs: release
|
|
47
|
-
if: needs.release.outputs.new_release_published == 'true'
|
|
48
|
-
env:
|
|
49
|
-
VERSION: "${{ needs.release.outputs.new_release_version }}"
|
|
50
|
-
steps:
|
|
51
|
-
- name: Checkout
|
|
52
|
-
uses: actions/checkout@v3
|
|
53
|
-
- name: Setup Node.js
|
|
54
|
-
uses: actions/setup-node@v3
|
|
55
|
-
with:
|
|
56
|
-
node-version: 16
|
|
57
|
-
- name: Set npm registry auth
|
|
58
|
-
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
|
|
59
|
-
- name: Install dependencies
|
|
60
|
-
run: yarn install
|
|
61
|
-
- name: Build
|
|
62
|
-
run: yarn build
|
|
63
|
-
- name: Set Environment Variables
|
|
64
|
-
run: |
|
|
65
|
-
echo "organization_id=${{ secrets.COCREATE_ORGANIZATION_ID }}" >> $GITHUB_ENV
|
|
66
|
-
echo "key=${{ secrets.COCREATE_KEY }}" >> $GITHUB_ENV
|
|
67
|
-
echo "host=${{ secrets.COCREATE_HOST }}" >> $GITHUB_ENV
|
|
68
|
-
- name: CoCreate Upload
|
|
69
|
-
run: coc upload
|
|
70
44
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## [1.14.1](https://github.com/CoCreate-app/CoCreate-indexeddb/compare/v1.14.0...v1.14.1) (2023-10-09)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* bump cocreate dependency versions ([147ab07](https://github.com/CoCreate-app/CoCreate-indexeddb/commit/147ab073cb7a86a5246c73657f9423e8ccdcd9cd))
|
|
7
|
+
|
|
8
|
+
# [1.14.0](https://github.com/CoCreate-app/CoCreate-indexeddb/compare/v1.13.5...v1.14.0) (2023-10-09)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* cursor() iteration bug ([394d1e9](https://github.com/CoCreate-app/CoCreate-indexeddb/commit/394d1e98d56f94b1495aad44a78718d56199b728))
|
|
14
|
+
* data.request and data.timeStamp conditions ([bf28152](https://github.com/CoCreate-app/CoCreate-indexeddb/commit/bf28152bf181ea0ad4552a5d829f5b0c0d87396c))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* $each operator adds each item to an array ([b085764](https://github.com/CoCreate-app/CoCreate-indexeddb/commit/b08576473b25534333d768930d97834fda885ff4))
|
|
20
|
+
* isValidDate imported from utils to check key values for date strings and convert to object ([a822f9b](https://github.com/CoCreate-app/CoCreate-indexeddb/commit/a822f9b97bbb11ab87b0ae47dcd543877b6c1cb4))
|
|
21
|
+
* support update operators similar to mongodb ([dc7bd71](https://github.com/CoCreate-app/CoCreate-indexeddb/commit/dc7bd71c57bcae8ad1760b01ebfe406aec3f8800))
|
|
22
|
+
|
|
1
23
|
## [1.13.5](https://github.com/CoCreate-app/CoCreate-indexeddb/compare/v1.13.4...v1.13.5) (2023-09-18)
|
|
2
24
|
|
|
3
25
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/indexeddb",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.1",
|
|
4
4
|
"description": "A simple indexeddb component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"indexeddb",
|
|
@@ -58,6 +58,6 @@
|
|
|
58
58
|
"webpack-log": "^3.0.1"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@cocreate/utils": "^1.
|
|
61
|
+
"@cocreate/utils": "^1.25.0"
|
|
62
62
|
}
|
|
63
63
|
}
|
package/src/index.js
CHANGED
|
@@ -15,15 +15,18 @@
|
|
|
15
15
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
16
|
********************************************************************************/
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Commercial Licensing Information:
|
|
20
|
+
* For commercial use of this software without the copyleft provisions of the AGPLv3,
|
|
21
|
+
* you must obtain a commercial license from CoCreate LLC.
|
|
22
|
+
* For details, visit <https://cocreate.app/licenses/> or contact us at sales@cocreate.app
|
|
23
|
+
*/
|
|
22
24
|
|
|
23
|
-
import { ObjectId, dotNotationToObject, searchData, sortData, queryData } from '@cocreate/utils'
|
|
25
|
+
import { ObjectId, dotNotationToObject, searchData, sortData, queryData, isValidDate } from '@cocreate/utils'
|
|
24
26
|
|
|
25
27
|
// let status = true;
|
|
26
28
|
let indexedDbFunction
|
|
29
|
+
|
|
27
30
|
function init() {
|
|
28
31
|
// Check for support.
|
|
29
32
|
if (!('indexedDB' in window)) {
|
|
@@ -73,9 +76,13 @@ async function send(data) {
|
|
|
73
76
|
data[type] = data.request
|
|
74
77
|
|
|
75
78
|
if (!data['timeStamp'])
|
|
76
|
-
data['timeStamp'] = new Date()
|
|
79
|
+
data['timeStamp'] = new Date()
|
|
80
|
+
else
|
|
81
|
+
data['timeStamp'] = new Date(data['timeStamp'])
|
|
77
82
|
|
|
78
83
|
let databases = data.database;
|
|
84
|
+
if (!databases && data.organization_id)
|
|
85
|
+
databases = [data.organization_id]
|
|
79
86
|
if (!Array.isArray(databases))
|
|
80
87
|
databases = [databases]
|
|
81
88
|
|
|
@@ -112,8 +119,8 @@ const processDatabase = (data, newData, type) => {
|
|
|
112
119
|
if (data.request)
|
|
113
120
|
data[type] = data.request
|
|
114
121
|
|
|
115
|
-
if (!data['timeStamp'])
|
|
116
|
-
|
|
122
|
+
// if (!data['timeStamp'])
|
|
123
|
+
data['timeStamp'] = new Date(data['timeStamp'])
|
|
117
124
|
|
|
118
125
|
if (data.method == 'read.database') {
|
|
119
126
|
indexedDB.databases().then((databases) => {
|
|
@@ -121,9 +128,9 @@ const processDatabase = (data, newData, type) => {
|
|
|
121
128
|
if (data.$filter && data.$filter.query) {
|
|
122
129
|
let isFilter = queryData(database, data.$filter.query)
|
|
123
130
|
if (isFilter)
|
|
124
|
-
newData.push({ $storage: 'indexeddb',
|
|
131
|
+
newData.push({ $storage: 'indexeddb', ...database })
|
|
125
132
|
} else
|
|
126
|
-
newData.push({ $storage: 'indexeddb',
|
|
133
|
+
newData.push({ $storage: 'indexeddb', ...database })
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
resolve()
|
|
@@ -435,20 +442,30 @@ async function processObject(data, newData, database, array, type) {
|
|
|
435
442
|
if (!array || !db)
|
|
436
443
|
throw new Error({ error: "This is an error message.", db, array });
|
|
437
444
|
|
|
438
|
-
let transactionType = "readwrite"
|
|
445
|
+
let transactionType = "readwrite" //test
|
|
439
446
|
if (data.method == 'read.object')
|
|
440
447
|
transactionType = "readonly"
|
|
441
448
|
|
|
442
449
|
let transaction = db.transaction([array], transactionType);
|
|
443
450
|
let objectStore = transaction.objectStore(array);
|
|
444
|
-
|
|
451
|
+
if (!data[type])
|
|
452
|
+
data[type] = []
|
|
445
453
|
if (data[type] && !Array.isArray(data[type]))
|
|
446
454
|
data[type] = [data[type]]
|
|
447
455
|
|
|
448
|
-
if (isFilter &&
|
|
456
|
+
if (isFilter && !data[type].length)
|
|
449
457
|
data[type] = [{}]
|
|
450
458
|
|
|
459
|
+
let globalOperators = getGlobalOperators(data)
|
|
451
460
|
let upsert = data.upsert
|
|
461
|
+
|
|
462
|
+
if (data.$filter) {
|
|
463
|
+
let count = objectStore.count();
|
|
464
|
+
count.onsuccess = function () {
|
|
465
|
+
data.$filter.count = count.result
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
452
469
|
try {
|
|
453
470
|
|
|
454
471
|
for (let i = 0; i < data[type].length; i++) {
|
|
@@ -457,6 +474,9 @@ async function processObject(data, newData, database, array, type) {
|
|
|
457
474
|
delete data[type][i].$array
|
|
458
475
|
|
|
459
476
|
if (data.method == 'create.object') {
|
|
477
|
+
if (data.organization_id)
|
|
478
|
+
data[type][i]['organization_id'] = data.organization_id
|
|
479
|
+
|
|
460
480
|
if (!data[type][i]._id)
|
|
461
481
|
data[type][i]['_id'] = ObjectId()
|
|
462
482
|
data[type][i] = dotNotationToObject(data[type][i])
|
|
@@ -467,15 +487,15 @@ async function processObject(data, newData, database, array, type) {
|
|
|
467
487
|
} else {
|
|
468
488
|
if (data[type][i].$filter)
|
|
469
489
|
isFilter = true
|
|
470
|
-
if (data.organization_id)
|
|
471
|
-
|
|
490
|
+
// if (data.organization_id)
|
|
491
|
+
// data[type][i]['organization_id'] = data.organization_id
|
|
472
492
|
|
|
473
493
|
if (data.method == 'update.object') {
|
|
494
|
+
if (data.organization_id)
|
|
495
|
+
data[type][i]['organization_id'] = data.organization_id
|
|
496
|
+
|
|
474
497
|
if (data[type][i].$upsert)
|
|
475
498
|
upsert = data[type][i].$upsert
|
|
476
|
-
|
|
477
|
-
if (!data[type][i]._id && upsert)
|
|
478
|
-
data[type][i]._id = ObjectId()
|
|
479
499
|
data[type][i]['modified'] = { on: data.timeStamp, by: data.user_id || data.clientId }
|
|
480
500
|
}
|
|
481
501
|
|
|
@@ -483,10 +503,10 @@ async function processObject(data, newData, database, array, type) {
|
|
|
483
503
|
if (data[type][i]._id)
|
|
484
504
|
range = IDBKeyRange.only(data[type][i]._id);
|
|
485
505
|
else if (isFilter) {
|
|
486
|
-
if (data
|
|
506
|
+
if (data.object.$filter) {
|
|
487
507
|
let count = objectStore.count();
|
|
488
508
|
count.onsuccess = function () {
|
|
489
|
-
data.$filter.count = count.result
|
|
509
|
+
data.object.$filter.count = count.result
|
|
490
510
|
}
|
|
491
511
|
}
|
|
492
512
|
|
|
@@ -529,52 +549,212 @@ async function processObject(data, newData, database, array, type) {
|
|
|
529
549
|
if (data.$filter.limit)
|
|
530
550
|
limit = data.$filter.limit
|
|
531
551
|
if (limit)
|
|
532
|
-
limit = index + limit;
|
|
552
|
+
limit = (index || 0) + limit;
|
|
533
553
|
}
|
|
534
554
|
}
|
|
535
555
|
|
|
536
|
-
|
|
537
|
-
if (cursor) {
|
|
538
|
-
let isMatch = true
|
|
539
|
-
|
|
540
|
-
if (isFilter)
|
|
541
|
-
isMatch = filter(objectStore, data[type][i], cursor.value)
|
|
542
|
-
|
|
543
|
-
if (isMatch !== false) {
|
|
544
|
-
let result
|
|
545
|
-
if (data.method == 'create.object') {
|
|
546
|
-
result = await add(objectStore, data[type][i])
|
|
547
|
-
} else if (data.method == 'read.object') {
|
|
548
|
-
result = await get(objectStore, data[type][i])
|
|
549
|
-
} else if (data.method == 'update.object') {
|
|
550
|
-
data[type][i] = dotNotationToObject(data[type][i], cursor.value)
|
|
551
|
-
data[type][i] = createUpdate(data, data[type][i])
|
|
552
|
-
result = await put(objectStore, data[type][i])
|
|
553
|
-
} else if (data.method == 'delete.object') {
|
|
554
|
-
result = await deleteObject(objectStore, data[type][i])
|
|
555
|
-
}
|
|
556
|
+
await openCursor(objectStore, range, direction, data, newData, isFilter, limit, database, array, upsert, type, i, globalOperators);
|
|
556
557
|
|
|
557
|
-
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
limit && limit == newData.length ? '' : cursor.continue();
|
|
561
|
-
|
|
562
|
-
} else if (index)
|
|
558
|
+
if (index)
|
|
563
559
|
newData = newData.slice(index)
|
|
560
|
+
|
|
564
561
|
}
|
|
562
|
+
|
|
565
563
|
}
|
|
566
564
|
} catch (error) {
|
|
565
|
+
console.log(error)
|
|
567
566
|
errorHandler(data, error, database, array)
|
|
568
567
|
}
|
|
569
568
|
|
|
570
569
|
db.close()
|
|
571
570
|
}
|
|
572
571
|
|
|
573
|
-
function
|
|
572
|
+
function getGlobalOperators(data, object = {}) {
|
|
573
|
+
for (let operator of Object.keys(data)) {
|
|
574
|
+
if (!operator.startsWith('$'))
|
|
575
|
+
return
|
|
576
|
+
for (let key of Object.keys(data[operator]))
|
|
577
|
+
object[operator + '.' + key] = data[operator][key]
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return object
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function createUpdate(update, data, globalOpertors) {
|
|
584
|
+
let operatorKeys = {}
|
|
585
|
+
if (globalOpertors)
|
|
586
|
+
operatorKeys = { ...globalOpertors }
|
|
587
|
+
|
|
588
|
+
Object.keys(data).forEach(key => {
|
|
589
|
+
if (key === '_id')
|
|
590
|
+
return
|
|
591
|
+
|
|
592
|
+
if (key.startsWith('$')) {
|
|
593
|
+
if (!key.includes('.'))
|
|
594
|
+
for (let oldkey of Object.keys(data[key]))
|
|
595
|
+
operatorKeys[key + '.' + oldkey] = data[key][oldkey]
|
|
596
|
+
else
|
|
597
|
+
operatorKeys[key] = data[key]
|
|
598
|
+
} else if (typeof data[key] === 'string' && data[key].startsWith('$')) {
|
|
599
|
+
operatorKeys[data[key] + '.' + key] = data[key]
|
|
600
|
+
} else if (key.endsWith(']')) {
|
|
601
|
+
const regex = /^(.*(?:\[\d+\].*?)?)\[(.*?)\](?:\[\])?$/;
|
|
602
|
+
const match = key.match(regex);
|
|
603
|
+
if (match[2] === '')
|
|
604
|
+
operatorKeys['$push.' + match[1]] = data[key]
|
|
605
|
+
else {
|
|
606
|
+
let index = parseInt(match[2], 10);
|
|
607
|
+
if (index === NaN)
|
|
608
|
+
operatorKeys[match[2] + '.' + match[1]] = data[key]
|
|
609
|
+
else
|
|
610
|
+
operatorKeys[key] = data[key]
|
|
611
|
+
}
|
|
612
|
+
} else if (key.includes('.')) {
|
|
613
|
+
operatorKeys[key] = data[key]
|
|
614
|
+
} else if (data[key] === undefined) {
|
|
615
|
+
delete update[key]
|
|
616
|
+
} else
|
|
617
|
+
update[key] = data[key]
|
|
618
|
+
|
|
619
|
+
})
|
|
620
|
+
|
|
621
|
+
return dotNotationToObjectUpdate(operatorKeys, update)
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
function dotNotationToObjectUpdate(data, object = {}) {
|
|
625
|
+
try {
|
|
626
|
+
for (const key of Object.keys(data)) {
|
|
627
|
+
let value = isValidDate(data[key])
|
|
628
|
+
let newObject = object
|
|
629
|
+
let oldObject = new Object(newObject)
|
|
630
|
+
let keys = key.replace(/\[(\d+)\]/g, '.$1').split('.');
|
|
631
|
+
|
|
632
|
+
if (keys[0].startsWith('$'))
|
|
633
|
+
var operator = keys.shift()
|
|
634
|
+
|
|
635
|
+
let length = keys.length - 1
|
|
636
|
+
for (let i = 0; i < keys.length; i++) {
|
|
637
|
+
if (/^\d+$/.test(keys[i]))
|
|
638
|
+
keys[i] = parseInt(keys[i]);
|
|
639
|
+
|
|
640
|
+
if (length == i) {
|
|
641
|
+
if (operator) {
|
|
642
|
+
let operators = ['$rename', '$inc', '$push', '$each', '$splice', '$unset', '$delete', '$slice', '$pop', '$shift', '$addToSet', '$pull']
|
|
643
|
+
if (!operators.includes(operator))
|
|
644
|
+
continue
|
|
645
|
+
if (operator === '$rename') {
|
|
646
|
+
newObject[value] = newObject[keys[i]]
|
|
647
|
+
delete newObject[keys[i]]
|
|
648
|
+
} else if (operator === '$delete' || operator === '$unset' || operator === '$slice') {
|
|
649
|
+
if (typeof keys[i] === 'number')
|
|
650
|
+
newObject.slice(keys[i], 1);
|
|
651
|
+
else
|
|
652
|
+
delete newObject[keys[i]]
|
|
653
|
+
} else if (operator === '$shift') {
|
|
654
|
+
newObject[keys[i]].shift();
|
|
655
|
+
} else if (operator === '$pop') {
|
|
656
|
+
newObject[keys[i]].pop();
|
|
657
|
+
} else if (operator === '$addToSet' || operator === '$pull') {
|
|
658
|
+
// find matching items and update or delete
|
|
659
|
+
key = arrayKey
|
|
660
|
+
updates[key] = data[originalKey]
|
|
661
|
+
} else if (operator === '$push' || operator === '$splice') {
|
|
662
|
+
if (typeof keys[i] === 'number' && newObject.length >= keys[i])
|
|
663
|
+
newObject.splice(keys[i], 0, value);
|
|
664
|
+
else
|
|
665
|
+
newObject[keys[i]].push(value);
|
|
666
|
+
} else if (operator === '$each') {
|
|
667
|
+
if (!Array.isArray(value))
|
|
668
|
+
value = [value]
|
|
669
|
+
if (typeof keys[i] === 'number')
|
|
670
|
+
newObject.splice(keys[i], 0, ...value);
|
|
671
|
+
else
|
|
672
|
+
newObject[keys[i]].push(...value);
|
|
673
|
+
} else if (operator === '$inc') {
|
|
674
|
+
newObject[keys[i]] += value
|
|
675
|
+
}
|
|
676
|
+
} else if (value === undefined) {
|
|
677
|
+
if (typeof keys[i] === 'number')
|
|
678
|
+
newObject.slice(keys[i], 1);
|
|
679
|
+
else
|
|
680
|
+
delete newObject[keys[i]]
|
|
681
|
+
} else
|
|
682
|
+
newObject[keys[i]] = value;
|
|
683
|
+
} else {
|
|
684
|
+
newObject[keys[i]] = oldObject[keys[i]] || {};
|
|
685
|
+
newObject = newObject[keys[i]]
|
|
686
|
+
oldObject = oldObject[keys[i]]
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
return object
|
|
691
|
+
} catch (error) {
|
|
692
|
+
console.log("Error converting dot notation to object", error);
|
|
693
|
+
return false;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
function openCursor(objectStore, range, direction, data, newData, isFilter, limit, database, array, upsert, type, i, globalOperators) {
|
|
574
698
|
return new Promise(async (resolve, reject) => {
|
|
575
|
-
const request = objectStore.openCursor(range, direction);// next, prev
|
|
576
|
-
|
|
577
|
-
request.
|
|
699
|
+
const request = objectStore.openCursor(range || null, direction);// next, prev
|
|
700
|
+
|
|
701
|
+
request.onsuccess = async () => {
|
|
702
|
+
let cursor = request.result
|
|
703
|
+
|
|
704
|
+
if (!cursor && data.method === 'update.object' && upsert) {
|
|
705
|
+
let isMatch = true
|
|
706
|
+
if (isFilter)
|
|
707
|
+
isMatch = filter(objectStore, data[type][i], data[type][i])
|
|
708
|
+
|
|
709
|
+
if (isMatch !== false) {
|
|
710
|
+
try {
|
|
711
|
+
data[type][i]._id = ObjectId(data[type][i]._id);
|
|
712
|
+
} catch (error) {
|
|
713
|
+
data[type][i]._id = ObjectId()
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
let result = await put(objectStore, data[type][i])
|
|
717
|
+
newData.push({ $storage: 'indexeddb', $database: database, $array: array, ...result })
|
|
718
|
+
}
|
|
719
|
+
} else if (cursor) {
|
|
720
|
+
let isMatch = true
|
|
721
|
+
|
|
722
|
+
if (isFilter)
|
|
723
|
+
isMatch = filter(objectStore, data, data[type][i], cursor.value)
|
|
724
|
+
|
|
725
|
+
if (isMatch !== false) {
|
|
726
|
+
let result = cursor.value
|
|
727
|
+
if (data.method == 'create.object') {
|
|
728
|
+
result = await add(objectStore, data[type][i])
|
|
729
|
+
} else if (data.method == 'update.object') {
|
|
730
|
+
let update = createUpdate(cursor.value, data[type][i], globalOperators)
|
|
731
|
+
if (update)
|
|
732
|
+
result = await put(objectStore, update)
|
|
733
|
+
// set dotnotation for keys with $operators for items that end in [] to be used by socket.id
|
|
734
|
+
// TODO: if update.$<operator>.someKey[] requires the index of inerted item added to the field name. update.$<operator>.someKey[<index>]
|
|
735
|
+
// TODO: if $addToSet get field name and item if it does not exist.
|
|
736
|
+
// TODO: if $pull get field name and find if item exist and delete.
|
|
737
|
+
} else if (data.method == 'delete.object') {
|
|
738
|
+
result = cursor.value
|
|
739
|
+
cursor.delete()
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
newData.push({ $storage: 'indexeddb', $database: database, $array: array, ...result })
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
if (!limit || limit && limit < newData.length) {
|
|
746
|
+
cursor.continue();
|
|
747
|
+
} else {
|
|
748
|
+
cursor.close()
|
|
749
|
+
}
|
|
750
|
+
} else {
|
|
751
|
+
resolve();
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
request.onerror = () => {
|
|
756
|
+
reject(request.error)
|
|
757
|
+
}
|
|
578
758
|
});
|
|
579
759
|
}
|
|
580
760
|
|
|
@@ -611,25 +791,7 @@ function deleteObject(objectStore, object) {
|
|
|
611
791
|
}
|
|
612
792
|
|
|
613
793
|
|
|
614
|
-
function
|
|
615
|
-
if (data.updateName) {
|
|
616
|
-
for (let key of Object.keys(data.updateName)) {
|
|
617
|
-
let val = object[key]
|
|
618
|
-
delete object[key]
|
|
619
|
-
object[data.updateName[key]] = val
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
if (data.deleteName) {
|
|
624
|
-
for (let key of Object.keys(data.deleteName)) {
|
|
625
|
-
delete object[key]
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
}
|
|
629
|
-
return object
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
function filter(data, object, result) {
|
|
794
|
+
function filter(objectStore, data, object, result) {
|
|
633
795
|
let isMatch = true;
|
|
634
796
|
|
|
635
797
|
if (data.$filter || object.$filter) {
|
|
@@ -689,4 +851,4 @@ function errorHandler(data, error, database, array) {
|
|
|
689
851
|
|
|
690
852
|
init();
|
|
691
853
|
|
|
692
|
-
export default { send }
|
|
854
|
+
export default { send, ObjectId }
|
package/test/index.html
CHANGED
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
|
|
16
16
|
<body>
|
|
17
17
|
<!-- <script src="../../../CoCreateJS/dist/CoCreate.js"></script> -->
|
|
18
|
-
<script src="https://
|
|
19
|
-
<!-- <script src="
|
|
18
|
+
<script src="https://cocreate.app/dist/CoCreate.js"></script>
|
|
19
|
+
<!-- <script src="../../../CoCreateJS/dist/indexeddb-chunk.js"></script> -->
|
|
20
|
+
<script src="./operators.js"></script>
|
|
20
21
|
<script src="./databases.js"></script>
|
|
21
22
|
<script src="./arrays.js"></script>
|
|
22
23
|
<script src="./indexes.js"></script>
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
function createUpdate(update, data, globalOpertors) {
|
|
2
|
+
let operatorKeys = {}
|
|
3
|
+
if (globalOpertors)
|
|
4
|
+
operatorKeys = { ...globalOpertors }
|
|
5
|
+
|
|
6
|
+
Object.keys(data).forEach(key => {
|
|
7
|
+
if (key === '_id')
|
|
8
|
+
return
|
|
9
|
+
|
|
10
|
+
if (key.startsWith('$')) {
|
|
11
|
+
if (!key.includes('.'))
|
|
12
|
+
for (let oldkey of Object.keys(data[key]))
|
|
13
|
+
operatorKeys[key + '.' + oldkey] = data[key][oldkey]
|
|
14
|
+
else
|
|
15
|
+
operatorKeys[key] = data[key]
|
|
16
|
+
} else if (typeof data[key] === 'string' && data[key].startsWith('$')) {
|
|
17
|
+
operatorKeys[data[key] + '.' + key] = data[key]
|
|
18
|
+
} else if (key.endsWith(']')) {
|
|
19
|
+
const regex = /^(.*(?:\[\d+\].*?)?)\[(.*?)\](?:\[\])?$/;
|
|
20
|
+
const match = key.match(regex);
|
|
21
|
+
if (match[2] === '')
|
|
22
|
+
operatorKeys['$push.' + match[1]] = data[key]
|
|
23
|
+
else {
|
|
24
|
+
let index = parseInt(match[2], 10);
|
|
25
|
+
if (index === NaN)
|
|
26
|
+
operatorKeys[match[2] + '.' + match[1]] = data[key]
|
|
27
|
+
else
|
|
28
|
+
operatorKeys[key] = data[key]
|
|
29
|
+
}
|
|
30
|
+
} else if (key.includes('.')) {
|
|
31
|
+
operatorKeys[key] = data[key]
|
|
32
|
+
} else if (data[key] === undefined) {
|
|
33
|
+
delete update[key]
|
|
34
|
+
} else
|
|
35
|
+
update[key] = data[key]
|
|
36
|
+
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
return dotNotationToObjectUpdate(operatorKeys, update)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function dotNotationToObjectUpdate(data, object = {}) {
|
|
43
|
+
try {
|
|
44
|
+
for (const key of Object.keys(data)) {
|
|
45
|
+
let value = data[key]
|
|
46
|
+
let newObject = object
|
|
47
|
+
let oldObject = new Object(newObject)
|
|
48
|
+
let keys = key.replace(/\[(\d+)\]/g, '.$1').split('.');
|
|
49
|
+
|
|
50
|
+
if (keys[0].startsWith('$'))
|
|
51
|
+
var operator = keys.shift()
|
|
52
|
+
|
|
53
|
+
let length = keys.length - 1
|
|
54
|
+
for (let i = 0; i < keys.length; i++) {
|
|
55
|
+
if (/^\d+$/.test(keys[i]))
|
|
56
|
+
keys[i] = parseInt(keys[i]);
|
|
57
|
+
|
|
58
|
+
if (length == i) {
|
|
59
|
+
// TODO: operator updates
|
|
60
|
+
if (operator) {
|
|
61
|
+
if (operator === '$rename') {
|
|
62
|
+
newObject[value] = newObject[keys[i]]
|
|
63
|
+
delete newObject[keys[i]]
|
|
64
|
+
} else if (operator === '$delete' || operator === '$unset' || operator === '$slice') {
|
|
65
|
+
if (typeof keys[i] === 'number')
|
|
66
|
+
newObject.slice(keys[i], 1);
|
|
67
|
+
else
|
|
68
|
+
delete newObject[keys[i]]
|
|
69
|
+
} else if (operator === '$shift') {
|
|
70
|
+
newObject[keys[i]].shift();
|
|
71
|
+
} else if (operator === '$pop') {
|
|
72
|
+
newObject[keys[i]].pop();
|
|
73
|
+
} else if (operator === '$addToSet' || operator === '$pull') {
|
|
74
|
+
// find matching items and update or delete
|
|
75
|
+
key = arrayKey
|
|
76
|
+
updates[key] = data[originalKey]
|
|
77
|
+
} else if (operator === '$push' || operator === '$splice') {
|
|
78
|
+
// TODO: support pushing an array as values
|
|
79
|
+
if (typeof keys[i] === 'number' && newObject.length >= keys[i])
|
|
80
|
+
newObject.splice(keys[i], 0, value);
|
|
81
|
+
else
|
|
82
|
+
newObject[keys[i]].push(value);
|
|
83
|
+
} else if (operator === '$inc') {
|
|
84
|
+
newObject[keys[i]] += value
|
|
85
|
+
}
|
|
86
|
+
} else if (value === undefined) {
|
|
87
|
+
if (typeof keys[i] === 'number')
|
|
88
|
+
newObject.slice(keys[i], 1);
|
|
89
|
+
else
|
|
90
|
+
delete newObject[keys[i]]
|
|
91
|
+
} else
|
|
92
|
+
newObject[keys[i]] = value;
|
|
93
|
+
} else {
|
|
94
|
+
newObject[keys[i]] = oldObject[keys[i]] || {};
|
|
95
|
+
newObject = newObject[keys[i]]
|
|
96
|
+
oldObject = oldObject[keys[i]]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return object
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.log("Error converting dot notation to object", error);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|