@roc-db/indexed-db 0.1.0-pre.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/dist/index.js +334 -0
- package/dist/roc-db-indexed-db-0.1.0-pre.1.tgz +0 -0
- package/dist/roc-db-indexed-db-0.1.0-pre.2.tgz +0 -0
- package/dist/types/createIndexedDBAdapter.d.ts +18 -0
- package/dist/types/functions/begin.d.ts +1 -0
- package/dist/types/functions/createEntity.d.ts +3 -0
- package/dist/types/functions/deleteEntity.d.ts +1 -0
- package/dist/types/functions/end.d.ts +4 -0
- package/dist/types/functions/findDebounceMutation.d.ts +3 -0
- package/dist/types/functions/getChangeSetMutations.d.ts +3 -0
- package/dist/types/functions/index.d.ts +11 -0
- package/dist/types/functions/patchEntity.d.ts +7 -0
- package/dist/types/functions/readEntity.d.ts +1 -0
- package/dist/types/functions/readMutation.d.ts +1 -0
- package/dist/types/functions/saveMutation.d.ts +1 -0
- package/dist/types/functions/updateEntity.d.ts +6 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/types/IndexedDBEngine.d.ts +5 -0
- package/dist/types/types/IndexedDBReadTransaction.d.ts +4 -0
- package/package.json +35 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, {
|
|
5
|
+
get: all[name],
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
set: (newValue) => all[name] = () => newValue
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// src/createIndexedDBAdapter.ts
|
|
13
|
+
import { createAdapter, Snowflake } from "roc-db";
|
|
14
|
+
|
|
15
|
+
// src/functions/index.ts
|
|
16
|
+
var exports_functions = {};
|
|
17
|
+
__export(exports_functions, {
|
|
18
|
+
updateEntity: () => updateEntity,
|
|
19
|
+
saveMutation: () => saveMutation,
|
|
20
|
+
readMutation: () => readMutation,
|
|
21
|
+
readEntity: () => readEntity,
|
|
22
|
+
patchEntity: () => patchEntity,
|
|
23
|
+
getChangeSetMutations: () => getChangeSetMutations,
|
|
24
|
+
findDebounceMutation: () => findDebounceMutation,
|
|
25
|
+
end: () => end,
|
|
26
|
+
deleteEntity: () => deleteEntity,
|
|
27
|
+
createEntity: () => createEntity,
|
|
28
|
+
begin: () => begin
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// src/functions/begin.ts
|
|
32
|
+
var begin = async (request, engineOpts) => {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
let db;
|
|
35
|
+
const idbRequest = indexedDB.open(engineOpts.dbName, 1);
|
|
36
|
+
idbRequest.onupgradeneeded = (event) => {
|
|
37
|
+
const entitiesObjectStore = idbRequest.result.createObjectStore("entities", { keyPath: "ref" });
|
|
38
|
+
const mutationsObjectStore = idbRequest.result.createObjectStore("mutations", { keyPath: "ref" });
|
|
39
|
+
mutationsObjectStore.createIndex("timestamp", "timestamp", {
|
|
40
|
+
unique: false
|
|
41
|
+
});
|
|
42
|
+
mutationsObjectStore.createIndex("byChangeSetRef", "changeSetRef", {
|
|
43
|
+
unique: false
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
idbRequest.onsuccess = (event) => {
|
|
47
|
+
db = idbRequest.result;
|
|
48
|
+
resolve({
|
|
49
|
+
...engineOpts,
|
|
50
|
+
db,
|
|
51
|
+
txn: db.transaction(["entities", "mutations"], request.type === "write" ? "readwrite" : "readonly"),
|
|
52
|
+
changeSet: request.changeSetRef ? {
|
|
53
|
+
entities: new Map([]),
|
|
54
|
+
mutations: new Map([])
|
|
55
|
+
} : null
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
// src/functions/createEntity.ts
|
|
61
|
+
import { entityFromRef } from "roc-db";
|
|
62
|
+
var createEntity = (txn, ref, { data = {}, children = {}, ancestors = {}, parents = {} }) => {
|
|
63
|
+
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
64
|
+
const entity = entityFromRef(ref);
|
|
65
|
+
const document = {
|
|
66
|
+
ref,
|
|
67
|
+
created: {
|
|
68
|
+
mutationRef: txn.mutation.ref,
|
|
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
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
const request = objectStore.add(document);
|
|
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
|
+
});
|
|
99
|
+
}
|
|
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);
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
|
+
request.onsuccess = () => {
|
|
107
|
+
resolve(true);
|
|
108
|
+
};
|
|
109
|
+
request.onerror = (event) => {
|
|
110
|
+
console.error("Error patching document", event?.target?.error);
|
|
111
|
+
reject(event?.target?.error);
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
var deleteEntity = async (txn, ref, cascade = false) => {
|
|
116
|
+
if (txn.request.changeSetRef) {
|
|
117
|
+
txn.engineOpts.changeSet.entities.set(ref, DELETED_IN_CHANGE_SET_SYMBOL);
|
|
118
|
+
if (cascade) {
|
|
119
|
+
throw new Error("TGOD");
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
} else {
|
|
123
|
+
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
124
|
+
await deleteIndexed(objectStore, ref);
|
|
125
|
+
if (cascade) {
|
|
126
|
+
throw new Error("TGOD");
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
// src/functions/end.ts
|
|
132
|
+
var end = (txn) => {
|
|
133
|
+
return new Promise((resolve, reject) => {
|
|
134
|
+
txn.engineOpts.txn.oncomplete = () => {
|
|
135
|
+
resolve(undefined);
|
|
136
|
+
};
|
|
137
|
+
txn.engineOpts.txn.onerror = (event) => {
|
|
138
|
+
reject(event.target.error);
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
// src/functions/getChangeSetMutations.ts
|
|
143
|
+
var getChangeSetMutations = async (txn, changeSetRef) => {
|
|
144
|
+
const objectStore = txn.engineOpts.txn.objectStore("mutations");
|
|
145
|
+
const index = objectStore.index("byChangeSetRef");
|
|
146
|
+
const range = IDBKeyRange.only(changeSetRef);
|
|
147
|
+
const idbRequest = index.openCursor(range);
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
const results = [];
|
|
150
|
+
idbRequest.onsuccess = () => {
|
|
151
|
+
const cursor = idbRequest.result;
|
|
152
|
+
if (cursor) {
|
|
153
|
+
results.push(cursor.value);
|
|
154
|
+
cursor.continue();
|
|
155
|
+
} else {
|
|
156
|
+
resolve(results);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
// src/functions/findDebounceMutation.ts
|
|
162
|
+
var findDebounceMutation = async (request, engine, now) => {
|
|
163
|
+
const mutationName = request.schema.shape.name.value;
|
|
164
|
+
const objectStore = engine.txn.objectStore("mutations");
|
|
165
|
+
const index = objectStore.index("timestamp");
|
|
166
|
+
const timestamp = new Date(now - request.settings.debounce * 1000).toISOString();
|
|
167
|
+
const range = IDBKeyRange.lowerBound(timestamp, true);
|
|
168
|
+
const idbRequest = index.openCursor(range);
|
|
169
|
+
return new Promise((resolve, reject) => {
|
|
170
|
+
const results = [];
|
|
171
|
+
idbRequest.onsuccess = () => {
|
|
172
|
+
const cursor = idbRequest.result;
|
|
173
|
+
if (cursor) {
|
|
174
|
+
const doc = cursor.value;
|
|
175
|
+
if (doc.name === mutationName && doc.payload.ref === request.payload.ref && doc.changeSetRef === request.changeSetRef) {
|
|
176
|
+
results.push(doc);
|
|
177
|
+
}
|
|
178
|
+
cursor.continue();
|
|
179
|
+
} else {
|
|
180
|
+
if (results.length) {
|
|
181
|
+
if (results.length > 1) {
|
|
182
|
+
throw new Error("Unhandled multiple debounced mutations");
|
|
183
|
+
}
|
|
184
|
+
resolve(results[0]);
|
|
185
|
+
} else {
|
|
186
|
+
resolve(undefined);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
// src/functions/patchEntity.ts
|
|
193
|
+
import { deepPatch, NotFoundError } from "roc-db";
|
|
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
|
+
}
|
|
205
|
+
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
206
|
+
const request = objectStore.get(ref);
|
|
207
|
+
return new Promise((resolve, reject) => {
|
|
208
|
+
request.onsuccess = (event) => {
|
|
209
|
+
const document = event.target.result;
|
|
210
|
+
resolve(document);
|
|
211
|
+
};
|
|
212
|
+
request.onerror = (event) => {
|
|
213
|
+
reject(event.target.error);
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// src/functions/patchEntity.ts
|
|
219
|
+
var patchEntity = async (txn, ref, { data = {}, children = {}, parents = {}, ancestors = {} }) => {
|
|
220
|
+
const existingDocument = await readEntity(txn, ref);
|
|
221
|
+
if (!existingDocument)
|
|
222
|
+
throw new NotFoundError(ref);
|
|
223
|
+
const updatedDocument = {
|
|
224
|
+
...existingDocument,
|
|
225
|
+
updated: {
|
|
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;
|
|
237
|
+
} else {
|
|
238
|
+
const objectStore = txn.engineOpts.txn.objectStore("entities");
|
|
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
|
+
});
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
// src/functions/readMutation.ts
|
|
252
|
+
var readMutation = (engineOpts, ref) => {
|
|
253
|
+
const objectStore = engineOpts.txn.objectStore("mutations");
|
|
254
|
+
const request = objectStore.get(ref);
|
|
255
|
+
return new Promise((resolve, reject) => {
|
|
256
|
+
request.onsuccess = (event) => {
|
|
257
|
+
const document = event.target.result;
|
|
258
|
+
resolve(document);
|
|
259
|
+
};
|
|
260
|
+
request.onerror = (event) => {
|
|
261
|
+
reject(event.target.error);
|
|
262
|
+
};
|
|
263
|
+
});
|
|
264
|
+
};
|
|
265
|
+
// src/functions/saveMutation.ts
|
|
266
|
+
var saveMutation = (txn, finalizedMutation) => {
|
|
267
|
+
const objectStore = txn.engineOpts.txn.objectStore("mutations");
|
|
268
|
+
let request;
|
|
269
|
+
if (finalizedMutation.debounceCount > 0) {
|
|
270
|
+
request = objectStore.put(finalizedMutation);
|
|
271
|
+
} else {
|
|
272
|
+
request = objectStore.add(finalizedMutation);
|
|
273
|
+
}
|
|
274
|
+
return new Promise((resolve, reject) => {
|
|
275
|
+
request.onsuccess = (event) => {
|
|
276
|
+
resolve(finalizedMutation);
|
|
277
|
+
};
|
|
278
|
+
request.onerror = (event) => {
|
|
279
|
+
console.error("Error saving mutation", event?.target?.error);
|
|
280
|
+
reject(event?.target?.error);
|
|
281
|
+
};
|
|
282
|
+
});
|
|
283
|
+
};
|
|
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
|
+
// src/createIndexedDBAdapter.ts
|
|
315
|
+
var createIndexedDBAdapter = ({
|
|
316
|
+
operations,
|
|
317
|
+
entities,
|
|
318
|
+
dbName = "roc-db"
|
|
319
|
+
}) => {
|
|
320
|
+
return createAdapter({
|
|
321
|
+
name: "indexed-db",
|
|
322
|
+
operations,
|
|
323
|
+
entities,
|
|
324
|
+
functions: exports_functions,
|
|
325
|
+
snowflake: new Snowflake(1, 1),
|
|
326
|
+
async: true
|
|
327
|
+
}, {
|
|
328
|
+
dbName,
|
|
329
|
+
version: 1
|
|
330
|
+
});
|
|
331
|
+
};
|
|
332
|
+
export {
|
|
333
|
+
createIndexedDBAdapter
|
|
334
|
+
};
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const createIndexedDBAdapter: ({ operations, entities, dbName, }: {
|
|
2
|
+
operations: any;
|
|
3
|
+
entities: any;
|
|
4
|
+
dbName?: string | undefined;
|
|
5
|
+
}) => {
|
|
6
|
+
_name: string;
|
|
7
|
+
_entityKinds: Entities[number]["shape"]["entity"]["value"];
|
|
8
|
+
_operationNames: Operations[number]["operationName"];
|
|
9
|
+
_operations: Operations;
|
|
10
|
+
_entites: Entities;
|
|
11
|
+
createRef: (entity: any) => string;
|
|
12
|
+
changeSet: (changeSetRef: any) => /*elided*/ any & {
|
|
13
|
+
[x: string]: any;
|
|
14
|
+
};
|
|
15
|
+
syncOptimisticMutation: (mutation: any) => any;
|
|
16
|
+
} & {
|
|
17
|
+
[x: string]: any;
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const begin: (request: any, engineOpts: any) => Promise<unknown>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const deleteEntity: (txn: any, ref: any, cascade?: boolean) => Promise<boolean>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { begin } from "./begin";
|
|
2
|
+
export { createEntity } from "./createEntity";
|
|
3
|
+
export { deleteEntity } from "./deleteEntity";
|
|
4
|
+
export { end } from "./end";
|
|
5
|
+
export { getChangeSetMutations } from "./getChangeSetMutations";
|
|
6
|
+
export { findDebounceMutation } from "./findDebounceMutation";
|
|
7
|
+
export { patchEntity } from "./patchEntity";
|
|
8
|
+
export { readEntity } from "./readEntity";
|
|
9
|
+
export { readMutation } from "./readMutation";
|
|
10
|
+
export { saveMutation } from "./saveMutation";
|
|
11
|
+
export { updateEntity } from "./updateEntity";
|
|
@@ -0,0 +1,7 @@
|
|
|
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>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const readEntity: (txn: any, ref: any) => any;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const readMutation: (engineOpts: any, ref: any) => Promise<unknown>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const saveMutation: (txn: any, finalizedMutation: any) => Promise<unknown>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createIndexedDBAdapter } from "./createIndexedDBAdapter";
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@roc-db/indexed-db",
|
|
3
|
+
"version": "0.1.0-pre.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./src/index.ts"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"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
|
+
"dependencies": {},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@roc-db/test-utils": "0.1.0-pre.1",
|
|
20
|
+
"fake-indexeddb": "6.0.0",
|
|
21
|
+
"roc-db": "0.1.0-pre.1",
|
|
22
|
+
"zod": "3.24.2"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"roc-db": "0.1.0-pre.1",
|
|
26
|
+
"zod": "3.24.2"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [],
|
|
29
|
+
"author": "Eigil Sagafos",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/eigilsagafos/roc-db.git"
|
|
33
|
+
},
|
|
34
|
+
"license": "MIT"
|
|
35
|
+
}
|