@workglow/storage 0.0.104 → 0.0.105
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/browser.js +494 -219
- package/dist/browser.js.map +12 -11
- package/dist/bun.js +595 -288
- package/dist/bun.js.map +14 -13
- package/dist/common.d.ts +1 -0
- package/dist/common.d.ts.map +1 -1
- package/dist/node.js +595 -288
- package/dist/node.js.map +14 -13
- package/dist/tabular/BaseTabularStorage.d.ts +21 -7
- package/dist/tabular/BaseTabularStorage.d.ts.map +1 -1
- package/dist/tabular/CachedTabularStorage.d.ts +14 -10
- package/dist/tabular/CachedTabularStorage.d.ts.map +1 -1
- package/dist/tabular/FsFolderTabularStorage.d.ts +6 -6
- package/dist/tabular/FsFolderTabularStorage.d.ts.map +1 -1
- package/dist/tabular/HuggingFaceTabularStorage.d.ts +11 -6
- package/dist/tabular/HuggingFaceTabularStorage.d.ts.map +1 -1
- package/dist/tabular/ITabularStorage.d.ts +22 -3
- package/dist/tabular/ITabularStorage.d.ts.map +1 -1
- package/dist/tabular/InMemoryTabularStorage.d.ts +12 -10
- package/dist/tabular/InMemoryTabularStorage.d.ts.map +1 -1
- package/dist/tabular/IndexedDbTabularStorage.d.ts +12 -10
- package/dist/tabular/IndexedDbTabularStorage.d.ts.map +1 -1
- package/dist/tabular/PostgresTabularStorage.d.ts +12 -11
- package/dist/tabular/PostgresTabularStorage.d.ts.map +1 -1
- package/dist/tabular/SharedInMemoryTabularStorage.d.ts +12 -10
- package/dist/tabular/SharedInMemoryTabularStorage.d.ts.map +1 -1
- package/dist/tabular/SqliteTabularStorage.d.ts +12 -11
- package/dist/tabular/SqliteTabularStorage.d.ts.map +1 -1
- package/dist/tabular/StorageError.d.ts +31 -0
- package/dist/tabular/StorageError.d.ts.map +1 -0
- package/dist/tabular/SupabaseTabularStorage.d.ts +12 -10
- package/dist/tabular/SupabaseTabularStorage.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/node.js
CHANGED
|
@@ -4,6 +4,58 @@ import {
|
|
|
4
4
|
EventEmitter,
|
|
5
5
|
makeFingerprint
|
|
6
6
|
} from "@workglow/util";
|
|
7
|
+
|
|
8
|
+
// src/tabular/ITabularStorage.ts
|
|
9
|
+
function isSearchCondition(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && "value" in value && "operator" in value && typeof value.operator === "string";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/tabular/StorageError.ts
|
|
14
|
+
import { BaseError } from "@workglow/util";
|
|
15
|
+
|
|
16
|
+
class StorageError extends BaseError {
|
|
17
|
+
static type = "StorageError";
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class StorageValidationError extends StorageError {
|
|
24
|
+
static type = "StorageValidationError";
|
|
25
|
+
constructor(message) {
|
|
26
|
+
super(message);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class StorageEmptyCriteriaError extends StorageValidationError {
|
|
31
|
+
static type = "StorageEmptyCriteriaError";
|
|
32
|
+
constructor() {
|
|
33
|
+
super("Query criteria must not be empty. Use getAll() to retrieve all records.");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
class StorageInvalidLimitError extends StorageValidationError {
|
|
38
|
+
static type = "StorageInvalidLimitError";
|
|
39
|
+
constructor(limit) {
|
|
40
|
+
super(`Query limit must be greater than 0, got ${limit}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
class StorageInvalidColumnError extends StorageValidationError {
|
|
45
|
+
static type = "StorageInvalidColumnError";
|
|
46
|
+
constructor(column) {
|
|
47
|
+
super(`Column "${column}" does not exist in the schema`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
class StorageUnsupportedError extends StorageError {
|
|
52
|
+
static type = "StorageUnsupportedError";
|
|
53
|
+
constructor(operation, backend) {
|
|
54
|
+
super(`${operation} is not supported for ${backend}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/tabular/BaseTabularStorage.ts
|
|
7
59
|
var TABULAR_REPOSITORY = createServiceToken("storage.tabularRepository");
|
|
8
60
|
|
|
9
61
|
class BaseTabularStorage {
|
|
@@ -162,6 +214,62 @@ class BaseTabularStorage {
|
|
|
162
214
|
subscribeToChanges(_callback, _options) {
|
|
163
215
|
throw new Error(`subscribeToChanges is not implemented for ${this.constructor.name}. ` + `All concrete repository implementations should override this method.`);
|
|
164
216
|
}
|
|
217
|
+
validateQueryParams(criteria, options) {
|
|
218
|
+
const criteriaKeys = Object.keys(criteria);
|
|
219
|
+
if (criteriaKeys.length === 0) {
|
|
220
|
+
throw new StorageEmptyCriteriaError;
|
|
221
|
+
}
|
|
222
|
+
if (options?.limit !== undefined && options.limit <= 0) {
|
|
223
|
+
throw new StorageInvalidLimitError(options.limit);
|
|
224
|
+
}
|
|
225
|
+
if (options?.offset !== undefined && options.offset < 0) {
|
|
226
|
+
throw new StorageValidationError(`Query offset must be non-negative, got ${options.offset}`);
|
|
227
|
+
}
|
|
228
|
+
for (const column of criteriaKeys) {
|
|
229
|
+
if (!(column in this.schema.properties)) {
|
|
230
|
+
throw new StorageInvalidColumnError(String(column));
|
|
231
|
+
}
|
|
232
|
+
const criterion = criteria[column];
|
|
233
|
+
if (isSearchCondition(criterion)) {
|
|
234
|
+
const validOperators = ["=", "<", "<=", ">", ">="];
|
|
235
|
+
if (!validOperators.includes(criterion.operator)) {
|
|
236
|
+
throw new StorageValidationError(`Invalid operator "${criterion.operator}". Must be one of: ${validOperators.join(", ")}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (options?.orderBy) {
|
|
241
|
+
const validDirections = ["ASC", "DESC"];
|
|
242
|
+
for (const { column, direction } of options.orderBy) {
|
|
243
|
+
if (!(column in this.schema.properties)) {
|
|
244
|
+
throw new StorageInvalidColumnError(String(column));
|
|
245
|
+
}
|
|
246
|
+
if (!validDirections.includes(direction)) {
|
|
247
|
+
throw new StorageValidationError(`Invalid sort direction "${direction}". Must be "ASC" or "DESC"`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
validateGetAllOptions(options) {
|
|
253
|
+
if (!options)
|
|
254
|
+
return;
|
|
255
|
+
if (options.limit !== undefined && options.limit <= 0) {
|
|
256
|
+
throw new StorageInvalidLimitError(options.limit);
|
|
257
|
+
}
|
|
258
|
+
if (options.offset !== undefined && options.offset < 0) {
|
|
259
|
+
throw new StorageValidationError(`Query offset must be non-negative, got ${options.offset}`);
|
|
260
|
+
}
|
|
261
|
+
if (options.orderBy) {
|
|
262
|
+
const validDirections = ["ASC", "DESC"];
|
|
263
|
+
for (const { column, direction } of options.orderBy) {
|
|
264
|
+
if (!(column in this.schema.properties)) {
|
|
265
|
+
throw new StorageInvalidColumnError(String(column));
|
|
266
|
+
}
|
|
267
|
+
if (!validDirections.includes(direction)) {
|
|
268
|
+
throw new StorageValidationError(`Invalid sort direction "${direction}". Must be "ASC" or "DESC"`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
165
273
|
primaryKeyColumns() {
|
|
166
274
|
const columns = [];
|
|
167
275
|
for (const key of Object.keys(this.primaryKeySchema.properties)) {
|
|
@@ -279,7 +387,8 @@ class BaseTabularStorage {
|
|
|
279
387
|
}
|
|
280
388
|
// src/tabular/CachedTabularStorage.ts
|
|
281
389
|
import {
|
|
282
|
-
createServiceToken as createServiceToken3
|
|
390
|
+
createServiceToken as createServiceToken3,
|
|
391
|
+
getLogger
|
|
283
392
|
} from "@workglow/util";
|
|
284
393
|
|
|
285
394
|
// src/tabular/InMemoryTabularStorage.ts
|
|
@@ -288,13 +397,6 @@ import {
|
|
|
288
397
|
makeFingerprint as makeFingerprint2,
|
|
289
398
|
uuid4
|
|
290
399
|
} from "@workglow/util";
|
|
291
|
-
|
|
292
|
-
// src/tabular/ITabularStorage.ts
|
|
293
|
-
function isSearchCondition(value) {
|
|
294
|
-
return typeof value === "object" && value !== null && "value" in value && "operator" in value && typeof value.operator === "string";
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// src/tabular/InMemoryTabularStorage.ts
|
|
298
400
|
var MEMORY_TABULAR_REPOSITORY = createServiceToken2("storage.tabularRepository.inMemory");
|
|
299
401
|
|
|
300
402
|
class InMemoryTabularStorage extends BaseTabularStorage {
|
|
@@ -348,24 +450,6 @@ class InMemoryTabularStorage extends BaseTabularStorage {
|
|
|
348
450
|
this.events.emit("get", key, out);
|
|
349
451
|
return out;
|
|
350
452
|
}
|
|
351
|
-
async search(key) {
|
|
352
|
-
const searchKeys = Object.keys(key);
|
|
353
|
-
if (searchKeys.length === 0) {
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
const bestIndex = this.findBestMatchingIndex(searchKeys);
|
|
357
|
-
if (!bestIndex) {
|
|
358
|
-
throw new Error(`No suitable index found for the search criteria, searching for ['${searchKeys.join("', '")}'] with pk ['${this.primaryKeyNames.join("', '")}'] and indexes ['${this.indexes.join("', '")}']`);
|
|
359
|
-
}
|
|
360
|
-
const results = Array.from(this.values.values()).filter((item) => Object.entries(key).every(([k, v]) => item[k] === v));
|
|
361
|
-
if (results.length > 0) {
|
|
362
|
-
this.events.emit("search", key, results);
|
|
363
|
-
return results;
|
|
364
|
-
} else {
|
|
365
|
-
this.events.emit("search", key, undefined);
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
453
|
async delete(value) {
|
|
370
454
|
const { key } = this.separateKeyValueFromCombined(value);
|
|
371
455
|
const id = await makeFingerprint2(key);
|
|
@@ -376,8 +460,34 @@ class InMemoryTabularStorage extends BaseTabularStorage {
|
|
|
376
460
|
this.values.clear();
|
|
377
461
|
this.events.emit("clearall");
|
|
378
462
|
}
|
|
379
|
-
async getAll() {
|
|
380
|
-
|
|
463
|
+
async getAll(options) {
|
|
464
|
+
this.validateGetAllOptions(options);
|
|
465
|
+
let all = Array.from(this.values.values());
|
|
466
|
+
if (options?.orderBy && options.orderBy.length > 0) {
|
|
467
|
+
all.sort((a, b) => {
|
|
468
|
+
for (const { column, direction } of options.orderBy) {
|
|
469
|
+
const aVal = a[column];
|
|
470
|
+
const bVal = b[column];
|
|
471
|
+
if (aVal == null && bVal == null)
|
|
472
|
+
continue;
|
|
473
|
+
if (aVal == null)
|
|
474
|
+
return direction === "ASC" ? -1 : 1;
|
|
475
|
+
if (bVal == null)
|
|
476
|
+
return direction === "ASC" ? 1 : -1;
|
|
477
|
+
if (aVal < bVal)
|
|
478
|
+
return direction === "ASC" ? -1 : 1;
|
|
479
|
+
if (aVal > bVal)
|
|
480
|
+
return direction === "ASC" ? 1 : -1;
|
|
481
|
+
}
|
|
482
|
+
return 0;
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
if (options?.offset !== undefined) {
|
|
486
|
+
all = all.slice(options.offset);
|
|
487
|
+
}
|
|
488
|
+
if (options?.limit !== undefined) {
|
|
489
|
+
all = all.slice(0, options.limit);
|
|
490
|
+
}
|
|
381
491
|
return all.length > 0 ? all : undefined;
|
|
382
492
|
}
|
|
383
493
|
async size() {
|
|
@@ -450,6 +560,77 @@ class InMemoryTabularStorage extends BaseTabularStorage {
|
|
|
450
560
|
this.events.emit("delete", key);
|
|
451
561
|
}
|
|
452
562
|
}
|
|
563
|
+
async query(criteria, options) {
|
|
564
|
+
this.validateQueryParams(criteria, options);
|
|
565
|
+
const criteriaKeys = Object.keys(criteria);
|
|
566
|
+
let results = Array.from(this.values.values()).filter((entity) => {
|
|
567
|
+
for (const column of criteriaKeys) {
|
|
568
|
+
const criterion = criteria[column];
|
|
569
|
+
const columnValue = entity[column];
|
|
570
|
+
if (isSearchCondition(criterion)) {
|
|
571
|
+
const { value, operator } = criterion;
|
|
572
|
+
const v = value;
|
|
573
|
+
const cv = columnValue;
|
|
574
|
+
switch (operator) {
|
|
575
|
+
case "=":
|
|
576
|
+
if (cv !== v)
|
|
577
|
+
return false;
|
|
578
|
+
break;
|
|
579
|
+
case "<":
|
|
580
|
+
if (cv === null || cv === undefined || !(cv < v))
|
|
581
|
+
return false;
|
|
582
|
+
break;
|
|
583
|
+
case "<=":
|
|
584
|
+
if (cv === null || cv === undefined || !(cv <= v))
|
|
585
|
+
return false;
|
|
586
|
+
break;
|
|
587
|
+
case ">":
|
|
588
|
+
if (cv === null || cv === undefined || !(cv > v))
|
|
589
|
+
return false;
|
|
590
|
+
break;
|
|
591
|
+
case ">=":
|
|
592
|
+
if (cv === null || cv === undefined || !(cv >= v))
|
|
593
|
+
return false;
|
|
594
|
+
break;
|
|
595
|
+
default:
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
} else {
|
|
599
|
+
if (columnValue !== criterion)
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
return true;
|
|
604
|
+
});
|
|
605
|
+
if (options?.orderBy && options.orderBy.length > 0) {
|
|
606
|
+
results.sort((a, b) => {
|
|
607
|
+
for (const { column, direction } of options.orderBy) {
|
|
608
|
+
const aVal = a[column];
|
|
609
|
+
const bVal = b[column];
|
|
610
|
+
if (aVal == null && bVal == null)
|
|
611
|
+
continue;
|
|
612
|
+
if (aVal == null)
|
|
613
|
+
return direction === "ASC" ? -1 : 1;
|
|
614
|
+
if (bVal == null)
|
|
615
|
+
return direction === "ASC" ? 1 : -1;
|
|
616
|
+
if (aVal < bVal)
|
|
617
|
+
return direction === "ASC" ? -1 : 1;
|
|
618
|
+
if (aVal > bVal)
|
|
619
|
+
return direction === "ASC" ? 1 : -1;
|
|
620
|
+
}
|
|
621
|
+
return 0;
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
if (options?.offset !== undefined) {
|
|
625
|
+
results = results.slice(options.offset);
|
|
626
|
+
}
|
|
627
|
+
if (options?.limit !== undefined) {
|
|
628
|
+
results = results.slice(0, options.limit);
|
|
629
|
+
}
|
|
630
|
+
const result = results.length > 0 ? results : undefined;
|
|
631
|
+
this.events.emit("query", criteria, result);
|
|
632
|
+
return result;
|
|
633
|
+
}
|
|
453
634
|
subscribeToChanges(callback, options) {
|
|
454
635
|
const handlePut = (entity) => {
|
|
455
636
|
callback({ type: "UPDATE", new: entity });
|
|
@@ -501,8 +682,8 @@ class CachedTabularStorage extends BaseTabularStorage {
|
|
|
501
682
|
this.cache.on("get", (key, entity) => {
|
|
502
683
|
this.events.emit("get", key, entity);
|
|
503
684
|
});
|
|
504
|
-
this.cache.on("
|
|
505
|
-
this.events.emit("
|
|
685
|
+
this.cache.on("query", (key, entities) => {
|
|
686
|
+
this.events.emit("query", key, entities);
|
|
506
687
|
});
|
|
507
688
|
this.cache.on("delete", (key) => {
|
|
508
689
|
this.events.emit("delete", key);
|
|
@@ -521,7 +702,7 @@ class CachedTabularStorage extends BaseTabularStorage {
|
|
|
521
702
|
}
|
|
522
703
|
this.cacheInitialized = true;
|
|
523
704
|
} catch (error) {
|
|
524
|
-
|
|
705
|
+
getLogger().warn("Failed to initialize cache from durable repository:", { error });
|
|
525
706
|
this.cacheInitialized = true;
|
|
526
707
|
}
|
|
527
708
|
}
|
|
@@ -548,17 +729,6 @@ class CachedTabularStorage extends BaseTabularStorage {
|
|
|
548
729
|
}
|
|
549
730
|
return result;
|
|
550
731
|
}
|
|
551
|
-
async search(key) {
|
|
552
|
-
await this.initializeCache();
|
|
553
|
-
let results = await this.cache.search(key);
|
|
554
|
-
if (results === undefined) {
|
|
555
|
-
results = await this.durable.search(key);
|
|
556
|
-
if (results && results.length > 0) {
|
|
557
|
-
await this.cache.putBulk(results);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
return results;
|
|
561
|
-
}
|
|
562
732
|
async delete(value) {
|
|
563
733
|
await this.initializeCache();
|
|
564
734
|
await this.durable.delete(value);
|
|
@@ -569,7 +739,7 @@ class CachedTabularStorage extends BaseTabularStorage {
|
|
|
569
739
|
await this.durable.deleteAll();
|
|
570
740
|
await this.cache.deleteAll();
|
|
571
741
|
}
|
|
572
|
-
async getAll() {
|
|
742
|
+
async getAll(options) {
|
|
573
743
|
await this.initializeCache();
|
|
574
744
|
let results = await this.cache.getAll();
|
|
575
745
|
if (!results || results.length === 0) {
|
|
@@ -578,6 +748,9 @@ class CachedTabularStorage extends BaseTabularStorage {
|
|
|
578
748
|
await this.cache.putBulk(results);
|
|
579
749
|
}
|
|
580
750
|
}
|
|
751
|
+
if (options && results && results.length > 0) {
|
|
752
|
+
return await this.cache.getAll(options);
|
|
753
|
+
}
|
|
581
754
|
return results;
|
|
582
755
|
}
|
|
583
756
|
async size() {
|
|
@@ -588,6 +761,10 @@ class CachedTabularStorage extends BaseTabularStorage {
|
|
|
588
761
|
await this.initializeCache();
|
|
589
762
|
return await this.durable.getBulk(offset, limit);
|
|
590
763
|
}
|
|
764
|
+
async query(criteria, options) {
|
|
765
|
+
await this.initializeCache();
|
|
766
|
+
return await this.cache.query(criteria, options);
|
|
767
|
+
}
|
|
591
768
|
async deleteSearch(criteria) {
|
|
592
769
|
await this.initializeCache();
|
|
593
770
|
await this.durable.deleteSearch(criteria);
|
|
@@ -708,7 +885,8 @@ class HuggingFaceTabularStorage extends BaseTabularStorage {
|
|
|
708
885
|
this.events.emit("get", key, undefined);
|
|
709
886
|
return;
|
|
710
887
|
}
|
|
711
|
-
async getAll() {
|
|
888
|
+
async getAll(options) {
|
|
889
|
+
this.validateGetAllOptions(options);
|
|
712
890
|
const allEntities = [];
|
|
713
891
|
let offset = 0;
|
|
714
892
|
const pageSize = 100;
|
|
@@ -723,7 +901,36 @@ class HuggingFaceTabularStorage extends BaseTabularStorage {
|
|
|
723
901
|
break;
|
|
724
902
|
}
|
|
725
903
|
}
|
|
726
|
-
|
|
904
|
+
if (allEntities.length === 0)
|
|
905
|
+
return;
|
|
906
|
+
let results = allEntities;
|
|
907
|
+
if (options?.orderBy && options.orderBy.length > 0) {
|
|
908
|
+
results = [...results];
|
|
909
|
+
results.sort((a, b) => {
|
|
910
|
+
for (const { column, direction } of options.orderBy) {
|
|
911
|
+
const aVal = a[column];
|
|
912
|
+
const bVal = b[column];
|
|
913
|
+
if (aVal == null && bVal == null)
|
|
914
|
+
continue;
|
|
915
|
+
if (aVal == null)
|
|
916
|
+
return direction === "ASC" ? -1 : 1;
|
|
917
|
+
if (bVal == null)
|
|
918
|
+
return direction === "ASC" ? 1 : -1;
|
|
919
|
+
if (aVal < bVal)
|
|
920
|
+
return direction === "ASC" ? -1 : 1;
|
|
921
|
+
if (aVal > bVal)
|
|
922
|
+
return direction === "ASC" ? 1 : -1;
|
|
923
|
+
}
|
|
924
|
+
return 0;
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
if (options?.offset !== undefined) {
|
|
928
|
+
results = results.slice(options.offset);
|
|
929
|
+
}
|
|
930
|
+
if (options?.limit !== undefined) {
|
|
931
|
+
results = results.slice(0, options.limit);
|
|
932
|
+
}
|
|
933
|
+
return results.length > 0 ? results : undefined;
|
|
727
934
|
}
|
|
728
935
|
async getBulk(offset, limit) {
|
|
729
936
|
const data = await this.fetchApi("/rows", {
|
|
@@ -739,18 +946,40 @@ class HuggingFaceTabularStorage extends BaseTabularStorage {
|
|
|
739
946
|
}
|
|
740
947
|
return entities;
|
|
741
948
|
}
|
|
742
|
-
async
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
949
|
+
async size() {
|
|
950
|
+
const data = await this.fetchApi("/size", {});
|
|
951
|
+
return data.size.num_rows;
|
|
952
|
+
}
|
|
953
|
+
async put(_value) {
|
|
954
|
+
throw new Error("HuggingFaceTabularStorage is readonly");
|
|
955
|
+
}
|
|
956
|
+
async putBulk(_values) {
|
|
957
|
+
throw new Error("HuggingFaceTabularStorage is readonly");
|
|
958
|
+
}
|
|
959
|
+
async delete(_value) {
|
|
960
|
+
throw new Error("HuggingFaceTabularStorage is readonly");
|
|
961
|
+
}
|
|
962
|
+
async deleteAll() {
|
|
963
|
+
throw new Error("HuggingFaceTabularStorage is readonly");
|
|
964
|
+
}
|
|
965
|
+
async query(criteria, options) {
|
|
966
|
+
this.validateQueryParams(criteria, options);
|
|
751
967
|
const whereConditions = [];
|
|
752
|
-
for (const [k, v] of Object.entries(
|
|
753
|
-
if (v
|
|
968
|
+
for (const [k, v] of Object.entries(criteria)) {
|
|
969
|
+
if (v === undefined || v === null)
|
|
970
|
+
continue;
|
|
971
|
+
if (isSearchCondition(v)) {
|
|
972
|
+
if (v.operator !== "=") {
|
|
973
|
+
throw new StorageUnsupportedError(`Operator "${v.operator}" in query`, "HuggingFaceTabularStorage");
|
|
974
|
+
}
|
|
975
|
+
const val = v.value;
|
|
976
|
+
if (typeof val === "string") {
|
|
977
|
+
const escaped = val.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
978
|
+
whereConditions.push(`${k}='${escaped}'`);
|
|
979
|
+
} else {
|
|
980
|
+
whereConditions.push(`${k}=${val}`);
|
|
981
|
+
}
|
|
982
|
+
} else {
|
|
754
983
|
if (typeof v === "string") {
|
|
755
984
|
const escaped = v.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
756
985
|
whereConditions.push(`${k}='${escaped}'`);
|
|
@@ -760,50 +989,60 @@ class HuggingFaceTabularStorage extends BaseTabularStorage {
|
|
|
760
989
|
}
|
|
761
990
|
}
|
|
762
991
|
if (whereConditions.length === 0) {
|
|
763
|
-
|
|
992
|
+
return;
|
|
764
993
|
}
|
|
765
994
|
const where = whereConditions.join(" AND ");
|
|
766
995
|
const allEntities = [];
|
|
767
|
-
let
|
|
768
|
-
const
|
|
996
|
+
let fetchOffset = 0;
|
|
997
|
+
const fetchLimit = 100;
|
|
769
998
|
while (true) {
|
|
770
999
|
const data = await this.fetchApi("/filter", {
|
|
771
1000
|
where,
|
|
772
|
-
offset:
|
|
773
|
-
limit:
|
|
1001
|
+
offset: fetchOffset.toString(),
|
|
1002
|
+
limit: fetchLimit.toString()
|
|
774
1003
|
});
|
|
775
1004
|
for (const row of data.rows) {
|
|
776
1005
|
allEntities.push(this.rowToEntity(row));
|
|
777
1006
|
}
|
|
778
|
-
|
|
779
|
-
if (
|
|
1007
|
+
fetchOffset += data.rows.length;
|
|
1008
|
+
if (fetchOffset >= data.num_rows_total || data.rows.length < fetchLimit) {
|
|
780
1009
|
break;
|
|
781
1010
|
}
|
|
782
1011
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
1012
|
+
let results = allEntities;
|
|
1013
|
+
if (options?.orderBy && options.orderBy.length > 0) {
|
|
1014
|
+
results.sort((a, b) => {
|
|
1015
|
+
for (const { column, direction } of options.orderBy) {
|
|
1016
|
+
const aVal = a[column];
|
|
1017
|
+
const bVal = b[column];
|
|
1018
|
+
if (aVal == null && bVal == null)
|
|
1019
|
+
continue;
|
|
1020
|
+
if (aVal == null)
|
|
1021
|
+
return direction === "ASC" ? -1 : 1;
|
|
1022
|
+
if (bVal == null)
|
|
1023
|
+
return direction === "ASC" ? 1 : -1;
|
|
1024
|
+
if (aVal < bVal)
|
|
1025
|
+
return direction === "ASC" ? -1 : 1;
|
|
1026
|
+
if (aVal > bVal)
|
|
1027
|
+
return direction === "ASC" ? 1 : -1;
|
|
1028
|
+
}
|
|
1029
|
+
return 0;
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
if (options?.offset !== undefined) {
|
|
1033
|
+
results = results.slice(options.offset);
|
|
1034
|
+
}
|
|
1035
|
+
if (options?.limit !== undefined) {
|
|
1036
|
+
results = results.slice(0, options.limit);
|
|
1037
|
+
}
|
|
1038
|
+
if (results.length > 0) {
|
|
1039
|
+
this.events.emit("query", criteria, results);
|
|
1040
|
+
return results;
|
|
786
1041
|
} else {
|
|
787
|
-
this.events.emit("
|
|
1042
|
+
this.events.emit("query", criteria, undefined);
|
|
788
1043
|
return;
|
|
789
1044
|
}
|
|
790
1045
|
}
|
|
791
|
-
async size() {
|
|
792
|
-
const data = await this.fetchApi("/size", {});
|
|
793
|
-
return data.size.num_rows;
|
|
794
|
-
}
|
|
795
|
-
async put(_value) {
|
|
796
|
-
throw new Error("HuggingFaceTabularStorage is readonly");
|
|
797
|
-
}
|
|
798
|
-
async putBulk(_values) {
|
|
799
|
-
throw new Error("HuggingFaceTabularStorage is readonly");
|
|
800
|
-
}
|
|
801
|
-
async delete(_value) {
|
|
802
|
-
throw new Error("HuggingFaceTabularStorage is readonly");
|
|
803
|
-
}
|
|
804
|
-
async deleteAll() {
|
|
805
|
-
throw new Error("HuggingFaceTabularStorage is readonly");
|
|
806
|
-
}
|
|
807
1046
|
async deleteSearch(_criteria) {
|
|
808
1047
|
throw new Error("HuggingFaceTabularStorage is readonly");
|
|
809
1048
|
}
|
|
@@ -1034,7 +1273,7 @@ class InMemoryKvStorage extends KvViaTabularStorage {
|
|
|
1034
1273
|
import {
|
|
1035
1274
|
createServiceToken as createServiceToken9,
|
|
1036
1275
|
EventEmitter as EventEmitter3,
|
|
1037
|
-
getLogger,
|
|
1276
|
+
getLogger as getLogger2,
|
|
1038
1277
|
makeFingerprint as makeFingerprint4,
|
|
1039
1278
|
sleep,
|
|
1040
1279
|
uuid4 as uuid42
|
|
@@ -1133,7 +1372,7 @@ class InMemoryQueueStorage {
|
|
|
1133
1372
|
const job = this.jobQueue.find((j) => j.id === id && this.matchesPrefixes(j));
|
|
1134
1373
|
if (!job) {
|
|
1135
1374
|
const jobWithAnyPrefix = this.jobQueue.find((j) => j.id === id);
|
|
1136
|
-
|
|
1375
|
+
getLogger2().warn("Job not found for progress update", {
|
|
1137
1376
|
id,
|
|
1138
1377
|
reason: jobWithAnyPrefix ? "prefix_mismatch" : "missing",
|
|
1139
1378
|
existingStatus: jobWithAnyPrefix?.status,
|
|
@@ -1143,7 +1382,7 @@ class InMemoryQueueStorage {
|
|
|
1143
1382
|
return;
|
|
1144
1383
|
}
|
|
1145
1384
|
if (job.status === JobStatus.COMPLETED || job.status === JobStatus.FAILED) {
|
|
1146
|
-
|
|
1385
|
+
getLogger2().warn("Job already completed or failed for progress update", {
|
|
1147
1386
|
id,
|
|
1148
1387
|
status: job.status,
|
|
1149
1388
|
completedAt: job.completed_at,
|
|
@@ -1929,15 +2168,15 @@ class FsFolderTabularStorage extends BaseTabularStorage {
|
|
|
1929
2168
|
const page = allEntities.slice(offset, offset + limit);
|
|
1930
2169
|
return page.length > 0 ? page : undefined;
|
|
1931
2170
|
}
|
|
1932
|
-
async search(key) {
|
|
1933
|
-
throw new Error("Search not supported for FsFolderTabularStorage");
|
|
1934
|
-
}
|
|
1935
2171
|
async getFilePath(value) {
|
|
1936
2172
|
const { key } = this.separateKeyValueFromCombined(value);
|
|
1937
2173
|
const filename = await this.getKeyAsIdString(key);
|
|
1938
2174
|
const fullPath = path.join(this.folderPath, `${filename}.json`);
|
|
1939
2175
|
return fullPath;
|
|
1940
2176
|
}
|
|
2177
|
+
async query(_criteria, _options) {
|
|
2178
|
+
throw new StorageUnsupportedError("query", "FsFolderTabularStorage");
|
|
2179
|
+
}
|
|
1941
2180
|
async deleteSearch(_criteria) {
|
|
1942
2181
|
throw new Error("deleteSearch is not supported for FsFolderTabularStorage");
|
|
1943
2182
|
}
|
|
@@ -2525,39 +2764,6 @@ class PostgresTabularStorage extends BaseSqlTabularStorage {
|
|
|
2525
2764
|
this.events.emit("get", key, val);
|
|
2526
2765
|
return val;
|
|
2527
2766
|
}
|
|
2528
|
-
async search(key) {
|
|
2529
|
-
const db = this.db;
|
|
2530
|
-
const searchKeys = Object.keys(key);
|
|
2531
|
-
if (searchKeys.length === 0) {
|
|
2532
|
-
return;
|
|
2533
|
-
}
|
|
2534
|
-
const bestIndex = this.findBestMatchingIndex(searchKeys);
|
|
2535
|
-
if (!bestIndex) {
|
|
2536
|
-
throw new Error(`No suitable index found for the search criteria, searching for ['${searchKeys.join("', '")}'] with pk ['${this.primaryKeyNames.join("', '")}'] and indexes ['${this.indexes.join("', '")}']`);
|
|
2537
|
-
}
|
|
2538
|
-
const validColumns = [...this.primaryKeyColumns(), ...this.valueColumns()];
|
|
2539
|
-
const invalidColumns = searchKeys.filter((key2) => !validColumns.includes(key2));
|
|
2540
|
-
if (invalidColumns.length > 0) {
|
|
2541
|
-
throw new Error(`Invalid columns in search criteria: ${invalidColumns.join(", ")}`);
|
|
2542
|
-
}
|
|
2543
|
-
const whereClauses = Object.keys(key).map((key2, i) => `"${key2}" = $${i + 1}`).join(" AND ");
|
|
2544
|
-
const whereClauseValues = Object.entries(key).map(([k, v]) => this.jsToSqlValue(k, v));
|
|
2545
|
-
const sql = `SELECT * FROM "${this.table}" WHERE ${whereClauses}`;
|
|
2546
|
-
const result = await db.query(sql, whereClauseValues);
|
|
2547
|
-
if (result.rows.length > 0) {
|
|
2548
|
-
for (const row of result.rows) {
|
|
2549
|
-
const record = row;
|
|
2550
|
-
for (const k in this.schema.properties) {
|
|
2551
|
-
record[k] = this.sqlToJsValue(k, record[k]);
|
|
2552
|
-
}
|
|
2553
|
-
}
|
|
2554
|
-
this.events.emit("search", key, result.rows);
|
|
2555
|
-
return result.rows;
|
|
2556
|
-
} else {
|
|
2557
|
-
this.events.emit("search", key, undefined);
|
|
2558
|
-
return;
|
|
2559
|
-
}
|
|
2560
|
-
}
|
|
2561
2767
|
async delete(value) {
|
|
2562
2768
|
const db = this.db;
|
|
2563
2769
|
const { key } = this.separateKeyValueFromCombined(value);
|
|
@@ -2566,10 +2772,24 @@ class PostgresTabularStorage extends BaseSqlTabularStorage {
|
|
|
2566
2772
|
await db.query(`DELETE FROM "${this.table}" WHERE ${whereClauses}`, params);
|
|
2567
2773
|
this.events.emit("delete", key);
|
|
2568
2774
|
}
|
|
2569
|
-
async getAll() {
|
|
2775
|
+
async getAll(options) {
|
|
2776
|
+
this.validateGetAllOptions(options);
|
|
2570
2777
|
const db = this.db;
|
|
2571
|
-
|
|
2572
|
-
const
|
|
2778
|
+
let sql = `SELECT * FROM "${this.table}"`;
|
|
2779
|
+
const params = [];
|
|
2780
|
+
if (options?.orderBy && options.orderBy.length > 0) {
|
|
2781
|
+
const orderClauses = options.orderBy.map((o) => `"${String(o.column)}" ${o.direction}`);
|
|
2782
|
+
sql += ` ORDER BY ${orderClauses.join(", ")}`;
|
|
2783
|
+
}
|
|
2784
|
+
if (options?.limit !== undefined) {
|
|
2785
|
+
sql += ` LIMIT $${params.length + 1}`;
|
|
2786
|
+
params.push(options.limit);
|
|
2787
|
+
}
|
|
2788
|
+
if (options?.offset !== undefined) {
|
|
2789
|
+
sql += ` OFFSET $${params.length + 1}`;
|
|
2790
|
+
params.push(options.offset);
|
|
2791
|
+
}
|
|
2792
|
+
const result = params.length > 0 ? await db.query(sql, params) : await db.query(sql);
|
|
2573
2793
|
if (result.rows.length > 0) {
|
|
2574
2794
|
for (const row of result.rows) {
|
|
2575
2795
|
const record = row;
|
|
@@ -2642,6 +2862,38 @@ class PostgresTabularStorage extends BaseSqlTabularStorage {
|
|
|
2642
2862
|
await db.query(`DELETE FROM "${this.table}" WHERE ${whereClause}`, params);
|
|
2643
2863
|
this.events.emit("delete", criteriaKeys[0]);
|
|
2644
2864
|
}
|
|
2865
|
+
async query(criteria, options) {
|
|
2866
|
+
this.validateQueryParams(criteria, options);
|
|
2867
|
+
const db = this.db;
|
|
2868
|
+
let sql = `SELECT * FROM "${this.table}"`;
|
|
2869
|
+
const { whereClause, params } = this.buildDeleteSearchWhere(criteria);
|
|
2870
|
+
sql += ` WHERE ${whereClause}`;
|
|
2871
|
+
if (options?.orderBy && options.orderBy.length > 0) {
|
|
2872
|
+
const orderClauses = options.orderBy.map((o) => `"${String(o.column)}" ${o.direction}`);
|
|
2873
|
+
sql += ` ORDER BY ${orderClauses.join(", ")}`;
|
|
2874
|
+
}
|
|
2875
|
+
if (options?.limit !== undefined) {
|
|
2876
|
+
sql += ` LIMIT $${params.length + 1}`;
|
|
2877
|
+
params.push(options.limit);
|
|
2878
|
+
}
|
|
2879
|
+
if (options?.offset !== undefined) {
|
|
2880
|
+
sql += ` OFFSET $${params.length + 1}`;
|
|
2881
|
+
params.push(options.offset);
|
|
2882
|
+
}
|
|
2883
|
+
const result = await db.query(sql, params);
|
|
2884
|
+
if (result.rows.length > 0) {
|
|
2885
|
+
for (const row of result.rows) {
|
|
2886
|
+
const record = row;
|
|
2887
|
+
for (const k in this.schema.properties) {
|
|
2888
|
+
record[k] = this.sqlToJsValue(k, record[k]);
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
this.events.emit("query", criteria, result.rows);
|
|
2892
|
+
return result.rows;
|
|
2893
|
+
}
|
|
2894
|
+
this.events.emit("query", criteria, undefined);
|
|
2895
|
+
return;
|
|
2896
|
+
}
|
|
2645
2897
|
subscribeToChanges(callback, options) {
|
|
2646
2898
|
throw new Error("subscribeToChanges is not supported for PostgresTabularStorage");
|
|
2647
2899
|
}
|
|
@@ -2974,40 +3226,6 @@ class SqliteTabularStorage extends BaseSqlTabularStorage {
|
|
|
2974
3226
|
return;
|
|
2975
3227
|
}
|
|
2976
3228
|
}
|
|
2977
|
-
async search(key) {
|
|
2978
|
-
const db = this.db;
|
|
2979
|
-
const searchKeys = Object.keys(key);
|
|
2980
|
-
if (searchKeys.length === 0) {
|
|
2981
|
-
return;
|
|
2982
|
-
}
|
|
2983
|
-
const bestIndex = super.findBestMatchingIndex(searchKeys);
|
|
2984
|
-
if (!bestIndex) {
|
|
2985
|
-
throw new Error(`No suitable index found for the search criteria, searching for ['${searchKeys.join("', '")}'] with pk ['${this.primaryKeyNames.join("', '")}'] and indexes ['${this.indexes.join("', '")}']`);
|
|
2986
|
-
}
|
|
2987
|
-
const validColumns = [...this.primaryKeyColumns(), ...this.valueColumns()];
|
|
2988
|
-
const invalidColumns = searchKeys.filter((key2) => !validColumns.includes(key2));
|
|
2989
|
-
if (invalidColumns.length > 0) {
|
|
2990
|
-
throw new Error(`Invalid columns in search criteria: ${invalidColumns.join(", ")}`);
|
|
2991
|
-
}
|
|
2992
|
-
const whereClauses = Object.keys(key).map((key2, i) => `"${key2}" = ?`).join(" AND ");
|
|
2993
|
-
const whereClauseValues = Object.entries(key).map(([k, v]) => this.jsToSqlValue(k, v));
|
|
2994
|
-
const sql = `SELECT * FROM \`${this.table}\` WHERE ${whereClauses}`;
|
|
2995
|
-
const stmt = db.prepare(sql);
|
|
2996
|
-
const result = stmt.all(...whereClauseValues);
|
|
2997
|
-
if (result.length > 0) {
|
|
2998
|
-
for (const row of result) {
|
|
2999
|
-
const record = row;
|
|
3000
|
-
for (const k in this.schema.properties) {
|
|
3001
|
-
record[k] = this.sqlToJsValue(k, record[k]);
|
|
3002
|
-
}
|
|
3003
|
-
}
|
|
3004
|
-
this.events.emit("search", key, result);
|
|
3005
|
-
return result;
|
|
3006
|
-
} else {
|
|
3007
|
-
this.events.emit("search", key, undefined);
|
|
3008
|
-
return;
|
|
3009
|
-
}
|
|
3010
|
-
}
|
|
3011
3229
|
async delete(key) {
|
|
3012
3230
|
const db = this.db;
|
|
3013
3231
|
const whereClauses = this.primaryKeyColumns().map((key2) => `${key2} = ?`).join(" AND ");
|
|
@@ -3016,11 +3234,28 @@ class SqliteTabularStorage extends BaseSqlTabularStorage {
|
|
|
3016
3234
|
stmt.run(...params);
|
|
3017
3235
|
this.events.emit("delete", key);
|
|
3018
3236
|
}
|
|
3019
|
-
async getAll() {
|
|
3237
|
+
async getAll(options) {
|
|
3238
|
+
this.validateGetAllOptions(options);
|
|
3020
3239
|
const db = this.db;
|
|
3021
|
-
|
|
3240
|
+
let sql = `SELECT * FROM \`${this.table}\``;
|
|
3241
|
+
const params = [];
|
|
3242
|
+
if (options?.orderBy && options.orderBy.length > 0) {
|
|
3243
|
+
const orderClauses = options.orderBy.map((o) => `\`${String(o.column)}\` ${o.direction}`);
|
|
3244
|
+
sql += ` ORDER BY ${orderClauses.join(", ")}`;
|
|
3245
|
+
}
|
|
3246
|
+
if (options?.limit !== undefined) {
|
|
3247
|
+
sql += ` LIMIT ?`;
|
|
3248
|
+
params.push(options.limit);
|
|
3249
|
+
}
|
|
3250
|
+
if (options?.offset !== undefined) {
|
|
3251
|
+
if (options.limit === undefined) {
|
|
3252
|
+
sql += ` LIMIT -1`;
|
|
3253
|
+
}
|
|
3254
|
+
sql += ` OFFSET ?`;
|
|
3255
|
+
params.push(options.offset);
|
|
3256
|
+
}
|
|
3022
3257
|
const stmt = db.prepare(sql);
|
|
3023
|
-
const value = stmt.all();
|
|
3258
|
+
const value = params.length > 0 ? stmt.all(...params) : stmt.all();
|
|
3024
3259
|
if (!value.length)
|
|
3025
3260
|
return;
|
|
3026
3261
|
for (const row of value) {
|
|
@@ -3096,6 +3331,42 @@ class SqliteTabularStorage extends BaseSqlTabularStorage {
|
|
|
3096
3331
|
stmt.run(...params);
|
|
3097
3332
|
this.events.emit("delete", criteriaKeys[0]);
|
|
3098
3333
|
}
|
|
3334
|
+
async query(criteria, options) {
|
|
3335
|
+
this.validateQueryParams(criteria, options);
|
|
3336
|
+
const db = this.db;
|
|
3337
|
+
let sql = `SELECT * FROM \`${this.table}\``;
|
|
3338
|
+
const { whereClause, params } = this.buildDeleteSearchWhere(criteria);
|
|
3339
|
+
sql += ` WHERE ${whereClause}`;
|
|
3340
|
+
if (options?.orderBy && options.orderBy.length > 0) {
|
|
3341
|
+
const orderClauses = options.orderBy.map((o) => `\`${String(o.column)}\` ${o.direction}`);
|
|
3342
|
+
sql += ` ORDER BY ${orderClauses.join(", ")}`;
|
|
3343
|
+
}
|
|
3344
|
+
if (options?.limit !== undefined) {
|
|
3345
|
+
sql += ` LIMIT ?`;
|
|
3346
|
+
params.push(options.limit);
|
|
3347
|
+
}
|
|
3348
|
+
if (options?.offset !== undefined) {
|
|
3349
|
+
if (options.limit === undefined) {
|
|
3350
|
+
sql += ` LIMIT -1`;
|
|
3351
|
+
}
|
|
3352
|
+
sql += ` OFFSET ?`;
|
|
3353
|
+
params.push(options.offset);
|
|
3354
|
+
}
|
|
3355
|
+
const stmt = db.prepare(sql);
|
|
3356
|
+
const result = stmt.all(...params);
|
|
3357
|
+
if (result.length > 0) {
|
|
3358
|
+
for (const row of result) {
|
|
3359
|
+
const record = row;
|
|
3360
|
+
for (const k in this.schema.properties) {
|
|
3361
|
+
record[k] = this.sqlToJsValue(k, record[k]);
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3364
|
+
this.events.emit("query", criteria, result);
|
|
3365
|
+
return result;
|
|
3366
|
+
}
|
|
3367
|
+
this.events.emit("query", criteria, undefined);
|
|
3368
|
+
return;
|
|
3369
|
+
}
|
|
3099
3370
|
subscribeToChanges(callback, options) {
|
|
3100
3371
|
throw new Error("subscribeToChanges is not supported for SqliteTabularStorage");
|
|
3101
3372
|
}
|
|
@@ -3379,41 +3650,6 @@ class SupabaseTabularStorage extends BaseSqlTabularStorage {
|
|
|
3379
3650
|
this.events.emit("get", key, val);
|
|
3380
3651
|
return val;
|
|
3381
3652
|
}
|
|
3382
|
-
async search(searchCriteria) {
|
|
3383
|
-
const searchKeys = Object.keys(searchCriteria);
|
|
3384
|
-
if (searchKeys.length === 0) {
|
|
3385
|
-
return;
|
|
3386
|
-
}
|
|
3387
|
-
const bestIndex = this.findBestMatchingIndex(searchKeys);
|
|
3388
|
-
if (!bestIndex) {
|
|
3389
|
-
throw new Error(`No suitable index found for the search criteria, searching for ['${searchKeys.join("', '")}'] with pk ['${this.primaryKeyNames.join("', '")}'] and indexes ['${this.indexes.join("', '")}']`);
|
|
3390
|
-
}
|
|
3391
|
-
const validColumns = [...this.primaryKeyColumns(), ...this.valueColumns()];
|
|
3392
|
-
const invalidColumns = searchKeys.filter((key) => !validColumns.includes(key));
|
|
3393
|
-
if (invalidColumns.length > 0) {
|
|
3394
|
-
throw new Error(`Invalid columns in search criteria: ${invalidColumns.join(", ")}`);
|
|
3395
|
-
}
|
|
3396
|
-
let query = this.client.from(this.table).select("*");
|
|
3397
|
-
for (const [key, value] of Object.entries(searchCriteria)) {
|
|
3398
|
-
query = query.eq(key, value);
|
|
3399
|
-
}
|
|
3400
|
-
const { data, error } = await query;
|
|
3401
|
-
if (error)
|
|
3402
|
-
throw error;
|
|
3403
|
-
if (data && data.length > 0) {
|
|
3404
|
-
for (const row of data) {
|
|
3405
|
-
const record = row;
|
|
3406
|
-
for (const key in this.schema.properties) {
|
|
3407
|
-
record[key] = this.sqlToJsValue(key, record[key]);
|
|
3408
|
-
}
|
|
3409
|
-
}
|
|
3410
|
-
this.events.emit("search", searchCriteria, data);
|
|
3411
|
-
return data;
|
|
3412
|
-
} else {
|
|
3413
|
-
this.events.emit("search", searchCriteria, undefined);
|
|
3414
|
-
return;
|
|
3415
|
-
}
|
|
3416
|
-
}
|
|
3417
3653
|
async delete(value) {
|
|
3418
3654
|
const { key } = this.separateKeyValueFromCombined(value);
|
|
3419
3655
|
let query = this.client.from(this.table).delete();
|
|
@@ -3426,8 +3662,23 @@ class SupabaseTabularStorage extends BaseSqlTabularStorage {
|
|
|
3426
3662
|
throw error;
|
|
3427
3663
|
this.events.emit("delete", key);
|
|
3428
3664
|
}
|
|
3429
|
-
async getAll() {
|
|
3430
|
-
|
|
3665
|
+
async getAll(options) {
|
|
3666
|
+
this.validateGetAllOptions(options);
|
|
3667
|
+
let query = this.client.from(this.table).select("*");
|
|
3668
|
+
if (options?.orderBy) {
|
|
3669
|
+
for (const { column, direction } of options.orderBy) {
|
|
3670
|
+
query = query.order(String(column), { ascending: direction === "ASC" });
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
if (options?.offset !== undefined || options?.limit !== undefined) {
|
|
3674
|
+
const start = options?.offset ?? 0;
|
|
3675
|
+
if (options?.limit !== undefined) {
|
|
3676
|
+
query = query.range(start, start + options.limit - 1);
|
|
3677
|
+
} else if (options?.offset !== undefined) {
|
|
3678
|
+
query = query.range(start, start + 999999);
|
|
3679
|
+
}
|
|
3680
|
+
}
|
|
3681
|
+
const { data, error } = await query;
|
|
3431
3682
|
if (error)
|
|
3432
3683
|
throw error;
|
|
3433
3684
|
if (data && data.length) {
|
|
@@ -3515,6 +3766,69 @@ class SupabaseTabularStorage extends BaseSqlTabularStorage {
|
|
|
3515
3766
|
throw error;
|
|
3516
3767
|
this.events.emit("delete", criteriaKeys[0]);
|
|
3517
3768
|
}
|
|
3769
|
+
async query(criteria, options) {
|
|
3770
|
+
this.validateQueryParams(criteria, options);
|
|
3771
|
+
const criteriaKeys = Object.keys(criteria);
|
|
3772
|
+
let query = this.client.from(this.table).select("*");
|
|
3773
|
+
for (const column of criteriaKeys) {
|
|
3774
|
+
const criterion = criteria[column];
|
|
3775
|
+
let operator = "=";
|
|
3776
|
+
let value;
|
|
3777
|
+
if (isSearchCondition(criterion)) {
|
|
3778
|
+
operator = criterion.operator;
|
|
3779
|
+
value = criterion.value;
|
|
3780
|
+
} else {
|
|
3781
|
+
value = criterion;
|
|
3782
|
+
}
|
|
3783
|
+
switch (operator) {
|
|
3784
|
+
case "=":
|
|
3785
|
+
query = query.eq(String(column), value);
|
|
3786
|
+
break;
|
|
3787
|
+
case "<":
|
|
3788
|
+
query = query.lt(String(column), value);
|
|
3789
|
+
break;
|
|
3790
|
+
case "<=":
|
|
3791
|
+
query = query.lte(String(column), value);
|
|
3792
|
+
break;
|
|
3793
|
+
case ">":
|
|
3794
|
+
query = query.gt(String(column), value);
|
|
3795
|
+
break;
|
|
3796
|
+
case ">=":
|
|
3797
|
+
query = query.gte(String(column), value);
|
|
3798
|
+
break;
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
if (options?.orderBy) {
|
|
3802
|
+
for (const { column, direction } of options.orderBy) {
|
|
3803
|
+
query = query.order(String(column), { ascending: direction === "ASC" });
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
if (options?.offset !== undefined || options?.limit !== undefined) {
|
|
3807
|
+
const start = options?.offset ?? 0;
|
|
3808
|
+
if (options?.limit !== undefined) {
|
|
3809
|
+
query = query.range(start, start + options.limit - 1);
|
|
3810
|
+
} else if (options?.offset !== undefined) {
|
|
3811
|
+
query = query.range(start, start + 999999);
|
|
3812
|
+
}
|
|
3813
|
+
} else if (options?.limit !== undefined) {
|
|
3814
|
+
query = query.limit(options.limit);
|
|
3815
|
+
}
|
|
3816
|
+
const { data, error } = await query;
|
|
3817
|
+
if (error)
|
|
3818
|
+
throw error;
|
|
3819
|
+
if (data && data.length > 0) {
|
|
3820
|
+
for (const row of data) {
|
|
3821
|
+
const record = row;
|
|
3822
|
+
for (const key in this.schema.properties) {
|
|
3823
|
+
record[key] = this.sqlToJsValue(key, record[key]);
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
this.events.emit("query", criteria, data);
|
|
3827
|
+
return data;
|
|
3828
|
+
}
|
|
3829
|
+
this.events.emit("query", criteria, undefined);
|
|
3830
|
+
return;
|
|
3831
|
+
}
|
|
3518
3832
|
convertRealtimeRow(row) {
|
|
3519
3833
|
const entity = { ...row };
|
|
3520
3834
|
const record = entity;
|
|
@@ -6079,7 +6393,8 @@ class IndexedDbTabularStorage extends BaseTabularStorage {
|
|
|
6079
6393
|
};
|
|
6080
6394
|
});
|
|
6081
6395
|
}
|
|
6082
|
-
async getAll() {
|
|
6396
|
+
async getAll(options) {
|
|
6397
|
+
this.validateGetAllOptions(options);
|
|
6083
6398
|
const db = await this.getDb();
|
|
6084
6399
|
const transaction = db.transaction(this.table, "readonly");
|
|
6085
6400
|
const store = transaction.objectStore(this.table);
|
|
@@ -6087,96 +6402,38 @@ class IndexedDbTabularStorage extends BaseTabularStorage {
|
|
|
6087
6402
|
return new Promise((resolve, reject) => {
|
|
6088
6403
|
request.onerror = () => reject(request.error);
|
|
6089
6404
|
request.onsuccess = () => {
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
}
|
|
6095
|
-
async search(key) {
|
|
6096
|
-
const db = await this.getDb();
|
|
6097
|
-
const searchKeys = Object.keys(key);
|
|
6098
|
-
if (searchKeys.length === 0) {
|
|
6099
|
-
return;
|
|
6100
|
-
}
|
|
6101
|
-
const bestIndex = this.findBestMatchingIndex(searchKeys);
|
|
6102
|
-
if (!bestIndex) {
|
|
6103
|
-
throw new Error("No suitable index found for the search criteria");
|
|
6104
|
-
}
|
|
6105
|
-
return new Promise((resolve, reject) => {
|
|
6106
|
-
const transaction = db.transaction(this.table, "readonly");
|
|
6107
|
-
const store = transaction.objectStore(this.table);
|
|
6108
|
-
const indexName = bestIndex.join("_");
|
|
6109
|
-
const primaryKeyName = this.primaryKeyColumns().join("_");
|
|
6110
|
-
const isPrimaryKey = indexName === primaryKeyName;
|
|
6111
|
-
const indexValues = [];
|
|
6112
|
-
for (const col of bestIndex) {
|
|
6113
|
-
const val = key[col];
|
|
6114
|
-
if (val === undefined)
|
|
6115
|
-
break;
|
|
6116
|
-
if (typeof val !== "string" && typeof val !== "number") {
|
|
6117
|
-
throw new Error(`Invalid value type for indexed column ${String(col)}`);
|
|
6405
|
+
let values = request.result;
|
|
6406
|
+
if (values.length === 0) {
|
|
6407
|
+
resolve(undefined);
|
|
6408
|
+
return;
|
|
6118
6409
|
}
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6410
|
+
if (options?.orderBy && options.orderBy.length > 0) {
|
|
6411
|
+
values.sort((a, b) => {
|
|
6412
|
+
for (const { column, direction } of options.orderBy) {
|
|
6413
|
+
const aVal = a[column];
|
|
6414
|
+
const bVal = b[column];
|
|
6415
|
+
if (aVal == null && bVal == null)
|
|
6416
|
+
continue;
|
|
6417
|
+
if (aVal == null)
|
|
6418
|
+
return direction === "ASC" ? -1 : 1;
|
|
6419
|
+
if (bVal == null)
|
|
6420
|
+
return direction === "ASC" ? 1 : -1;
|
|
6421
|
+
if (aVal < bVal)
|
|
6422
|
+
return direction === "ASC" ? -1 : 1;
|
|
6423
|
+
if (aVal > bVal)
|
|
6424
|
+
return direction === "ASC" ? 1 : -1;
|
|
6425
|
+
}
|
|
6426
|
+
return 0;
|
|
6128
6427
|
});
|
|
6129
|
-
if (allColumnsRequired) {
|
|
6130
|
-
const results = [];
|
|
6131
|
-
const keyRange = IDBKeyRange.lowerBound(indexValues);
|
|
6132
|
-
const cursorRequest = index.openCursor(keyRange);
|
|
6133
|
-
cursorRequest.onsuccess = () => {
|
|
6134
|
-
const cursor = cursorRequest.result;
|
|
6135
|
-
if (cursor) {
|
|
6136
|
-
const item = cursor.value;
|
|
6137
|
-
const cursorKey = Array.isArray(cursor.key) ? cursor.key : [cursor.key];
|
|
6138
|
-
const prefixMatches = indexValues.every((val, idx) => cursorKey[idx] === val);
|
|
6139
|
-
if (!prefixMatches) {
|
|
6140
|
-
resolve(results.length > 0 ? results : undefined);
|
|
6141
|
-
return;
|
|
6142
|
-
}
|
|
6143
|
-
const matches = Object.entries(key).every(([k, v]) => item[k] === v);
|
|
6144
|
-
if (matches) {
|
|
6145
|
-
results.push(item);
|
|
6146
|
-
}
|
|
6147
|
-
cursor.continue();
|
|
6148
|
-
} else {
|
|
6149
|
-
resolve(results.length > 0 ? results : undefined);
|
|
6150
|
-
}
|
|
6151
|
-
};
|
|
6152
|
-
cursorRequest.onerror = () => {
|
|
6153
|
-
reject(cursorRequest.error);
|
|
6154
|
-
};
|
|
6155
|
-
} else {
|
|
6156
|
-
const getAllRequest = store.getAll();
|
|
6157
|
-
getAllRequest.onsuccess = () => {
|
|
6158
|
-
const allRecords = getAllRequest.result;
|
|
6159
|
-
const results = allRecords.filter((item) => Object.entries(key).every(([k, v]) => item[k] === v));
|
|
6160
|
-
resolve(results.length > 0 ? results : undefined);
|
|
6161
|
-
};
|
|
6162
|
-
getAllRequest.onerror = () => {
|
|
6163
|
-
reject(getAllRequest.error);
|
|
6164
|
-
};
|
|
6165
|
-
}
|
|
6166
|
-
} else {
|
|
6167
|
-
const request = index.getAll(indexValues.length === 1 ? indexValues[0] : indexValues);
|
|
6168
|
-
request.onsuccess = () => {
|
|
6169
|
-
const results = request.result.filter((item) => Object.entries(key).every(([k, v]) => item[k] === v));
|
|
6170
|
-
resolve(results.length > 0 ? results : undefined);
|
|
6171
|
-
};
|
|
6172
|
-
request.onerror = () => {
|
|
6173
|
-
console.error("Search error:", request.error);
|
|
6174
|
-
reject(request.error);
|
|
6175
|
-
};
|
|
6176
6428
|
}
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6429
|
+
if (options?.offset !== undefined) {
|
|
6430
|
+
values = values.slice(options.offset);
|
|
6431
|
+
}
|
|
6432
|
+
if (options?.limit !== undefined) {
|
|
6433
|
+
values = values.slice(0, options.limit);
|
|
6434
|
+
}
|
|
6435
|
+
resolve(values.length > 0 ? values : undefined);
|
|
6436
|
+
};
|
|
6180
6437
|
});
|
|
6181
6438
|
}
|
|
6182
6439
|
async delete(key) {
|
|
@@ -6342,6 +6599,50 @@ class IndexedDbTabularStorage extends BaseTabularStorage {
|
|
|
6342
6599
|
}
|
|
6343
6600
|
});
|
|
6344
6601
|
}
|
|
6602
|
+
async query(criteria, options) {
|
|
6603
|
+
this.validateQueryParams(criteria, options);
|
|
6604
|
+
const db = await this.getDb();
|
|
6605
|
+
return new Promise((resolve, reject) => {
|
|
6606
|
+
const transaction = db.transaction(this.table, "readonly");
|
|
6607
|
+
const store = transaction.objectStore(this.table);
|
|
6608
|
+
const getAllRequest = store.getAll();
|
|
6609
|
+
getAllRequest.onsuccess = () => {
|
|
6610
|
+
const allRecords = getAllRequest.result;
|
|
6611
|
+
let results = allRecords.filter((record) => this.matchesCriteria(record, criteria));
|
|
6612
|
+
if (options?.orderBy && options.orderBy.length > 0) {
|
|
6613
|
+
results.sort((a, b) => {
|
|
6614
|
+
for (const { column, direction } of options.orderBy) {
|
|
6615
|
+
const aVal = a[column];
|
|
6616
|
+
const bVal = b[column];
|
|
6617
|
+
if (aVal == null && bVal == null)
|
|
6618
|
+
continue;
|
|
6619
|
+
if (aVal == null)
|
|
6620
|
+
return direction === "ASC" ? -1 : 1;
|
|
6621
|
+
if (bVal == null)
|
|
6622
|
+
return direction === "ASC" ? 1 : -1;
|
|
6623
|
+
if (aVal < bVal)
|
|
6624
|
+
return direction === "ASC" ? -1 : 1;
|
|
6625
|
+
if (aVal > bVal)
|
|
6626
|
+
return direction === "ASC" ? 1 : -1;
|
|
6627
|
+
}
|
|
6628
|
+
return 0;
|
|
6629
|
+
});
|
|
6630
|
+
}
|
|
6631
|
+
if (options?.offset !== undefined) {
|
|
6632
|
+
results = results.slice(options.offset);
|
|
6633
|
+
}
|
|
6634
|
+
if (options?.limit !== undefined) {
|
|
6635
|
+
results = results.slice(0, options.limit);
|
|
6636
|
+
}
|
|
6637
|
+
const result = results.length > 0 ? results : undefined;
|
|
6638
|
+
this.events.emit("query", criteria, result);
|
|
6639
|
+
resolve(result);
|
|
6640
|
+
};
|
|
6641
|
+
getAllRequest.onerror = () => {
|
|
6642
|
+
reject(getAllRequest.error);
|
|
6643
|
+
};
|
|
6644
|
+
});
|
|
6645
|
+
}
|
|
6345
6646
|
getHybridManager() {
|
|
6346
6647
|
if (!this.hybridManager) {
|
|
6347
6648
|
const channelName = `indexeddb-tabular-${this.table}`;
|
|
@@ -7296,6 +7597,12 @@ export {
|
|
|
7296
7597
|
SupabaseRateLimiterStorage,
|
|
7297
7598
|
SupabaseQueueStorage,
|
|
7298
7599
|
SupabaseKvStorage,
|
|
7600
|
+
StorageValidationError,
|
|
7601
|
+
StorageUnsupportedError,
|
|
7602
|
+
StorageInvalidLimitError,
|
|
7603
|
+
StorageInvalidColumnError,
|
|
7604
|
+
StorageError,
|
|
7605
|
+
StorageEmptyCriteriaError,
|
|
7299
7606
|
SqliteVectorStorage,
|
|
7300
7607
|
SqliteTabularStorage,
|
|
7301
7608
|
SqliteRateLimiterStorage,
|
|
@@ -7361,4 +7668,4 @@ export {
|
|
|
7361
7668
|
BaseTabularStorage
|
|
7362
7669
|
};
|
|
7363
7670
|
|
|
7364
|
-
//# debugId=
|
|
7671
|
+
//# debugId=10EEBA1FB4F879DB64756E2164756E21
|