@cocreate/indexeddb 1.2.11 → 1.3.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/src/index.js CHANGED
@@ -7,632 +7,868 @@
7
7
  import {dotNotationToObject} from '@cocreate/utils'
8
8
  import {searchData, sortData, queryData} from '@cocreate/filter/src/filter.js'
9
9
 
10
- const createDatabase = (data) => {
11
- return new Promise((resolve, reject) => {
12
-
13
- let openRequest = indexedDB.open(data.database);
10
+ function createDatabase(data){
11
+ return Database('createDatabase', data)
12
+ }
14
13
 
15
- openRequest.onsuccess = function() {
16
- resolve(openRequest.result)
17
- };
14
+ const readDatabase = () => {
15
+ return Database('readDatabase', data)
16
+ }
18
17
 
19
- openRequest.onerror = function() {
20
- reject(openRequest.error)
21
- };
18
+ const updateDatabase = (data) => {
19
+ return Database('updateDatabase', data)
20
+ }
22
21
 
23
- }, (err) => {
24
- console.log(err);
25
- });
22
+ const deleteDatabase = (data) => {
23
+ return Database('deleteDatabase', data)
26
24
  }
27
25
 
28
- const readDatabase = (data) => {
26
+ const getDatabase = (data) => {
27
+ return Database('getDatabase', data)
28
+ }
29
+
30
+ const dbVersion = new Map()
31
+ const Database = (action, data) => {
29
32
  return new Promise((resolve, reject) => {
33
+ let type = 'database'
34
+ let databaseArray = [];
30
35
 
31
- let openRequest = indexedDB.open(data.database);
36
+ if (data.request)
37
+ data[type] = data.request
32
38
 
33
- openRequest.onsuccess = function() {
34
- let db = openRequest.result;
35
- if (data.upgrade == true) {
36
- let version = openRequest.result.version
37
- db.close()
38
-
39
- let request = indexedDB.open(data.database, Number(version += 1));
40
- request.onupgradeneeded = function() {
41
- db = request.result
42
- };
39
+ if (!data['timeStamp'])
40
+ data['timeStamp'] = new Date().toISOString()
41
+
42
+ if (action == 'readDatabase') {
43
+ indexedDB.databases().then((databases) => {
44
+ data.databases = databases
45
+ resolve(data)
46
+ })
47
+ } else {
48
+ let databases
49
+ if (action == 'updateDatabase')
50
+ databases = Object.entries(data.database)
51
+ else
52
+ databases = data.database;
53
+
54
+ if (!Array.isArray(databases))
55
+ databases = [databases]
56
+
57
+ let databasesLength = databases.length
58
+ for (let database of databases) {
59
+ if (action == 'updateDatabase')
60
+ [database, value] = database
61
+
62
+ let openRequest;
63
+ switch(action) {
64
+ case 'getDatabase':
65
+ case 'createDatabase':
66
+ case 'updateDatabase':
67
+ openRequest = indexedDB.open(database);
68
+ break;
69
+ case 'deleteDatabase':
70
+ openRequest = indexedDB.deleteDatabase(database);
71
+ break;
72
+ default:
73
+ errorHandler(data, 'unknown action', database)
74
+ resolve(data) }
75
+
76
+ openRequest.onsuccess = function() {
77
+ let db = openRequest.result;
78
+ let dbs = [] // ToDo: return an array of dbinstance??
79
+ if (action == 'updateDatabase') {
80
+ // ToDo: open a cursor at database collection and save each collection and document at value
81
+
82
+ let objectStoreNames = Array.from(db.objectStoreNames)
83
+ for (let collection of objectStoreNames) {
84
+ let request = collection.openCursor();
85
+
86
+ request.onsuccess = function() {
87
+ let cursor = request.result;
88
+ if (cursor) {
89
+ let value = cursor.value;
90
+
91
+ cursor.continue();
92
+ } else {
93
+ // -1
94
+ }
95
+ };
96
+
97
+ request.onerror = function() {
98
+ errorHandler(data, request.error, database, collection)
99
+ };
100
+
101
+ }
43
102
 
44
- request.onsuccess = function() {
45
- resolve(db)
46
- };
103
+ } else if (data.collection && data.collection.length) {
104
+ let collections = data.collection;
105
+ if (!Array.isArray(collections))
106
+ collections = [collections]
107
+
108
+ let collectionsLength = collections.length
109
+ for (let collection of collections) {
110
+
111
+ let collectionExist = db.objectStoreNames.contains(collection)
112
+ if (!collectionExist || collectionsLength == 1 && data.upgrade == true) {
113
+ db.close()
114
+
115
+ let version = dbVersion.get(database) || openRequest.result.version
116
+ let request = indexedDB.open(database, Number(version += 1));
117
+ dbVersion.set(database, version)
47
118
 
48
- request.onerror = function() {
49
- reject(request.error)
50
- };
119
+ request.onupgradeneeded = function() {
120
+ db = request.result;
121
+
122
+ if (!collectionExist) {
123
+ db = request.result;
124
+ try {
125
+ db.createObjectStore(collection, {keyPath: '_id', autoIncrement: true});
126
+ } catch (error) {
127
+ errorHandler(data, error, database, collection)
128
+ }
129
+ }
130
+ };
131
+
132
+ request.onsuccess = function() {
133
+ collectionsLength -= 1
134
+
135
+ if (!collectionsLength)
136
+ databasesLength -= 1
137
+
138
+ if (!databasesLength && !collectionsLength) {
139
+ if (action == 'getDatabase') {
140
+ let transaction = request.transaction
141
+
142
+ if (data.upgrade == true && !transaction) {
143
+ request.result.close()
144
+
145
+ let version = dbVersion.get(database) || openRequest.result.version
146
+ let upgrade = indexedDB.open(database, Number(version += 1));
147
+ dbVersion.set(database, version)
148
+
149
+ upgrade.onupgradeneeded = function() {
150
+ resolve(upgrade)
151
+ };
152
+
153
+ } else {
154
+ resolve(request.result)
155
+ }
156
+ }
157
+ else
158
+ resolve(data)
159
+ }
160
+ };
161
+
162
+ request.onerror = function() {
163
+ errorHandler(data, request.error, database, collection)
164
+ collectionsLength -= 1
165
+
166
+ if (!collectionsLength)
167
+ databasesLength -= 1
168
+ if (!databasesLength && !collectionsLength) {
169
+ if (action == 'getDatabase')
170
+ resolve(request)
171
+ else
172
+ resolve(data)
173
+ }
174
+ };
175
+ } else {
176
+ collectionsLength -= 1
177
+
178
+ if (!collectionsLength)
179
+ databasesLength -= 1
180
+ if (!databasesLength && !collectionsLength) {
181
+ if (action == 'getDatabase')
182
+ resolve(db)
183
+ else
184
+ resolve(data)
185
+ }
186
+ }
187
+ }
188
+ } else {
189
+ databasesLength -= 1
190
+ if (!databasesLength) {
191
+ if (action == 'getDatabase') {
192
+ let transaction = openRequest.transaction
193
+
194
+ if (data.upgrade == true && !transaction) {
195
+ db.close()
196
+
197
+ let version = dbVersion.get(database) || openRequest.result.version
198
+ let upgrade = indexedDB.open(database, Number(version += 1));
199
+ dbVersion.set(database, version)
200
+
201
+ upgrade.onupgradeneeded = function() {
202
+ resolve(upgrade)
203
+ };
204
+
205
+ } else {
206
+ resolve(db)
207
+ }
208
+ }
209
+ else
210
+ resolve(data)
211
+ }
212
+ }
51
213
 
52
- } else {
53
- resolve(db)
54
- }
55
- };
214
+ }
56
215
 
57
- openRequest.onerror = function() {
58
- reject(openRequest.error)
59
- };
216
+ openRequest.onerror = function() {
217
+ errorHandler(data, openRequest.error, database)
218
+ resolve(data)
219
+ };
60
220
 
61
- }, (err) => {
62
- console.log(err);
63
- });
64
- }
221
+ }
222
+ }
65
223
 
66
- const readDatabases = () => {
67
- return new Promise((resolve, reject) => {
68
- indexedDB.databases().then((databases) => {
69
- resolve(databases)
70
- })
71
224
  }, (err) => {
72
- console.log(err);
225
+ errorHandler(data, err)
73
226
  });
74
227
  }
75
228
 
76
- const updateDatabase = (data) => {
77
- return new Promise((resolve, reject) => {
78
-
79
- let openRequest = indexedDB.open(data.database);
80
229
 
81
- openRequest.onsuccess = function() {
82
- let db = openRequest.result;
83
- if (data.newDatabase) {
84
- // function to clone db with new name
85
- } else {
86
- resolve(db)
87
- }
88
- };
230
+ function createCollection(data){
231
+ return collection('createCollection', data)
232
+ }
89
233
 
90
- openRequest.onerror = function() {
91
- reject(openRequest.error)
92
- };
234
+ function readCollection(data) {
235
+ return collection('readCollection', data)
236
+ }
93
237
 
94
- }, (err) => {
95
- console.log(err);
96
- });
238
+ function updateCollection(data) {
239
+ return collection('updateCollection', data)
97
240
  }
98
241
 
99
- const deleteDatabase = (data) => {
242
+ function deleteCollection(data) {
243
+ return collection('deleteCollection', data)
244
+ }
245
+
246
+ const collection = (action, data) => {
100
247
  return new Promise((resolve, reject) => {
101
- let openRequest = indexedDB.deleteDatabase(data.database);
248
+ let type = 'collection'
249
+ let collectionArray = [];
102
250
 
103
- openRequest.onsuccess = function() {
104
- resolve(openRequest.result);
105
- };
251
+ if (data.request)
252
+ data[type] = data.request
106
253
 
107
- openRequest.onerror = function() {
108
- reject(openRequest.error);
109
- };
254
+ if (!data['timeStamp'])
255
+ data['timeStamp'] = new Date().toISOString()
110
256
 
111
- }, (err) => {
112
- console.log(err);
113
- });
114
- }
257
+ let databases = data.database;
115
258
 
116
- const database = (data) => {
117
- return new Promise((resolve, reject) => {
118
- let openRequest = indexedDB.open(data.database);
259
+ if (!Array.isArray(databases))
260
+ databases = [databases]
261
+ let databasesLength = databases.length
262
+ for (let database of databases) {
263
+ let openRequest = indexedDB.open(database)
119
264
 
120
- openRequest.onsuccess = function() {
121
- let db = openRequest.result;
122
- let collectionExist = db.objectStoreNames.contains(data.collection)
123
- if (data.collection && !collectionExist || data.upgrade == true) {
124
- let version = openRequest.result.version
265
+ openRequest.onsuccess = function() {
266
+ let db = openRequest.result;
125
267
  db.close()
126
-
127
- let request = indexedDB.open(data.database, Number(version += 1));
128
- request.onupgradeneeded = function() {
129
- if (!collectionExist) {
130
- db = request.result;
131
- db.createObjectStore(data.collection, {keyPath: '_id', autoIncrement: true});
268
+ let objectStoreNames = Array.from(db.objectStoreNames)
269
+ if (action == 'readCollection') {
270
+ if (!data[type])
271
+ data[type] = []
272
+
273
+ for (let collection of Array.from(objectStoreNames)){
274
+ collectionArray.push({name: collection, db: 'indexeddb', database})
132
275
  }
133
- };
134
-
135
- request.onsuccess = function() {
136
- resolve(db)
137
- };
138
-
139
- request.onerror = function() {
140
- reject(request.error)
141
- };
142
-
143
- } else {
144
- resolve(db)
145
- }
146
- };
147
-
148
- openRequest.onerror = function() {
149
- reject(openRequest.error)
150
- };
151
276
 
152
- }, (err) => {
153
- console.log(err);
154
- });
155
- }
277
+ databasesLength -= 1
278
+ if (!databasesLength) {
279
+ resolve(createData(data, collectionArray, type))
280
+ }
156
281
 
282
+ } else {
283
+ let collections
284
+ if (action == 'updateCollection')
285
+ collections = Object.entries(data[type])
286
+ else
287
+ collections = data[type];
288
+ if (!Array.isArray(collections))
289
+ collections = [collections]
290
+ let collectionsLength = collections.length
291
+ for (let collection of collections) {
292
+ let value
293
+ if (action == 'updateCollection')
294
+ [collection, value] = collection
295
+ let collectionExist = db.objectStoreNames.contains(collection)
296
+ if (
297
+ collectionExist && ['updateCollection', 'deleteCollection'].includes(action) ||
298
+ !collectionExist && ['createCollection', 'updateCollection'].includes(action)
299
+ ) {
300
+ getDatabase({database, collection, upgrade: true}).then((db) => {
301
+ if (collectionExist && action == 'updateCollection') {
302
+ let transaction = db.transaction;
303
+ let objectStore = transaction.objectStore(collection);
304
+
305
+ let valueExist = objectStoreNames.includes(value)
306
+ if (!valueExist) {
307
+ objectStore.name = value;
308
+ }
309
+ else
310
+ errorHandler(data, 'collection does not exist', database)
311
+
312
+ db.result.close()
313
+
314
+ collectionArray.push({name: value, db: 'indexeddb', database})
315
+ collectionsLength -= 1
316
+
317
+ if (!collectionsLength)
318
+ databasesLength -= 1
319
+
320
+ if (!databasesLength && !collectionsLength){
321
+ resolve(createData(data, collectionArray, type))
322
+ }
323
+
324
+ } else {
325
+ db = db.result
326
+
327
+ if (action == 'deleteCollection') {
328
+ db.deleteObjectStore(collection)
329
+ }
330
+
331
+ db.close()
332
+
333
+ collectionArray.push({name: collection, db: 'indexeddb', database})
334
+ collectionsLength -= 1
335
+
336
+ if (!collectionsLength)
337
+ databasesLength -= 1
338
+
339
+ if (!databasesLength && !collectionsLength) {
340
+ resolve(createData(data, collectionArray, type))
341
+ }
342
+
343
+ }
344
+ }, (err) => {
345
+ errorHandler(data, err, database)
346
+ })
347
+
348
+ } else {
349
+ collectionArray.push({name: collection, db: 'indexeddb', database})
350
+ collectionsLength -= 1
351
+
352
+ if (!collectionsLength)
353
+ databasesLength -= 1
354
+
355
+ if (!databasesLength && !collectionsLength) {
356
+ resolve(createData(data, collectionArray, type))
357
+ }
358
+ }
157
359
 
158
- const createCollection = (data) => {
159
- return new Promise((resolve, reject) => {
160
- let openRequest = indexedDB.open(data.database);
360
+ }
361
+
362
+ }
161
363
 
162
- openRequest.onsuccess = function() {
163
- let db = openRequest.result;
164
- if (!db.objectStoreNames.contains(data.collection)) {
165
- let version = openRequest.result.version
166
- db.close()
167
-
168
- let request = indexedDB.open(data.database, Number(version += 1));
169
- request.onupgradeneeded = function() {
170
- db = request.result;
171
- db.createObjectStore(data.collection, {keyPath: '_id', autoIncrement: true});
172
- };
173
-
174
- request.onsuccess = function() {
175
- resolve(request.result)
176
- };
177
-
178
- request.onerror = function() {
179
- console.log("Error", request.error);
180
- reject(request.error)
181
- };
364
+ };
182
365
 
183
- } else {
184
- resolve(db)
185
- }
186
- };
187
-
188
- openRequest.onerror = function() {
189
- reject(openRequest.error)
190
- };
366
+ openRequest.onerror = function() {
367
+ errorHandler(data, openRequest.error, database)
368
+ databasesLength -= 1
191
369
 
370
+ if (!databasesLength) {
371
+ resolve(data)
372
+ }
373
+ };
374
+ }
192
375
  }, (err) => {
193
- console.log(err);
376
+ errorHandler(data, err)
194
377
  });
195
378
  }
196
379
 
197
- const readCollections = (data) => {
198
- return new Promise((resolve, reject) => {
199
- let openRequest = indexedDB.open(data.database);
200
380
 
201
- openRequest.onsuccess = function() {
202
- let db = openRequest.result;
203
- let collections = db.objectStoreNames
204
- data.data = [];
205
-
206
- for (let collection of Array.from(collections)){
207
- data.data.push({name: collection})
208
- }
381
+ function createIndex(data){
382
+ return index('createIndex', data)
383
+ }
209
384
 
210
- data.collection = 'collections'
211
- resolve(data)
212
- }
385
+ function readIndex(data) {
386
+ return index('readIndex', data)
387
+ }
213
388
 
214
- openRequest.onerror = function() {
215
- reject(openRequest.error)
216
- };
389
+ function updateIndex(data) {
390
+ return index('updateIndex', data)
391
+ }
217
392
 
218
- }, (err) => {
219
- console.log(err);
220
- });
393
+ function deleteIndex(data) {
394
+ return index('deleteIndex', data)
221
395
  }
222
396
 
223
- const updateCollection = (data) => {
397
+ const index = (action, data) => {
224
398
  return new Promise((resolve, reject) => {
225
- let openRequest = indexedDB.open(data.dastabase);
399
+ let type = 'index'
400
+ let indexArray = [];
226
401
 
227
- openRequest.onsuccess = function() {
228
- let db = openRequest.result;
229
- if (db.objectStoreNames.contains(data.collection)) {
230
- let version = openRequest.result.version
231
- db.close()
232
-
233
- let request = indexedDB.open(data.dastabase, Number(version += 1));
234
- request.onupgradeneeded = function() {
235
- let db = request.result;
236
- let transaction = db.transaction([data.collection], "readonly");
237
- let collection = transaction.objectStore(data.collection);
238
- collection.name = data.newCollection
239
- }
240
-
241
- request.onsuccess = function() {
242
- db.close()
243
- resolve(request.result)
244
- };
245
-
246
- request.onerror = function() {
247
- reject(request.error)
248
- };
249
-
250
- } else {
251
- db.createObjectStore(data.newCollection, {keyPath: '_id', autoIncrement: true})
252
- resolve(data.newCollection)
253
- }
254
- };
402
+ if (data.request)
403
+ data[type] = data.request
255
404
 
256
- openRequest.onerror = function() {
257
- reject(openRequest.error)
258
- };
259
-
260
- }, (err) => {
261
- console.log(err);
262
- });
263
- }
405
+ if (!data['timeStamp'])
406
+ data['timeStamp'] = new Date().toISOString()
407
+
408
+ let databases = data.database;
409
+ if (!Array.isArray(databases))
410
+ databases = [databases]
411
+
412
+ let databasesLength = databases.length
413
+ for (let database of databases) {
414
+ let collections = data.collection;
415
+ if (!Array.isArray(collections))
416
+ collections = [collections]
417
+
418
+ let collectionsLength = collections.length
419
+ for (let collection of collections) {
420
+ getDatabase({database}).then((db) => {
421
+ let objectStoreNames = Array.from(db.objectStoreNames)
422
+ if (objectStoreNames.includes(collection)) {
423
+ let transaction = db.transaction(collection, "readonly");
424
+ let objectStore = transaction.objectStore(collection);
425
+ let indexNames = Array.from(objectStore.indexNames)
426
+
427
+ if (action == 'readIndex') {
428
+ for (let index of Array.from(indexNames)) {
429
+ indexArray.push({name: index, db: 'indexeddb', database, collection})
430
+ }
431
+ collectionsLength -= 1
432
+ db.close()
264
433
 
265
- const deleteCollection = (data) => {
266
- return new Promise((resolve, reject) => {
267
- let openRequest = indexedDB.open(data.database);
434
+ if (!collectionsLength)
435
+ databasesLength -= 1
436
+
437
+ if (!databasesLength && !collectionsLength)
438
+ resolve(createData(data, indexArray, type))
268
439
 
269
- openRequest.onsuccess = function() {
270
- let db = openRequest.result;
271
- if (db.objectStoreNames.contains(data.collection)) {
272
- let version = openRequest.result.version
273
- db.close()
274
-
275
- let request = indexedDB.open(data.database, Number(version += 1));
276
- request.onupgradeneeded = function() {
277
- db = request.result;
278
- db.deleteObjectStore(data.collection)
279
- }
440
+ } else {
441
+ db.close()
442
+ let indexes
443
+ if (action == 'updateIndex')
444
+ indexes = Object.entries(data[type])
445
+ else
446
+ indexes = data[type];
447
+ if (!Array.isArray(indexes))
448
+ indexes = [indexes]
449
+
450
+ let indexesLength = indexes.length
451
+ for (let index of indexes) {
452
+
453
+ getDatabase({database, upgrade: true}).then((db2) => {
454
+ let transaction = db2.transaction;
455
+ let objectStore = transaction.objectStore(collection);
456
+
457
+ let value
458
+ if (action == 'updateIndex')
459
+ [index, value] = index
460
+
461
+ let indexExist = indexNames.includes(index)
462
+
463
+ if (action == 'createIndex') {
464
+ if (!indexExist) {
465
+ objectStore.createIndex(index, index, {unique: false})
466
+ indexArray.push({name: index, db: 'indexeddb', database, collection})
467
+ }
468
+ else
469
+ errorHandler(data, 'index exist', database, collection)
470
+ }
471
+ if (action == 'updateIndex') {
472
+ let valueExist = indexNames.includes(value)
473
+ let indexObj = objectStore.index(index);
474
+ if (indexExist && !valueExist) {
475
+ indexObj.name = value;
476
+ indexArray.push({name: value, db: 'indexeddb', database, collection})
477
+ }
478
+ else
479
+ errorHandler(data, 'index does not exist', database, collection)
480
+
481
+ }
482
+ if (action == 'deleteIndex') {
483
+ if (indexExist) {
484
+ objectStore.deleteIndex(index)
485
+ indexArray.push({name: index, db: 'indexeddb', database, collection})
486
+ }
487
+ else
488
+ errorHandler(data, 'index does not exist', database, collection)
489
+ }
490
+ db2.result.close()
491
+
492
+ indexesLength -= 1
493
+
494
+ if (!indexesLength)
495
+ collectionsLength -= 1
496
+
497
+ if (!collectionsLength)
498
+ databasesLength -= 1
499
+
500
+ if (!databasesLength && !collectionsLength && !indexesLength) {
501
+ resolve(createData(data, indexArray, type))
502
+ }
503
+ });
504
+ }
505
+
506
+ }
507
+
508
+ } else {
509
+ db.close()
510
+ errorHandler(data, `collection: ${collection} does not exist`, database, collection)
511
+ resolve(data)
512
+ }
513
+ });
280
514
 
281
- request.onsuccess = function() {
282
- // let db = request.result;
283
- db.close()
284
- resolve(data.collection)
285
- };
286
-
287
- request.onerror = function() {
288
- reject(request.error)
289
- };
290
-
291
- };
292
- };
293
-
294
- openRequest.onerror = function() {
295
- reject(openRequest.error)
296
- };
515
+ }
516
+ }
297
517
 
298
518
  }, (err) => {
299
- console.log(err);
519
+ errorHandler(data, err)
300
520
  });
301
521
  }
302
522
 
303
- const createIndex = (data) => {
304
- return new Promise((resolve, reject) => {
305
- let openRequest = indexedDB.open(data.database);
306
-
307
- openRequest.onsuccess = function() {
308
- let db = openRequest.result;
309
- let transaction = db.transaction([data.collection], "readonly");
310
- let collection = transaction.objectStore(data.collection);
311
-
312
- if (!collection.indexNames.contains(data.name)){
313
- let version = openRequest.result.version
314
- db.close()
315
-
316
- let request = indexedDB.open(data.database, Number(version += 1));
317
- request.onupgradeneeded = function() {
318
- db = request.result;
319
- transaction = db.transaction([data.collection], "readonly");
320
- collection = transaction.objectStore(data.collection);
321
- collection.createIndex(data.name, data.name, {unique: false})
322
- }
323
-
324
- request.onsuccess = function() {
325
- db.close()
326
- resolve('index created')
327
- };
328
-
329
- request.onerror = function() {
330
- reject(request.error)
331
- };
332
-
333
- } else {
334
- resolve('index created')
335
- }
336
- };
337
-
338
- openRequest.onerror = function() {
339
- reject(openRequest.error)
340
- };
341
- })
342
-
523
+ function createDocument(data){
524
+ return document('createDocument', data)
525
+ }
343
526
 
527
+ function readDocument(data) {
528
+ return document('readDocument', data)
344
529
  }
345
- const readIndex = (data) => {
346
- return new Promise((resolve, reject) => {
347
- let openRequest = indexedDB.open(data.database);
348
530
 
349
- openRequest.onsuccess = function() {
350
- let db = openRequest.result;
351
- let transaction = db.transaction([data.collection], "readonly");
352
- let collection = transaction.objectStore(data.collection);
353
- let indexes = collection.indexNames
354
- db.close()
355
- resolve(indexes)
356
- };
357
-
358
- openRequest.onerror = function() {
359
- reject(openRequest.error)
360
- };
361
- })
531
+ function updateDocument(data) {
532
+ return document('updateDocument', data)
533
+ }
362
534
 
535
+ function deleteDocument(data) {
536
+ return document('deleteDocument', data)
363
537
  }
364
538
 
365
- const updateIndex = (data) => {
539
+
540
+ const document = (action, data) => {
366
541
  return new Promise((resolve, reject) => {
367
- let openRequest = indexedDB.open(data.database);
542
+ let type = 'document'
543
+ let documents = []
544
+
545
+ if (data.request)
546
+ data[type] = data.request
368
547
 
369
- openRequest.onsuccess = function() {
370
- let db = openRequest.result;
371
- let transaction = db.transaction([data.collection], "readonly");
372
- let collection = transaction.objectStore(data.collection);
373
-
374
- if (collection.indexNames.contains(data.oldName)){
375
- let version = openRequest.result.version
376
- db.close()
377
-
378
- let request = indexedDB.open(data.database, Number(version += 1));
379
- request.onupgradeneeded = function() {
380
- db = request.result;
381
- transaction = db.transaction([data.collection], "readonly");
382
- collection = transaction.objectStore(data.collection);
383
- let index = store.index(data.oldName);
384
- index.name = data.newName;
385
- }
548
+ if (!data['timeStamp'])
549
+ data['timeStamp'] = new Date().toISOString()
550
+
551
+ let databases = data.database;
552
+ if (!Array.isArray(databases))
553
+ databases = [databases]
554
+
555
+ let databasesLength = databases.length
556
+ for (let database of databases) {
557
+ getDatabase({database}).then((db) => {
558
+ let collections = data.collection;
559
+ if (!Array.isArray(collections))
560
+ collections = [collections]
561
+
562
+ let collectionsLength = collections.length
563
+ for (let collection of collections) {
564
+ let collectionExist = db.objectStoreNames.contains(collection)
565
+ if (!collectionExist) {
566
+ db.close()
567
+ getDatabase({database, collection}).then((db) => {
568
+ if (data.filter || action == 'readDocument') {
569
+ db.close()
570
+ readDocuments(data, database, collection).then((filterDocs) => {
571
+ getDatabase({database}).then((db) => {
572
+ let transaction = db.transaction([collection], "readwrite");
573
+ let objectStore = transaction.objectStore(collection);
574
+
575
+ runDocs({action, data, objectStore, documents, filterDocs, database, collection, type}).then(() => {
576
+ db.close()
577
+ collectionsLength -= 1
578
+
579
+ if (!collectionsLength)
580
+ databasesLength -= 1
581
+
582
+ if (!databasesLength && !collectionsLength) {
583
+ resolve(createData(data, documents, type))
584
+ }
585
+ })
586
+ })
587
+
588
+ })
589
+ } else {
590
+ let transaction = db.transaction([collection], "readwrite");
591
+ let objectStore = transaction.objectStore(collection);
592
+
593
+ runDocs({action, data, objectStore, documents, database, collection, type}).then(() => {
594
+ db.close()
595
+ collectionsLength -= 1
596
+
597
+ if (!collectionsLength)
598
+ databasesLength -= 1
599
+
600
+ if (!databasesLength && !collectionsLength) {
601
+ resolve(createData(data, documents, type))
602
+ }
603
+ })
604
+ }
386
605
 
387
- request.onsuccess = function() {
388
- let db = request.result;
389
- db.close()
390
- resolve('index does not exist')
391
- };
606
+ }).catch((error) => {
607
+ errorHandler(data, {message: error, data}, database)
608
+ collectionsLength -= 1
609
+
610
+ if (!collectionsLength)
611
+ databasesLength -= 1
392
612
 
393
- request.onerror = function() {
394
- reject(request.error)
395
- };
613
+ if (!databasesLength && !collectionsLength)
614
+ resolve(createData(data, documents, type))
615
+
616
+ })
617
+
618
+ } else {
619
+ if (data.filter || action == 'readDocument' && !data.document) {
620
+ db.close()
621
+ readDocuments(data, database, collection).then((filterDocs) => {
622
+ getDatabase({database}).then((db) => {
623
+ let transaction = db.transaction([collection], "readwrite");
624
+ let objectStore = transaction.objectStore(collection);
625
+
626
+ runDocs({action, data, objectStore, documents, filterDocs, database, collection, type}).then(() => {
627
+ db.close()
628
+ collectionsLength -= 1
629
+
630
+ if (!collectionsLength)
631
+ databasesLength -= 1
632
+
633
+ if (!databasesLength && !collectionsLength) {
634
+ resolve(createData(data, documents, type))
635
+ }
636
+ })
637
+ })
638
+ })
639
+ } else {
640
+ let transaction = db.transaction([collection], "readwrite");
641
+ let objectStore = transaction.objectStore(collection);
396
642
 
397
- } else {
398
- collection.createIndex(data.newName, data.newName, {unique: false})
399
- db.close()
400
- resolve('index does not exist')
401
- }
402
- };
403
-
404
- openRequest.onerror = function() {
405
- reject(openRequest.error)
406
- };
407
- })
643
+ runDocs({action, data, objectStore, documents, database, collection, type}).then(() => {
644
+ db.close()
645
+ collectionsLength -= 1
646
+
647
+ if (!collectionsLength)
648
+ databasesLength -= 1
649
+ if (!databasesLength && !collectionsLength) {
650
+ resolve(createData(data, documents, type))
651
+ }
652
+ })
653
+ }
654
+ }
655
+ }
408
656
 
409
- }
410
- const deleteIndex = (data) => {
411
- return new Promise((resolve, reject) => {
412
- let openRequest = indexedDB.open(data.database);
657
+ }).catch((error) => {
658
+ errorHandler(data, {message: error, data}, database)
413
659
 
414
- openRequest.onsuccess = function() {
415
- let db = openRequest.result;
416
- let transaction = db.transaction([data.collection], "readonly");
417
- let collection = transaction.objectStore(data.collection);
418
-
419
- if (collection.indexNames.contains(data.name)){
420
- let version = openRequest.result.version
421
- db.close()
422
-
423
- let request = indexedDB.open(data.database, Number(version += 1));
424
- request.onupgradeneeded = function() {
425
- db = request.result;
426
- transaction = db.transaction([data.collection], "readonly");
427
- collection = transaction.objectStore(data.collection);
428
- collection.deleteIndex(data.name)
429
- }
660
+ databasesLength -= 1
430
661
 
431
- request.onsuccess = function() {
432
- let db = request.result;
433
- db.close()
434
- resolve('index does not exist')
435
- };
662
+ if (!databasesLength)
663
+ resolve(createData(data, documents, type))
664
+ })
436
665
 
437
- request.onerror = function() {
438
- reject(request.error)
439
- };
440
-
441
- } else {
442
- db.close()
443
- resolve('index does not exist')
444
- }
445
- };
446
-
447
- openRequest.onerror = function() {
448
- reject(openRequest.error)
449
- };
666
+ }
450
667
  })
451
-
452
668
  }
453
669
 
454
- const createDocument = (data) => {
670
+ function runDocs({action, data, objectStore, documents, filterDocs, database, collection, type}) {
455
671
  return new Promise((resolve, reject) => {
456
- database(data).then((db) => {
457
- let transaction = db.transaction([data.collection], "readwrite");
458
- let collection = transaction.objectStore(data.collection);
459
- if (!data.data._id)
460
- data.data['_id'] = ObjectId()
461
- let request = collection.add(data.data);
462
-
463
- request.onsuccess = function() {
464
- db.close()
465
- resolve(data)
466
- };
467
-
468
- request.onerror = function() {
469
- db.close()
470
- reject(request.error)
471
- };
672
+ let docs = []
673
+
674
+ if (Array.isArray(data[type]))
675
+ docs.push(...data[type]);
676
+ else if (data[type] != undefined && action == 'createDocument')
677
+ docs.push(data[type])
678
+ else if (data[type] != undefined)
679
+ docs.push({...data[type]})
680
+
472
681
 
473
- }, (err) => {
474
- console.log(err);
475
- })
476
- })
477
- }
682
+ if (filterDocs && filterDocs.length) {
683
+ if (action == 'readDocument') {
684
+ for (let i = 0; i < filterDocs.length; i++)
685
+ documents.push({db: 'indexeddb', database, collection, ...filterDocs[i]})
478
686
 
479
- const readDocument = (data, db, collection) => {
480
- return new Promise((resolve, reject) => {
481
- if (db && collection) {
482
- let request = collection.get(data.data._id);
483
-
484
- request.onsuccess = function() {
485
- data.data = request.result
486
- resolve(data)
487
- };
488
-
489
- request.onerror = function() {
490
- reject(request.error)
491
- };
492
- } else {
687
+ }
493
688
 
494
- let openRequest = indexedDB.open(data.database);
689
+ if (action == 'updateDocument') {
690
+ let updateData = docs[0];
691
+ if (updateData)
692
+ docs.shift();
693
+ for (let filterDoc of filterDocs) {
694
+ filterDoc = dotNotationToObject(filterDoc, updateData)
695
+ docs.push(filterDoc)
696
+ }
697
+ }
495
698
 
496
- openRequest.onsuccess = function() {
497
- try {
699
+ if (action == 'deleteDocument')
700
+ docs.push(...filterDocs)
701
+ }
498
702
 
499
- let db = openRequest.result;
500
- let transaction = db.transaction([data.collection], "readwrite");
501
- let collection = transaction.objectStore(data.collection);
502
- let request = collection.get(data.data._id);
503
-
504
- request.onsuccess = function() {
505
- db.close()
506
- data.data = request.result
507
- resolve(data)
508
- };
509
-
510
- request.onerror = function() {
511
- db.close()
512
- reject(request.error)
513
- };
514
- } catch (err) {
515
- data.data = {}
516
- // data.error = err
517
- resolve(data)
518
- return
703
+ let docsLength = docs.length
704
+
705
+ if (docsLength > 0) {
706
+ for (let doc of docs) {
707
+ // ToDo deDuplcate document_id per collection
708
+ if (action == 'updateDocument' || action == 'deleteDocument') {
709
+ if (doc._id) {
710
+ doc['organization_id'] = data.organization_id
711
+ doc['modified'] = {on: data.timeStamp, by: data.user || data.clientId}
712
+
713
+ updateDoc(action, data, doc, objectStore, database, collection).then((doc) => {
714
+ doc.db = 'indexeddb'
715
+ doc.database = database
716
+ doc.collection = collection
717
+ documents.push(doc)
718
+ docsLength -= 1
719
+ if (!docsLength) {
720
+ resolve()
721
+ }
722
+ })
723
+ } else {
724
+ docsLength -= 1
725
+ if (!docsLength)
726
+ resolve()
727
+ }
728
+ } else {
729
+ let request;
730
+ if (action == 'createDocument') {
731
+ if (!doc._id)
732
+ doc['_id'] = ObjectId()
733
+ doc = dotNotationToObject(doc)
734
+
735
+ doc['organization_id'] = data.organization_id
736
+ doc['created'] = {on: data.timeStamp, by: data.user || data.clientId}
737
+ request = objectStore.add(doc);
519
738
  }
520
- };
521
739
 
522
- openRequest.onerror = function() {
523
- reject(openRequest.error)
524
- };
740
+ if (action == 'readDocument') {
741
+ request = objectStore.get(doc._id);
742
+ }
743
+
744
+ request.onsuccess = function() {
745
+ if (request.result) {
746
+ if (action == 'readDocument')
747
+ doc = request.result
748
+ doc.db = 'indexeddb'
749
+ doc.database = database
750
+ doc.collection = collection
525
751
 
752
+ documents.push(doc)
753
+ }
754
+ docsLength -= 1
755
+ if (!docsLength) {
756
+ resolve()
757
+ }
758
+ };
759
+
760
+ request.onerror = function() {
761
+ errorHandler(data, {message: request.error, document: doc}, database, objectStore.name)
762
+ resolve()
763
+ };
764
+ }
765
+ }
766
+ } else {
767
+ resolve()
526
768
  }
769
+ }, (err) => {
770
+ errorHandler(data, {message: err, document: doc}, database, objectStore.name)
527
771
  })
528
772
  }
529
773
 
530
- const updateDocument = (data) => {
774
+ function updateDoc(action, data, doc, objectStore, database, collection) {
531
775
  return new Promise((resolve, reject) => {
532
- database(data).then((db) => {
533
- let transaction = db.transaction([data.collection], "readwrite");
534
- let collection = transaction.objectStore(data.collection);
535
-
536
- if (!data.data._id && data.upsert == true) {
537
- data.data['_id'] = ObjectId()
538
- }
539
- if (!data.data._id) {
540
- db.close()
541
- resolve(data['error'] = 'requires _id')
542
- } else {
543
- let get = collection.get(data.data._id)
544
- get.onsuccess = function() {;
545
- // ToDo: merge objects and update using dot notation
546
- if (get.result || data.upsert == true) {
547
- data.data = dotNotationToObject(data.data, get.result)
548
-
549
- if (data.updateName){
550
- for (let [key, value] of Object.entries(data.updateName)){
551
- let val = data.data[key]
552
- delete data.data[key]
553
- data.data[value] = val
554
- }
555
-
556
- }
557
-
558
- if (data.deleteName){
559
- for (let key of Object.keys(data.deleteName)){
560
- delete data.data[key]
776
+ let get = objectStore.get(doc._id)
777
+ get.onsuccess = function() {;
778
+
779
+ let result = get.result
780
+ if (result || data.upsert == true) {
781
+ let modify = true
782
+ if (result && doc.modified && result.modified)
783
+ if (doc.modified.on < result.modified.on)
784
+ modify = false
785
+
786
+ if (modify) {
787
+ if (action == 'updateDocument') {
788
+ doc = dotNotationToObject(doc, get.result)
789
+
790
+ if (data.updateName){
791
+ for (let [key, value] of Object.entries(data.updateName)){
792
+ let val = doc[key]
793
+ delete doc[key]
794
+ doc[value] = val
795
+ }
796
+ }
797
+
798
+ if (data.deleteName){
799
+ for (let key of Object.keys(data.deleteName)){
800
+ delete doc[key]
801
+ }
802
+
561
803
  }
804
+
805
+ let put = objectStore.put(doc);
806
+
807
+ put.onsuccess = function() {
808
+ resolve(doc)
809
+ };
810
+
811
+ put.onerror = function() {
812
+ errorHandler(data, put.error, database, collection, doc)
813
+ resolve(doc)
814
+ };
815
+
816
+ }
562
817
 
818
+ if (action == 'deleteDocument') {
819
+ let deleteDoc = objectStore.delete(doc._id);
820
+
821
+ deleteDoc.onsuccess = function() {
822
+ resolve(doc)
823
+ };
824
+
825
+ deleteDoc.onerror = function() {
826
+ errorHandler(data, deleteDoc.error, database, collection, doc)
827
+ resolve(doc)
828
+ };
563
829
  }
564
830
 
565
- let put = collection.put(data.data);
566
-
567
- put.onsuccess = function() {
568
- db.close()
569
- resolve(data)
570
- };
571
-
572
- put.onerror = function() {
573
- db.close()
574
- reject(put.error)
575
- };
576
831
  } else {
577
- db.close()
578
- reject('document doest not exist and upsert is not true')
832
+ // ToDo: handle if _id not found upsert
833
+ errorHandler(data, 'doc in db is newer', database, collection, doc)
834
+ resolve(doc)
579
835
  }
580
- };
581
-
582
- get.onerror = function() {
583
- db.close()
584
- reject(get.error)
585
- };
586
- }
587
- })
588
- })
589
- }
836
+ } else {
837
+ errorHandler(data, 'document doest not exist and upsert is not true', database, collection, doc)
838
+ resolve(doc)
839
+ }
590
840
 
591
- const deleteDocument = (data) => {
592
- return new Promise((resolve, reject) => {
593
- let openRequest = indexedDB.open(data.database);
594
-
595
- openRequest.onsuccess = function() {
596
- let db = openRequest.result;
597
- let transaction = db.transaction([data.collection], "readwrite");
598
- let collection = transaction.objectStore(data.collection);
599
-
600
- let request = collection.delete(data.data._id);
601
-
602
- request.onsuccess = function() {
603
- db.close()
604
- resolve(data)
605
841
  };
606
842
 
607
- request.onerror = function() {
608
- db.close()
609
- reject(request.error)
843
+ get.onerror = function() {
844
+ errorHandler(data, get.error, database, collection, doc)
845
+ resolve(doc)
610
846
  };
611
- }
612
- openRequest.onerror = function() {
613
- reject(openRequest.error)
614
- };
847
+
615
848
  })
616
849
  }
617
850
 
618
- const readDocuments = (data) => {
851
+ const readDocuments = (data, database, collection) => {
619
852
  return new Promise((resolve, reject) => {
620
- let openRequest = indexedDB.open(data.database);
853
+ let openRequest = indexedDB.open(database);
621
854
 
622
855
  openRequest.onsuccess = function() {
623
856
  let db = openRequest.result;
624
857
  try {
625
- // var transaction = db.transaction([data.collection], "readonly");
626
- let transaction = db.transaction([data.collection], "readonly");
627
- let collection = transaction.objectStore(data.collection);
858
+ let transaction = db.transaction([collection], "readonly");
859
+ let objectStore = transaction.objectStore(collection);
628
860
  let results = [];
629
- // let index = collection.index(filter.name);
861
+ // let index = objectStore.index(filter.name);
630
862
  // let request = index.openCursor(IDBKeyRange.upperBound(filter.value));
631
- let request = collection.openCursor();
863
+ let request = objectStore.openCursor();
632
864
  // transaction.oncomplete = resolve(results);
633
865
 
634
866
  request.onsuccess = function() {
635
867
  let isFilter;
868
+ // if (data['organization_id']) {
869
+ // data['filter']['query']['organization_id'] = data['organization_id'];
870
+ // }
871
+
636
872
  let cursor = request.result;
637
873
  if (cursor) {
638
874
  let value = cursor.value;
@@ -642,69 +878,31 @@ const readDocuments = (data) => {
642
878
  results.push(value)
643
879
  cursor.continue();
644
880
  } else {
645
- data.data = results
881
+ let docs = results
646
882
  if (data.filter) {
647
883
  if (data.filter.search)
648
- data.data = searchData(data.data, data.filter)
649
- if (data.filter.sort)
650
- data.data = sortData(data.data, data.filter.sort)
884
+ docs = searchData(docs, data.filter)
651
885
  }
652
- resolve(data)
886
+
887
+ resolve(docs)
653
888
  }
654
889
  };
655
890
 
656
891
  request.onerror = function() {
657
- request.data = []
658
- reject(request.error)
892
+ errorHandler(data, request.error, database, collection)
893
+ resolve([])
659
894
  };
660
895
  } catch (err) {
661
- data.data = []
662
- // data.error = err
663
- resolve(data)
896
+ errorHandler(data, err, database)
897
+ resolve([])
664
898
  return
665
899
  }
666
900
 
667
901
  };
668
902
 
669
903
  openRequest.onerror = function() {
670
- reject(openRequest.error)
671
- };
672
- })
673
- }
674
-
675
- const sync = (action, data) => {
676
- return new Promise((resolve, reject) => {
677
- let openRequest = indexedDB.open(data.database);
678
-
679
- openRequest.onsuccess = function() {
680
- let db = openRequest.result;
681
- let transaction = db.transaction([data.collection], "readonly");
682
- let collection = transaction.objectStore(data.collection);
683
-
684
- if (Array.isArray(data.data)) {
685
- for (let item of data.data) {
686
- readDocument(item, db, collection).then((doc) => {
687
- if (doc.modified.on < item.modifed.on) {
688
- collection.put(item)
689
- }
690
-
691
- })
692
- }
693
- } else {
694
- readDocument(item, db, collection).then((doc) => {
695
- if (doc.modified.on < item.modifed.on) {
696
- collection.put(item)
697
- }
698
-
699
- })
700
- }
701
-
702
- db.close()
703
- resolve('synced')
704
- };
705
-
706
- openRequest.onerror = function() {
707
- reject(openRequest.error)
904
+ errorHandler(data, openRequest.error)
905
+ resolve(data)
708
906
  };
709
907
  })
710
908
  }
@@ -721,7 +919,7 @@ async function generateDB(data) {
721
919
  let organization = {
722
920
  database: organization_id,
723
921
  collection: 'organizatons',
724
- data: {
922
+ document: {
725
923
  _id: organization_id,
726
924
  name: 'untitled',
727
925
  organization_id,
@@ -735,7 +933,7 @@ async function generateDB(data) {
735
933
  let permissions = {
736
934
  database: organization_id,
737
935
  collection: 'permissions',
738
- data: {
936
+ document: {
739
937
  _id: ObjectId(),
740
938
  organization_id,
741
939
  type: "apikey",
@@ -778,7 +976,7 @@ async function generateDB(data) {
778
976
  let user = {
779
977
  database: organization_id,
780
978
  collection: 'users',
781
- data: {
979
+ document: {
782
980
  _id: user_id,
783
981
  password: btoa('0000'),
784
982
  connected_orgs: [organization_id],
@@ -794,7 +992,7 @@ async function generateDB(data) {
794
992
  let role = {
795
993
  database: organization_id,
796
994
  collection: 'permissions',
797
- data: {
995
+ document: {
798
996
  _id: ObjectId(),
799
997
  organization_id,
800
998
  "type": "role",
@@ -818,7 +1016,7 @@ async function generateDB(data) {
818
1016
  let data = {
819
1017
  database: organization_id,
820
1018
  collection: 'permissions',
821
- data: {
1019
+ document: {
822
1020
  _id: ObjectId(),
823
1021
  organization_id,
824
1022
  "type": "user_id",
@@ -832,10 +1030,45 @@ async function generateDB(data) {
832
1030
  return true
833
1031
 
834
1032
  } catch (error) {
835
- console.log(error)
1033
+ errorHandler(data, error)
836
1034
  }
837
1035
  }
838
1036
 
1037
+ function errorHandler(data, error, database, collection){
1038
+ if (typeof error == 'object')
1039
+ error['db'] = 'indexeddb'
1040
+ else
1041
+ error = {db: 'indexeddb', message: error}
1042
+
1043
+ if (database)
1044
+ error['database'] = database
1045
+ if (collection)
1046
+ error['collection'] = collection
1047
+ if(data.error)
1048
+ data.error.push(error)
1049
+ else
1050
+ data.error = [error]
1051
+
1052
+ }
1053
+
1054
+ function createData(data, array, type) {
1055
+ data.request = data[type] || {}
1056
+
1057
+ if (data.filter && data.filter.sort)
1058
+ data[type] = sortData(array, data.filter.sort)
1059
+ else
1060
+ data[type] = array
1061
+
1062
+ if (data.returnLog){
1063
+ if (!data.log)
1064
+ data.log = []
1065
+ data.log.push(...data[type])
1066
+ }
1067
+
1068
+ return data
1069
+ }
1070
+
1071
+
839
1072
  const ObjectId = (rnd = r16 => Math.floor(r16).toString(16)) =>
840
1073
  rnd(Date.now()/1000) + ' '.repeat(16).replace(/./g, () => rnd(Math.random()*16));
841
1074
 
@@ -850,15 +1083,14 @@ function init() {
850
1083
  init();
851
1084
 
852
1085
  export default {
853
- database,
1086
+ getDatabase,
854
1087
  createDatabase,
855
1088
  readDatabase,
856
- readDatabases,
857
1089
  updateDatabase,
858
1090
  deleteDatabase,
859
1091
 
860
1092
  createCollection,
861
- readCollections,
1093
+ readCollection,
862
1094
  updateCollection,
863
1095
  deleteCollection,
864
1096
 
@@ -869,11 +1101,9 @@ export default {
869
1101
 
870
1102
  createDocument,
871
1103
  readDocument,
872
- readDocuments,
873
1104
  updateDocument,
874
1105
  deleteDocument,
875
1106
 
876
- sync,
877
1107
  ObjectId,
878
1108
  generateDB
879
1109
  };