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