@workglow/storage 0.0.104 → 0.0.106

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