@roc-db/indexed-db 0.2.0-pre.10 → 0.2.0-pre.101

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.
Files changed (30) hide show
  1. package/dist/index.js +323 -209
  2. package/dist/types/createIndexedDBAdapter.d.ts +11 -18
  3. package/dist/types/functions/batchReadEntities.d.ts +3 -0
  4. package/dist/types/functions/begin.d.ts +3 -1
  5. package/dist/types/functions/commit.d.ts +3 -0
  6. package/dist/types/functions/commitCreate.d.ts +3 -0
  7. package/dist/types/functions/commitDelete.d.ts +3 -0
  8. package/dist/types/functions/commitUpdate.d.ts +3 -0
  9. package/dist/types/functions/end.d.ts +1 -2
  10. package/dist/types/functions/findRecentMutations.d.ts +2 -0
  11. package/dist/types/functions/getChangeSetMutations.d.ts +2 -3
  12. package/dist/types/functions/index.d.ts +6 -5
  13. package/dist/types/functions/pageEntities.d.ts +2 -0
  14. package/dist/types/functions/pageEntitiesByIndex.d.ts +2 -0
  15. package/dist/types/functions/pageMutations.d.ts +2 -2
  16. package/dist/types/functions/readEntity.d.ts +3 -1
  17. package/dist/types/functions/readMutation.d.ts +2 -1
  18. package/dist/types/functions/refByUniqueField.d.ts +2 -0
  19. package/dist/types/functions/saveMutation.d.ts +2 -1
  20. package/dist/types/lib/documentFromDBRow.d.ts +1 -0
  21. package/dist/types/lib/documentToDBRow.d.ts +1 -0
  22. package/dist/types/types/IndexedDBEngine.d.ts +5 -0
  23. package/dist/types/types/IndexedDBReadTransaction.d.ts +1 -2
  24. package/dist/types/types/IndexedDBWriteTransaction.d.ts +3 -0
  25. package/package.json +8 -4
  26. package/dist/types/functions/createEntity.d.ts +0 -3
  27. package/dist/types/functions/deleteEntity.d.ts +0 -1
  28. package/dist/types/functions/findDebounceMutation.d.ts +0 -3
  29. package/dist/types/functions/patchEntity.d.ts +0 -7
  30. package/dist/types/functions/updateEntity.d.ts +0 -6
package/dist/index.js CHANGED
@@ -10,33 +10,83 @@ var __export = (target, all) => {
10
10
  };
11
11
 
12
12
  // src/createIndexedDBAdapter.ts
13
- import { createAdapter, Snowflake } from "roc-db";
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
- patchEntity: () => patchEntity,
23
25
  pageMutations: () => pageMutations,
26
+ pageEntitiesByIndex: () => pageEntitiesByIndex,
27
+ pageEntities: () => pageEntities,
24
28
  getChangeSetMutations: () => getChangeSetMutations,
25
- findDebounceMutation: () => findDebounceMutation,
29
+ findRecentMutations: () => findRecentMutations,
26
30
  end: () => end,
27
- deleteEntity: () => deleteEntity,
28
- createEntity: () => createEntity,
29
- begin: () => begin
31
+ commit: () => commit,
32
+ begin: () => begin,
33
+ batchReadEntities: () => batchReadEntities
30
34
  });
31
35
 
32
- // src/functions/begin.ts
33
- var begin = async (request, engineOpts, callback) => {
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);
34
56
  return new Promise((resolve, reject) => {
35
- let db;
36
- const idbRequest = indexedDB.open(engineOpts.dbName, 1);
37
- idbRequest.onupgradeneeded = (event) => {
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 = () => {
38
83
  const entitiesObjectStore = idbRequest.result.createObjectStore("entities", { keyPath: "ref" });
39
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
+ });
40
90
  mutationsObjectStore.createIndex("timestamp", "timestamp", {
41
91
  unique: false
42
92
  });
@@ -44,104 +94,209 @@ var begin = async (request, engineOpts, callback) => {
44
94
  unique: false
45
95
  });
46
96
  };
47
- idbRequest.onsuccess = (event) => {
48
- db = idbRequest.result;
49
- resolve(callback({
50
- ...engineOpts,
51
- db,
52
- txn: db.transaction(["entities", "mutations"], request.type === "write" ? "readwrite" : "readonly"),
53
- changeSet: request.changeSetRef ? {
54
- entities: new Map([]),
55
- mutations: new Map([])
56
- } : null
57
- }));
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);
58
108
  };
