@cocreate/indexeddb 1.22.4 → 1.23.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 +23 -0
- package/docs/index.html +9 -23
- package/package.json +2 -2
- package/prettier.config.js +16 -0
- package/src/index.js +768 -678
package/src/index.js
CHANGED
|
@@ -22,769 +22,859 @@
|
|
|
22
22
|
* For details, visit <https://cocreate.app/licenses/> or contact us at sales@cocreate.app
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
import {
|
|
26
|
+
ObjectId,
|
|
27
|
+
dotNotationToObject,
|
|
28
|
+
searchData,
|
|
29
|
+
sortData,
|
|
30
|
+
queryData,
|
|
31
|
+
createUpdate,
|
|
32
|
+
isEqualArray,
|
|
33
|
+
isEqualObject,
|
|
34
|
+
} from "@cocreate/utils";
|
|
35
|
+
|
|
36
|
+
let indexedDbFunction;
|
|
28
37
|
|
|
29
38
|
function init() {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
39
|
+
// Check for support.
|
|
40
|
+
if (!("indexedDB" in window)) {
|
|
41
|
+
console.log("This browser doesn't support IndexedDB.");
|
|
42
|
+
setStatus(false);
|
|
43
|
+
return;
|
|
44
|
+
} else {
|
|
45
|
+
try {
|
|
46
|
+
indexedDB.databases();
|
|
47
|
+
if (window.CoCreateConfig && window.CoCreateConfig.indexeddb !== false)
|
|
48
|
+
setStatus(true);
|
|
49
|
+
} catch (e) {
|
|
50
|
+
setStatus(false);
|
|
43
51
|
}
|
|
52
|
+
}
|
|
44
53
|
}
|
|
45
54
|
|
|
46
55
|
function setStatus(value) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
indexedDbFunction = true
|
|
58
|
-
}
|
|
56
|
+
if (window.CoCreateConfig) window.CoCreateConfig.indexeddb = value;
|
|
57
|
+
else window.CoCreateConfig = { indexeddb: value };
|
|
58
|
+
|
|
59
|
+
if (!value) {
|
|
60
|
+
indexedDbFunction = indexedDb;
|
|
61
|
+
send = value;
|
|
62
|
+
} else if (!send) {
|
|
63
|
+
send = indexedDbFunction;
|
|
64
|
+
indexedDbFunction = true;
|
|
65
|
+
}
|
|
59
66
|
}
|
|
60
67
|
|
|
61
68
|
async function send(data) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (!data['timeStamp'])
|
|
73
|
-
data['timeStamp'] = new Date().toISOString();
|
|
74
|
-
|
|
75
|
-
let databases = data.database;
|
|
76
|
-
if (!databases && data.organization_id)
|
|
77
|
-
databases = [data.organization_id]
|
|
78
|
-
if (!Array.isArray(databases))
|
|
79
|
-
databases = [databases]
|
|
80
|
-
|
|
81
|
-
let arrays = data.array || [];
|
|
82
|
-
if (!Array.isArray(arrays))
|
|
83
|
-
arrays = [arrays]
|
|
84
|
-
|
|
85
|
-
for (let i = 0; i < databases.length; i++) {
|
|
86
|
-
let database = databases[i]
|
|
87
|
-
if (type === 'array') {
|
|
88
|
-
await processArray(data, newData, database, type)
|
|
89
|
-
} else {
|
|
90
|
-
for (let j = 0; j < arrays.length; j++) {
|
|
91
|
-
if (type === 'index')
|
|
92
|
-
await processIndex(data, newData, database, type)
|
|
93
|
-
else if (type === 'object')
|
|
94
|
-
await processObject(data, newData, database, arrays[j], type)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
69
|
+
try {
|
|
70
|
+
let newData = [];
|
|
71
|
+
|
|
72
|
+
let type = data.method.split(".")[0];
|
|
73
|
+
if (type === "database") {
|
|
74
|
+
if (data.method === "database.get") {
|
|
75
|
+
return await processDatabase(data);
|
|
76
|
+
} else await processDatabase(data, newData, type);
|
|
77
|
+
} else {
|
|
78
|
+
if (!data["timeStamp"]) data["timeStamp"] = new Date().toISOString();
|
|
99
79
|
|
|
100
|
-
|
|
80
|
+
let databases = data.database;
|
|
81
|
+
if (!databases && data.organization_id)
|
|
82
|
+
databases = [data.organization_id];
|
|
83
|
+
if (!Array.isArray(databases)) databases = [databases];
|
|
101
84
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const dbVersion = new Map()
|
|
108
|
-
const processDatabase = (data, newData, type) => {
|
|
109
|
-
return new Promise((resolve, reject) => {
|
|
110
|
-
if (!data)
|
|
111
|
-
data = {}
|
|
112
|
-
if (!data[type])
|
|
113
|
-
data[type] = []
|
|
114
|
-
|
|
115
|
-
if (data.method == 'database.read') {
|
|
116
|
-
indexedDB.databases().then((databases) => {
|
|
117
|
-
for (let database of databases) {
|
|
118
|
-
if (data.$filter && data.$filter.query) {
|
|
119
|
-
let isFilter = queryData(database, data.$filter.query)
|
|
120
|
-
if (isFilter)
|
|
121
|
-
newData.push({ $storage: ['indexeddb'], ...database })
|
|
122
|
-
} else
|
|
123
|
-
newData.push({ $storage: ['indexeddb'], ...database })
|
|
124
|
-
}
|
|
85
|
+
let arrays = data.array || [];
|
|
86
|
+
if (!Array.isArray(arrays)) arrays = [arrays];
|
|
125
87
|
|
|
126
|
-
|
|
127
|
-
|
|
88
|
+
for (let i = 0; i < databases.length; i++) {
|
|
89
|
+
let database = databases[i];
|
|
90
|
+
if (type === "array") {
|
|
91
|
+
await processArray(data, newData, database, type);
|
|
128
92
|
} else {
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
else
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (!Array.isArray(databases))
|
|
136
|
-
databases = [databases]
|
|
137
|
-
|
|
138
|
-
for (let i = 0; i < databases.length; i++) {
|
|
139
|
-
let openRequest, database = databases[i];
|
|
140
|
-
switch (data.method) {
|
|
141
|
-
case 'database.get':
|
|
142
|
-
case 'database.create':
|
|
143
|
-
case 'database.update':
|
|
144
|
-
openRequest = indexedDB.open(database);
|
|
145
|
-
break;
|
|
146
|
-
case 'database.delete':
|
|
147
|
-
openRequest = indexedDB.deleteprocessDatabase(database);
|
|
148
|
-
break;
|
|
149
|
-
default:
|
|
150
|
-
errorHandler(data, 'unknown method', database)
|
|
151
|
-
resolve(data)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
openRequest.onsuccess = function () {
|
|
155
|
-
let db = openRequest.result;
|
|
156
|
-
|
|
157
|
-
if (data.method == 'database.update') {
|
|
158
|
-
let objectStoreNames = Array.from(db.objectStoreNames)
|
|
159
|
-
for (let array of objectStoreNames) {
|
|
160
|
-
let request = array.openCursor();
|
|
161
|
-
|
|
162
|
-
request.onsuccess = function () {
|
|
163
|
-
let cursor = request.result;
|
|
164
|
-
if (cursor) {
|
|
165
|
-
let value = cursor.value;
|
|
166
|
-
|
|
167
|
-
cursor.continue();
|
|
168
|
-
} else {
|
|
169
|
-
// -1
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
request.onerror = function () {
|
|
174
|
-
errorHandler(data, request.error, database, array)
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
} else if (data.upgrade === true) {
|
|
180
|
-
db.close()
|
|
181
|
-
|
|
182
|
-
let version = dbVersion.get(database) || openRequest.result.version
|
|
183
|
-
resolve(indexedDB.open(database, Number(version += 1)))
|
|
184
|
-
dbVersion.set(database, version)
|
|
185
|
-
|
|
186
|
-
} else if (data.array) {
|
|
187
|
-
db.close()
|
|
188
|
-
|
|
189
|
-
let version = dbVersion.get(database) || openRequest.result.version
|
|
190
|
-
let request = indexedDB.open(database, Number(version += 1));
|
|
191
|
-
dbVersion.set(database, version)
|
|
192
|
-
|
|
193
|
-
request.onupgradeneeded = function (event) {
|
|
194
|
-
const db = event.target.result;
|
|
195
|
-
|
|
196
|
-
let arrays = data.array;
|
|
197
|
-
if (!Array.isArray(arrays))
|
|
198
|
-
arrays = [arrays]
|
|
199
|
-
|
|
200
|
-
for (let j = 0; j < arrays.length; j++) {
|
|
201
|
-
if (!db.objectStoreNames.contains(arrays[j])) {
|
|
202
|
-
try {
|
|
203
|
-
db.createObjectStore(arrays[j], { keyPath: '_id', autoIncrement: true });
|
|
204
|
-
} catch (error) {
|
|
205
|
-
errorHandler(data, error, database, arrays[j])
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (data.indexName) {
|
|
210
|
-
let index = data.indexName;
|
|
211
|
-
if (!Array.isArray(index))
|
|
212
|
-
index = [index]
|
|
213
|
-
for (let k = 0; k < index.length; k++) {
|
|
214
|
-
const transaction = event.target.transaction;
|
|
215
|
-
const objectStore = transaction.objectStore(arrays[j]);
|
|
216
|
-
objectStore.createIndex(index[k], index[k], { unique: data.unique || false });
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
request.onsuccess = function (event) {
|
|
223
|
-
if (databases.length - 1 === i) {
|
|
224
|
-
if (data.method == 'database.get')
|
|
225
|
-
resolve(event.target.result)
|
|
226
|
-
else
|
|
227
|
-
resolve(data)
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
request.onerror = function (event) {
|
|
232
|
-
errorHandler(data, event.target.error, database, array)
|
|
233
|
-
if (databases.length - 1 === i) {
|
|
234
|
-
if (data.method == 'database.get')
|
|
235
|
-
resolve(event.target.result)
|
|
236
|
-
else
|
|
237
|
-
resolve(data)
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
} else if (databases.length - 1 === i) {
|
|
242
|
-
if (data.method == 'database.get')
|
|
243
|
-
resolve(db)
|
|
244
|
-
else
|
|
245
|
-
resolve(data)
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
openRequest.onerror = function () {
|
|
250
|
-
errorHandler(data, openRequest.error, database)
|
|
251
|
-
resolve(data)
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
}
|
|
93
|
+
for (let j = 0; j < arrays.length; j++) {
|
|
94
|
+
if (type === "index")
|
|
95
|
+
await processIndex(data, newData, database, type);
|
|
96
|
+
else if (type === "object")
|
|
97
|
+
await processObject(data, newData, database, arrays[j], type);
|
|
98
|
+
}
|
|
255
99
|
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
256
102
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
103
|
+
return createData(data, newData, type);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
errorHandler(data, error);
|
|
106
|
+
}
|
|
260
107
|
}
|
|
261
108
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
109
|
+
const dbVersion = new Map();
|
|
110
|
+
const processDatabase = (data, newData, type) => {
|
|
111
|
+
return new Promise(
|
|
112
|
+
(resolve, reject) => {
|
|
113
|
+
if (!data) data = {};
|
|
114
|
+
if (!data[type]) data[type] = [];
|
|
115
|
+
|
|
116
|
+
if (data.method == "database.read") {
|
|
117
|
+
indexedDB.databases().then((databases) => {
|
|
118
|
+
for (let database of databases) {
|
|
271
119
|
if (data.$filter && data.$filter.query) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
} else
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
} else {
|
|
279
|
-
db.close()
|
|
280
|
-
|
|
281
|
-
let request = await processDatabase({ method: 'database.get', database, upgrade: true })
|
|
282
|
-
await new Promise((resolve) => {
|
|
283
|
-
request.onupgradeneeded = function (event) {
|
|
284
|
-
let db = event.target.result
|
|
285
|
-
let arrays
|
|
286
|
-
if (data.method == 'array.update')
|
|
287
|
-
arrays = Object.keys(data[type])
|
|
288
|
-
else
|
|
289
|
-
arrays = data[type];
|
|
290
|
-
if (!Array.isArray(arrays))
|
|
291
|
-
arrays = [arrays]
|
|
292
|
-
|
|
293
|
-
for (let i = 0; i < arrays.length; i++) {
|
|
294
|
-
let error, array = arrays[i]
|
|
295
|
-
|
|
296
|
-
let arrayExist = db.objectStoreNames.contains(array)
|
|
297
|
-
if (arrayExist && data.method == 'array.create') {
|
|
298
|
-
error = 'array already exists'
|
|
299
|
-
} else if (data.method == 'array.delete') {
|
|
300
|
-
if (objectStoreNames.includes(array)) {
|
|
301
|
-
db.deleteObjectStore(array);
|
|
302
|
-
} else {
|
|
303
|
-
error = 'the array does not exist'
|
|
304
|
-
}
|
|
305
|
-
} else {
|
|
306
|
-
if (!arrayExist && data.method == 'array.update')
|
|
307
|
-
array = data[type][arrays[i]]
|
|
308
|
-
|
|
309
|
-
if (arrayExist) {
|
|
310
|
-
if (data.method == 'array.update') {
|
|
311
|
-
let transaction = event.target.transaction;
|
|
312
|
-
let objectStore = transaction.objectStore(array);
|
|
313
|
-
|
|
314
|
-
if (!objectStoreNames.includes(data[type][arrays[i]]))
|
|
315
|
-
array = objectStore.name = data[type][arrays[i]];
|
|
316
|
-
else
|
|
317
|
-
error = 'An array with the new name already exist'
|
|
318
|
-
}
|
|
319
|
-
} else if (data.method == 'array.update')
|
|
320
|
-
error = 'array does not exists'
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if (!error)
|
|
324
|
-
newData.push({ name: array, $storage: ['indexeddb'], $database: [database] })
|
|
325
|
-
else
|
|
326
|
-
errorHandler(data, error, database)
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
request.onsuccess = function (event) {
|
|
332
|
-
event.target.result.close()
|
|
333
|
-
resolve()
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
request.onerror = function (event) {
|
|
337
|
-
errorHandler(data, event.target.error, database)
|
|
338
|
-
resolve()
|
|
339
|
-
};
|
|
340
|
-
|
|
120
|
+
let isFilter = queryData(database, data.$filter.query);
|
|
121
|
+
if (isFilter)
|
|
122
|
+
newData.push({ $storage: ["indexeddb"], ...database });
|
|
123
|
+
} else newData.push({ $storage: ["indexeddb"], ...database });
|
|
124
|
+
}
|
|
341
125
|
|
|
126
|
+
resolve();
|
|
342
127
|
});
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
let
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
128
|
+
} else {
|
|
129
|
+
let databases;
|
|
130
|
+
if (data.method == "database.update")
|
|
131
|
+
databases = Object.keys(data.database);
|
|
132
|
+
else databases = data.database;
|
|
133
|
+
|
|
134
|
+
if (!Array.isArray(databases)) databases = [databases];
|
|
135
|
+
|
|
136
|
+
for (let i = 0; i < databases.length; i++) {
|
|
137
|
+
let openRequest,
|
|
138
|
+
database = databases[i];
|
|
139
|
+
switch (data.method) {
|
|
140
|
+
case "database.get":
|
|
141
|
+
case "database.create":
|
|
142
|
+
case "database.update":
|
|
143
|
+
openRequest = indexedDB.open(database);
|
|
144
|
+
break;
|
|
145
|
+
case "database.delete":
|
|
146
|
+
openRequest = indexedDB.deleteprocessDatabase(database);
|
|
147
|
+
break;
|
|
148
|
+
default:
|
|
149
|
+
errorHandler(data, "unknown method", database);
|
|
150
|
+
resolve(data);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
openRequest.onsuccess = function () {
|
|
154
|
+
let db = openRequest.result;
|
|
155
|
+
|
|
156
|
+
if (data.method == "database.update") {
|
|
157
|
+
let objectStoreNames = Array.from(db.objectStoreNames);
|
|
158
|
+
for (let array of objectStoreNames) {
|
|
159
|
+
let request = array.openCursor();
|
|
160
|
+
|
|
161
|
+
request.onsuccess = function () {
|
|
162
|
+
let cursor = request.result;
|
|
163
|
+
if (cursor) {
|
|
164
|
+
let value = cursor.value;
|
|
165
|
+
|
|
166
|
+
cursor.continue();
|
|
167
|
+
} else {
|
|
168
|
+
// -1
|
|
169
|
+
}
|
|
170
|
+
};
|
|
360
171
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
if (
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
error = 'new index name already exist'
|
|
172
|
+
request.onerror = function () {
|
|
173
|
+
errorHandler(data, request.error, database, array);
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
} else if (data.upgrade === true) {
|
|
177
|
+
db.close();
|
|
178
|
+
|
|
179
|
+
let version =
|
|
180
|
+
dbVersion.get(database) || openRequest.result.version;
|
|
181
|
+
resolve(indexedDB.open(database, Number((version += 1))));
|
|
182
|
+
dbVersion.set(database, version);
|
|
183
|
+
} else if (data.array) {
|
|
184
|
+
db.close();
|
|
185
|
+
|
|
186
|
+
let version =
|
|
187
|
+
dbVersion.get(database) || openRequest.result.version;
|
|
188
|
+
let request = indexedDB.open(database, Number((version += 1)));
|
|
189
|
+
dbVersion.set(database, version);
|
|
190
|
+
|
|
191
|
+
request.onupgradeneeded = function (event) {
|
|
192
|
+
const db = event.target.result;
|
|
193
|
+
|
|
194
|
+
let arrays = data.array;
|
|
195
|
+
if (!Array.isArray(arrays)) arrays = [arrays];
|
|
196
|
+
|
|
197
|
+
for (let j = 0; j < arrays.length; j++) {
|
|
198
|
+
if (!db.objectStoreNames.contains(arrays[j])) {
|
|
199
|
+
try {
|
|
200
|
+
db.createObjectStore(arrays[j], {
|
|
201
|
+
keyPath: "_id",
|
|
202
|
+
autoIncrement: true,
|
|
203
|
+
});
|
|
204
|
+
} catch (error) {
|
|
205
|
+
errorHandler(data, error, database, arrays[j]);
|
|
396
206
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (data.indexName) {
|
|
210
|
+
const transaction = event.target.transaction;
|
|
211
|
+
const objectStore = transaction.objectStore(arrays[j]);
|
|
212
|
+
if (!objectStore.indexNames.contains(data.indexName))
|
|
213
|
+
objectStore.createIndex(
|
|
214
|
+
data.indexName,
|
|
215
|
+
data.indexFields,
|
|
216
|
+
{ unique: data.unique || false }
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
};
|
|
404
221
|
|
|
405
|
-
|
|
222
|
+
request.onsuccess = function (event) {
|
|
223
|
+
if (databases.length - 1 === i) {
|
|
224
|
+
if (data.method == "database.get")
|
|
225
|
+
resolve(event.target.result);
|
|
226
|
+
else resolve(data);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
request.onerror = function (event) {
|
|
231
|
+
errorHandler(data, event.target.error, database, array);
|
|
232
|
+
if (databases.length - 1 === i) {
|
|
233
|
+
if (data.method == "database.get")
|
|
234
|
+
resolve(event.target.result);
|
|
235
|
+
else resolve(data);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
} else if (databases.length - 1 === i) {
|
|
239
|
+
if (data.method == "database.get") resolve(db);
|
|
240
|
+
else resolve(data);
|
|
406
241
|
}
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
openRequest.onerror = function () {
|
|
245
|
+
errorHandler(data, openRequest.error, database);
|
|
246
|
+
resolve(data);
|
|
247
|
+
};
|
|
407
248
|
}
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
(error) => {
|
|
252
|
+
errorHandler(data, error);
|
|
408
253
|
}
|
|
409
|
-
|
|
254
|
+
);
|
|
255
|
+
};
|
|
410
256
|
|
|
411
|
-
async function
|
|
412
|
-
|
|
257
|
+
async function processArray(data, newData, database, type) {
|
|
258
|
+
let db = await processDatabase({ method: "database.get", database });
|
|
259
|
+
|
|
260
|
+
let objectStoreNames = Array.from(db.objectStoreNames);
|
|
261
|
+
if (data.method == "array.read") {
|
|
262
|
+
if (!data[type]) data[type] = [];
|
|
263
|
+
|
|
264
|
+
for (let i = 0; i < objectStoreNames.length; i++) {
|
|
265
|
+
if (data.$filter && data.$filter.query) {
|
|
266
|
+
let isFilter = queryData(
|
|
267
|
+
{ name: objectStoreNames[i] },
|
|
268
|
+
data.$filter.query
|
|
269
|
+
);
|
|
270
|
+
if (isFilter)
|
|
271
|
+
newData.push({
|
|
272
|
+
name: objectStoreNames,
|
|
273
|
+
$storage: ["indexeddb"],
|
|
274
|
+
$database: [database],
|
|
275
|
+
});
|
|
276
|
+
} else
|
|
277
|
+
newData.push({
|
|
278
|
+
name: objectStoreNames[i],
|
|
279
|
+
$storage: ["indexeddb"],
|
|
280
|
+
$database: [database],
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
} else {
|
|
284
|
+
db.close();
|
|
413
285
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
let
|
|
423
|
-
if (data
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
286
|
+
let request = await processDatabase({
|
|
287
|
+
method: "database.get",
|
|
288
|
+
database,
|
|
289
|
+
upgrade: true,
|
|
290
|
+
});
|
|
291
|
+
await new Promise((resolve) => {
|
|
292
|
+
request.onupgradeneeded = function (event) {
|
|
293
|
+
let db = event.target.result;
|
|
294
|
+
let arrays;
|
|
295
|
+
if (data.method == "array.update") arrays = Object.keys(data[type]);
|
|
296
|
+
else arrays = data[type];
|
|
297
|
+
if (!Array.isArray(arrays)) arrays = [arrays];
|
|
298
|
+
|
|
299
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
300
|
+
let error,
|
|
301
|
+
array = arrays[i];
|
|
302
|
+
|
|
303
|
+
let arrayExist = db.objectStoreNames.contains(array);
|
|
304
|
+
if (arrayExist && data.method == "array.create") {
|
|
305
|
+
error = "array already exists";
|
|
306
|
+
} else if (data.method == "array.delete") {
|
|
307
|
+
if (objectStoreNames.includes(array)) {
|
|
308
|
+
db.deleteObjectStore(array);
|
|
431
309
|
} else {
|
|
432
|
-
|
|
310
|
+
error = "the array does not exist";
|
|
433
311
|
}
|
|
434
|
-
|
|
312
|
+
} else {
|
|
313
|
+
if (!arrayExist && data.method == "array.update")
|
|
314
|
+
array = data[type][arrays[i]];
|
|
435
315
|
|
|
436
|
-
|
|
437
|
-
|
|
316
|
+
if (arrayExist) {
|
|
317
|
+
if (data.method == "array.update") {
|
|
318
|
+
let transaction = event.target.transaction;
|
|
319
|
+
let objectStore = transaction.objectStore(array);
|
|
438
320
|
|
|
321
|
+
if (!objectStoreNames.includes(data[type][arrays[i]]))
|
|
322
|
+
array = objectStore.name = data[type][arrays[i]];
|
|
323
|
+
else error = "An array with the new name already exist";
|
|
324
|
+
}
|
|
325
|
+
} else if (data.method == "array.update")
|
|
326
|
+
error = "array does not exists";
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (!error)
|
|
330
|
+
newData.push({
|
|
331
|
+
name: array,
|
|
332
|
+
$storage: ["indexeddb"],
|
|
333
|
+
$database: [database],
|
|
334
|
+
});
|
|
335
|
+
else errorHandler(data, error, database);
|
|
336
|
+
}
|
|
337
|
+
};
|
|
439
338
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
339
|
+
request.onsuccess = function (event) {
|
|
340
|
+
event.target.result.close();
|
|
341
|
+
resolve();
|
|
342
|
+
};
|
|
443
343
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
344
|
+
request.onerror = function (event) {
|
|
345
|
+
errorHandler(data, event.target.error, database);
|
|
346
|
+
resolve();
|
|
347
|
+
};
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
}
|
|
447
351
|
|
|
448
|
-
|
|
352
|
+
async function processIndex(data, newData, database, array, type) {
|
|
353
|
+
let db = await processDatabase({ method: "database.get", database });
|
|
354
|
+
let arrayExist = db.objectStoreNames.contains(array);
|
|
355
|
+
if (arrayExist) {
|
|
356
|
+
// ToDO: switch here to types
|
|
357
|
+
let transaction = db.transaction(array, "readonly");
|
|
358
|
+
let objectStore = transaction.objectStore(array);
|
|
359
|
+
let indexNames = Array.from(objectStore.indexNames);
|
|
360
|
+
|
|
361
|
+
if (data.method == "index.read") {
|
|
362
|
+
for (let i = 0; i < indexNames.length; i++) {
|
|
363
|
+
let name = indexNames[i];
|
|
364
|
+
if (data.$filter && data.$filter.query)
|
|
365
|
+
if (!queryData({ name }, data.$filter.query)) continue;
|
|
366
|
+
|
|
367
|
+
newData.push({
|
|
368
|
+
name,
|
|
369
|
+
$storage: ["indexeddb"],
|
|
370
|
+
$database: [database],
|
|
371
|
+
$array: [array],
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
db.close();
|
|
375
|
+
} else {
|
|
376
|
+
db.close();
|
|
377
|
+
let indexes;
|
|
378
|
+
if (data.method == "index.update") indexes = Object.keys(data[type]);
|
|
379
|
+
else indexes = data[type];
|
|
380
|
+
|
|
381
|
+
if (!Array.isArray(indexes)) indexes = [indexes];
|
|
382
|
+
|
|
383
|
+
for (let i = 0; i < indexes.length; i++) {
|
|
384
|
+
let error,
|
|
385
|
+
index = indexes[i];
|
|
386
|
+
db = await processDatabase({
|
|
387
|
+
method: "database.get",
|
|
388
|
+
database,
|
|
389
|
+
upgrade: true,
|
|
390
|
+
});
|
|
391
|
+
let transaction = db.transaction;
|
|
449
392
|
let objectStore = transaction.objectStore(array);
|
|
393
|
+
let indexExist = indexNames.includes(index);
|
|
394
|
+
|
|
395
|
+
if (data.method == "index.create") {
|
|
396
|
+
if (!indexExist)
|
|
397
|
+
objectStore.createIndex(index, index, { unique: false });
|
|
398
|
+
else error = "index already exist";
|
|
399
|
+
} else if (indexExist) {
|
|
400
|
+
if (data.method == "index.delete") objectStore.deleteIndex(index);
|
|
401
|
+
else if (
|
|
402
|
+
data.method == "index.update" &&
|
|
403
|
+
!indexNames.includes(data[type][indexes[i]])
|
|
404
|
+
) {
|
|
405
|
+
if (!indexNames.includes(data[type][indexes[i]])) {
|
|
406
|
+
let indexObj = objectStore.index(index);
|
|
407
|
+
index = indexObj.name = data[type][indexes[i]];
|
|
408
|
+
} else error = "new index name already exist";
|
|
409
|
+
}
|
|
410
|
+
} else error = "index does not exist";
|
|
411
|
+
|
|
412
|
+
if (!error)
|
|
413
|
+
newData.push({
|
|
414
|
+
name: index,
|
|
415
|
+
$storage: ["indexeddb"],
|
|
416
|
+
$database: [database],
|
|
417
|
+
$array: [array],
|
|
418
|
+
});
|
|
419
|
+
else errorHandler(data, error, database, array);
|
|
420
|
+
|
|
421
|
+
db.result.close();
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
450
426
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
data[type][i] = await add(objectStore, data[type][i])
|
|
472
|
-
data[type][i] = { ...reference, ...data[type][i] }
|
|
473
|
-
|
|
474
|
-
} else {
|
|
475
|
-
if (data[type][i].$filter)
|
|
476
|
-
isFilter = true
|
|
477
|
-
|
|
478
|
-
if (data.method == 'object.update') {
|
|
479
|
-
if (data.organization_id)
|
|
480
|
-
data[type][i]['organization_id'] = data.organization_id
|
|
481
|
-
|
|
482
|
-
if (data[type][i].$upsert)
|
|
483
|
-
upsert = data[type][i].$upsert
|
|
484
|
-
// TODO: user_id || clientId shohould be retrieved from CoCreate
|
|
485
|
-
if (!data[type][i].modified)
|
|
486
|
-
data[type][i].modified = { on: data.timeStamp, by: data.user_id || data.clientId }
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
let index = 0, limit, range, direction
|
|
490
|
-
if (data[type][i]._id)
|
|
491
|
-
range = IDBKeyRange.only(data[type][i]._id);
|
|
492
|
-
else if (isFilter) {
|
|
493
|
-
let isIndex = false
|
|
494
|
-
let indexName, direction;
|
|
495
|
-
|
|
496
|
-
if (data.$filter) {
|
|
497
|
-
if (data.$filter.sort && data.$filter.sort[0] && data.$filter.sort[0].key) {
|
|
498
|
-
indexName = data.$filter.sort[0].key
|
|
499
|
-
if (indexName.includes('-'))
|
|
500
|
-
isIndex = false
|
|
501
|
-
else
|
|
502
|
-
isIndex = true
|
|
503
|
-
|
|
504
|
-
direction = data.$filter.sort[0].direction
|
|
505
|
-
if (direction == 'desc')
|
|
506
|
-
direction = 'prev'
|
|
507
|
-
else
|
|
508
|
-
direction = 'next'
|
|
509
|
-
|
|
510
|
-
} else if (data.$filter.query && data.$filter.query[0] && data.$filter.query[0].key && data.$filter.query[0].index) {
|
|
511
|
-
if (data.$filter.query[0].operator === '$eq')
|
|
512
|
-
range = IDBKeyRange.only(data.$filter.query[0].value);
|
|
513
|
-
else if (data.$filter.query[0].operator === '$gt')
|
|
514
|
-
range = IDBKeyRange.lowerBound(data.$filter.query[0].value, true);
|
|
515
|
-
else if (data.$filter.query[0].operator === '$lt')
|
|
516
|
-
range = IDBKeyRange.upperBound(data.$filter.query[0].value, true);
|
|
517
|
-
|
|
518
|
-
indexName = data.$filter.query[0].key
|
|
519
|
-
if (indexName.includes('-'))
|
|
520
|
-
isIndex = false
|
|
521
|
-
else
|
|
522
|
-
isIndex = true
|
|
523
|
-
}
|
|
524
|
-
}
|
|
427
|
+
async function processObject(data, newData, database, array, type) {
|
|
428
|
+
let db = await processDatabase({ method: "database.get", database });
|
|
429
|
+
|
|
430
|
+
try {
|
|
431
|
+
if (!data[type]) data[type] = [];
|
|
432
|
+
else if (typeof data[type] === "string") data[type] = [{ _id: data[type] }];
|
|
433
|
+
else if (!Array.isArray(data[type])) data[type] = [data[type]];
|
|
434
|
+
|
|
435
|
+
let isFilter;
|
|
436
|
+
if (data.$filter) isFilter = true;
|
|
437
|
+
|
|
438
|
+
let arrayExist = db.objectStoreNames.contains(array);
|
|
439
|
+
if (!arrayExist) {
|
|
440
|
+
db.close();
|
|
441
|
+
if (data.method == "object.create" || data.method == "object.update") {
|
|
442
|
+
db = await processDatabase({ method: "database.get", database, array });
|
|
443
|
+
} else {
|
|
444
|
+
return errorHandler(data, "array does not exist", database, array);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
525
447
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
let indexExist = indexNames.includes(indexName)
|
|
529
|
-
if (!indexExist) {
|
|
530
|
-
db.close()
|
|
531
|
-
db = await processDatabase({ method: 'database.get', database, array, indexName })
|
|
532
|
-
transaction = db.transaction(array, 'readwrite');
|
|
533
|
-
objectStore = transaction.objectStore(array);
|
|
534
|
-
}
|
|
535
|
-
objectStore = objectStore.index(indexName);
|
|
536
|
-
}
|
|
448
|
+
if (!array || !db)
|
|
449
|
+
throw new Error({ error: "This is an error message.", db, array });
|
|
537
450
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
else if (data.object.$filter)
|
|
543
|
-
data.object.$filter.count = count.result
|
|
544
|
-
}
|
|
451
|
+
let lastItem;
|
|
452
|
+
if ((isFilter && !data[type].length) || data.isFilter) {
|
|
453
|
+
if (data[type].length) lastItem = data[type][data[type].length - 1];
|
|
454
|
+
data[type] = [{ isFilter: "isEmptyObjectFilter" }];
|
|
545
455
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
index = data.$filter.index
|
|
549
|
-
if (data.$filter.limit)
|
|
550
|
-
limit = data.$filter.limit
|
|
551
|
-
}
|
|
456
|
+
// data[type].splice(0, 0, { isFilter: 'isEmptyObjectFilter' });
|
|
457
|
+
}
|
|
552
458
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
459
|
+
let transactionType = "readwrite";
|
|
460
|
+
if (data.method == "object.read") transactionType = "readonly";
|
|
461
|
+
|
|
462
|
+
let transaction = db.transaction([array], transactionType);
|
|
463
|
+
let objectStore = transaction.objectStore(array);
|
|
464
|
+
|
|
465
|
+
let globalOperators = getGlobalOperators(data);
|
|
466
|
+
let upsert = data.upsert;
|
|
467
|
+
|
|
468
|
+
for (let i = 0; i < data[type].length; i++) {
|
|
469
|
+
const reference = {
|
|
470
|
+
$storage: ["indexeddb"],
|
|
471
|
+
$database: [database],
|
|
472
|
+
$array: [array],
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
delete data[type][i].$storage;
|
|
476
|
+
delete data[type][i].$database;
|
|
477
|
+
delete data[type][i].$array;
|
|
478
|
+
|
|
479
|
+
if (data.method == "object.create") {
|
|
480
|
+
if (data.organization_id)
|
|
481
|
+
data[type][i]["organization_id"] = data.organization_id;
|
|
482
|
+
|
|
483
|
+
if (!data[type][i]._id) data[type][i]["_id"] = ObjectId().toString();
|
|
484
|
+
data[type][i] = dotNotationToObject(data[type][i]);
|
|
485
|
+
|
|
486
|
+
// TODO: user_id || clientId shohould be retrieved from CoCreate
|
|
487
|
+
data[type][i]["created"] = {
|
|
488
|
+
on: data.timeStamp,
|
|
489
|
+
by: data.user_id || data.clientId,
|
|
490
|
+
};
|
|
491
|
+
data[type][i] = await add(objectStore, data[type][i]);
|
|
492
|
+
data[type][i] = { ...reference, ...data[type][i] };
|
|
493
|
+
} else {
|
|
494
|
+
if (data[type][i].$filter) isFilter = true;
|
|
495
|
+
|
|
496
|
+
if (data.method == "object.update") {
|
|
497
|
+
if (data.organization_id)
|
|
498
|
+
data[type][i]["organization_id"] = data.organization_id;
|
|
499
|
+
|
|
500
|
+
if (data[type][i].$upsert) upsert = data[type][i].$upsert;
|
|
501
|
+
// TODO: user_id || clientId shohould be retrieved from CoCreate
|
|
502
|
+
if (!data[type][i].modified)
|
|
503
|
+
data[type][i].modified = {
|
|
504
|
+
on: data.timeStamp,
|
|
505
|
+
by: data.user_id || data.clientId,
|
|
506
|
+
};
|
|
507
|
+
}
|
|
559
508
|
|
|
560
|
-
|
|
561
|
-
|
|
509
|
+
let index = 0,
|
|
510
|
+
limit,
|
|
511
|
+
range,
|
|
512
|
+
direction;
|
|
513
|
+
if (data[type][i]._id) {
|
|
514
|
+
range = IDBKeyRange.only(data[type][i]._id);
|
|
515
|
+
} else if (isFilter) {
|
|
516
|
+
let indexName;
|
|
517
|
+
let indexFields;
|
|
518
|
+
|
|
519
|
+
if (data.$filter) {
|
|
520
|
+
// TODO: requires a more robust sorting thats suports various directions
|
|
521
|
+
// Build compound index name from sort keys
|
|
522
|
+
if (data.$filter.sort && data.$filter.sort.length > 0) {
|
|
523
|
+
// Create a standard index name without _id
|
|
524
|
+
let sortKeys = data.$filter.sort
|
|
525
|
+
.map((sort) => sort.key)
|
|
526
|
+
.filter((key) => key !== "_id");
|
|
527
|
+
indexName = sortKeys.join("_"); // e.g., "createdAt_category"
|
|
528
|
+
|
|
529
|
+
// Define compound index fields
|
|
530
|
+
indexFields = [...sortKeys];
|
|
531
|
+
|
|
532
|
+
// Set cursor direction based on the first sort key direction
|
|
533
|
+
direction =
|
|
534
|
+
data.$filter.sort[0].direction === "desc" ? "prev" : "next";
|
|
535
|
+
|
|
536
|
+
// Use last item's values, including _id, to set up the range for pagination
|
|
537
|
+
if (indexName && lastItem && lastItem._id) {
|
|
538
|
+
indexName += "_id";
|
|
539
|
+
indexFields.push("_id");
|
|
540
|
+
let lastKeyValues = [
|
|
541
|
+
...sortKeys.map((key) => lastItem[key]),
|
|
542
|
+
lastItem._id,
|
|
543
|
+
]; // Compound key array with _id
|
|
544
|
+
|
|
545
|
+
// Create IDBKeyRange based on direction and lastKeyValues
|
|
546
|
+
if (direction === "next") {
|
|
547
|
+
range = IDBKeyRange.lowerBound(lastKeyValues, true);
|
|
548
|
+
} else {
|
|
549
|
+
range = IDBKeyRange.upperBound(lastKeyValues, true);
|
|
562
550
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
551
|
+
}
|
|
552
|
+
} else if (
|
|
553
|
+
data.$filter.query &&
|
|
554
|
+
data.$filter.query[0] &&
|
|
555
|
+
data.$filter.query[0].key
|
|
556
|
+
) {
|
|
557
|
+
if (data.$filter.query[0].operator === "$eq") {
|
|
558
|
+
range = IDBKeyRange.only(data.$filter.query[0].value);
|
|
559
|
+
} else if (data.$filter.query[0].operator === "$gt") {
|
|
560
|
+
range = IDBKeyRange.lowerBound(
|
|
561
|
+
data.$filter.query[0].value,
|
|
562
|
+
true
|
|
563
|
+
);
|
|
564
|
+
} else if (data.$filter.query[0].operator === "$lt") {
|
|
565
|
+
range = IDBKeyRange.upperBound(
|
|
566
|
+
data.$filter.query[0].value,
|
|
567
|
+
true
|
|
568
|
+
);
|
|
569
|
+
} else if (data.$filter.query[0].operator === "$gte") {
|
|
570
|
+
range = IDBKeyRange.lowerBound(data.$filter.query[0].value);
|
|
571
|
+
} else if (data.$filter.query[0].operator === "$lte") {
|
|
572
|
+
range = IDBKeyRange.upperBound(data.$filter.query[0].value);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
indexName = data.$filter.query[0].key;
|
|
568
576
|
}
|
|
569
|
-
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
if (indexName && !indexName.includes("-")) {
|
|
580
|
+
// Check if the compound index exists; create it if not
|
|
581
|
+
let indexNames = Array.from(objectStore.indexNames);
|
|
582
|
+
if (!indexNames.includes(indexName)) {
|
|
583
|
+
db.close();
|
|
584
|
+
db = await processDatabase({
|
|
585
|
+
method: "database.get",
|
|
586
|
+
database,
|
|
587
|
+
array,
|
|
588
|
+
indexName,
|
|
589
|
+
indexFields,
|
|
590
|
+
});
|
|
591
|
+
transaction = db.transaction(array, "readwrite");
|
|
592
|
+
objectStore = transaction.objectStore(array);
|
|
593
|
+
}
|
|
594
|
+
objectStore = objectStore.index(indexName);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
let count = objectStore.count();
|
|
598
|
+
count.onsuccess = function () {
|
|
599
|
+
if (data.$filter) data.$filter.count = count.result;
|
|
600
|
+
else if (data.object.$filter)
|
|
601
|
+
data.object.$filter.count = count.result;
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
if (data.$filter) {
|
|
605
|
+
if (data.$filter.index) index = data.$filter.index;
|
|
606
|
+
if (data.$filter.limit) limit = data.$filter.limit;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if (data[type][i].$filter) {
|
|
610
|
+
if (data[type][i].$filter.index)
|
|
611
|
+
index = data[type][i].$filter.index;
|
|
612
|
+
if (data[type][i].$filter.limit)
|
|
613
|
+
limit = data[type][i].$filter.limit;
|
|
614
|
+
}
|
|
615
|
+
} else if (
|
|
616
|
+
data.method == "object.delete" ||
|
|
617
|
+
(data.method == "object.update" && !range && !upsert && !isFilter)
|
|
618
|
+
) {
|
|
619
|
+
continue;
|
|
570
620
|
}
|
|
571
621
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
622
|
+
await openCursor(
|
|
623
|
+
objectStore,
|
|
624
|
+
range,
|
|
625
|
+
direction,
|
|
626
|
+
data,
|
|
627
|
+
newData,
|
|
628
|
+
isFilter,
|
|
629
|
+
index,
|
|
630
|
+
limit,
|
|
631
|
+
database,
|
|
632
|
+
array,
|
|
633
|
+
upsert,
|
|
634
|
+
type,
|
|
635
|
+
i,
|
|
636
|
+
globalOperators,
|
|
637
|
+
reference
|
|
638
|
+
);
|
|
639
|
+
|
|
640
|
+
if (index) newData = newData.slice(index);
|
|
641
|
+
}
|
|
580
642
|
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
function openCursor(objectStore, range, direction, data, newData, isFilter, index, limit, database, array, upsert, type, i, globalOperators, reference) {
|
|
584
|
-
return new Promise(async (resolve, reject) => {
|
|
585
|
-
const request = objectStore.openCursor(range || null, direction);// next, prev
|
|
586
|
-
|
|
587
|
-
let hasUpdated, matchedLength = 0, hasSkipped
|
|
588
|
-
request.onsuccess = async () => {
|
|
589
|
-
let cursor = request.result
|
|
590
|
-
|
|
591
|
-
if (data.method === 'object.create'
|
|
592
|
-
|| data.method === 'object.update'
|
|
593
|
-
&& (!range && !isFilter && upsert || !cursor && upsert && !hasUpdated)) {
|
|
594
|
-
let isMatch = true
|
|
595
|
-
if (isFilter) {
|
|
596
|
-
if (cursor)
|
|
597
|
-
isMatch = filter(objectStore, data[type][i], data[type][i], cursor.value)
|
|
598
|
-
else if (data.method === 'object.update' && !upsert)
|
|
599
|
-
isMatch = false
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
if (isMatch !== false) {
|
|
603
|
-
try {
|
|
604
|
-
data[type][i]._id = ObjectId(data[type][i]._id).toString();
|
|
605
|
-
} catch (error) {
|
|
606
|
-
data[type][i]._id = ObjectId().toString()
|
|
607
|
-
}
|
|
608
643
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
await put(objectStore, update)
|
|
616
|
-
data[type][i].$update = update
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
data[type][i] = { ...reference, ...data[type][i] }
|
|
620
|
-
|
|
621
|
-
matchedLength++
|
|
622
|
-
|
|
623
|
-
}
|
|
624
|
-
resolve();
|
|
625
|
-
} else if (cursor) {
|
|
626
|
-
if (index && !hasSkipped) {
|
|
627
|
-
cursor.advance(index);
|
|
628
|
-
hasSkipped = true;
|
|
629
|
-
} else {
|
|
630
|
-
let isMatch = true
|
|
631
|
-
if (isFilter)
|
|
632
|
-
isMatch = filter(objectStore, data, data[type][i], cursor.value)
|
|
633
|
-
|
|
634
|
-
if (isMatch !== false) {
|
|
635
|
-
let result = cursor.value
|
|
636
|
-
|
|
637
|
-
if (data.method == 'object.update') {
|
|
638
|
-
let update = createUpdate(cursor.value, data[type][i], globalOperators)
|
|
639
|
-
if (update)
|
|
640
|
-
await cursorUpdate(cursor, update)
|
|
641
|
-
result = data[type][i]
|
|
642
|
-
result.$update = update
|
|
643
|
-
// result = cursor.update(update)
|
|
644
|
-
hasUpdated = true
|
|
645
|
-
// set dotnotation for keys with $operators for items that end in [] to be used by socket.id
|
|
646
|
-
// TODO: if update.$<operator>.someKey[] requires the index of inerted item added to the field name. update.$<operator>.someKey[<index>]
|
|
647
|
-
// TODO: if $addToSet get field name and item if it does not exist.
|
|
648
|
-
// TODO: if $pull get field name and find if item exist and delete.
|
|
649
|
-
} else if (data.method == 'object.delete') {
|
|
650
|
-
result = cursor.value
|
|
651
|
-
cursor.delete()
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
if (data[type][i]._id)
|
|
655
|
-
data[type][i] = { ...reference, ...result }
|
|
656
|
-
else {
|
|
657
|
-
let object = data[type].find(obj => obj._id && obj._id === result._id)
|
|
658
|
-
if (object)
|
|
659
|
-
object = { ...reference, ...object, ...result }
|
|
660
|
-
else
|
|
661
|
-
newData.push({ ...reference, ...result })
|
|
662
|
-
}
|
|
663
|
-
}
|
|
644
|
+
if (db.close) db.close();
|
|
645
|
+
} catch (error) {
|
|
646
|
+
errorHandler(data, error, database, array);
|
|
647
|
+
if (db.close) db.close();
|
|
648
|
+
}
|
|
649
|
+
}
|
|
664
650
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
651
|
+
function openCursor(
|
|
652
|
+
objectStore,
|
|
653
|
+
range,
|
|
654
|
+
direction,
|
|
655
|
+
data,
|
|
656
|
+
newData,
|
|
657
|
+
isFilter,
|
|
658
|
+
index,
|
|
659
|
+
limit,
|
|
660
|
+
database,
|
|
661
|
+
array,
|
|
662
|
+
upsert,
|
|
663
|
+
type,
|
|
664
|
+
i,
|
|
665
|
+
globalOperators,
|
|
666
|
+
reference
|
|
667
|
+
) {
|
|
668
|
+
return new Promise(async (resolve, reject) => {
|
|
669
|
+
const request = objectStore.openCursor(range || null, direction); // next, prev
|
|
670
|
+
|
|
671
|
+
let hasUpdated,
|
|
672
|
+
matchedLength = 0,
|
|
673
|
+
hasSkipped;
|
|
674
|
+
request.onsuccess = async () => {
|
|
675
|
+
let cursor = request.result;
|
|
676
|
+
|
|
677
|
+
if (
|
|
678
|
+
data.method === "object.create" ||
|
|
679
|
+
(data.method === "object.update" &&
|
|
680
|
+
((!range && !isFilter && upsert) ||
|
|
681
|
+
(!cursor && upsert && !hasUpdated)))
|
|
682
|
+
) {
|
|
683
|
+
let isMatch = true;
|
|
684
|
+
if (isFilter) {
|
|
685
|
+
if (cursor)
|
|
686
|
+
isMatch = filter(
|
|
687
|
+
objectStore,
|
|
688
|
+
data[type][i],
|
|
689
|
+
data[type][i],
|
|
690
|
+
cursor.value
|
|
691
|
+
);
|
|
692
|
+
else if (data.method === "object.update" && !upsert) isMatch = false;
|
|
693
|
+
}
|
|
671
694
|
|
|
672
|
-
|
|
673
|
-
|
|
695
|
+
if (isMatch !== false) {
|
|
696
|
+
try {
|
|
697
|
+
data[type][i]._id = ObjectId(data[type][i]._id).toString();
|
|
698
|
+
} catch (error) {
|
|
699
|
+
data[type][i]._id = ObjectId().toString();
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
let result;
|
|
703
|
+
if (data.method == "object.create") {
|
|
704
|
+
data[type][i] = await add(objectStore, data[type][i]);
|
|
705
|
+
} else if (data.method == "object.update") {
|
|
706
|
+
let update = createUpdate(
|
|
707
|
+
cursor && cursor.value ? cursor.value : {},
|
|
708
|
+
data[type][i],
|
|
709
|
+
globalOperators
|
|
710
|
+
);
|
|
711
|
+
if (update) {
|
|
712
|
+
await put(objectStore, update);
|
|
713
|
+
data[type][i].$update = update;
|
|
674
714
|
}
|
|
715
|
+
}
|
|
716
|
+
data[type][i] = { ...reference, ...data[type][i] };
|
|
675
717
|
|
|
718
|
+
matchedLength++;
|
|
676
719
|
}
|
|
720
|
+
resolve();
|
|
721
|
+
} else if (cursor) {
|
|
722
|
+
if (index && !hasSkipped) {
|
|
723
|
+
cursor.advance(index);
|
|
724
|
+
hasSkipped = true;
|
|
725
|
+
} else {
|
|
726
|
+
let isMatch = true;
|
|
727
|
+
if (isFilter)
|
|
728
|
+
isMatch = filter(objectStore, data, data[type][i], cursor.value);
|
|
729
|
+
|
|
730
|
+
if (isMatch !== false) {
|
|
731
|
+
let result = cursor.value;
|
|
732
|
+
|
|
733
|
+
if (data.method == "object.update") {
|
|
734
|
+
let update = createUpdate(
|
|
735
|
+
cursor.value,
|
|
736
|
+
data[type][i],
|
|
737
|
+
globalOperators
|
|
738
|
+
);
|
|
739
|
+
if (update) await cursorUpdate(cursor, update);
|
|
740
|
+
result = data[type][i];
|
|
741
|
+
result.$update = update;
|
|
742
|
+
// result = cursor.update(update)
|
|
743
|
+
hasUpdated = true;
|
|
744
|
+
// set dotnotation for keys with $operators for items that end in [] to be used by socket.id
|
|
745
|
+
// TODO: if update.$<operator>.someKey[] requires the index of inerted item added to the field name. update.$<operator>.someKey[<index>]
|
|
746
|
+
// TODO: if $addToSet get field name and item if it does not exist.
|
|
747
|
+
// TODO: if $pull get field name and find if item exist and delete.
|
|
748
|
+
} else if (data.method == "object.delete") {
|
|
749
|
+
result = cursor.value;
|
|
750
|
+
cursor.delete();
|
|
751
|
+
}
|
|
677
752
|
|
|
678
|
-
|
|
679
|
-
|
|
753
|
+
if (data[type][i]._id) data[type][i] = { ...reference, ...result };
|
|
754
|
+
else {
|
|
755
|
+
let object = data[type].find(
|
|
756
|
+
(obj) => obj._id && obj._id === result._id
|
|
757
|
+
);
|
|
758
|
+
if (object) object = { ...reference, ...object, ...result };
|
|
759
|
+
else newData.push({ ...reference, ...result });
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
if (!limit || (limit && limit > newData.length + matchedLength)) {
|
|
764
|
+
cursor.continue();
|
|
765
|
+
} else {
|
|
766
|
+
resolve();
|
|
767
|
+
}
|
|
680
768
|
}
|
|
681
|
-
|
|
769
|
+
} else {
|
|
770
|
+
resolve();
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
request.onerror = () => {
|
|
775
|
+
reject(request.error);
|
|
776
|
+
};
|
|
777
|
+
});
|
|
682
778
|
}
|
|
683
779
|
|
|
684
780
|
function add(objectStore, object) {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
781
|
+
return new Promise((resolve, reject) => {
|
|
782
|
+
const store = objectStore.objectStore || objectStore;
|
|
783
|
+
let request = store.add(object);
|
|
784
|
+
request.onsuccess = () => resolve(object);
|
|
785
|
+
request.onerror = () => reject(request.error);
|
|
786
|
+
});
|
|
691
787
|
}
|
|
692
788
|
|
|
693
789
|
function get(objectStore, object) {
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
790
|
+
return new Promise((resolve, reject) => {
|
|
791
|
+
const request = objectStore.get(object._id);
|
|
792
|
+
request.onsuccess = () => resolve(request.result);
|
|
793
|
+
request.onerror = () => reject(request.error);
|
|
794
|
+
});
|
|
699
795
|
}
|
|
700
796
|
|
|
701
797
|
function put(objectStore, object) {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
798
|
+
return new Promise((resolve, reject) => {
|
|
799
|
+
const store = objectStore.objectStore || objectStore;
|
|
800
|
+
let request = store.put(object);
|
|
705
801
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
802
|
+
request.onsuccess = () => resolve(object);
|
|
803
|
+
request.onerror = () => reject(request.error);
|
|
804
|
+
});
|
|
709
805
|
}
|
|
710
806
|
|
|
711
807
|
function deleteObject(objectStore, object) {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
808
|
+
return new Promise((resolve, reject) => {
|
|
809
|
+
const request = objectStore.delete(object._id);
|
|
810
|
+
request.onsuccess = () => resolve(object);
|
|
811
|
+
request.onerror = () => reject(request.error);
|
|
812
|
+
});
|
|
717
813
|
}
|
|
718
814
|
|
|
719
815
|
function cursorUpdate(cursor, update) {
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
816
|
+
return new Promise((resolve, reject) => {
|
|
817
|
+
const request = cursor.update(update);
|
|
818
|
+
request.onsuccess = () => resolve(request.source.value);
|
|
819
|
+
request.onerror = () => reject(request.error);
|
|
820
|
+
});
|
|
725
821
|
}
|
|
726
822
|
|
|
727
|
-
|
|
728
823
|
function filter(objectStore, data, object, result) {
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
return isMatch
|
|
824
|
+
let isMatch = true;
|
|
825
|
+
let filter = data.$filter || object.$filter;
|
|
826
|
+
if (filter) {
|
|
827
|
+
if (filter.query) isMatch = queryData(result, filter.query);
|
|
828
|
+
if (isMatch && filter.search) isMatch = searchData(result, filter.search);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
return isMatch;
|
|
739
832
|
}
|
|
740
833
|
|
|
741
834
|
function getGlobalOperators(data, object = {}) {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
}
|
|
835
|
+
for (let operator of Object.keys(data)) {
|
|
836
|
+
if (!operator.startsWith("$")) return;
|
|
837
|
+
for (let key of Object.keys(data[operator]))
|
|
838
|
+
object[operator + "." + key] = data[operator][key];
|
|
839
|
+
}
|
|
748
840
|
|
|
749
|
-
|
|
841
|
+
return object;
|
|
750
842
|
}
|
|
751
843
|
|
|
752
844
|
function createData(data, newData, type) {
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
data[type].
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
845
|
+
// data.request = data[type] || {}
|
|
846
|
+
if (
|
|
847
|
+
data[type] &&
|
|
848
|
+
data[type][0] &&
|
|
849
|
+
data[type][0].isFilter === "isEmptyObjectFilter"
|
|
850
|
+
) {
|
|
851
|
+
data[type].shift();
|
|
852
|
+
data.isFilter = true;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
data[type].push(...newData);
|
|
856
|
+
|
|
857
|
+
if (data.$filter) {
|
|
858
|
+
if (data.$filter.sort) data[type] = sortData(data[type], data.$filter.sort);
|
|
859
|
+
|
|
860
|
+
data.$filter.startingIndex = data.$filter.index;
|
|
861
|
+
data.$filter.index += data[type].length;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
return data;
|
|
770
865
|
}
|
|
771
866
|
|
|
772
867
|
function errorHandler(data, error, database, array) {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
error['array'] = array
|
|
782
|
-
if (data.error)
|
|
783
|
-
data.error.push(error)
|
|
784
|
-
else
|
|
785
|
-
data.error = [error]
|
|
868
|
+
console.error(error, data);
|
|
869
|
+
if (typeof error == "object") error["storage"] = "indexeddb";
|
|
870
|
+
else error = { storage: "indexeddb", message: error };
|
|
871
|
+
|
|
872
|
+
if (database) error["database"] = database;
|
|
873
|
+
if (array) error["array"] = array;
|
|
874
|
+
if (data.error) data.error.push(error);
|
|
875
|
+
else data.error = [error];
|
|
786
876
|
}
|
|
787
877
|
|
|
788
878
|
init();
|
|
789
879
|
|
|
790
|
-
export default { send, ObjectId }
|
|
880
|
+
export default { send, ObjectId };
|