@roc-db/indexed-db 0.2.0-pre.1 → 0.2.0-pre.100
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/dist/index.js +333 -188
- package/dist/types/createIndexedDBAdapter.d.ts +12 -0
- package/dist/types/functions/batchReadEntities.d.ts +3 -0
- package/dist/types/functions/begin.d.ts +3 -0
- package/dist/types/functions/commit.d.ts +3 -0
- package/dist/types/functions/commitCreate.d.ts +3 -0
- package/dist/types/functions/commitDelete.d.ts +3 -0
- package/dist/types/functions/commitUpdate.d.ts +3 -0
- package/dist/types/functions/end.d.ts +3 -0
- package/dist/types/functions/findDebounceMutation.d.ts +2 -0
- package/dist/types/functions/getChangeSetMutations.d.ts +2 -0
- package/dist/types/functions/index.d.ts +13 -0
- package/dist/types/functions/pageEntities.d.ts +2 -0
- package/dist/types/functions/pageEntitiesByIndex.d.ts +2 -0
- package/dist/types/functions/pageMutations.d.ts +2 -0
- package/dist/types/functions/readEntity.d.ts +3 -0
- package/dist/types/functions/readMutation.d.ts +2 -0
- package/dist/types/functions/refByUniqueField.d.ts +2 -0
- package/dist/types/functions/saveMutation.d.ts +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/lib/documentFromDBRow.d.ts +1 -0
- package/dist/types/lib/documentToDBRow.d.ts +1 -0
- package/dist/types/types/IndexedDBEngine.d.ts +10 -0
- package/dist/types/types/IndexedDBReadTransaction.d.ts +3 -0
- package/dist/types/types/IndexedDBWriteTransaction.d.ts +3 -0
- package/package.json +12 -16
- package/dist/roc-db-indexed-db-0.2.0-pre.1.tgz +0 -0
package/dist/index.js
CHANGED
|
@@ -10,32 +10,83 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/createIndexedDBAdapter.ts
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
createAdapter,
|
|
15
|
+
Snowflake
|
|
16
|
+
} from "roc-db";
|
|
14
17
|
|
|
15
18
|
// src/functions/index.ts
|
|
16
19
|
var exports_functions = {};
|
|
17
20
|
__export(exports_functions, {
|
|
18
|
-
updateEntity: () => updateEntity,
|
|
19
21
|
saveMutation: () => saveMutation,
|
|
22
|
+
refByUniqueField: () => refByUniqueField,
|
|
20
23
|
readMutation: () => readMutation,
|
|
21
24
|
readEntity: () => readEntity,
|
|
22
|
-
|
|
25
|
+
pageMutations: () => pageMutations,
|
|
26
|
+
pageEntitiesByIndex: () => pageEntitiesByIndex,
|
|
27
|
+
pageEntities: () => pageEntities,
|
|
23
28
|
getChangeSetMutations: () => getChangeSetMutations,
|
|
24
29
|
findDebounceMutation: () => findDebounceMutation,
|
|
25
30
|
end: () => end,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
commit: () => commit,
|
|
32
|
+
begin: () => begin,
|
|
33
|
+
batchReadEntities: () => batchReadEntities
|
|
29
34
|
});
|
|
30
35
|
|
|
31
|
-
// src/
|
|
32
|
-
var
|
|
36
|
+
// src/lib/documentFromDBRow.ts
|
|
37
|
+
var documentFromDBRow = ({
|
|
38
|
+
unique_constraint_0,
|
|
39
|
+
unique_constraint_1,
|
|
40
|
+
index_entries,
|
|
41
|
+
...document
|
|
42
|
+
}) => {
|
|
43
|
+
return {
|
|
44
|
+
...document,
|
|
45
|
+
__: {
|
|
46
|
+
uniqueExisting: [],
|
|
47
|
+
indexExisting: []
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/functions/readEntity.ts
|
|
53
|
+
var readEntity = async (txn, ref) => {
|
|
54
|
+
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
55
|
+
const request = objectStore.get(ref);
|
|
33
56
|
return new Promise((resolve, reject) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
57
|
+
request.onsuccess = (event) => {
|
|
58
|
+
const result = event.target.result;
|
|
59
|
+
if (!result) {
|
|
60
|
+
return resolve(undefined);
|
|
61
|
+
}
|
|
62
|
+
resolve(documentFromDBRow(result));
|
|
63
|
+
};
|
|
64
|
+
request.onerror = (event) => {
|
|
65
|
+
reject(event.target.error);
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// src/functions/batchReadEntities.ts
|
|
71
|
+
var batchReadEntities = (txn, refs) => {
|
|
72
|
+
return Promise.all(refs.map((ref) => readEntity(txn, ref)));
|
|
73
|
+
};
|
|
74
|
+
// src/functions/begin.ts
|
|
75
|
+
var DB_CACHE = new WeakMap;
|
|
76
|
+
var openDatabase = (engineOpts) => {
|
|
77
|
+
let cached = DB_CACHE.get(engineOpts);
|
|
78
|
+
if (cached)
|
|
79
|
+
return cached;
|
|
80
|
+
const promise = new Promise((resolve, reject) => {
|
|
81
|
+
const idbRequest = indexedDB.open(engineOpts.dbName, engineOpts.version);
|
|
82
|
+
idbRequest.onupgradeneeded = () => {
|
|
37
83
|
const entitiesObjectStore = idbRequest.result.createObjectStore("entities", { keyPath: "ref" });
|
|
38
84
|
const mutationsObjectStore = idbRequest.result.createObjectStore("mutations", { keyPath: "ref" });
|
|
85
|
+
entitiesObjectStore.createIndex("unique_constraint_0", ["entity", "unique_constraint_0"], { unique: true });
|
|
86
|
+
entitiesObjectStore.createIndex("unique_constraint_1", ["entity", "unique_constraint_1"], { unique: true });
|
|
87
|
+
entitiesObjectStore.createIndex("byIndexEntry", "index_entries", {
|
|
88
|
+
multiEntry: true
|
|
89
|
+
});
|
|
39
90
|
mutationsObjectStore.createIndex("timestamp", "timestamp", {
|
|
40
91
|
unique: false
|
|
41
92
|
});
|
|
@@ -43,104 +94,209 @@ var begin = async (request, engineOpts) => {
|
|
|
43
94
|
unique: false
|
|
44
95
|
});
|
|
45
96
|
};
|
|
46
|
-
idbRequest.onsuccess = (
|
|
47
|
-
db = idbRequest.result;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
97
|
+
idbRequest.onsuccess = () => {
|
|
98
|
+
const db = idbRequest.result;
|
|
99
|
+
db.onversionchange = () => {
|
|
100
|
+
db.close();
|
|
101
|
+
DB_CACHE.delete(engineOpts);
|
|
102
|
+
};
|
|
103
|
+
resolve(db);
|
|
104
|
+
};
|
|
105
|
+
idbRequest.onerror = () => {
|
|
106
|
+
DB_CACHE.delete(engineOpts);
|
|
107
|
+
reject(idbRequest.error);
|
|
57
108
|
};
|
|
58
109
|
});
|
|
110
|
+
DB_CACHE.set(engineOpts, promise);
|
|
111
|
+
return promise;
|
|
59
112
|
};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
113
|
+
var begin = async (engineOpts, callback) => {
|
|
114
|
+
const db = await openDatabase(engineOpts);
|
|
115
|
+
return new Promise((resolve, reject) => {
|
|
116
|
+
const txn = db.transaction(["entities", "mutations"], "readwrite");
|
|
117
|
+
let callbackResult;
|
|
118
|
+
let callbackDone = false;
|
|
119
|
+
let txnComplete = false;
|
|
120
|
+
let settled = false;
|
|
121
|
+
const maybeResolve = () => {
|
|
122
|
+
if (settled)
|
|
123
|
+
return;
|
|
124
|
+
if (callbackDone && txnComplete) {
|
|
125
|
+
settled = true;
|
|
126
|
+
resolve(callbackResult);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
txn.oncomplete = () => {
|
|
130
|
+
txnComplete = true;
|
|
131
|
+
maybeResolve();
|
|
132
|
+
};
|
|
133
|
+
txn.onerror = (event) => {
|
|
134
|
+
if (settled)
|
|
135
|
+
return;
|
|
136
|
+
settled = true;
|
|
137
|
+
reject(txn.error ?? event.target?.error);
|
|
138
|
+
};
|
|
139
|
+
txn.onabort = () => {
|
|
140
|
+
if (settled)
|
|
141
|
+
return;
|
|
142
|
+
settled = true;
|
|
143
|
+
reject(txn.error ?? new Error("Transaction aborted"));
|
|
144
|
+
};
|
|
145
|
+
Promise.resolve(callback({
|
|
146
|
+
...engineOpts,
|
|
147
|
+
db,
|
|
148
|
+
txn
|
|
149
|
+
})).then((result) => {
|
|
150
|
+
callbackResult = result;
|
|
151
|
+
callbackDone = true;
|
|
152
|
+
maybeResolve();
|
|
153
|
+
}).catch((error) => {
|
|
154
|
+
if (settled)
|
|
155
|
+
return;
|
|
156
|
+
settled = true;
|
|
157
|
+
try {
|
|
158
|
+
txn.abort();
|
|
159
|
+
} catch {}
|
|
160
|
+
reject(error);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
// src/functions/commitCreate.ts
|
|
165
|
+
import { createUniqueConstraintConflictError } from "roc-db";
|
|
166
|
+
var commitCreate = (txn, document) => {
|
|
63
167
|
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
168
|
+
const request = objectStore.add(document);
|
|
169
|
+
return new Promise((resolve, reject) => {
|
|
170
|
+
request.onsuccess = (event) => {
|
|
171
|
+
resolve(document);
|
|
172
|
+
};
|
|
173
|
+
request.onerror = (event) => {
|
|
174
|
+
const error = event?.target?.error;
|
|
175
|
+
if (error?.name === "ConstraintError") {
|
|
176
|
+
event.stopPropagation();
|
|
177
|
+
event.preventDefault();
|
|
178
|
+
reject(createUniqueConstraintConflictError(document.entity));
|
|
179
|
+
} else {
|
|
180
|
+
console.error("Error creating entity:", document, error);
|
|
181
|
+
reject(error);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// src/functions/commitDelete.ts
|
|
188
|
+
import { entityFromRef } from "roc-db";
|
|
189
|
+
var commitDelete = async (txn, ref) => {
|
|
64
190
|
const entity = entityFromRef(ref);
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
timestamp: txn.mutation.timestamp
|
|
70
|
-
},
|
|
71
|
-
updated: {
|
|
72
|
-
mutationRef: txn.mutation.ref,
|
|
73
|
-
timestamp: txn.mutation.timestamp
|
|
74
|
-
},
|
|
75
|
-
entity,
|
|
76
|
-
data,
|
|
77
|
-
children,
|
|
78
|
-
ancestors,
|
|
79
|
-
parents
|
|
80
|
-
};
|
|
81
|
-
if (txn.request.changeSetRef) {
|
|
82
|
-
if (txn.engineOpts.changeSet.entities.has(ref)) {
|
|
83
|
-
throw new Error("Entity already exists in changeSet");
|
|
84
|
-
} else {
|
|
85
|
-
txn.engineOpts.changeSet.entities.set(ref, document);
|
|
86
|
-
return document;
|
|
87
|
-
}
|
|
191
|
+
const engineTxn = txn.engineOpts.txn;
|
|
192
|
+
let objectStore;
|
|
193
|
+
if (entity === "Mutation") {
|
|
194
|
+
objectStore = engineTxn.objectStore("mutations");
|
|
88
195
|
} else {
|
|
89
|
-
|
|
90
|
-
return new Promise((resolve, reject) => {
|
|
91
|
-
request.onsuccess = (event) => {
|
|
92
|
-
resolve(document);
|
|
93
|
-
};
|
|
94
|
-
request.onerror = (event) => {
|
|
95
|
-
console.error("Error creating entity:", document, event?.target?.error);
|
|
96
|
-
reject(event?.target?.error);
|
|
97
|
-
};
|
|
98
|
-
});
|
|
196
|
+
objectStore = engineTxn.objectStore("entities");
|
|
99
197
|
}
|
|
100
|
-
|
|
101
|
-
// src/functions/deleteEntity.ts
|
|
102
|
-
import { DELETED_IN_CHANGE_SET_SYMBOL } from "roc-db";
|
|
103
|
-
var deleteIndexed = (store, ref) => {
|
|
104
|
-
const request = store.delete(ref);
|
|
198
|
+
const request = objectStore.delete(ref);
|
|
105
199
|
return new Promise((resolve, reject) => {
|
|
106
200
|
request.onsuccess = () => {
|
|
107
201
|
resolve(true);
|
|
108
202
|
};
|
|
109
203
|
request.onerror = (event) => {
|
|
110
|
-
console.error("Error
|
|
204
|
+
console.error("Error deleting document", event?.target?.error);
|
|
111
205
|
reject(event?.target?.error);
|
|
112
206
|
};
|
|
113
207
|
});
|
|
114
208
|
};
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
209
|
+
|
|
210
|
+
// src/functions/commitUpdate.ts
|
|
211
|
+
var commitUpdate = async (txn, document) => {
|
|
212
|
+
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
213
|
+
const request = objectStore.put(document);
|
|
214
|
+
return new Promise((resolve, reject) => {
|
|
215
|
+
request.onsuccess = (event) => {
|
|
216
|
+
resolve(document);
|
|
217
|
+
};
|
|
218
|
+
request.onerror = (event) => {
|
|
219
|
+
console.error("Error updating document", event?.target?.error);
|
|
220
|
+
reject(event?.target?.error);
|
|
221
|
+
};
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// src/functions/saveMutation.ts
|
|
226
|
+
var saveMutation = (txn, finalizedMutation) => {
|
|
227
|
+
const objectStore = txn.engineOpts.txn.objectStore("mutations");
|
|
228
|
+
let request;
|
|
229
|
+
if (finalizedMutation.debounceCount > 0 || finalizedMutation.appliedAt) {
|
|
230
|
+
request = objectStore.put(finalizedMutation);
|
|
122
231
|
} else {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
232
|
+
request = objectStore.add(finalizedMutation);
|
|
233
|
+
}
|
|
234
|
+
return new Promise((resolve, reject) => {
|
|
235
|
+
request.onsuccess = (event) => {
|
|
236
|
+
resolve(finalizedMutation);
|
|
237
|
+
};
|
|
238
|
+
request.onerror = (event) => {
|
|
239
|
+
console.error("Error saving mutation", event?.target?.error);
|
|
240
|
+
reject(event?.target?.error);
|
|
241
|
+
};
|
|
242
|
+
});
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// src/lib/documentToDBRow.ts
|
|
246
|
+
var stringifyIndexEntry = (entity, [k, v]) => `${entity}:${k}:${JSON.stringify(v)}`;
|
|
247
|
+
var stringifyUniqueEntry = ([k, v]) => `${k}:${JSON.stringify(v)}`;
|
|
248
|
+
var stringifyIndexEntries = (entity, arr) => {
|
|
249
|
+
return arr.map((pair) => stringifyIndexEntry(entity, pair));
|
|
250
|
+
};
|
|
251
|
+
var documentToDBRow = (document) => {
|
|
252
|
+
return {
|
|
253
|
+
...document,
|
|
254
|
+
index_entries: document.__.index ? stringifyIndexEntries(document.entity, document.__.index) : [],
|
|
255
|
+
unique_constraint_0: document.__?.unique?.[0] ? stringifyUniqueEntry(document.__?.unique?.[0]) : null,
|
|
256
|
+
unique_constraint_1: document.__?.unique?.[1] ? stringifyUniqueEntry(document.__?.unique?.[1]) : null
|
|
257
|
+
};
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
// src/functions/commit.ts
|
|
261
|
+
var commit = async (txn, mutation, { created, updated, deleted }) => {
|
|
262
|
+
const currentMutation = await txn.readMutation(txn.mutation.ref, false);
|
|
263
|
+
if (currentMutation) {
|
|
264
|
+
if (currentMutation && mutation.appliedAt === txn.timestamp) {
|
|
265
|
+
await saveMutation(txn, mutation);
|
|
266
|
+
} else if (currentMutation && mutation.debounceCount > currentMutation.debounceCount) {
|
|
267
|
+
await saveMutation(txn, mutation);
|
|
268
|
+
} else {
|
|
269
|
+
throw new Error("Mutation already exists");
|
|
127
270
|
}
|
|
128
|
-
|
|
271
|
+
} else {
|
|
272
|
+
await saveMutation(txn, mutation);
|
|
273
|
+
}
|
|
274
|
+
if (txn.request.changeSetRef)
|
|
275
|
+
return mutation;
|
|
276
|
+
for (const doc of created) {
|
|
277
|
+
await commitCreate(txn, documentToDBRow(doc));
|
|
278
|
+
}
|
|
279
|
+
for (const doc of updated) {
|
|
280
|
+
await commitUpdate(txn, documentToDBRow(doc));
|
|
281
|
+
}
|
|
282
|
+
for (const ref of deleted) {
|
|
283
|
+
await commitDelete(txn, ref);
|
|
129
284
|
}
|
|
285
|
+
return mutation;
|
|
130
286
|
};
|
|
131
287
|
// src/functions/end.ts
|
|
132
|
-
var end = (
|
|
288
|
+
var end = (engineOpts) => {
|
|
133
289
|
return new Promise((resolve, reject) => {
|
|
134
|
-
|
|
290
|
+
engineOpts.txn.oncomplete = () => {
|
|
135
291
|
resolve(undefined);
|
|
136
292
|
};
|
|
137
|
-
|
|
293
|
+
engineOpts.txn.onerror = (event) => {
|
|
138
294
|
reject(event.target.error);
|
|
139
295
|
};
|
|
140
296
|
});
|
|
141
297
|
};
|
|
142
298
|
// src/functions/getChangeSetMutations.ts
|
|
143
|
-
var getChangeSetMutations =
|
|
299
|
+
var getChangeSetMutations = (txn, changeSetRef) => {
|
|
144
300
|
const objectStore = txn.engineOpts.txn.objectStore("mutations");
|
|
145
301
|
const index = objectStore.index("byChangeSetRef");
|
|
146
302
|
const range = IDBKeyRange.only(changeSetRef);
|
|
@@ -159,11 +315,10 @@ var getChangeSetMutations = async (txn, changeSetRef) => {
|
|
|
159
315
|
});
|
|
160
316
|
};
|
|
161
317
|
// src/functions/findDebounceMutation.ts
|
|
162
|
-
var findDebounceMutation =
|
|
163
|
-
const mutationName = request.schema.shape.name.value;
|
|
318
|
+
var findDebounceMutation = (request, engine, now, mutationName, identityRef) => {
|
|
164
319
|
const objectStore = engine.txn.objectStore("mutations");
|
|
165
320
|
const index = objectStore.index("timestamp");
|
|
166
|
-
const timestamp = new Date(now - request.
|
|
321
|
+
const timestamp = new Date(now.getTime() - request.operation.debounce * 1000).toISOString();
|
|
167
322
|
const range = IDBKeyRange.lowerBound(timestamp, true);
|
|
168
323
|
const idbRequest = index.openCursor(range);
|
|
169
324
|
return new Promise((resolve, reject) => {
|
|
@@ -172,81 +327,97 @@ var findDebounceMutation = async (request, engine, now) => {
|
|
|
172
327
|
const cursor = idbRequest.result;
|
|
173
328
|
if (cursor) {
|
|
174
329
|
const doc = cursor.value;
|
|
175
|
-
if (doc.name === mutationName && doc.payload.ref === request.payload.ref && doc.changeSetRef === request.changeSetRef) {
|
|
330
|
+
if (doc.operation.name === mutationName && doc.payload.ref === request.payload.ref && doc.changeSetRef === request.changeSetRef && doc.identityRef === identityRef) {
|
|
176
331
|
results.push(doc);
|
|
177
332
|
}
|
|
178
333
|
cursor.continue();
|
|
179
334
|
} else {
|
|
180
|
-
if (results.length) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
resolve(results[0]);
|
|
185
|
-
} else {
|
|
186
|
-
resolve(undefined);
|
|
335
|
+
if (results.length > 1) {
|
|
336
|
+
reject(new Error("Unhandled multiple debounced mutations"));
|
|
337
|
+
return;
|
|
187
338
|
}
|
|
339
|
+
resolve(results[0]);
|
|
188
340
|
}
|
|
189
341
|
};
|
|
342
|
+
idbRequest.onerror = () => {
|
|
343
|
+
reject(idbRequest.error);
|
|
344
|
+
};
|
|
190
345
|
});
|
|
191
346
|
};
|
|
192
|
-
// src/functions/
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
// src/functions/readEntity.ts
|
|
196
|
-
import { DELETED_IN_CHANGE_SET_SYMBOL as DELETED_IN_CHANGE_SET_SYMBOL2 } from "roc-db";
|
|
197
|
-
var readEntity = (txn, ref) => {
|
|
198
|
-
if (txn.request.changeSetRef) {
|
|
199
|
-
const doc = txn.engineOpts.changeSet.entities.get(ref);
|
|
200
|
-
if (doc === DELETED_IN_CHANGE_SET_SYMBOL2)
|
|
201
|
-
return;
|
|
202
|
-
if (doc)
|
|
203
|
-
return doc;
|
|
204
|
-
}
|
|
347
|
+
// src/functions/pageEntities.ts
|
|
348
|
+
var pageEntities = async (txn, args) => {
|
|
349
|
+
const { size, entities, childrenOf } = args;
|
|
205
350
|
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
206
|
-
const
|
|
351
|
+
const idbRequest = objectStore.openCursor();
|
|
207
352
|
return new Promise((resolve, reject) => {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
353
|
+
const results = [];
|
|
354
|
+
idbRequest.onsuccess = () => {
|
|
355
|
+
if (results.length >= size) {
|
|
356
|
+
resolve(results);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const cursor = idbRequest.result;
|
|
360
|
+
if (cursor) {
|
|
361
|
+
if (entities && entities !== "*" && !entities.includes(cursor.value.entity)) {
|
|
362
|
+
cursor.continue();
|
|
363
|
+
} else {
|
|
364
|
+
if (childrenOf && childrenOf.length > 0 && !childrenOf.some((childRef) => cursor.value.__.parentRefs.includes(childRef))) {
|
|
365
|
+
cursor.continue();
|
|
366
|
+
} else {
|
|
367
|
+
results.push(cursor.value);
|
|
368
|
+
cursor.continue();
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
} else {
|
|
372
|
+
resolve(results);
|
|
373
|
+
}
|
|
211
374
|
};
|
|
212
|
-
|
|
213
|
-
|
|
375
|
+
});
|
|
376
|
+
};
|
|
377
|
+
// src/functions/pageEntitiesByIndex.ts
|
|
378
|
+
var pageEntitiesByIndex = async (txn, entity, field, value) => {
|
|
379
|
+
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
380
|
+
const index = objectStore.index("byIndexEntry");
|
|
381
|
+
const entry = `${entity}:${field}:${JSON.stringify(value)}`;
|
|
382
|
+
const range = IDBKeyRange.only(entry);
|
|
383
|
+
const idbRequest = index.openCursor(range);
|
|
384
|
+
return new Promise((resolve, reject) => {
|
|
385
|
+
const results = [];
|
|
386
|
+
idbRequest.onsuccess = () => {
|
|
387
|
+
const cursor = idbRequest.result;
|
|
388
|
+
if (cursor) {
|
|
389
|
+
results.push(cursor.value);
|
|
390
|
+
cursor.continue();
|
|
391
|
+
} else {
|
|
392
|
+
resolve(results);
|
|
393
|
+
}
|
|
214
394
|
};
|
|
215
395
|
});
|
|
216
396
|
};
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
timestamp: txn.mutation.timestamp,
|
|
227
|
-
mutationRef: txn.mutation.ref
|
|
228
|
-
},
|
|
229
|
-
data: deepPatch(existingDocument.data, data),
|
|
230
|
-
children: deepPatch(existingDocument.children, children),
|
|
231
|
-
parents: deepPatch(existingDocument.parents, parents),
|
|
232
|
-
ancestors: deepPatch(existingDocument.ancestors, ancestors)
|
|
233
|
-
};
|
|
234
|
-
if (txn.request.changeSetRef) {
|
|
235
|
-
txn.engineOpts.changeSet.entities.set(ref, updatedDocument);
|
|
236
|
-
return updatedDocument;
|
|
397
|
+
// src/functions/pageMutations.ts
|
|
398
|
+
var pageMutations = async (txn, args) => {
|
|
399
|
+
const { size, changeSetRef, skip } = args;
|
|
400
|
+
const objectStore = txn.engineOpts.txn.objectStore("mutations");
|
|
401
|
+
let idbRequest;
|
|
402
|
+
if (changeSetRef) {
|
|
403
|
+
const index = objectStore.index("byChangeSetRef");
|
|
404
|
+
const range = IDBKeyRange.only(changeSetRef);
|
|
405
|
+
idbRequest = index.openCursor(range);
|
|
237
406
|
} else {
|
|
238
|
-
|
|
239
|
-
const request = objectStore.put(updatedDocument);
|
|
240
|
-
return new Promise((resolve, reject) => {
|
|
241
|
-
request.onsuccess = (event) => {
|
|
242
|
-
resolve(updatedDocument);
|
|
243
|
-
};
|
|
244
|
-
request.onerror = (event) => {
|
|
245
|
-
console.error("Error patching document", event?.target?.error);
|
|
246
|
-
reject(event?.target?.error);
|
|
247
|
-
};
|
|
248
|
-
});
|
|
407
|
+
idbRequest = objectStore.openCursor();
|
|
249
408
|
}
|
|
409
|
+
return new Promise((resolve, reject) => {
|
|
410
|
+
const results = [];
|
|
411
|
+
idbRequest.onsuccess = () => {
|
|
412
|
+
const cursor = idbRequest.result;
|
|
413
|
+
if (cursor) {
|
|
414
|
+
results.push(cursor.value);
|
|
415
|
+
cursor.continue();
|
|
416
|
+
} else {
|
|
417
|
+
resolve(results);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
});
|
|
250
421
|
};
|
|
251
422
|
// src/functions/readMutation.ts
|
|
252
423
|
var readMutation = (engineOpts, ref) => {
|
|
@@ -262,67 +433,41 @@ var readMutation = (engineOpts, ref) => {
|
|
|
262
433
|
};
|
|
263
434
|
});
|
|
264
435
|
};
|
|
265
|
-
// src/functions/
|
|
266
|
-
var
|
|
267
|
-
const objectStore = txn.engineOpts.txn.objectStore("
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
436
|
+
// src/functions/refByUniqueField.ts
|
|
437
|
+
var refByUniqueField = (txn, entity, field, fieldIndex, value) => {
|
|
438
|
+
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
439
|
+
if (fieldIndex > 1)
|
|
440
|
+
throw new Error("Field index must be 0 or 1");
|
|
441
|
+
const index = objectStore.index(`unique_constraint_${fieldIndex}`);
|
|
442
|
+
const range = IDBKeyRange.only([
|
|
443
|
+
entity,
|
|
444
|
+
`${field}:${JSON.stringify(value)}`
|
|
445
|
+
]);
|
|
446
|
+
const idbRequest = index.openCursor(range);
|
|
274
447
|
return new Promise((resolve, reject) => {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
request.onerror = (event) => {
|
|
279
|
-
console.error("Error saving mutation", event?.target?.error);
|
|
280
|
-
reject(event?.target?.error);
|
|
448
|
+
idbRequest.onsuccess = () => {
|
|
449
|
+
const cursor = idbRequest.result;
|
|
450
|
+
resolve(cursor?.value?.ref);
|
|
281
451
|
};
|
|
282
452
|
});
|
|
283
453
|
};
|
|
284
|
-
// src/functions/updateEntity.ts
|
|
285
|
-
var updateEntity = async (txn, ref, { data = {}, children = {}, parents = {}, ancestors = {} }) => {
|
|
286
|
-
const currentEntity = await readEntity(txn, ref);
|
|
287
|
-
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
288
|
-
const document = {
|
|
289
|
-
...currentEntity,
|
|
290
|
-
updated: {
|
|
291
|
-
mutationRef: txn.mutation.ref,
|
|
292
|
-
timestamp: txn.mutation.timestamp
|
|
293
|
-
},
|
|
294
|
-
data,
|
|
295
|
-
children,
|
|
296
|
-
parents,
|
|
297
|
-
ancestors
|
|
298
|
-
};
|
|
299
|
-
if (txn.request.changeSetRef) {
|
|
300
|
-
throw new Error("TODO support changeSetRef");
|
|
301
|
-
} else {
|
|
302
|
-
const request = objectStore.put(document);
|
|
303
|
-
return new Promise((resolve, reject) => {
|
|
304
|
-
request.onsuccess = (event) => {
|
|
305
|
-
resolve(document);
|
|
306
|
-
};
|
|
307
|
-
request.onerror = (event) => {
|
|
308
|
-
console.error("Error updating document", event?.target?.error);
|
|
309
|
-
reject(event?.target?.error);
|
|
310
|
-
};
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
454
|
// src/createIndexedDBAdapter.ts
|
|
315
455
|
var createIndexedDBAdapter = ({
|
|
316
456
|
operations,
|
|
317
457
|
entities,
|
|
318
|
-
|
|
458
|
+
session,
|
|
459
|
+
dbName = "roc-db",
|
|
460
|
+
optimistic = false,
|
|
461
|
+
snowflake = new Snowflake(1, 1)
|
|
319
462
|
}) => {
|
|
320
463
|
return createAdapter({
|
|
321
464
|
name: "indexed-db",
|
|
322
465
|
operations,
|
|
323
466
|
entities,
|
|
324
467
|
functions: exports_functions,
|
|
325
|
-
|
|
468
|
+
optimistic,
|
|
469
|
+
session,
|
|
470
|
+
snowflake,
|
|
326
471
|
async: true
|
|
327
472
|
}, {
|
|
328
473
|
dbName,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Snowflake, type Adapter, type Entity, type Operation } from "roc-db";
|
|
2
|
+
export declare const createIndexedDBAdapter: ({ operations, entities, session, dbName, optimistic, snowflake, }: {
|
|
3
|
+
operations: readonly Operation[];
|
|
4
|
+
entities: readonly Entity<any>[];
|
|
5
|
+
session: {
|
|
6
|
+
identityRef: string;
|
|
7
|
+
sessionRef?: string;
|
|
8
|
+
};
|
|
9
|
+
dbName?: string;
|
|
10
|
+
optimistic?: boolean;
|
|
11
|
+
snowflake?: Snowflake;
|
|
12
|
+
}) => Adapter;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { batchReadEntities } from "./batchReadEntities";
|
|
2
|
+
export { begin } from "./begin";
|
|
3
|
+
export { commit } from "./commit";
|
|
4
|
+
export { end } from "./end";
|
|
5
|
+
export { getChangeSetMutations } from "./getChangeSetMutations";
|
|
6
|
+
export { findDebounceMutation } from "./findDebounceMutation";
|
|
7
|
+
export { pageEntities } from "./pageEntities";
|
|
8
|
+
export { pageEntitiesByIndex } from "./pageEntitiesByIndex";
|
|
9
|
+
export { pageMutations } from "./pageMutations";
|
|
10
|
+
export { readEntity } from "./readEntity";
|
|
11
|
+
export { readMutation } from "./readMutation";
|
|
12
|
+
export { refByUniqueField } from "./refByUniqueField";
|
|
13
|
+
export { saveMutation } from "./saveMutation";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createIndexedDBAdapter } from "./createIndexedDBAdapter";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const documentFromDBRow: ({ unique_constraint_0, unique_constraint_1, index_entries, ...document }: any) => any;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const documentToDBRow: (document: any) => any;
|
package/package.json
CHANGED
|
@@ -1,29 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roc-db/indexed-db",
|
|
3
|
-
"version": "0.2.0-pre.
|
|
3
|
+
"version": "0.2.0-pre.100",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
|
-
".":
|
|
6
|
+
".": {
|
|
7
|
+
"import": "./dist/index.js",
|
|
8
|
+
"types": "./dist/types/index.d.ts"
|
|
9
|
+
}
|
|
7
10
|
},
|
|
8
11
|
"files": [
|
|
9
12
|
"dist"
|
|
10
13
|
],
|
|
11
14
|
"sideEffects": false,
|
|
12
|
-
"scripts": {
|
|
13
|
-
"build": "NODE_ENV=production bun run scripts/build.ts",
|
|
14
|
-
"build:types": "rm -rf dist/types && bun run tsc --noCheck",
|
|
15
|
-
"test": "bun test"
|
|
16
|
-
},
|
|
17
15
|
"dependencies": {},
|
|
18
|
-
"devDependencies": {
|
|
19
|
-
"@roc-db/test-utils": "0.2.0-pre.1",
|
|
20
|
-
"fake-indexeddb": "6.0.0",
|
|
21
|
-
"roc-db": "0.2.0-pre.1",
|
|
22
|
-
"zod": "3.24.2"
|
|
23
|
-
},
|
|
24
16
|
"peerDependencies": {
|
|
25
|
-
"roc-db": "0.2.0-pre.1",
|
|
26
|
-
"zod": "
|
|
17
|
+
"roc-db": ">=0.2.0-pre.98 <1.0.0",
|
|
18
|
+
"zod": ">=4.0.0"
|
|
27
19
|
},
|
|
28
20
|
"keywords": [],
|
|
29
21
|
"author": "Eigil Sagafos",
|
|
@@ -31,5 +23,9 @@
|
|
|
31
23
|
"type": "git",
|
|
32
24
|
"url": "git+https://github.com/eigilsagafos/roc-db.git"
|
|
33
25
|
},
|
|
34
|
-
"license": "MIT"
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public",
|
|
29
|
+
"registry": "https://registry.npmjs.org/"
|
|
30
|
+
}
|
|
35
31
|
}
|
|
Binary file
|