59
109
  });
110
+ DB_CACHE.set(engineOpts, promise);
111
+ return promise;
60
112
  };
61
- // src/functions/createEntity.ts
62
- import { entityFromRef } from "roc-db";
63
- var createEntity = (txn, ref, { data = {}, children = {}, ancestors = {}, parents = {} }) => {
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) => {
64
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) => {
65
190
  const entity = entityFromRef(ref);
66
- const document = {
67
- ref,
68
- created: {
69
- mutationRef: txn.mutation.ref,
70
- timestamp: txn.mutation.timestamp
71
- },
72
- updated: {
73
- mutationRef: txn.mutation.ref,
74
- timestamp: txn.mutation.timestamp
75
- },
76
- entity,
77
- data,
78
- children,
79
- ancestors,
80
- parents
81
- };
82
- if (txn.request.changeSetRef) {
83
- if (txn.engineOpts.changeSet.entities.has(ref)) {
84
- throw new Error("Entity already exists in changeSet");
85
- } else {
86
- txn.engineOpts.changeSet.entities.set(ref, document);
87
- return document;
88
- }
191
+ const engineTxn = txn.engineOpts.txn;
192
+ let objectStore;
193
+ if (entity === "Mutation") {
194
+ objectStore = engineTxn.objectStore("mutations");
89
195
  } else {
90
- const request = objectStore.add(document);
91
- return new Promise((resolve, reject) => {
92
- request.onsuccess = (event) => {
93
- resolve(document);
94
- };
95
- request.onerror = (event) => {
96
- console.error("Error creating entity:", document, event?.target?.error);
97
- reject(event?.target?.error);
98
- };
99
- });
196
+ objectStore = engineTxn.objectStore("entities");
100
197
  }
101
- };
102
- // src/functions/deleteEntity.ts
103
- import { DELETED_IN_CHANGE_SET_SYMBOL } from "roc-db";
104
- var deleteIndexed = (store, ref) => {
105
- const request = store.delete(ref);
198
+ const request = objectStore.delete(ref);
106
199
  return new Promise((resolve, reject) => {
107
200
  request.onsuccess = () => {
108
201
  resolve(true);
109
202
  };
110
203
  request.onerror = (event) => {
111
- console.error("Error patching document", event?.target?.error);
204
+ console.error("Error deleting document", event?.target?.error);
112
205
  reject(event?.target?.error);
113
206
  };
114
207
  });
115
208
  };
116
- var deleteEntity = async (txn, ref, cascade = false) => {
117
- if (txn.request.changeSetRef) {
118
- txn.engineOpts.changeSet.entities.set(ref, DELETED_IN_CHANGE_SET_SYMBOL);
119
- if (cascade) {
120
- throw new Error("TGOD");
121
- }
122
- return true;
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);
123
231
  } else {
124
- const objectStore = txn.engineOpts.txn.objectStore("entities");
125
- await deleteIndexed(objectStore, ref);
126
- if (cascade) {
127
- throw new Error("TGOD");
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");
128
270
  }
129
- return true;
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);
130
284
  }
285
+ return mutation;
131
286
  };
132
287
  // src/functions/end.ts
