@effect/platform-browser 4.0.0-beta.42 → 4.0.0-beta.44
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/BrowserHttpClient.d.ts +3 -3
- package/dist/BrowserHttpClient.d.ts.map +1 -1
- package/dist/BrowserHttpClient.js +5 -5
- package/dist/BrowserHttpClient.js.map +1 -1
- package/dist/BrowserWorkerRunner.js +1 -1
- package/dist/BrowserWorkerRunner.js.map +1 -1
- package/dist/Clipboard.d.ts +5 -2
- package/dist/Clipboard.d.ts.map +1 -1
- package/dist/Clipboard.js +2 -2
- package/dist/Clipboard.js.map +1 -1
- package/dist/Geolocation.d.ts +2 -2
- package/dist/Geolocation.d.ts.map +1 -1
- package/dist/Geolocation.js +2 -2
- package/dist/Geolocation.js.map +1 -1
- package/dist/IndexedDb.d.ts +50 -0
- package/dist/IndexedDb.d.ts.map +1 -0
- package/dist/IndexedDb.js +65 -0
- package/dist/IndexedDb.js.map +1 -0
- package/dist/IndexedDbDatabase.d.ts +105 -0
- package/dist/IndexedDbDatabase.d.ts.map +1 -0
- package/dist/IndexedDbDatabase.js +321 -0
- package/dist/IndexedDbDatabase.js.map +1 -0
- package/dist/IndexedDbQueryBuilder.d.ts +342 -0
- package/dist/IndexedDbQueryBuilder.d.ts.map +1 -0
- package/dist/IndexedDbQueryBuilder.js +869 -0
- package/dist/IndexedDbQueryBuilder.js.map +1 -0
- package/dist/IndexedDbTable.d.ts +109 -0
- package/dist/IndexedDbTable.d.ts.map +1 -0
- package/dist/IndexedDbTable.js +38 -0
- package/dist/IndexedDbTable.js.map +1 -0
- package/dist/IndexedDbVersion.d.ts +50 -0
- package/dist/IndexedDbVersion.d.ts.map +1 -0
- package/dist/IndexedDbVersion.js +23 -0
- package/dist/IndexedDbVersion.js.map +1 -0
- package/dist/Permissions.d.ts +5 -2
- package/dist/Permissions.d.ts.map +1 -1
- package/dist/Permissions.js +2 -2
- package/dist/Permissions.js.map +1 -1
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/BrowserHttpClient.ts +6 -6
- package/src/BrowserWorkerRunner.ts +1 -1
- package/src/Clipboard.ts +2 -2
- package/src/Geolocation.ts +2 -2
- package/src/IndexedDb.ts +97 -0
- package/src/IndexedDbDatabase.ts +631 -0
- package/src/IndexedDbQueryBuilder.ts +1890 -0
- package/src/IndexedDbTable.ts +203 -0
- package/src/IndexedDbVersion.ts +89 -0
- package/src/Permissions.ts +2 -2
- package/src/index.ts +25 -0
|
@@ -0,0 +1,869 @@
|
|
|
1
|
+
import * as Context from "effect/Context";
|
|
2
|
+
import * as Data from "effect/Data";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Fiber from "effect/Fiber";
|
|
5
|
+
import { BaseProto } from "effect/Inspectable";
|
|
6
|
+
import * as Option from "effect/Option";
|
|
7
|
+
import * as Pipeable from "effect/Pipeable";
|
|
8
|
+
import * as References from "effect/References";
|
|
9
|
+
import * as Schema from "effect/Schema";
|
|
10
|
+
import * as SchemaIssue from "effect/SchemaIssue";
|
|
11
|
+
import * as SchemaParser from "effect/SchemaParser";
|
|
12
|
+
import * as Stream from "effect/Stream";
|
|
13
|
+
import * as Utils from "effect/Utils";
|
|
14
|
+
const ErrorTypeId = "~@effect/platform-browser/IndexedDbQueryBuilder/IndexedDbQueryError";
|
|
15
|
+
const CommonProto = {
|
|
16
|
+
[Symbol.iterator]() {
|
|
17
|
+
return new Utils.SingleShotGen(this);
|
|
18
|
+
},
|
|
19
|
+
...Pipeable.Prototype,
|
|
20
|
+
...BaseProto,
|
|
21
|
+
toJSON() {
|
|
22
|
+
return {
|
|
23
|
+
_id: "IndexedDbQueryBuilder"
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* @since 4.0.0
|
|
29
|
+
* @category errors
|
|
30
|
+
*/
|
|
31
|
+
export class IndexedDbQueryError extends /*#__PURE__*/Data.TaggedError("IndexedDbQueryError") {
|
|
32
|
+
/**
|
|
33
|
+
* @since 4.0.0
|
|
34
|
+
*/
|
|
35
|
+
[ErrorTypeId] = ErrorTypeId;
|
|
36
|
+
message = this.reason;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* @since 4.0.0
|
|
40
|
+
* @category models
|
|
41
|
+
*/
|
|
42
|
+
export class IndexedDbTransaction extends /*#__PURE__*/Context.Service()("@effect/platform-browser/IndexedDbQueryBuilder/IndexedDbTransaction") {}
|
|
43
|
+
const applyDelete = query => Effect.callback(resume => {
|
|
44
|
+
const database = query.delete.from.database;
|
|
45
|
+
const IDBKeyRange = query.delete.from.IDBKeyRange;
|
|
46
|
+
const transaction = getOrCreateTransaction(database.current, [query.delete.from.table.tableName], "readwrite", {
|
|
47
|
+
durability: query.delete.from.table.durability
|
|
48
|
+
});
|
|
49
|
+
const objectStore = transaction.objectStore(query.delete.from.table.tableName);
|
|
50
|
+
const predicate = query.predicate;
|
|
51
|
+
let keyRange = undefined;
|
|
52
|
+
if (query.only !== undefined) {
|
|
53
|
+
keyRange = IDBKeyRange.only(query.only);
|
|
54
|
+
} else if (query.lowerBound !== undefined && query.upperBound !== undefined) {
|
|
55
|
+
keyRange = IDBKeyRange.bound(query.lowerBound, query.upperBound, query.excludeLowerBound, query.excludeUpperBound);
|
|
56
|
+
} else if (query.lowerBound !== undefined) {
|
|
57
|
+
keyRange = IDBKeyRange.lowerBound(query.lowerBound, query.excludeLowerBound);
|
|
58
|
+
} else if (query.upperBound !== undefined) {
|
|
59
|
+
keyRange = IDBKeyRange.upperBound(query.upperBound, query.excludeUpperBound);
|
|
60
|
+
}
|
|
61
|
+
let request;
|
|
62
|
+
if (query.limitValue !== undefined || predicate) {
|
|
63
|
+
const cursorRequest = objectStore.openCursor();
|
|
64
|
+
let count = 0;
|
|
65
|
+
cursorRequest.onerror = () => {
|
|
66
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
67
|
+
reason: "TransactionError",
|
|
68
|
+
cause: cursorRequest.error
|
|
69
|
+
})));
|
|
70
|
+
};
|
|
71
|
+
cursorRequest.onsuccess = () => {
|
|
72
|
+
const cursor = cursorRequest.result;
|
|
73
|
+
if (cursor === null) {
|
|
74
|
+
return resume(Effect.void);
|
|
75
|
+
}
|
|
76
|
+
if (predicate === undefined || predicate(cursor.value)) {
|
|
77
|
+
const deleteRequest = cursor.delete();
|
|
78
|
+
deleteRequest.onerror = () => {
|
|
79
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
80
|
+
reason: "TransactionError",
|
|
81
|
+
cause: deleteRequest.error
|
|
82
|
+
})));
|
|
83
|
+
};
|
|
84
|
+
count += 1;
|
|
85
|
+
}
|
|
86
|
+
if (query.limitValue === undefined || count < query.limitValue) {
|
|
87
|
+
return cursor.continue();
|
|
88
|
+
}
|
|
89
|
+
resume(Effect.void);
|
|
90
|
+
};
|
|
91
|
+
} else if (keyRange !== undefined) {
|
|
92
|
+
request = objectStore.delete(keyRange);
|
|
93
|
+
request.onerror = event => {
|
|
94
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
95
|
+
reason: "TransactionError",
|
|
96
|
+
cause: event
|
|
97
|
+
})));
|
|
98
|
+
};
|
|
99
|
+
request.onsuccess = () => {
|
|
100
|
+
resume(Effect.succeed(request.result));
|
|
101
|
+
};
|
|
102
|
+
} else {
|
|
103
|
+
resume(Effect.die(new Error("No key range provided for delete operation")));
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
const getReadonlyObjectStore = query => {
|
|
107
|
+
const database = query.from.database;
|
|
108
|
+
const IDBKeyRange = query.from.IDBKeyRange;
|
|
109
|
+
const transaction = getOrCreateTransaction(database.current, [query.from.table.tableName], "readonly", {
|
|
110
|
+
durability: query.from.table.durability
|
|
111
|
+
});
|
|
112
|
+
const objectStore = transaction.objectStore(query.from.table.tableName);
|
|
113
|
+
let keyRange = undefined;
|
|
114
|
+
let store;
|
|
115
|
+
if (query.only !== undefined) {
|
|
116
|
+
keyRange = IDBKeyRange.only(query.only);
|
|
117
|
+
} else if (query.lowerBound !== undefined && query.upperBound !== undefined) {
|
|
118
|
+
keyRange = IDBKeyRange.bound(query.lowerBound, query.upperBound, query.excludeLowerBound, query.excludeUpperBound);
|
|
119
|
+
} else if (query.lowerBound !== undefined) {
|
|
120
|
+
keyRange = IDBKeyRange.lowerBound(query.lowerBound, query.excludeLowerBound);
|
|
121
|
+
} else if (query.upperBound !== undefined) {
|
|
122
|
+
keyRange = IDBKeyRange.upperBound(query.upperBound, query.excludeUpperBound);
|
|
123
|
+
}
|
|
124
|
+
if (query.index !== undefined) {
|
|
125
|
+
store = objectStore.index(query.index);
|
|
126
|
+
} else {
|
|
127
|
+
store = objectStore;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
store,
|
|
131
|
+
keyRange
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
const applySelect = /*#__PURE__*/Effect.fnUntraced(function* (query) {
|
|
135
|
+
const keyPath = query.from.table.keyPath;
|
|
136
|
+
const predicate = query.predicate;
|
|
137
|
+
const data = predicate || keyPath === undefined || query.offsetValue !== undefined ? yield* Effect.callback(resume => {
|
|
138
|
+
const {
|
|
139
|
+
keyRange,
|
|
140
|
+
store
|
|
141
|
+
} = getReadonlyObjectStore(query);
|
|
142
|
+
const cursorRequest = store.openCursor(keyRange, query.reverseValue ? "prev" : "next");
|
|
143
|
+
const results = [];
|
|
144
|
+
let count = 0;
|
|
145
|
+
let offsetApplied = false;
|
|
146
|
+
cursorRequest.onerror = () => {
|
|
147
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
148
|
+
reason: "TransactionError",
|
|
149
|
+
cause: cursorRequest.error
|
|
150
|
+
})));
|
|
151
|
+
};
|
|
152
|
+
cursorRequest.onsuccess = () => {
|
|
153
|
+
const cursor = cursorRequest.result;
|
|
154
|
+
if (cursor === null) {
|
|
155
|
+
return resume(Effect.succeed(results));
|
|
156
|
+
}
|
|
157
|
+
if (query.offsetValue && !offsetApplied) {
|
|
158
|
+
offsetApplied = true;
|
|
159
|
+
return cursor.advance(query.offsetValue);
|
|
160
|
+
}
|
|
161
|
+
if (predicate === undefined || predicate(cursor.value)) {
|
|
162
|
+
results.push(keyPath === undefined ? {
|
|
163
|
+
...cursor.value,
|
|
164
|
+
key: cursor.key
|
|
165
|
+
} : cursor.value);
|
|
166
|
+
count += 1;
|
|
167
|
+
}
|
|
168
|
+
if (query.limitValue === undefined || count < query.limitValue) {
|
|
169
|
+
return cursor.continue();
|
|
170
|
+
}
|
|
171
|
+
resume(Effect.succeed(results));
|
|
172
|
+
};
|
|
173
|
+
}) : yield* Effect.callback(resume => {
|
|
174
|
+
const {
|
|
175
|
+
keyRange,
|
|
176
|
+
store
|
|
177
|
+
} = getReadonlyObjectStore(query);
|
|
178
|
+
const request = store.getAll(keyRange, query.limitValue);
|
|
179
|
+
request.onerror = event => {
|
|
180
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
181
|
+
reason: "TransactionError",
|
|
182
|
+
cause: event
|
|
183
|
+
})));
|
|
184
|
+
};
|
|
185
|
+
request.onsuccess = () => {
|
|
186
|
+
if (query.reverseValue) {
|
|
187
|
+
request.result.reverse();
|
|
188
|
+
}
|
|
189
|
+
resume(Effect.succeed(request.result));
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
const tableSchema = query.from.table.arraySchema;
|
|
193
|
+
return yield* Schema.decodeUnknownEffect(tableSchema)(data).pipe(Effect.mapError(error => new IndexedDbQueryError({
|
|
194
|
+
reason: "DecodeError",
|
|
195
|
+
cause: error
|
|
196
|
+
})));
|
|
197
|
+
});
|
|
198
|
+
const getFirst = /*#__PURE__*/Effect.fnUntraced(function* (query) {
|
|
199
|
+
const keyPath = query.select.from.table.keyPath;
|
|
200
|
+
const data = yield* Effect.callback(resume => {
|
|
201
|
+
const {
|
|
202
|
+
keyRange,
|
|
203
|
+
store
|
|
204
|
+
} = getReadonlyObjectStore(query.select);
|
|
205
|
+
if (keyRange !== undefined) {
|
|
206
|
+
const request = store.get(keyRange);
|
|
207
|
+
request.onerror = event => {
|
|
208
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
209
|
+
reason: "TransactionError",
|
|
210
|
+
cause: event
|
|
211
|
+
})));
|
|
212
|
+
};
|
|
213
|
+
request.onsuccess = () => {
|
|
214
|
+
resume(Effect.succeed(request.result));
|
|
215
|
+
};
|
|
216
|
+
} else {
|
|
217
|
+
const request = store.openCursor();
|
|
218
|
+
request.onerror = event => {
|
|
219
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
220
|
+
reason: "TransactionError",
|
|
221
|
+
cause: event
|
|
222
|
+
})));
|
|
223
|
+
};
|
|
224
|
+
request.onsuccess = () => {
|
|
225
|
+
const value = request.result?.value;
|
|
226
|
+
const key = request.result?.key;
|
|
227
|
+
if (value === undefined) {
|
|
228
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
229
|
+
reason: "NotFoundError",
|
|
230
|
+
cause: request.error
|
|
231
|
+
})));
|
|
232
|
+
} else {
|
|
233
|
+
resume(Effect.succeed(keyPath === undefined ? {
|
|
234
|
+
...value,
|
|
235
|
+
key
|
|
236
|
+
} : value));
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
return yield* Schema.decodeUnknownEffect(query.select.from.table.readSchema)(data).pipe(Effect.mapError(error => new IndexedDbQueryError({
|
|
242
|
+
reason: "DecodeError",
|
|
243
|
+
cause: error
|
|
244
|
+
})));
|
|
245
|
+
});
|
|
246
|
+
const applyModify = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
247
|
+
query,
|
|
248
|
+
value
|
|
249
|
+
}) {
|
|
250
|
+
const autoIncrement = query.from.table.autoIncrement;
|
|
251
|
+
const keyPath = query.from.table.keyPath;
|
|
252
|
+
const table = query.from.table;
|
|
253
|
+
const schema = autoIncrement && value[keyPath] === undefined ? table.autoincrementSchema : table.tableSchema;
|
|
254
|
+
const encodedValue = yield* SchemaParser.makeEffect(autoIncrement && value[keyPath] === undefined ? table.autoincrementSchema : table.tableSchema)(value).pipe(Effect.flatMap(Schema.encodeUnknownEffect(schema)), Effect.mapError(error => new IndexedDbQueryError({
|
|
255
|
+
reason: "EncodeError",
|
|
256
|
+
cause: error
|
|
257
|
+
})));
|
|
258
|
+
return yield* Effect.callback(resume => {
|
|
259
|
+
const database = query.from.database;
|
|
260
|
+
const transaction = getOrCreateTransaction(database.current, [query.from.table.tableName], "readwrite", {
|
|
261
|
+
durability: query.from.table.durability
|
|
262
|
+
});
|
|
263
|
+
const objectStore = transaction.objectStore(query.from.table.tableName);
|
|
264
|
+
let request;
|
|
265
|
+
if (query.operation === "add") {
|
|
266
|
+
request = objectStore.add(encodedValue, keyPath === undefined ? value["key"] : undefined);
|
|
267
|
+
} else if (query.operation === "put") {
|
|
268
|
+
request = objectStore.put(encodedValue, keyPath === undefined ? value["key"] : undefined);
|
|
269
|
+
} else {
|
|
270
|
+
return resume(Effect.die(new Error("Invalid modify operation")));
|
|
271
|
+
}
|
|
272
|
+
request.onerror = event => {
|
|
273
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
274
|
+
reason: "TransactionError",
|
|
275
|
+
cause: event
|
|
276
|
+
})));
|
|
277
|
+
};
|
|
278
|
+
request.onsuccess = () => {
|
|
279
|
+
resume(Effect.succeed(request.result));
|
|
280
|
+
};
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
const applyModifyAll = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
284
|
+
query,
|
|
285
|
+
values
|
|
286
|
+
}) {
|
|
287
|
+
const autoIncrement = query.from.table.autoIncrement;
|
|
288
|
+
const keyPath = query.from.table.keyPath;
|
|
289
|
+
const schema = query.from.table.tableSchema;
|
|
290
|
+
const encodedValues = new Array(values.length);
|
|
291
|
+
const makeValue = SchemaParser.makeEffect(schema);
|
|
292
|
+
const encodeValue = SchemaParser.encodeUnknownEffect(schema);
|
|
293
|
+
const makeValueAutoincrement = SchemaParser.makeEffect(query.from.table.autoincrementSchema);
|
|
294
|
+
const encodeValueAutoincrement = SchemaParser.encodeUnknownEffect(query.from.table.autoincrementSchema);
|
|
295
|
+
for (let i = 0; i < values.length; i++) {
|
|
296
|
+
const value = values[i];
|
|
297
|
+
if (autoIncrement && value[keyPath] === undefined) {
|
|
298
|
+
encodedValues[i] = yield* encodeValueAutoincrement(yield* makeValueAutoincrement(value));
|
|
299
|
+
} else {
|
|
300
|
+
encodedValues[i] = yield* encodeValue(yield* makeValue(value));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return yield* Effect.callback(resume => {
|
|
304
|
+
const database = query.from.database;
|
|
305
|
+
const transaction = getOrCreateTransaction(database.current, [query.from.table.tableName], "readwrite", {
|
|
306
|
+
durability: query.from.table.durability
|
|
307
|
+
});
|
|
308
|
+
const objectStore = transaction.objectStore(query.from.table.tableName);
|
|
309
|
+
const results = [];
|
|
310
|
+
if (query.operation === "add") {
|
|
311
|
+
for (let i = 0; i < encodedValues.length; i++) {
|
|
312
|
+
const request = objectStore.add(encodedValues[i], keyPath === undefined ? values[i]["key"] : undefined);
|
|
313
|
+
request.onerror = () => {
|
|
314
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
315
|
+
reason: "TransactionError",
|
|
316
|
+
cause: request.error
|
|
317
|
+
})));
|
|
318
|
+
};
|
|
319
|
+
request.onsuccess = () => {
|
|
320
|
+
results.push(request.result);
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
} else if (query.operation === "put") {
|
|
324
|
+
for (let i = 0; i < encodedValues.length; i++) {
|
|
325
|
+
const request = objectStore.put(encodedValues[i], keyPath === undefined ? values[i]["key"] : undefined);
|
|
326
|
+
request.onerror = () => {
|
|
327
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
328
|
+
reason: "TransactionError",
|
|
329
|
+
cause: request.error
|
|
330
|
+
})));
|
|
331
|
+
};
|
|
332
|
+
request.onsuccess = () => {
|
|
333
|
+
results.push(request.result);
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
} else {
|
|
337
|
+
return resume(Effect.die(new Error("Invalid modify all operation")));
|
|
338
|
+
}
|
|
339
|
+
objectStore.transaction.onerror = () => {
|
|
340
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
341
|
+
reason: "TransactionError",
|
|
342
|
+
cause: objectStore.transaction.error
|
|
343
|
+
})));
|
|
344
|
+
};
|
|
345
|
+
objectStore.transaction.oncomplete = () => {
|
|
346
|
+
resume(Effect.succeed(results));
|
|
347
|
+
};
|
|
348
|
+
});
|
|
349
|
+
}, /*#__PURE__*/Effect.catchIf(SchemaIssue.isIssue, issue => Effect.fail(new IndexedDbQueryError({
|
|
350
|
+
reason: "EncodeError",
|
|
351
|
+
cause: new Schema.SchemaError(issue)
|
|
352
|
+
}))));
|
|
353
|
+
const applyClear = options => Effect.callback(resume => {
|
|
354
|
+
const database = options.database;
|
|
355
|
+
const transaction = getOrCreateTransaction(database, [options.table.tableName], "readwrite", {
|
|
356
|
+
durability: options.table.durability
|
|
357
|
+
});
|
|
358
|
+
const objectStore = transaction.objectStore(options.table.tableName);
|
|
359
|
+
const request = objectStore.clear();
|
|
360
|
+
request.onerror = event => {
|
|
361
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
362
|
+
reason: "TransactionError",
|
|
363
|
+
cause: event
|
|
364
|
+
})));
|
|
365
|
+
};
|
|
366
|
+
request.onsuccess = () => {
|
|
367
|
+
resume(Effect.void);
|
|
368
|
+
};
|
|
369
|
+
});
|
|
370
|
+
const applyClearAll = options => Effect.callback(resume => {
|
|
371
|
+
const database = options.database;
|
|
372
|
+
const tables = database.objectStoreNames;
|
|
373
|
+
const transaction = getOrCreateTransaction(database, [...tables], "readwrite");
|
|
374
|
+
for (let t = 0; t < tables.length; t++) {
|
|
375
|
+
const objectStore = transaction.objectStore(tables[t]);
|
|
376
|
+
const request = objectStore.clear();
|
|
377
|
+
request.onerror = () => {
|
|
378
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
379
|
+
reason: "TransactionError",
|
|
380
|
+
cause: request.error
|
|
381
|
+
})));
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
transaction.onerror = () => {
|
|
385
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
386
|
+
reason: "TransactionError",
|
|
387
|
+
cause: transaction.error
|
|
388
|
+
})));
|
|
389
|
+
};
|
|
390
|
+
transaction.oncomplete = () => {
|
|
391
|
+
resume(Effect.void);
|
|
392
|
+
};
|
|
393
|
+
});
|
|
394
|
+
const getCount = query => Effect.callback(resume => {
|
|
395
|
+
const {
|
|
396
|
+
keyRange,
|
|
397
|
+
store
|
|
398
|
+
} = getReadonlyObjectStore(query);
|
|
399
|
+
const request = store.count(keyRange);
|
|
400
|
+
request.onerror = event => {
|
|
401
|
+
resume(Effect.fail(new IndexedDbQueryError({
|
|
402
|
+
reason: "TransactionError",
|
|
403
|
+
cause: event
|
|
404
|
+
})));
|
|
405
|
+
};
|
|
406
|
+
request.onsuccess = () => {
|
|
407
|
+
resume(Effect.succeed(request.result));
|
|
408
|
+
};
|
|
409
|
+
});
|
|
410
|
+
const FromProto = {
|
|
411
|
+
...CommonProto,
|
|
412
|
+
select(index) {
|
|
413
|
+
return makeSelect({
|
|
414
|
+
from: this,
|
|
415
|
+
index
|
|
416
|
+
});
|
|
417
|
+
},
|
|
418
|
+
count(index) {
|
|
419
|
+
return makeCount({
|
|
420
|
+
from: this,
|
|
421
|
+
index
|
|
422
|
+
});
|
|
423
|
+
},
|
|
424
|
+
delete(index) {
|
|
425
|
+
return makeDeletePartial({
|
|
426
|
+
from: this,
|
|
427
|
+
index
|
|
428
|
+
});
|
|
429
|
+
},
|
|
430
|
+
insert(value) {
|
|
431
|
+
return makeModify({
|
|
432
|
+
from: this,
|
|
433
|
+
value,
|
|
434
|
+
operation: "add"
|
|
435
|
+
});
|
|
436
|
+
},
|
|
437
|
+
upsert(value) {
|
|
438
|
+
return makeModify({
|
|
439
|
+
from: this,
|
|
440
|
+
value,
|
|
441
|
+
operation: "put"
|
|
442
|
+
});
|
|
443
|
+
},
|
|
444
|
+
insertAll(values) {
|
|
445
|
+
return makeModifyAll({
|
|
446
|
+
from: this,
|
|
447
|
+
values,
|
|
448
|
+
operation: "add"
|
|
449
|
+
});
|
|
450
|
+
},
|
|
451
|
+
upsertAll(values) {
|
|
452
|
+
return makeModifyAll({
|
|
453
|
+
from: this,
|
|
454
|
+
values,
|
|
455
|
+
operation: "put"
|
|
456
|
+
});
|
|
457
|
+
},
|
|
458
|
+
get clear() {
|
|
459
|
+
const self = this;
|
|
460
|
+
return applyClear({
|
|
461
|
+
database: self.database.current,
|
|
462
|
+
table: self.table
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
const makeFrom = options => {
|
|
467
|
+
const self = Object.create(FromProto);
|
|
468
|
+
self.table = options.table;
|
|
469
|
+
self.database = options.database;
|
|
470
|
+
self.IDBKeyRange = options.IDBKeyRange;
|
|
471
|
+
self.reactivity = options.reactivity;
|
|
472
|
+
return self;
|
|
473
|
+
};
|
|
474
|
+
const DeletePartialProto = {
|
|
475
|
+
...CommonProto,
|
|
476
|
+
limit(limit) {
|
|
477
|
+
return makeDelete({
|
|
478
|
+
delete: this,
|
|
479
|
+
limitValue: limit
|
|
480
|
+
});
|
|
481
|
+
},
|
|
482
|
+
equals(value) {
|
|
483
|
+
return makeDelete({
|
|
484
|
+
delete: this,
|
|
485
|
+
only: value
|
|
486
|
+
});
|
|
487
|
+
},
|
|
488
|
+
gte(value) {
|
|
489
|
+
return makeDelete({
|
|
490
|
+
delete: this,
|
|
491
|
+
lowerBound: value,
|
|
492
|
+
excludeLowerBound: false
|
|
493
|
+
});
|
|
494
|
+
},
|
|
495
|
+
lte(value) {
|
|
496
|
+
return makeDelete({
|
|
497
|
+
delete: this,
|
|
498
|
+
upperBound: value,
|
|
499
|
+
excludeUpperBound: false
|
|
500
|
+
});
|
|
501
|
+
},
|
|
502
|
+
gt(value) {
|
|
503
|
+
return makeDelete({
|
|
504
|
+
delete: this,
|
|
505
|
+
lowerBound: value,
|
|
506
|
+
excludeLowerBound: true
|
|
507
|
+
});
|
|
508
|
+
},
|
|
509
|
+
lt(value) {
|
|
510
|
+
return makeDelete({
|
|
511
|
+
delete: this,
|
|
512
|
+
upperBound: value,
|
|
513
|
+
excludeUpperBound: true
|
|
514
|
+
});
|
|
515
|
+
},
|
|
516
|
+
between(lowerBound, upperBound, queryOptions) {
|
|
517
|
+
return makeDelete({
|
|
518
|
+
delete: this,
|
|
519
|
+
lowerBound,
|
|
520
|
+
upperBound,
|
|
521
|
+
excludeLowerBound: queryOptions?.excludeLowerBound ?? false,
|
|
522
|
+
excludeUpperBound: queryOptions?.excludeUpperBound ?? false
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
const makeDeletePartial = options => {
|
|
527
|
+
const self = Object.create(DeletePartialProto);
|
|
528
|
+
self.from = options.from;
|
|
529
|
+
self.index = options.index;
|
|
530
|
+
return self;
|
|
531
|
+
};
|
|
532
|
+
const DeleteProto = {
|
|
533
|
+
...CommonProto,
|
|
534
|
+
asEffect() {
|
|
535
|
+
return applyDelete(this);
|
|
536
|
+
},
|
|
537
|
+
limit(limit) {
|
|
538
|
+
return makeDelete({
|
|
539
|
+
...this,
|
|
540
|
+
limitValue: limit
|
|
541
|
+
});
|
|
542
|
+
},
|
|
543
|
+
filter(filter) {
|
|
544
|
+
const prev = this.predicate;
|
|
545
|
+
return makeDelete({
|
|
546
|
+
delete: this.delete,
|
|
547
|
+
predicate: prev ? item => prev(item) && filter(item) : filter
|
|
548
|
+
});
|
|
549
|
+
},
|
|
550
|
+
invalidate(keys) {
|
|
551
|
+
keys ??= this.only !== undefined ? {
|
|
552
|
+
[this.delete.from.table.tableName]: [this.only]
|
|
553
|
+
} : [this.delete.from.table.tableName];
|
|
554
|
+
return this.delete.from.reactivity.mutation(keys, this.asEffect());
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
const makeDelete = options => {
|
|
558
|
+
const self = Object.create(DeleteProto);
|
|
559
|
+
self.delete = options.delete;
|
|
560
|
+
self.limitValue = options.limitValue;
|
|
561
|
+
self.only = options.only;
|
|
562
|
+
self.lowerBound = options.lowerBound;
|
|
563
|
+
self.upperBound = options.upperBound;
|
|
564
|
+
self.excludeLowerBound = options.excludeLowerBound ?? false;
|
|
565
|
+
self.excludeUpperBound = options.excludeUpperBound ?? false;
|
|
566
|
+
self.predicate = options.predicate;
|
|
567
|
+
return self;
|
|
568
|
+
};
|
|
569
|
+
const CountProto = {
|
|
570
|
+
...CommonProto,
|
|
571
|
+
asEffect() {
|
|
572
|
+
return getCount(this);
|
|
573
|
+
},
|
|
574
|
+
equals(value) {
|
|
575
|
+
return makeCount({
|
|
576
|
+
from: this.from,
|
|
577
|
+
index: this.index,
|
|
578
|
+
only: value
|
|
579
|
+
});
|
|
580
|
+
},
|
|
581
|
+
gte(value) {
|
|
582
|
+
return makeCount({
|
|
583
|
+
from: this.from,
|
|
584
|
+
index: this.index,
|
|
585
|
+
lowerBound: value,
|
|
586
|
+
excludeLowerBound: false
|
|
587
|
+
});
|
|
588
|
+
},
|
|
589
|
+
lte(value) {
|
|
590
|
+
return makeCount({
|
|
591
|
+
from: this.from,
|
|
592
|
+
index: this.index,
|
|
593
|
+
upperBound: value,
|
|
594
|
+
excludeUpperBound: false
|
|
595
|
+
});
|
|
596
|
+
},
|
|
597
|
+
gt(value) {
|
|
598
|
+
return makeCount({
|
|
599
|
+
from: this.from,
|
|
600
|
+
index: this.index,
|
|
601
|
+
lowerBound: value,
|
|
602
|
+
excludeLowerBound: true
|
|
603
|
+
});
|
|
604
|
+
},
|
|
605
|
+
lt(value) {
|
|
606
|
+
return makeCount({
|
|
607
|
+
from: this.from,
|
|
608
|
+
index: this.index,
|
|
609
|
+
upperBound: value,
|
|
610
|
+
excludeUpperBound: true
|
|
611
|
+
});
|
|
612
|
+
},
|
|
613
|
+
between(lowerBound, upperBound, queryOptions) {
|
|
614
|
+
return makeCount({
|
|
615
|
+
from: this.from,
|
|
616
|
+
index: this.index,
|
|
617
|
+
lowerBound,
|
|
618
|
+
upperBound,
|
|
619
|
+
excludeLowerBound: queryOptions?.excludeLowerBound ?? false,
|
|
620
|
+
excludeUpperBound: queryOptions?.excludeUpperBound ?? false
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
const makeCount = options => {
|
|
625
|
+
const self = Object.create(CountProto);
|
|
626
|
+
self.from = options.from;
|
|
627
|
+
self.index = options.index;
|
|
628
|
+
self.only = options.only;
|
|
629
|
+
self.lowerBound = options.lowerBound;
|
|
630
|
+
self.upperBound = options.upperBound;
|
|
631
|
+
self.excludeLowerBound = options.excludeLowerBound;
|
|
632
|
+
self.excludeUpperBound = options.excludeUpperBound;
|
|
633
|
+
return self;
|
|
634
|
+
};
|
|
635
|
+
const SelectProto = {
|
|
636
|
+
...CommonProto,
|
|
637
|
+
limit(limit) {
|
|
638
|
+
return makeSelect({
|
|
639
|
+
...this,
|
|
640
|
+
limitValue: limit
|
|
641
|
+
});
|
|
642
|
+
},
|
|
643
|
+
offset(offset) {
|
|
644
|
+
return makeSelect({
|
|
645
|
+
...this,
|
|
646
|
+
offsetValue: offset
|
|
647
|
+
});
|
|
648
|
+
},
|
|
649
|
+
equals(value) {
|
|
650
|
+
return makeSelect({
|
|
651
|
+
...this,
|
|
652
|
+
only: value
|
|
653
|
+
});
|
|
654
|
+
},
|
|
655
|
+
gte(value) {
|
|
656
|
+
return makeSelect({
|
|
657
|
+
...this,
|
|
658
|
+
lowerBound: value,
|
|
659
|
+
excludeLowerBound: false
|
|
660
|
+
});
|
|
661
|
+
},
|
|
662
|
+
lte(value) {
|
|
663
|
+
return makeSelect({
|
|
664
|
+
...this,
|
|
665
|
+
upperBound: value,
|
|
666
|
+
excludeUpperBound: false
|
|
667
|
+
});
|
|
668
|
+
},
|
|
669
|
+
gt(value) {
|
|
670
|
+
return makeSelect({
|
|
671
|
+
...this,
|
|
672
|
+
lowerBound: value,
|
|
673
|
+
excludeLowerBound: true
|
|
674
|
+
});
|
|
675
|
+
},
|
|
676
|
+
lt(value) {
|
|
677
|
+
return makeSelect({
|
|
678
|
+
...this,
|
|
679
|
+
upperBound: value,
|
|
680
|
+
excludeUpperBound: true
|
|
681
|
+
});
|
|
682
|
+
},
|
|
683
|
+
between(lowerBound, upperBound, queryOptions) {
|
|
684
|
+
return makeSelect({
|
|
685
|
+
...this,
|
|
686
|
+
lowerBound,
|
|
687
|
+
upperBound,
|
|
688
|
+
excludeLowerBound: queryOptions?.excludeLowerBound ?? false,
|
|
689
|
+
excludeUpperBound: queryOptions?.excludeUpperBound ?? false
|
|
690
|
+
});
|
|
691
|
+
},
|
|
692
|
+
reverse() {
|
|
693
|
+
return makeSelect({
|
|
694
|
+
...this,
|
|
695
|
+
reverseValue: true
|
|
696
|
+
});
|
|
697
|
+
},
|
|
698
|
+
first() {
|
|
699
|
+
return makeFirst({
|
|
700
|
+
select: this
|
|
701
|
+
});
|
|
702
|
+
},
|
|
703
|
+
filter(filter) {
|
|
704
|
+
const prev = this.predicate;
|
|
705
|
+
return makeSelect({
|
|
706
|
+
...this,
|
|
707
|
+
predicate: prev ? item => prev(item) && filter(item) : filter
|
|
708
|
+
});
|
|
709
|
+
},
|
|
710
|
+
asEffect() {
|
|
711
|
+
return applySelect(this);
|
|
712
|
+
},
|
|
713
|
+
stream(options) {
|
|
714
|
+
const limit = this.limitValue;
|
|
715
|
+
const chunkSize = Math.min(options?.chunkSize ?? 100, limit ?? Number.MAX_SAFE_INTEGER);
|
|
716
|
+
const initial = this.limit(chunkSize);
|
|
717
|
+
return Stream.suspend(() => {
|
|
718
|
+
let total = 0;
|
|
719
|
+
return Stream.paginate(initial, select => Effect.map(applySelect(select), data => {
|
|
720
|
+
total += data.length;
|
|
721
|
+
select.offsetValue = total;
|
|
722
|
+
const reachedLimit = limit && total >= limit;
|
|
723
|
+
const isPartial = data.length < chunkSize;
|
|
724
|
+
return [data, isPartial || reachedLimit ? Option.none() : Option.some(select)];
|
|
725
|
+
}));
|
|
726
|
+
});
|
|
727
|
+
},
|
|
728
|
+
reactive(keys) {
|
|
729
|
+
keys ??= [this.from.table.tableName];
|
|
730
|
+
return this.from.reactivity.stream(keys, this.asEffect());
|
|
731
|
+
},
|
|
732
|
+
reactiveQueue(keys) {
|
|
733
|
+
keys ??= [this.from.table.tableName];
|
|
734
|
+
return this.from.reactivity.query(keys, this.asEffect());
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
const makeSelect = options => {
|
|
738
|
+
const self = Object.create(SelectProto);
|
|
739
|
+
self.from = options.from;
|
|
740
|
+
self.index = options.index;
|
|
741
|
+
self.only = options.only;
|
|
742
|
+
self.limitValue = options.limitValue;
|
|
743
|
+
self.offsetValue = options.offsetValue;
|
|
744
|
+
self.reverseValue = options.reverseValue;
|
|
745
|
+
self.lowerBound = options.lowerBound;
|
|
746
|
+
self.upperBound = options.upperBound;
|
|
747
|
+
self.excludeLowerBound = options.excludeLowerBound;
|
|
748
|
+
self.excludeUpperBound = options.excludeUpperBound;
|
|
749
|
+
self.predicate = options.predicate;
|
|
750
|
+
return self;
|
|
751
|
+
};
|
|
752
|
+
const FirstProto = {
|
|
753
|
+
...CommonProto,
|
|
754
|
+
asEffect() {
|
|
755
|
+
return getFirst(this);
|
|
756
|
+
},
|
|
757
|
+
reactive(keys) {
|
|
758
|
+
keys ??= this.select.only !== undefined ? [`${this.select.from.table.tableName}:${String(this.select.only)}`] : [this.select.from.table.tableName];
|
|
759
|
+
return this.select.from.reactivity.stream(keys, this.asEffect());
|
|
760
|
+
},
|
|
761
|
+
reactiveQueue(keys) {
|
|
762
|
+
keys ??= this.select.only !== undefined ? [`${this.select.from.table.tableName}:${this.select.only}`] : [this.select.from.table.tableName];
|
|
763
|
+
return this.select.from.reactivity.query(keys, this.asEffect());
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
const makeFirst = options => {
|
|
767
|
+
const self = Object.create(FirstProto);
|
|
768
|
+
self.select = options.select;
|
|
769
|
+
return self;
|
|
770
|
+
};
|
|
771
|
+
const ModifyProto = {
|
|
772
|
+
...CommonProto,
|
|
773
|
+
asEffect() {
|
|
774
|
+
return applyModify({
|
|
775
|
+
query: this,
|
|
776
|
+
value: this.value
|
|
777
|
+
});
|
|
778
|
+
},
|
|
779
|
+
invalidate(keys) {
|
|
780
|
+
const keyPath = this.from.table.keyPath;
|
|
781
|
+
keys ??= typeof keyPath === "string" && this.value[keyPath] !== undefined ? {
|
|
782
|
+
[this.from.table.tableName]: [this.value[keyPath]]
|
|
783
|
+
} : [this.from.table.tableName];
|
|
784
|
+
return this.from.reactivity.mutation(keys, this.asEffect());
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
const makeModify = options => {
|
|
788
|
+
const self = Object.create(ModifyProto);
|
|
789
|
+
self.from = options.from;
|
|
790
|
+
self.value = options.value;
|
|
791
|
+
self.operation = options.operation;
|
|
792
|
+
return self;
|
|
793
|
+
};
|
|
794
|
+
const ModifyAllProto = {
|
|
795
|
+
...CommonProto,
|
|
796
|
+
asEffect() {
|
|
797
|
+
return applyModifyAll({
|
|
798
|
+
query: this,
|
|
799
|
+
values: this.values
|
|
800
|
+
});
|
|
801
|
+
},
|
|
802
|
+
invalidate(keys) {
|
|
803
|
+
keys ??= [this.from.table.tableName];
|
|
804
|
+
return this.from.reactivity.mutation(keys, this.asEffect());
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
const makeModifyAll = options => {
|
|
808
|
+
const self = Object.create(ModifyAllProto);
|
|
809
|
+
self.from = options.from;
|
|
810
|
+
self.values = options.values;
|
|
811
|
+
self.operation = options.operation;
|
|
812
|
+
return self;
|
|
813
|
+
};
|
|
814
|
+
const QueryBuilderProto = {
|
|
815
|
+
...CommonProto,
|
|
816
|
+
use(f) {
|
|
817
|
+
return Effect.try({
|
|
818
|
+
try: () => f(this.database.current),
|
|
819
|
+
catch: error => new IndexedDbQueryError({
|
|
820
|
+
reason: "UnknownError",
|
|
821
|
+
cause: error
|
|
822
|
+
})
|
|
823
|
+
});
|
|
824
|
+
},
|
|
825
|
+
from(table) {
|
|
826
|
+
return makeFrom({
|
|
827
|
+
database: this.database,
|
|
828
|
+
IDBKeyRange: this.IDBKeyRange,
|
|
829
|
+
table: this.tables.get(table),
|
|
830
|
+
reactivity: this.reactivity
|
|
831
|
+
});
|
|
832
|
+
},
|
|
833
|
+
get clearAll() {
|
|
834
|
+
const self = this;
|
|
835
|
+
return applyClearAll({
|
|
836
|
+
database: self.database.current
|
|
837
|
+
});
|
|
838
|
+
},
|
|
839
|
+
withTransaction(options) {
|
|
840
|
+
return effect => Effect.suspend(() => {
|
|
841
|
+
const transaction = this.database.current.transaction(options.tables, options.mode, options);
|
|
842
|
+
return Effect.provideService(effect, IndexedDbTransaction, transaction);
|
|
843
|
+
}).pipe(
|
|
844
|
+
// To prevent async gaps between transaction queries
|
|
845
|
+
Effect.provideService(References.PreventSchedulerYield, true));
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
/**
|
|
849
|
+
* @since 4.0.0
|
|
850
|
+
* @category constructors
|
|
851
|
+
*/
|
|
852
|
+
export const make = ({
|
|
853
|
+
IDBKeyRange,
|
|
854
|
+
database,
|
|
855
|
+
tables,
|
|
856
|
+
reactivity
|
|
857
|
+
}) => {
|
|
858
|
+
const self = Object.create(QueryBuilderProto);
|
|
859
|
+
self.tables = tables;
|
|
860
|
+
self.database = database;
|
|
861
|
+
self.reactivity = reactivity;
|
|
862
|
+
self.IDBKeyRange = IDBKeyRange;
|
|
863
|
+
return self;
|
|
864
|
+
};
|
|
865
|
+
const getOrCreateTransaction = (database, tables, mode, options) => {
|
|
866
|
+
const fiber = Fiber.getCurrent();
|
|
867
|
+
return Context.getOrUndefined(fiber.context, IndexedDbTransaction) ?? database.transaction(tables, mode, options);
|
|
868
|
+
};
|
|
869
|
+
//# sourceMappingURL=IndexedDbQueryBuilder.js.map
|