@workglow/storage 0.0.77 → 0.0.79
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/README.md +41 -8
- package/dist/browser.js +159 -119
- package/dist/browser.js.map +10 -9
- package/dist/bun.js +219 -133
- package/dist/bun.js.map +12 -11
- package/dist/node.js +219 -133
- package/dist/node.js.map +12 -11
- package/dist/tabular/CachedTabularRepository.d.ts +6 -6
- package/dist/tabular/CachedTabularRepository.d.ts.map +1 -1
- package/dist/tabular/FsFolderTabularRepository.d.ts +7 -6
- package/dist/tabular/FsFolderTabularRepository.d.ts.map +1 -1
- package/dist/tabular/ITabularRepository.d.ts +48 -1
- package/dist/tabular/ITabularRepository.d.ts.map +1 -1
- package/dist/tabular/InMemoryTabularRepository.d.ts +6 -6
- package/dist/tabular/InMemoryTabularRepository.d.ts.map +1 -1
- package/dist/tabular/IndexedDbTabularRepository.d.ts +13 -6
- package/dist/tabular/IndexedDbTabularRepository.d.ts.map +1 -1
- package/dist/tabular/PostgresTabularRepository.d.ts +15 -7
- package/dist/tabular/PostgresTabularRepository.d.ts.map +1 -1
- package/dist/tabular/SharedInMemoryTabularRepository.d.ts +6 -6
- package/dist/tabular/SharedInMemoryTabularRepository.d.ts.map +1 -1
- package/dist/tabular/SqliteTabularRepository.d.ts +15 -7
- package/dist/tabular/SqliteTabularRepository.d.ts.map +1 -1
- package/dist/tabular/SupabaseTabularRepository.d.ts +6 -7
- package/dist/tabular/SupabaseTabularRepository.d.ts.map +1 -1
- package/dist/tabular/TabularRepository.d.ts +8 -2
- package/dist/tabular/TabularRepository.d.ts.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -327,9 +327,15 @@ const userCount = await userRepo.size();
|
|
|
327
327
|
const engineeringUsers = await userRepo.search({ department: "Engineering" });
|
|
328
328
|
const adultUsers = await userRepo.search({ age: 25 }); // Exact match
|
|
329
329
|
|
|
330
|
-
// Delete by search criteria
|
|
331
|
-
await userRepo.deleteSearch(
|
|
332
|
-
await userRepo.deleteSearch(
|
|
330
|
+
// Delete by search criteria (supports multiple columns)
|
|
331
|
+
await userRepo.deleteSearch({ department: "Sales" }); // Equality
|
|
332
|
+
await userRepo.deleteSearch({ age: { value: 65, operator: ">=" } }); // Delete users 65 and older
|
|
333
|
+
|
|
334
|
+
// Multiple criteria (AND logic)
|
|
335
|
+
await userRepo.deleteSearch({
|
|
336
|
+
department: "Sales",
|
|
337
|
+
age: { value: 30, operator: "<" },
|
|
338
|
+
}); // Delete young Sales employees
|
|
333
339
|
```
|
|
334
340
|
|
|
335
341
|
#### Environment-Specific Tabular Storage
|
|
@@ -629,11 +635,7 @@ interface ITabularRepository<Schema, PrimaryKeyNames, Entity, PrimaryKey, Value>
|
|
|
629
635
|
|
|
630
636
|
// Search operations
|
|
631
637
|
search(criteria: Partial<Entity>): Promise<Entity[] | undefined>;
|
|
632
|
-
deleteSearch(
|
|
633
|
-
column: keyof Entity,
|
|
634
|
-
value: any,
|
|
635
|
-
operator: "=" | "<" | "<=" | ">" | ">="
|
|
636
|
-
): Promise<void>;
|
|
638
|
+
deleteSearch(criteria: DeleteSearchCriteria<Entity>): Promise<void>;
|
|
637
639
|
|
|
638
640
|
// Event handling
|
|
639
641
|
on(event: "put" | "get" | "search" | "delete" | "clearall", callback: Function): void;
|
|
@@ -644,6 +646,37 @@ interface ITabularRepository<Schema, PrimaryKeyNames, Entity, PrimaryKey, Value>
|
|
|
644
646
|
}
|
|
645
647
|
```
|
|
646
648
|
|
|
649
|
+
#### DeleteSearchCriteria<Entity>
|
|
650
|
+
|
|
651
|
+
The `deleteSearch` method accepts a criteria object that supports multiple columns with optional comparison operators:
|
|
652
|
+
|
|
653
|
+
```typescript
|
|
654
|
+
// Type definitions
|
|
655
|
+
type SearchOperator = "=" | "<" | "<=" | ">" | ">=";
|
|
656
|
+
|
|
657
|
+
interface SearchCondition<T> {
|
|
658
|
+
readonly value: T;
|
|
659
|
+
readonly operator: SearchOperator;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
type DeleteSearchCriteria<Entity> = {
|
|
663
|
+
readonly [K in keyof Entity]?: Entity[K] | SearchCondition<Entity[K]>;
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
// Usage examples
|
|
667
|
+
// Equality match (direct value)
|
|
668
|
+
await repo.deleteSearch({ category: "electronics" });
|
|
669
|
+
|
|
670
|
+
// With comparison operator
|
|
671
|
+
await repo.deleteSearch({ createdAt: { value: date, operator: "<" } });
|
|
672
|
+
|
|
673
|
+
// Multiple criteria (AND logic)
|
|
674
|
+
await repo.deleteSearch({
|
|
675
|
+
category: "electronics",
|
|
676
|
+
value: { value: 100, operator: ">=" },
|
|
677
|
+
});
|
|
678
|
+
```
|
|
679
|
+
|
|
647
680
|
### IQueueStorage<Input, Output>
|
|
648
681
|
|
|
649
682
|
Core interface for job queue storage:
|
package/dist/browser.js
CHANGED
|
@@ -7,6 +7,11 @@ import {
|
|
|
7
7
|
makeFingerprint as makeFingerprint2
|
|
8
8
|
} from "@workglow/util";
|
|
9
9
|
|
|
10
|
+
// src/tabular/ITabularRepository.ts
|
|
11
|
+
function isSearchCondition(value) {
|
|
12
|
+
return typeof value === "object" && value !== null && "value" in value && "operator" in value && typeof value.operator === "string";
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
// src/tabular/TabularRepository.ts
|
|
11
16
|
import {
|
|
12
17
|
createServiceToken,
|
|
@@ -258,24 +263,50 @@ class InMemoryTabularRepository extends TabularRepository {
|
|
|
258
263
|
async size() {
|
|
259
264
|
return this.values.size;
|
|
260
265
|
}
|
|
261
|
-
async deleteSearch(
|
|
262
|
-
const
|
|
266
|
+
async deleteSearch(criteria) {
|
|
267
|
+
const criteriaKeys = Object.keys(criteria);
|
|
268
|
+
if (criteriaKeys.length === 0) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const entries = Array.from(this.values.entries());
|
|
263
272
|
const entriesToDelete = entries.filter(([_, entity]) => {
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
273
|
+
for (const column of criteriaKeys) {
|
|
274
|
+
const criterion = criteria[column];
|
|
275
|
+
const columnValue = entity[column];
|
|
276
|
+
if (isSearchCondition(criterion)) {
|
|
277
|
+
const { value, operator } = criterion;
|
|
278
|
+
const v = value;
|
|
279
|
+
const cv = columnValue;
|
|
280
|
+
switch (operator) {
|
|
281
|
+
case "=":
|
|
282
|
+
if (cv !== v)
|
|
283
|
+
return false;
|
|
284
|
+
break;
|
|
285
|
+
case "<":
|
|
286
|
+
if (cv === null || cv === undefined || !(cv < v))
|
|
287
|
+
return false;
|
|
288
|
+
break;
|
|
289
|
+
case "<=":
|
|
290
|
+
if (cv === null || cv === undefined || !(cv <= v))
|
|
291
|
+
return false;
|
|
292
|
+
break;
|
|
293
|
+
case ">":
|
|
294
|
+
if (cv === null || cv === undefined || !(cv > v))
|
|
295
|
+
return false;
|
|
296
|
+
break;
|
|
297
|
+
case ">=":
|
|
298
|
+
if (cv === null || cv === undefined || !(cv >= v))
|
|
299
|
+
return false;
|
|
300
|
+
break;
|
|
301
|
+
default:
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
} else {
|
|
305
|
+
if (columnValue !== criterion)
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
278
308
|
}
|
|
309
|
+
return true;
|
|
279
310
|
});
|
|
280
311
|
for (const [id, entity] of entriesToDelete) {
|
|
281
312
|
this.values.delete(id);
|
|
@@ -417,10 +448,10 @@ class CachedTabularRepository extends TabularRepository {
|
|
|
417
448
|
await this.initializeCache();
|
|
418
449
|
return await this.durable.size();
|
|
419
450
|
}
|
|
420
|
-
async deleteSearch(
|
|
451
|
+
async deleteSearch(criteria) {
|
|
421
452
|
await this.initializeCache();
|
|
422
|
-
await this.durable.deleteSearch(
|
|
423
|
-
await this.cache.deleteSearch(
|
|
453
|
+
await this.durable.deleteSearch(criteria);
|
|
454
|
+
await this.cache.deleteSearch(criteria);
|
|
424
455
|
}
|
|
425
456
|
async invalidateCache() {
|
|
426
457
|
await this.cache.deleteAll();
|
|
@@ -1731,32 +1762,76 @@ class IndexedDbTabularRepository extends TabularRepository {
|
|
|
1731
1762
|
request.onsuccess = () => resolve(request.result);
|
|
1732
1763
|
});
|
|
1733
1764
|
}
|
|
1734
|
-
|
|
1765
|
+
matchesCriteria(record, criteria) {
|
|
1766
|
+
for (const column of Object.keys(criteria)) {
|
|
1767
|
+
const criterion = criteria[column];
|
|
1768
|
+
const recordValue = record[column];
|
|
1769
|
+
let operator = "=";
|
|
1770
|
+
let value;
|
|
1771
|
+
if (isSearchCondition(criterion)) {
|
|
1772
|
+
operator = criterion.operator;
|
|
1773
|
+
value = criterion.value;
|
|
1774
|
+
} else {
|
|
1775
|
+
value = criterion;
|
|
1776
|
+
}
|
|
1777
|
+
if (operator !== "=" && (recordValue === null || recordValue === undefined)) {
|
|
1778
|
+
return false;
|
|
1779
|
+
}
|
|
1780
|
+
switch (operator) {
|
|
1781
|
+
case "=":
|
|
1782
|
+
if (recordValue !== value)
|
|
1783
|
+
return false;
|
|
1784
|
+
break;
|
|
1785
|
+
case "<":
|
|
1786
|
+
if (!(recordValue < value))
|
|
1787
|
+
return false;
|
|
1788
|
+
break;
|
|
1789
|
+
case "<=":
|
|
1790
|
+
if (!(recordValue <= value))
|
|
1791
|
+
return false;
|
|
1792
|
+
break;
|
|
1793
|
+
case ">":
|
|
1794
|
+
if (!(recordValue > value))
|
|
1795
|
+
return false;
|
|
1796
|
+
break;
|
|
1797
|
+
case ">=":
|
|
1798
|
+
if (!(recordValue >= value))
|
|
1799
|
+
return false;
|
|
1800
|
+
break;
|
|
1801
|
+
default:
|
|
1802
|
+
return false;
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
return true;
|
|
1806
|
+
}
|
|
1807
|
+
async deleteSearch(criteria) {
|
|
1808
|
+
const criteriaKeys = Object.keys(criteria);
|
|
1809
|
+
if (criteriaKeys.length === 0) {
|
|
1810
|
+
return;
|
|
1811
|
+
}
|
|
1735
1812
|
const db = await this.getDb();
|
|
1736
1813
|
return new Promise(async (resolve, reject) => {
|
|
1737
1814
|
try {
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1815
|
+
const transaction = db.transaction(this.table, "readwrite");
|
|
1816
|
+
const store = transaction.objectStore(this.table);
|
|
1817
|
+
transaction.oncomplete = () => {
|
|
1818
|
+
this.events.emit("delete", criteriaKeys[0]);
|
|
1819
|
+
this.hybridManager?.notifyLocalChange();
|
|
1820
|
+
resolve();
|
|
1821
|
+
};
|
|
1822
|
+
transaction.onerror = () => {
|
|
1823
|
+
reject(transaction.error);
|
|
1824
|
+
};
|
|
1825
|
+
const getAllRequest = store.getAll();
|
|
1826
|
+
getAllRequest.onsuccess = () => {
|
|
1827
|
+
const allRecords = getAllRequest.result;
|
|
1828
|
+
const recordsToDelete = allRecords.filter((record) => this.matchesCriteria(record, criteria));
|
|
1829
|
+
if (recordsToDelete.length === 0) {
|
|
1745
1830
|
return;
|
|
1746
1831
|
}
|
|
1747
|
-
const transaction = db.transaction(this.table, "readwrite");
|
|
1748
|
-
const store = transaction.objectStore(this.table);
|
|
1749
|
-
transaction.oncomplete = () => {
|
|
1750
|
-
this.events.emit("delete", column);
|
|
1751
|
-
this.hybridManager?.notifyLocalChange();
|
|
1752
|
-
resolve();
|
|
1753
|
-
};
|
|
1754
|
-
transaction.onerror = () => {
|
|
1755
|
-
reject(transaction.error);
|
|
1756
|
-
};
|
|
1757
1832
|
for (const record of recordsToDelete) {
|
|
1758
|
-
const primaryKey = this.primaryKeyColumns().reduce((key,
|
|
1759
|
-
key[
|
|
1833
|
+
const primaryKey = this.primaryKeyColumns().reduce((key, col) => {
|
|
1834
|
+
key[col] = record[col];
|
|
1760
1835
|
return key;
|
|
1761
1836
|
}, {});
|
|
1762
1837
|
const request = store.delete(this.getIndexedKey(primaryKey));
|
|
@@ -1764,56 +1839,10 @@ class IndexedDbTabularRepository extends TabularRepository {
|
|
|
1764
1839
|
console.error("Error deleting record:", request.error);
|
|
1765
1840
|
};
|
|
1766
1841
|
}
|
|
1767
|
-
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
this.events.emit("delete", column);
|
|
1772
|
-
this.hybridManager?.notifyLocalChange();
|
|
1773
|
-
resolve();
|
|
1774
|
-
};
|
|
1775
|
-
transaction.onerror = () => {
|
|
1776
|
-
reject(transaction.error);
|
|
1777
|
-
};
|
|
1778
|
-
const getAllRequest = store.getAll();
|
|
1779
|
-
getAllRequest.onsuccess = () => {
|
|
1780
|
-
const allRecords = getAllRequest.result;
|
|
1781
|
-
const recordsToDelete = allRecords.filter((record) => {
|
|
1782
|
-
const recordValue = record[column];
|
|
1783
|
-
if (recordValue === null || recordValue === undefined || value === null || value === undefined) {
|
|
1784
|
-
return false;
|
|
1785
|
-
}
|
|
1786
|
-
switch (operator) {
|
|
1787
|
-
case "<":
|
|
1788
|
-
return recordValue < value;
|
|
1789
|
-
case "<=":
|
|
1790
|
-
return recordValue <= value;
|
|
1791
|
-
case ">":
|
|
1792
|
-
return recordValue > value;
|
|
1793
|
-
case ">=":
|
|
1794
|
-
return recordValue >= value;
|
|
1795
|
-
default:
|
|
1796
|
-
return false;
|
|
1797
|
-
}
|
|
1798
|
-
});
|
|
1799
|
-
if (recordsToDelete.length === 0) {
|
|
1800
|
-
return;
|
|
1801
|
-
}
|
|
1802
|
-
for (const record of recordsToDelete) {
|
|
1803
|
-
const primaryKey = this.primaryKeyColumns().reduce((key, column2) => {
|
|
1804
|
-
key[column2] = record[column2];
|
|
1805
|
-
return key;
|
|
1806
|
-
}, {});
|
|
1807
|
-
const request = store.delete(this.getIndexedKey(primaryKey));
|
|
1808
|
-
request.onerror = () => {
|
|
1809
|
-
console.error("Error deleting record:", request.error);
|
|
1810
|
-
};
|
|
1811
|
-
}
|
|
1812
|
-
};
|
|
1813
|
-
getAllRequest.onerror = () => {
|
|
1814
|
-
reject(getAllRequest.error);
|
|
1815
|
-
};
|
|
1816
|
-
}
|
|
1842
|
+
};
|
|
1843
|
+
getAllRequest.onerror = () => {
|
|
1844
|
+
reject(getAllRequest.error);
|
|
1845
|
+
};
|
|
1817
1846
|
} catch (error) {
|
|
1818
1847
|
reject(error);
|
|
1819
1848
|
}
|
|
@@ -1941,7 +1970,7 @@ class SharedInMemoryTabularRepository extends TabularRepository {
|
|
|
1941
1970
|
await this.inMemoryRepo.deleteAll();
|
|
1942
1971
|
break;
|
|
1943
1972
|
case "DELETE_SEARCH":
|
|
1944
|
-
await this.inMemoryRepo.deleteSearch(message.
|
|
1973
|
+
await this.inMemoryRepo.deleteSearch(message.criteria);
|
|
1945
1974
|
break;
|
|
1946
1975
|
}
|
|
1947
1976
|
}
|
|
@@ -2002,13 +2031,11 @@ class SharedInMemoryTabularRepository extends TabularRepository {
|
|
|
2002
2031
|
async size() {
|
|
2003
2032
|
return await this.inMemoryRepo.size();
|
|
2004
2033
|
}
|
|
2005
|
-
async deleteSearch(
|
|
2006
|
-
await this.inMemoryRepo.deleteSearch(
|
|
2034
|
+
async deleteSearch(criteria) {
|
|
2035
|
+
await this.inMemoryRepo.deleteSearch(criteria);
|
|
2007
2036
|
this.broadcast({
|
|
2008
2037
|
type: "DELETE_SEARCH",
|
|
2009
|
-
|
|
2010
|
-
value,
|
|
2011
|
-
operator
|
|
2038
|
+
criteria
|
|
2012
2039
|
});
|
|
2013
2040
|
}
|
|
2014
2041
|
subscribeToChanges(callback, options) {
|
|
@@ -2541,35 +2568,47 @@ class SupabaseTabularRepository extends BaseSqlTabularRepository {
|
|
|
2541
2568
|
throw error;
|
|
2542
2569
|
return count ?? 0;
|
|
2543
2570
|
}
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2571
|
+
async deleteSearch(criteria) {
|
|
2572
|
+
const criteriaKeys = Object.keys(criteria);
|
|
2573
|
+
if (criteriaKeys.length === 0) {
|
|
2574
|
+
return;
|
|
2547
2575
|
}
|
|
2548
|
-
return `${String(column)} ${operator} $1`;
|
|
2549
|
-
}
|
|
2550
|
-
async deleteSearch(column, value, operator = "=") {
|
|
2551
2576
|
let query = this.client.from(this.table).delete();
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2577
|
+
for (const column of criteriaKeys) {
|
|
2578
|
+
if (!(column in this.schema.properties)) {
|
|
2579
|
+
throw new Error(`Schema must have a ${String(column)} field to use deleteSearch`);
|
|
2580
|
+
}
|
|
2581
|
+
const criterion = criteria[column];
|
|
2582
|
+
let operator = "=";
|
|
2583
|
+
let value;
|
|
2584
|
+
if (isSearchCondition(criterion)) {
|
|
2585
|
+
operator = criterion.operator;
|
|
2586
|
+
value = criterion.value;
|
|
2587
|
+
} else {
|
|
2588
|
+
value = criterion;
|
|
2589
|
+
}
|
|
2590
|
+
switch (operator) {
|
|
2591
|
+
case "=":
|
|
2592
|
+
query = query.eq(String(column), value);
|
|
2593
|
+
break;
|
|
2594
|
+
case "<":
|
|
2595
|
+
query = query.lt(String(column), value);
|
|
2596
|
+
break;
|
|
2597
|
+
case "<=":
|
|
2598
|
+
query = query.lte(String(column), value);
|
|
2599
|
+
break;
|
|
2600
|
+
case ">":
|
|
2601
|
+
query = query.gt(String(column), value);
|
|
2602
|
+
break;
|
|
2603
|
+
case ">=":
|
|
2604
|
+
query = query.gte(String(column), value);
|
|
2605
|
+
break;
|
|
2606
|
+
}
|
|
2568
2607
|
}
|
|
2569
2608
|
const { error } = await query;
|
|
2570
2609
|
if (error)
|
|
2571
2610
|
throw error;
|
|
2572
|
-
this.events.emit("delete",
|
|
2611
|
+
this.events.emit("delete", criteriaKeys[0]);
|
|
2573
2612
|
}
|
|
2574
2613
|
convertRealtimeRow(row) {
|
|
2575
2614
|
const entity = { ...row };
|
|
@@ -4078,6 +4117,7 @@ class SupabaseRateLimiterStorage {
|
|
|
4078
4117
|
}
|
|
4079
4118
|
}
|
|
4080
4119
|
export {
|
|
4120
|
+
isSearchCondition,
|
|
4081
4121
|
ensureIndexedDbTable,
|
|
4082
4122
|
dropIndexedDbTable,
|
|
4083
4123
|
TabularRepository,
|
|
@@ -4122,4 +4162,4 @@ export {
|
|
|
4122
4162
|
CACHED_TABULAR_REPOSITORY
|
|
4123
4163
|
};
|
|
4124
4164
|
|
|
4125
|
-
//# debugId=
|
|
4165
|
+
//# debugId=DD99166332ED2CB564756E2164756E21
|