133
- var end = (txn) => {
288
+ var end = (engineOpts) => {
134
289
  return new Promise((resolve, reject) => {
135
- txn.engineOpts.txn.oncomplete = () => {
290
+ engineOpts.txn.oncomplete = () => {
136
291
  resolve(undefined);
137
292
  };
138
- txn.engineOpts.txn.onerror = (event) => {
293
+ engineOpts.txn.onerror = (event) => {
139
294
  reject(event.target.error);
140
295
  };
141
296
  });
142
297
  };
143
298
  // src/functions/getChangeSetMutations.ts
144
- var getChangeSetMutations = async (txn, changeSetRef) => {
299
+ var getChangeSetMutations = (txn, changeSetRef) => {
145
300
  const objectStore = txn.engineOpts.txn.objectStore("mutations");
146
301
  const index = objectStore.index("byChangeSetRef");
147
302
  const range = IDBKeyRange.only(changeSetRef);
@@ -159,45 +314,64 @@ var getChangeSetMutations = async (txn, changeSetRef) => {
159
314
  };
160
315
  });
161
316
  };
162
- // src/functions/findDebounceMutation.ts
163
- var findDebounceMutation = async (request, engine, now) => {
164
- const mutationName = request.schema.shape.name.value;
317
+ // src/functions/findRecentMutations.ts
318
+ var collect = (idbRequest, results) => new Promise((resolve, reject) => {
319
+ idbRequest.onsuccess = () => {
320
+ const cursor = idbRequest.result;
321
+ if (cursor) {
322
+ results.set(cursor.value.ref, cursor.value);
323
+ cursor.continue();
324
+ } else {
325
+ resolve();
326
+ }
327
+ };
328
+ idbRequest.onerror = () => reject(idbRequest.error);
329
+ });
330
+ var findRecentMutations = async (engine, { changeSetRef, identityRef, since }) => {
165
331
  const objectStore = engine.txn.objectStore("mutations");
166
- const index = objectStore.index("timestamp");
167
- const timestamp = new Date(now - request.settings.debounce * 1000).toISOString();
168
- const range = IDBKeyRange.lowerBound(timestamp, true);
169
- const idbRequest = index.openCursor(range);
332
+ const results = new Map;
333
+ await Promise.all([
334
+ collect(objectStore.index("timestamp").openCursor(IDBKeyRange.lowerBound(since, true)), results),
335
+ changeSetRef && collect(objectStore.index("byChangeSetRef").openCursor(IDBKeyRange.only(changeSetRef)), results)
336
+ ]);
337
+ return [...results.values()].filter((mutation) => (mutation.timestamp > since || !!mutation.persistedAt && mutation.persistedAt > since) && ((mutation.changeSetRef ?? null) === changeSetRef || mutation.identityRef === identityRef));
338
+ };
339
+ // src/functions/pageEntities.ts
340
+ var pageEntities = async (txn, args) => {
341
+ const { size, entities, childrenOf } = args;
342
+ const objectStore = txn.engineOpts.txn.objectStore("entities");
343
+ const idbRequest = objectStore.openCursor();
170
344
  return new Promise((resolve, reject) => {
171
345
  const results = [];
172
346
  idbRequest.onsuccess = () => {
347
+ if (results.length >= size) {
348
+ resolve(results);
349
+ return;
350
+ }
173
351
  const cursor = idbRequest.result;
174
352
  if (cursor) {
175
- const doc = cursor.value;
176
- if (doc.name === mutationName && doc.payload.ref === request.payload.ref && doc.changeSetRef === request.changeSetRef) {
177
- results.push(doc);
178
- }
179
- cursor.continue();
180
- } else {
181
- if (results.length) {
182
- if (results.length > 1) {
183
- throw new Error("Unhandled multiple debounced mutations");
184
- }
185
- resolve(results[0]);
353
+ if (entities && entities !== "*" && !entities.includes(cursor.value.entity)) {
354
+ cursor.continue();
186
355
  } else {
187
- resolve(undefined);
356
+ if (childrenOf && childrenOf.length > 0 && !childrenOf.some((childRef) => cursor.value.__.parentRefs.includes(childRef))) {
357
+ cursor.continue();
358
+ } else {
359
+ results.push(cursor.value);
360
+ cursor.continue();
361
+ }
188
362
  }
363
+ } else {
364
+ resolve(results);
189
365
  }
190
366
  };
191
367
  });
192
368
  };
193
- // src/functions/pageMutations.ts
194
- var pageMutations = async (txn, args) => {
195
- const { size, changeSetRef, skip } = args;
196
- if (!changeSetRef)
197
- throw new Error("changeSetRef is required");
198
- const objectStore = txn.engineOpts.txn.objectStore("mutations");
199
- const index = objectStore.index("byChangeSetRef");
200
- const range = IDBKeyRange.only(changeSetRef);
369
+ // src/functions/pageEntitiesByIndex.ts
370
+ var pageEntitiesByIndex = async (txn, entity, field, value) => {
371
+ const objectStore = txn.engineOpts.txn.objectStore("entities");
372
+ const index = objectStore.index("byIndexEntry");
373
+ const entry = `${entity}:${field}:${JSON.stringify(value)}`;
374
+ const range = IDBKeyRange.only(entry);
201
375
  const idbRequest = index.openCursor(range);
202
376
  return new Promise((resolve, reject) => {
203
377
  const results = [];
@@ -212,65 +386,31 @@ var pageMutations = async (txn, args) => {
212
386
  };
213
387
  });
214
388
  };
215
- // src/functions/patchEntity.ts
216
- import { deepPatch, NotFoundError } from "roc-db";
217
-
218
- // src/functions/readEntity.ts
219
- import { DELETED_IN_CHANGE_SET_SYMBOL as DELETED_IN_CHANGE_SET_SYMBOL2 } from "roc-db";
220
- var readEntity = (txn, ref) => {
221
- if (txn.request.changeSetRef) {
222
- const doc = txn.engineOpts.changeSet.entities.get(ref);
223
- if (doc === DELETED_IN_CHANGE_SET_SYMBOL2)
224
- return;
225
- if (doc)
226
- return doc;
389
+ // src/functions/pageMutations.ts
390
+ var pageMutations = async (txn, args) => {
391
+ const { size, changeSetRef, skip } = args;
392
+ const objectStore = txn.engineOpts.txn.objectStore("mutations");
393
+ let idbRequest;
394
+ if (changeSetRef) {
395
+ const index = objectStore.index("byChangeSetRef");
396
+ const range = IDBKeyRange.only(changeSetRef);
397
+ idbRequest = index.openCursor(range);
398
+ } else {
399
+ idbRequest = objectStore.openCursor();
227
400
  }
228
- const objectStore = txn.engineOpts.txn.objectStore("entities");
229
- const request = objectStore.get(ref);
230
401
  return new Promise((resolve, reject) => {
231
- request.onsuccess = (event) => {
232
- const document = event.target.result;
233
- resolve(document);
234
- };
235
- request.onerror = (event) => {
236
- reject(event.target.error);
402
+ const results = [];
403
+ idbRequest.onsuccess = () => {
404
+ const cursor = idbRequest.result;
405
+ if (cursor) {
406
+ results.push(cursor.value);
407
+ cursor.continue();
408
+ } else {
409
+ resolve(results);
410
+ }
237
411
  };
238
412
  });
239
413
  };
240
-
241
- // src/functions/patchEntity.ts
242
- var patchEntity = async (txn, ref, { data = {}, children = {}, parents = {}, ancestors = {} }) => {
243
- const existingDocument = await readEntity(txn, ref);
244
- if (!existingDocument)
245
- throw new NotFoundError(ref);
246
- const updatedDocument = {
247
- ...existingDocument,
248
- updated: {
249
- timestamp: txn.mutation.timestamp,
250
- mutationRef: txn.mutation.ref
251
- },
252
- data: deepPatch(existingDocument.data, data),
253
- children: deepPatch(existingDocument.children, children),
254
- parents: deepPatch(existingDocument.parents, parents),
255
- ancestors: deepPatch(existingDocument.ancestors, ancestors)
256
- };
257
- if (txn.request.changeSetRef) {
258
- txn.engineOpts.changeSet.entities.set(ref, updatedDocument);
259
- return updatedDocument;
260
- } else {
261
- const objectStore = txn.engineOpts.txn.objectStore("entities");
262
- const request = objectStore.put(updatedDocument);
263
- return new Promise((resolve, reject) => {
264
- request.onsuccess = (event) => {
265
- resolve(updatedDocument);
266
- };
267
- request.onerror = (event) => {
268
- console.error("Error patching document", event?.target?.error);
269
- reject(event?.target?.error);
270
- };
271
- });
272
- }
273
- };
274
414
  // src/functions/readMutation.ts
275
415
  var readMutation = (engineOpts, ref) => {
276
416
  const objectStore = engineOpts.txn.objectStore("mutations");
@@ -285,67 +425,41 @@ var readMutation = (engineOpts, ref) => {
285
425
  };
286
426
  });
287
427
  };
288
- // src/functions/saveMutation.ts
289
- var saveMutation = (txn, finalizedMutation) => {
290
- const objectStore = txn.engineOpts.txn.objectStore("mutations");
291
- let request;
292
- if (finalizedMutation.debounceCount > 0) {
293
- request = objectStore.put(finalizedMutation);
294
- } else {
295
- request = objectStore.add(finalizedMutation);
296
- }
428
+ // src/functions/refByUniqueField.ts
429
+ var refByUniqueField = (txn, entity, field, fieldIndex, value) => {
430
+ const objectStore = txn.engineOpts.txn.objectStore("entities");
431
+ if (fieldIndex > 1)
432
+ throw new Error("Field index must be 0 or 1");
433
+ const index = objectStore.index(`unique_constraint_${fieldIndex}`);
434
+ const range = IDBKeyRange.only([
435
+ entity,
436
+ `${field}:${JSON.stringify(value)}`
437
+ ]);
438
+ const idbRequest = index.openCursor(range);
297
439
  return new Promise((resolve, reject) => {
298
- request.onsuccess = (event) => {
299
- resolve(finalizedMutation);
300
- };
301
- request.onerror = (event) => {
302
- console.error("Error saving mutation", event?.target?.error);
303
- reject(event?.target?.error);
440
+ idbRequest.onsuccess = () => {
441
+ const cursor = idbRequest.result;
442
+ resolve(cursor?.value?.ref);
304
443
  };
305
444
  });
306
445
  };
307
- // src/functions/updateEntity.ts
308
- var updateEntity = async (txn, ref, { data = {}, children = {}, parents = {}, ancestors = {} }) => {
309
- const currentEntity = await readEntity(txn, ref);
310
- const objectStore = txn.engineOpts.txn.objectStore("entities");
311
- const document = {
312
- ...currentEntity,
313
- updated: {
314
- mutationRef: txn.mutation.ref,
315
- timestamp: txn.mutation.timestamp
316
- },
317
- data,
318
- children,
319
- parents,
320
- ancestors
321
- };
322
- if (txn.request.changeSetRef) {
323
- throw new Error("TODO support changeSetRef");
324
- } else {
325
- const request = objectStore.put(document);
326
- return new Promise((resolve, reject) => {
327
- request.onsuccess = (event) => {
328
- resolve(document);
329
- };
330
- request.onerror = (event) => {
331
- console.error("Error updating document", event?.target?.error);
332
- reject(event?.target?.error);
333
- };
334
- });
335
- }
336
- };
337
446
  // src/createIndexedDBAdapter.ts
338
447
  var createIndexedDBAdapter = ({
339
448
  operations,
340
449
  entities,
341
- dbName = "roc-db"
450
+ session,
451
+ dbName = "roc-db",
452
+ optimistic = false,
453
+ snowflake = new Snowflake(1, 1)
342
454
  }) => {
343
455
  return createAdapter({
344
456
  name: "indexed-db",
345
457
  operations,
346
458
  entities,
347
459
  functions: exports_functions,
348
- snowflake: new Snowflake(1, 1),
460
+ optimistic,
461
+ session,
462
+ snowflake,
349
463
  async: true
350
464
  }, {
351
465
  dbName,
@@ -1,19 +1,12 @@
1
- export declare const createIndexedDBAdapter: ({ operations, entities, dbName, }: {
2
- operations: any;
3
- entities: any;
4
- dbName?: string | undefined;
5
- }) => {
6
- _name: string;
7
- _engineOpts: EngineOptions;
8
- _entityKinds: Entities[number]["shape"]["entity"]["value"];
9
- _operationNames: Operations[number]["operationName"];
10
- _operations: Operations;
11
- _entites: Entities;
12
- createRef: (entity: any) => string;
13
- changeSet: (changeSetRef: any) => /*elided*/ any & {
14
- [x: string]: any;
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;
15
8
  };
16
- syncOptimisticMutation: (mutation: any) => any;
17
- } & {
18
- [x: string]: any;
19
- };
9
+ dbName?: string;
10
+ optimistic?: boolean;
11
+ snowflake?: Snowflake;
12
+ }) => Adapter;
@@ -0,0 +1,3 @@
1
+ import type { Ref, Transaction } from "roc-db";
2
+ import type { IndexedDBEngine } from "../types/IndexedDBEngine";
3
+ export declare const batchReadEntities: (txn: Transaction<IndexedDBEngine>, refs: Ref[]) => Promise<any[]>;
@@ -1 +1,3 @@
1
- export declare const begin: (request: any, engineOpts: any, callback: any) => Promise<unknown>;
1
+ import type { BeginFunction } from "roc-db";
2
+ import type { IndexedDBEngine } from "../types/IndexedDBEngine";
3
+ export declare const begin: BeginFunction<IndexedDBEngine>;
@@ -0,0 +1,3 @@
1
+ import type { CommitFunction } from "roc-db";
2
+ import type { IndexedDBEngine } from "../types/IndexedDBEngine";
3
+ export declare const commit: CommitFunction<IndexedDBEngine>;
@@ -0,0 +1,3 @@
1
+ import type { WriteTransaction } from "roc-db";
2
+ import type { IndexedDBEngine } from "../types/IndexedDBEngine";
3
+ export declare const commitCreate: (txn: WriteTransaction<IndexedDBEngine>, document: any) => Promise<unknown>;
@@ -0,0 +1,3 @@
1
+ import { type Ref, type WriteTransaction } from "roc-db";
2
+ import type { IndexedDBEngine } from "../types/IndexedDBEngine";
3
+ export declare const commitDelete: (txn: WriteTransaction<IndexedDBEngine>, ref: Ref) => Promise<unknown>;
@@ -0,0 +1,3 @@
1
+ import type { WriteTransaction } from "roc-db";
2
+ import type { IndexedDBEngine } from "../types/IndexedDBEngine";
3
+ export declare const commitUpdate: (txn: WriteTransaction<IndexedDBEngine>, document: any) => Promise<unknown>;
@@ -1,4 +1,3 @@
1
1
  import type { EndFunction } from "roc-db";
2
2
  import type { IndexedDBEngine } from "../types/IndexedDBEngine";
3
- import type { WriteRequest } from "roc-db/src/types/WriteRequest";
4
- export declare const end: EndFunction<WriteRequest, IndexedDBEngine, [], any>;
3
+ export declare const end: EndFunction<IndexedDBEngine>;
@@ -0,0 +1,2 @@
1
+ import type { FindRecentMutationsFunction } from "roc-db";
2
+ export declare const findRecentMutations: FindRecentMutationsFunction;
@@ -1,3 +1,2 @@
1
- import type { Ref } from "roc-db";
2
- import type { IndexedDBReadTransaction } from "../types/IndexedDBReadTransaction";
3
- export declare const getChangeSetMutations: (txn: IndexedDBReadTransaction, changeSetRef: Ref) => Promise<unknown>;
1
+ import type { GetChangeSetMutationsFunction } from "roc-db";
2
+ export declare const getChangeSetMutations: GetChangeSetMutationsFunction;
@@ -1,12 +1,13 @@
1
+ export { batchReadEntities } from "./batchReadEntities";
1
2
  export { begin } from "./begin";
2
- export { createEntity } from "./createEntity";
3
- export { deleteEntity } from "./deleteEntity";
3
+ export { commit } from "./commit";
4
4
  export { end } from "./end";
5
5
  export { getChangeSetMutations } from "./getChangeSetMutations";
6
- export { findDebounceMutation } from "./findDebounceMutation";
6
+ export { findRecentMutations } from "./findRecentMutations";
7
+ export { pageEntities } from "./pageEntities";
8
+ export { pageEntitiesByIndex } from "./pageEntitiesByIndex";
7
9
  export { pageMutations } from "./pageMutations";
8
- export { patchEntity } from "./patchEntity";
9
10
  export { readEntity } from "./readEntity";
10
11
  export { readMutation } from "./readMutation";
12
+ export { refByUniqueField } from "./refByUniqueField";
11
13
  export { saveMutation } from "./saveMutation";
12
- export { updateEntity } from "./updateEntity";
@@ -0,0 +1,2 @@
1
+ import type { PageEntitiesFunction } from "roc-db";
2
+ export declare const pageEntities: PageEntitiesFunction;
@@ -0,0 +1,2 @@
1
+ import type { PageEntitiesByIndexFunction } from "roc-db";
2
+ export declare const pageEntitiesByIndex: PageEntitiesByIndexFunction;
@@ -1,2 +1,2 @@
1
- import type { IndexedDBReadTransaction } from "../types/IndexedDBReadTransaction";
2
- export declare const pageMutations: (txn: IndexedDBReadTransaction, args: any) => Promise<unknown>;
1
+ import type { PageMutationsFunction } from "roc-db";
2
+ export declare const pageMutations: PageMutationsFunction;
@@ -1 +1,3 @@
1
- export declare const readEntity: (txn: any, ref: any) => any;
1
+ import type { ReadEntityFunctiun } from "roc-db";
2
+ import type { IndexedDBEngine } from "../types/IndexedDBEngine";
3
+ export declare const readEntity: ReadEntityFunctiun<IndexedDBEngine>;
@@ -1 +1,2 @@
1
- export declare const readMutation: (engineOpts: any, ref: any) => Promise<unknown>;
1
+ import type { ReadMutationFunction } from "roc-db";
2
+ export declare const readMutation: ReadMutationFunction;
@@ -0,0 +1,2 @@
1
+ import type { RefByUniqueFieldFunction } from "roc-db";
2
+ export declare const refByUniqueField: RefByUniqueFieldFunction;
@@ -1 +1,2 @@
1
- export declare const saveMutation: (txn: any, finalizedMutation: any) => Promise<unknown>;
1
+ import type { SaveMutationFunction } from "roc-db";
2
+ export declare const saveMutation: SaveMutationFunction;
@@ -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;
@@ -1,5 +1,10 @@
1
1
  export type IndexedDBEngine = {
2
2
  dbName: string;
3
+ version?: number;
4
+ db?: IDBDatabase;
5
+ txn?: IDBTransaction;
6
+ };
7
+ export type IndexedDBTxnEngine = IndexedDBEngine & {
3
8
  db: IDBDatabase;
4
9
  txn: IDBTransaction;
5
10
  };
@@ -1,4 +1,3 @@
1
1
  import type { ReadTransaction } from "roc-db";
2
2
  import type { IndexedDBEngine } from "./IndexedDBEngine";
3
- export type IndexedDBReadTransaction = ReadTransaction<any, IndexedDBEngine, [
4
- ], any>;
3
+ export type IndexedDBReadTransaction = ReadTransaction<IndexedDBEngine>;
@@ -0,0 +1,3 @@
1
+ import type { IndexedDBEngine } from "./IndexedDBEngine";
2
+ import type { WriteTransaction } from "roc-db";
3
+ export type IndexedDBWriteTransaction = WriteTransaction<IndexedDBEngine>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roc-db/indexed-db",
3
- "version": "0.2.0-pre.10",
3
+ "version": "0.2.0-pre.101",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -14,8 +14,8 @@
14
14
  "sideEffects": false,
15
15
  "dependencies": {},
16
16
  "peerDependencies": {
17
- "roc-db": "0.2.0-pre.10",
18
- "zod": "^3.0.0"
17
+ "roc-db": ">=0.2.0-pre.98 <1.0.0",
18
+ "zod": ">=4.0.0"
19
19
  },
20
20
  "keywords": [],
21
21
  "author": "Eigil Sagafos",
@@ -23,5 +23,9 @@
23
23
  "type": "git",
24
24
  "url": "git+https://github.com/eigilsagafos/roc-db.git"
25
25
  },
26
- "license": "MIT"
26
+ "license": "MIT",
27
+ "publishConfig": {
28
+ "access": "public",
29
+ "registry": "https://registry.npmjs.org/"
30
+ }
27
31
  }
@@ -1,3 +0,0 @@
1
- import { type CreateEntityFunction } from "roc-db";
2
- import type { IndexedDBEngine } from "../types/IndexedDBEngine";
3
- export declare const createEntity: CreateEntityFunction<IndexedDBEngine>;
@@ -1 +0,0 @@
1
- export declare const deleteEntity: (txn: any, ref: any, cascade?: boolean) => Promise<boolean>;
@@ -1,3 +0,0 @@
1
- import type { WriteRequest } from "roc-db";
2
- import type { IndexedDBEngine } from "../types/IndexedDBEngine";
3
- export declare const findDebounceMutation: (request: WriteRequest, engine: IndexedDBEngine, now: number) => Promise<unknown>;
@@ -1,7 +0,0 @@
1
- import type { IndexedDBReadTransaction } from "../types/IndexedDBReadTransaction";
2
- export declare const patchEntity: (txn: IndexedDBReadTransaction, ref: any, { data, children, parents, ancestors }: {
3
- data?: {} | undefined;
4
- children?: {} | undefined;
5
- parents?: {} | undefined;
6
- ancestors?: {} | undefined;
7
- }) => Promise<any>;
@@ -1,6 +0,0 @@
1
- export declare const updateEntity: (txn: any, ref: any, { data, children, parents, ancestors }: {
2
- data?: {} | undefined;
3
- children?: {} | undefined;
4
- parents?: {} | undefined;
5
- ancestors?: {} | undefined;
6
- }) => Promise<unknown>;