ueberdb2 6.0.3 → 6.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +79 -15
  2. package/dist/{AbstractDatabase-DfQ39Ry6.js → AbstractDatabase-WBFqc8ye.js} +1 -1
  3. package/dist/{cassandra_db-B_5ANRzM.js → cassandra_db-B96_l9V7.js} +1 -1
  4. package/dist/{couch_db-BXyzauwJ.js → couch_db-DZ6MLt5j.js} +1 -1
  5. package/dist/databases/mysql_db.d.ts +4 -0
  6. package/dist/databases/mysql_db.d.ts.map +1 -1
  7. package/dist/databases/postgres_db.d.ts +4 -0
  8. package/dist/databases/postgres_db.d.ts.map +1 -1
  9. package/dist/{dirty_db-C1KQTMCv.js → dirty_db-BGvHB8ud.js} +1 -1
  10. package/dist/{dirty_git_db-7tkfx6PK.js → dirty_git_db-LJWW2YT6.js} +1 -1
  11. package/dist/{elasticsearch_db-C6G-Wnou.js → elasticsearch_db-D2XR08mV.js} +1 -1
  12. package/dist/index.d.ts +10 -0
  13. package/dist/index.js +49 -18
  14. package/dist/lib/AbstractDatabase.d.ts.map +1 -1
  15. package/dist/lib/CacheAndBufferLayer.d.ts +4 -0
  16. package/dist/lib/CacheAndBufferLayer.d.ts.map +1 -1
  17. package/dist/{memory_db-CGTi0Ck-.js → memory_db-BQaHRpkv.js} +1 -1
  18. package/dist/{mongodb_db-DgkIuEMZ.js → mongodb_db-DJVvvNTo.js} +1 -1
  19. package/dist/{mssql_db-LiEvv4Sm.js → mssql_db-BqtTYXk9.js} +1 -1
  20. package/dist/{mysql_db-48mMBbKZ.js → mysql_db-DIXEbML4.js} +21 -1
  21. package/dist/{postgres_db-7Hiezhpi.js → postgres_db-BzDKMRC5.js} +22 -1
  22. package/dist/{postgrespool_db-CdF-1S34.js → postgrespool_db-B6FOhTY3.js} +1 -1
  23. package/dist/{redis_db-DKRC8sR9.js → redis_db-C8LRkRGe.js} +1 -1
  24. package/dist/{rethink_db-BGxY_SA3.js → rethink_db-qv884MUM.js} +1 -1
  25. package/dist/{rusty_db-Msjxckfm.js → rusty_db-90_S-z-w.js} +1 -1
  26. package/dist/{sqlite_db-Cy8OT62U.js → sqlite_db-Bp4nZn-c.js} +1 -1
  27. package/dist/{surrealdb_db-XnhMQEwL.js → surrealdb_db-K8QAySpG.js} +1 -1
  28. package/package.json +9 -9
  29. /package/dist/{logging-DOvFhjsQ.js → logging-CLbyQV5A.js} +0 -0
  30. /package/dist/{mock_db-DCUmGtUq.js → mock_db-CgEDPTpF.js} +0 -0
package/README.md CHANGED
@@ -86,6 +86,57 @@ const ueberdb = require('ueberdb2');
86
86
  })();
87
87
  ```
88
88
 
89
+ ### findKeysPaged (memory-bounded iteration)
90
+
91
+ `findKeys()` materialises every matching key into a single array. On very
92
+ large keyspaces that loads the whole result set into memory at once — see
93
+ [ether/etherpad#7830][7830] where a multi-million-row `sessionstorage:*`
94
+ sweep OOMed the host. `findKeysPaged()` walks the same keyspace in
95
+ fixed-size pages using an exclusive `after` cursor:
96
+
97
+ ```javascript
98
+ const ueberdb = require('ueberdb2');
99
+
100
+ (async () => {
101
+ const db = new ueberdb.Database('mysql', settings);
102
+ await db.init();
103
+ try {
104
+ let after;
105
+ let total = 0;
106
+ while (true) {
107
+ const page = await db.findKeysPaged('sessionstorage:*', null, {
108
+ limit: 500,
109
+ ...(after != null ? {after} : {}),
110
+ });
111
+ if (page.length === 0) break;
112
+ total += page.length;
113
+ for (const key of page) {
114
+ // ...process key...
115
+ }
116
+ after = page[page.length - 1];
117
+ }
118
+ console.log(`processed ${total} keys`);
119
+ } finally {
120
+ await db.close();
121
+ }
122
+ })();
123
+ ```
124
+
125
+ Semantics:
126
+
127
+ - Keys are returned in ascending byte-order, up to `limit` per call.
128
+ - `after` is **exclusive** — pass the last returned key as the next
129
+ `after` value. Final page is when the returned array is empty.
130
+ - `limit` must be a positive integer; non-positive or non-integer values
131
+ throw.
132
+ - Native implementations: **mysql** (ranged `BINARY \`key\` > ?`),
133
+ **postgres** (`key > $n`). All other backends fall back to
134
+ `findKeys() + JS-side slicing` via the cache layer — correct, but
135
+ defeats the OOM-mitigation purpose. PRs for native paged paths on
136
+ other backends welcome.
137
+
138
+ [7830]: https://github.com/ether/etherpad/issues/7830
139
+
89
140
  ### Getting and setting subkeys
90
141
 
91
142
  ueberDB can store complex JSON objects. Sometimes you only want to get or set a
@@ -210,21 +261,21 @@ const ueberdb = require('ueberdb2');
210
261
 
211
262
  ## Feature support
212
263
 
213
- | | Get | Set | findKeys | Remove | getSub | setSub | doBulk | CI Coverage |
214
- |---------------|-----|-----|----------|--------|--------|--------|--------|-------------|
215
- | cassandra | ✓ | ✓ | * | ✓ | ✓ | ✓ | ✓ | ✓ |
216
- | couchdb | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
217
- | dirty | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ |
218
- | dirty_git | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ |
219
- | elasticsearch | ✓ | ✓ | * | ✓ | ✓ | ✓ | ✓ | ✓ |
220
- | maria | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
221
- | mysql | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
222
- | postgres | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
223
- | redis | ✓ | ✓ | * | ✓ | ✓ | ✓ | ✓ | ✓ |
224
- | rethinkdb | ✓ | ✓ | * | ✓ | ✓ | ✓ | ✓ |
225
- | rustydb | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
226
- | sqlite | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
227
- | surrealdb | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
264
+ | | Get | Set | findKeys | findKeysPaged | Remove | getSub | setSub | doBulk | CI Coverage |
265
+ |---------------|-----|-----|----------|---------------|--------|--------|--------|--------|-------------|
266
+ | cassandra | ✓ | ✓ | * | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
267
+ | couchdb | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
268
+ | dirty | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ |
269
+ | dirty_git | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ |
270
+ | elasticsearch | ✓ | ✓ | * | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
271
+ | maria | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
272
+ | mysql | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
273
+ | postgres | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
274
+ | redis | ✓ | ✓ | * | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
275
+ | rethinkdb | ✓ | ✓ | * | ✓ | ✓ | ✓ | ✓ | ✓ |
276
+ | rustydb | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
277
+ | sqlite | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
278
+ | surrealdb | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
228
279
 
229
280
  ## Limitations
230
281
 
@@ -245,6 +296,19 @@ The following have limitations on findKeys
245
296
  For details on how it works please refer to the wiki:
246
297
  https://github.com/ether/UeberDB/wiki/findKeys-functionality
247
298
 
299
+ ### findKeysPaged database support
300
+
301
+ `findKeysPaged` is supported on every backend, but only the SQL backends
302
+ (mysql, mariadb, postgres) iterate the keyspace with a server-side ranged
303
+ query — that's the variant that actually bounds memory for the OOM case it
304
+ was added for ([ether/etherpad#7830][7830]). Other backends share the same
305
+ API surface via a wrapper that falls back to `findKeys()` plus in-JS
306
+ slicing; correct, but the underlying `findKeys()` still materialises every
307
+ matching key, so the OOM-mitigation benefit only applies to the SQL
308
+ backends. PRs adding native paged paths for the rest are welcome.
309
+
310
+ [7830]: https://github.com/ether/etherpad/issues/7830
311
+
248
312
  ### Scaling, High availability and disaster recovery.
249
313
 
250
314
  To scale UeberDB you should use sharding especially for real time applications.
@@ -1,4 +1,4 @@
1
- import { t as normalizeLogger } from "./logging-DOvFhjsQ.js";
1
+ import { t as normalizeLogger } from "./logging-CLbyQV5A.js";
2
2
  //#region lib/AbstractDatabase.ts
3
3
  const nullLogger = normalizeLogger(null);
4
4
  const simpleGlobToRegExp = (s) => s.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import { Client } from "cassandra-driver";
3
3
  //#region databases/cassandra_db.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import nano from "nano";
3
3
  //#region databases/couch_db.ts
4
4
  /**
@@ -25,6 +25,10 @@ export default class extends AbstractDatabase {
25
25
  init(): Promise<void>;
26
26
  get(key: string): Promise<any>;
27
27
  findKeys(key: string, notKey: string): Promise<any>;
28
+ findKeysPaged(key: string, notKey: string | null | undefined, options: {
29
+ limit: number;
30
+ after?: string;
31
+ }): Promise<any>;
28
32
  set(key: string, value: string): Promise<void>;
29
33
  remove(key: string): Promise<void>;
30
34
  doBulk(bulk: BulkObject[]): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"mysql_db.d.ts","sourceRoot":"","sources":["../../databases/mysql_db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,gBAAgB,EAAE,EAAC,KAAK,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AAExE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EAAmB,IAAI,EAAa,MAAM,QAAQ,CAAC;AAE/D,MAAM,CAAC,OAAO,MAAO,SAAQ,gBAAgB;IAC3C,SAAgB,cAAc,EAAE,QAAQ,CAAC;IAClC,KAAK,EAAE,IAAI,GAAC,IAAI,CAAC;gBACZ,QAAQ,EAAC,QAAQ;IAiB7B,IAAI,OAAO,YAAmB;IAExB,MAAM,CAAC,OAAO,EAAE,GAAG,GAAE,OAAO,CAAC,GAAG,CAAC;IAkBjC,IAAI;IAqEJ,GAAG,CAAC,GAAG,EAAC,MAAM;IAQd,QAAQ,CAAC,GAAG,EAAC,MAAM,EAAE,MAAM,EAAC,MAAM;IAkBlC,GAAG,CAAC,GAAG,EAAC,MAAM,EAAE,KAAK,EAAC,MAAM;IAK5B,MAAM,CAAC,GAAG,EAAC,MAAM;IAOjB,MAAM,CAAC,IAAI,EAAC,UAAU,EAAE;IAsBxB,KAAK;CAGZ"}
1
+ {"version":3,"file":"mysql_db.d.ts","sourceRoot":"","sources":["../../databases/mysql_db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,gBAAgB,EAAE,EAAC,KAAK,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AAExE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EAAmB,IAAI,EAAa,MAAM,QAAQ,CAAC;AAE/D,MAAM,CAAC,OAAO,MAAO,SAAQ,gBAAgB;IAC3C,SAAgB,cAAc,EAAE,QAAQ,CAAC;IAClC,KAAK,EAAE,IAAI,GAAC,IAAI,CAAC;gBACZ,QAAQ,EAAC,QAAQ;IAiB7B,IAAI,OAAO,YAAmB;IAExB,MAAM,CAAC,OAAO,EAAE,GAAG,GAAE,OAAO,CAAC,GAAG,CAAC;IAkBjC,IAAI;IAqEJ,GAAG,CAAC,GAAG,EAAC,MAAM;IAQd,QAAQ,CAAC,GAAG,EAAC,MAAM,EAAE,MAAM,EAAC,MAAM;IAkBlC,aAAa,CACjB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,OAAO,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC;IAuBpC,GAAG,CAAC,GAAG,EAAC,MAAM,EAAE,KAAK,EAAC,MAAM;IAK5B,MAAM,CAAC,GAAG,EAAC,MAAM;IAOjB,MAAM,CAAC,IAAI,EAAC,UAAU,EAAE;IAsBxB,KAAK;CAGZ"}
@@ -23,6 +23,10 @@ export default class extends AbstractDatabase {
23
23
  init(callback: (err: Error) => {}): void;
24
24
  get(key: string, callback: (err: Error | null, value: any) => {}): void;
25
25
  findKeys(key: string, notKey: string, callback: (err: Error | null, value: any) => {}): void;
26
+ findKeysPaged(key: string, notKey: string | null | undefined, options: {
27
+ limit: number;
28
+ after?: string;
29
+ }, callback: (err: Error | null, value: string[]) => void): void;
26
30
  set(key: string, value: string, callback: (err: Error, result: pg.QueryResult) => void): void;
27
31
  remove(key: string, callback: () => {}): void;
28
32
  doBulk(bulk: BulkObject[], callback: () => {}): void;
@@ -1 +1 @@
1
- {"version":3,"file":"postgres_db.d.ts","sourceRoot":"","sources":["../../databases/postgres_db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,gBAAgB,EAAE,EAAC,KAAK,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AAExE,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAE/C,MAAM,CAAC,OAAO,MAAO,SAAQ,gBAAgB;IACpC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC;IACZ,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;gBACtC,QAAQ,EAAC,QAAQ,GAAG,MAAM;IAgBtC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,KAAG,EAAE;IA2E/B,GAAG,CAAC,GAAG,EAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,KAAG,EAAE;IAY7D,QAAQ,CAAC,GAAG,EAAC,MAAM,EAAE,MAAM,EAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,KAAG,EAAE;IA0BjF,GAAG,CAAC,GAAG,EAAC,MAAM,EAAE,KAAK,EAAC,MAAM,EAAE,QAAQ,EAAC,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,WAAW,KAAK,IAAI;IASnF,MAAM,CAAC,GAAG,EAAC,MAAM,EAAE,QAAQ,EAAC,MAAI,EAAE;IAIlC,MAAM,CAAC,IAAI,EAAC,UAAU,EAAE,EAAE,QAAQ,EAAC,MAAI,EAAE;IAsCzC,KAAK,CAAC,QAAQ,EAAC,MAAI,EAAE;CAGtB"}
1
+ {"version":3,"file":"postgres_db.d.ts","sourceRoot":"","sources":["../../databases/postgres_db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,gBAAgB,EAAE,EAAC,KAAK,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AAExE,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAE/C,MAAM,CAAC,OAAO,MAAO,SAAQ,gBAAgB;IACpC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC;IACZ,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;gBACtC,QAAQ,EAAC,QAAQ,GAAG,MAAM;IAgBtC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,KAAG,EAAE;IA2E/B,GAAG,CAAC,GAAG,EAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,KAAG,EAAE;IAY7D,QAAQ,CAAC,GAAG,EAAC,MAAM,EAAE,MAAM,EAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,KAAG,EAAE;IA0BjF,aAAa,CACX,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,OAAO,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC,EACxC,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI;IA2BxD,GAAG,CAAC,GAAG,EAAC,MAAM,EAAE,KAAK,EAAC,MAAM,EAAE,QAAQ,EAAC,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,WAAW,KAAK,IAAI;IASnF,MAAM,CAAC,GAAG,EAAC,MAAM,EAAE,QAAQ,EAAC,MAAI,EAAE;IAIlC,MAAM,CAAC,IAAI,EAAC,UAAU,EAAE,EAAE,QAAQ,EAAC,MAAI,EAAE;IAsCzC,KAAK,CAAC,QAAQ,EAAC,MAAI,EAAE;CAGtB"}
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import DirtyImport from "dirty-ts";
3
3
  //#region databases/dirty_db.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import DirtyImport from "dirty-ts";
3
3
  import { dirname } from "node:path";
4
4
  import { simpleGit } from "simple-git";
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import assert, { equal } from "assert";
3
3
  import { Buffer } from "buffer";
4
4
  import { createHash } from "crypto";
package/dist/index.d.ts CHANGED
@@ -42,6 +42,16 @@ export declare class Database {
42
42
  doShutdown(): Promise<void>;
43
43
  get(key: string): Promise<unknown>;
44
44
  findKeys(key: string, notKey?: string): Promise<string[]>;
45
+ /**
46
+ * Returns up to `options.limit` keys matching `key` (excluding `notKey`),
47
+ * sorted ascending. Page by passing the last returned key as `options.after`
48
+ * on the next call; the final page returns fewer than `options.limit` keys.
49
+ * Designed for memory-bounded iteration over large keyspaces.
50
+ */
51
+ findKeysPaged(key: string, notKey: string | null | undefined, options: {
52
+ limit: number;
53
+ after?: string;
54
+ }): Promise<string[]>;
45
55
  remove(key: string): Promise<void>;
46
56
  set(key: string, value: unknown): Promise<void>;
47
57
  getSub(key: string, sub: string[]): Promise<unknown>;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as normalizeLogger } from "./logging-DOvFhjsQ.js";
1
+ import { t as normalizeLogger } from "./logging-CLbyQV5A.js";
2
2
  import { promisify } from "node:util";
3
3
  //#region lib/CacheAndBufferLayer.ts
4
4
  /**
@@ -92,6 +92,7 @@ var Database$1 = class {
92
92
  "close",
93
93
  "doBulk",
94
94
  "findKeys",
95
+ "findKeysPaged",
95
96
  "get",
96
97
  "init",
97
98
  "remove",
@@ -225,6 +226,27 @@ var Database$1 = class {
225
226
  if (this.logger.isDebugEnabled()) this.logger.debug(`GET - ${key}-${notKey} - ${JSON.stringify(keyValues)} - from database `);
226
227
  return clone(keyValues);
227
228
  }
229
+ async findKeysPaged(key, notKey, options) {
230
+ if (!options || !Number.isInteger(options.limit) || options.limit <= 0) throw new Error("findKeysPaged requires a positive integer limit");
231
+ await this.flush();
232
+ if (typeof this.wrappedDB.findKeysPaged !== "function") {
233
+ const all = await this.wrappedDB.findKeys(key, notKey ?? void 0) || [];
234
+ all.sort();
235
+ const start = options.after == null ? 0 : (() => {
236
+ let lo = 0, hi = all.length;
237
+ while (lo < hi) {
238
+ const mid = lo + hi >>> 1;
239
+ if (all[mid] <= options.after) lo = mid + 1;
240
+ else hi = mid;
241
+ }
242
+ return lo;
243
+ })();
244
+ return clone(all.slice(start, start + options.limit));
245
+ }
246
+ const keys = await this.wrappedDB.findKeysPaged(key, notKey, options);
247
+ if (this.logger.isDebugEnabled()) this.logger.debug(`GET - ${key}-${notKey} (paged limit=${options.limit} after=${options.after ?? ""}) - ${JSON.stringify(keys)} - from database `);
248
+ return clone(keys);
249
+ }
228
250
  async remove(key) {
229
251
  if (this.logger.isDebugEnabled()) this.logger.debug(`DELETE - ${key} - from database `);
230
252
  await this.set(key, null);
@@ -466,23 +488,23 @@ var Database = class {
466
488
  }
467
489
  async initDB() {
468
490
  switch (this.type) {
469
- case "mysql": return new (await (import("./mysql_db-48mMBbKZ.js"))).default(this.dbSettings);
470
- case "postgres": return new (await (import("./postgres_db-7Hiezhpi.js"))).default(this.dbSettings);
471
- case "sqlite": return new (await (import("./sqlite_db-Cy8OT62U.js"))).default(this.dbSettings);
472
- case "rustydb": return new (await (import("./rusty_db-Msjxckfm.js"))).default(this.dbSettings);
473
- case "mongodb": return new (await (import("./mongodb_db-DgkIuEMZ.js"))).default(this.dbSettings);
474
- case "redis": return new (await (import("./redis_db-DKRC8sR9.js"))).default(this.dbSettings);
475
- case "cassandra": return new (await (import("./cassandra_db-B_5ANRzM.js"))).default(this.dbSettings);
476
- case "dirty": return new (await (import("./dirty_db-C1KQTMCv.js"))).default(this.dbSettings);
477
- case "dirtygit": return new (await (import("./dirty_git_db-7tkfx6PK.js"))).default(this.dbSettings);
478
- case "elasticsearch": return new (await (import("./elasticsearch_db-C6G-Wnou.js"))).default(this.dbSettings);
479
- case "memory": return new (await (import("./memory_db-CGTi0Ck-.js"))).default(this.dbSettings);
480
- case "mock": return new (await (import("./mock_db-DCUmGtUq.js"))).default(this.dbSettings);
481
- case "mssql": return new (await (import("./mssql_db-LiEvv4Sm.js"))).default(this.dbSettings);
482
- case "postgrespool": return new (await (import("./postgrespool_db-CdF-1S34.js"))).default(this.dbSettings);
483
- case "rethink": return new (await (import("./rethink_db-BGxY_SA3.js"))).default(this.dbSettings);
484
- case "couch": return new (await (import("./couch_db-BXyzauwJ.js"))).default(this.dbSettings);
485
- case "surrealdb": return new (await (import("./surrealdb_db-XnhMQEwL.js"))).default(this.dbSettings);
491
+ case "mysql": return new (await (import("./mysql_db-DIXEbML4.js"))).default(this.dbSettings);
492
+ case "postgres": return new (await (import("./postgres_db-BzDKMRC5.js"))).default(this.dbSettings);
493
+ case "sqlite": return new (await (import("./sqlite_db-Bp4nZn-c.js"))).default(this.dbSettings);
494
+ case "rustydb": return new (await (import("./rusty_db-90_S-z-w.js"))).default(this.dbSettings);
495
+ case "mongodb": return new (await (import("./mongodb_db-DJVvvNTo.js"))).default(this.dbSettings);
496
+ case "redis": return new (await (import("./redis_db-C8LRkRGe.js"))).default(this.dbSettings);
497
+ case "cassandra": return new (await (import("./cassandra_db-B96_l9V7.js"))).default(this.dbSettings);
498
+ case "dirty": return new (await (import("./dirty_db-BGvHB8ud.js"))).default(this.dbSettings);
499
+ case "dirtygit": return new (await (import("./dirty_git_db-LJWW2YT6.js"))).default(this.dbSettings);
500
+ case "elasticsearch": return new (await (import("./elasticsearch_db-D2XR08mV.js"))).default(this.dbSettings);
501
+ case "memory": return new (await (import("./memory_db-BQaHRpkv.js"))).default(this.dbSettings);
502
+ case "mock": return new (await (import("./mock_db-CgEDPTpF.js"))).default(this.dbSettings);
503
+ case "mssql": return new (await (import("./mssql_db-BqtTYXk9.js"))).default(this.dbSettings);
504
+ case "postgrespool": return new (await (import("./postgrespool_db-B6FOhTY3.js"))).default(this.dbSettings);
505
+ case "rethink": return new (await (import("./rethink_db-qv884MUM.js"))).default(this.dbSettings);
506
+ case "couch": return new (await (import("./couch_db-DZ6MLt5j.js"))).default(this.dbSettings);
507
+ case "surrealdb": return new (await (import("./surrealdb_db-K8QAySpG.js"))).default(this.dbSettings);
486
508
  default: throw new Error(`Invalid database type: ${this.type}`);
487
509
  }
488
510
  }
@@ -499,6 +521,15 @@ var Database = class {
499
521
  async findKeys(key, notKey) {
500
522
  return this.db.findKeys(key, notKey);
501
523
  }
524
+ /**
525
+ * Returns up to `options.limit` keys matching `key` (excluding `notKey`),
526
+ * sorted ascending. Page by passing the last returned key as `options.after`
527
+ * on the next call; the final page returns fewer than `options.limit` keys.
528
+ * Designed for memory-bounded iteration over large keyspaces.
529
+ */
530
+ async findKeysPaged(key, notKey, options) {
531
+ return this.db.findKeysPaged(key, notKey, options);
532
+ }
502
533
  async remove(key) {
503
534
  return this.db.remove(key);
504
535
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AbstractDatabase.d.ts","sourceRoot":"","sources":["../../lib/AbstractDatabase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,MAAM,EAAC,MAAM,WAAW,CAAC;AAOvD,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,cAAM,gBAAgB;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;gBAEd,QAAQ,EAAE,QAAQ;IAa9B,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM;IAOrD,MAAM,CAAC,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,IAAI,OAAO,IAAI,OAAO,CAAkB;CACzC;AAED,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"AbstractDatabase.d.ts","sourceRoot":"","sources":["../../lib/AbstractDatabase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,MAAM,EAAC,MAAM,WAAW,CAAC;AAOvD,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,cAAM,gBAAgB;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;gBAEd,QAAQ,EAAE,QAAQ;IAa9B,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM;IAarD,MAAM,CAAC,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,IAAI,OAAO,IAAI,OAAO,CAAkB;CACzC;AAED,eAAe,gBAAgB,CAAC"}
@@ -92,6 +92,10 @@ export declare class Database {
92
92
  get(key: string): Promise<unknown>;
93
93
  private _getLocked;
94
94
  findKeys(key: string, notKey?: string): Promise<string[]>;
95
+ findKeysPaged(key: string, notKey: string | null | undefined, options: {
96
+ limit: number;
97
+ after?: string;
98
+ }): Promise<string[]>;
95
99
  remove(key: string): Promise<void>;
96
100
  set(key: string, value: unknown): Promise<void>;
97
101
  private _setLocked;
@@ -1 +1 @@
1
- {"version":3,"file":"CacheAndBufferLayer.d.ts","sourceRoot":"","sources":["../../lib/CacheAndBufferLayer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CacheAndBufferLayer.d.ts","sourceRoot":"","sources":["../../lib/CacheAndBufferLayer.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  //#region databases/memory_db.ts
3
3
  var MemoryDB = class extends AbstractDatabase {
4
4
  _data;
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import { MongoClient } from "mongodb";
3
3
  //#region databases/mongodb_db.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import async from "async";
3
3
  import mssql from "mssql";
4
4
  //#region databases/mssql_db.ts
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import util from "util";
3
3
  import { createPool } from "mysql2";
4
4
  //#region databases/mysql_db.ts
@@ -105,6 +105,26 @@ var mysql_db_default = class extends AbstractDatabase {
105
105
  });
106
106
  return results.map((val) => val.key);
107
107
  }
108
+ async findKeysPaged(key, notKey, options) {
109
+ if (!options || !Number.isInteger(options.limit) || options.limit <= 0) throw new Error("findKeysPaged requires a positive integer limit");
110
+ let query = "SELECT `key` FROM `store` WHERE `key` LIKE ?";
111
+ const params = [key.replace(/\*/g, "%")];
112
+ if (notKey != null) {
113
+ query += " AND `key` NOT LIKE ?";
114
+ params.push(notKey.replace(/\*/g, "%"));
115
+ }
116
+ if (options.after != null) {
117
+ query += " AND BINARY `key` > ?";
118
+ params.push(options.after);
119
+ }
120
+ query += " ORDER BY BINARY `key` ASC LIMIT ?";
121
+ params.push(options.limit);
122
+ const [results] = await this._query({
123
+ sql: query,
124
+ values: params
125
+ });
126
+ return results.map((val) => val.key);
127
+ }
108
128
  async set(key, value) {
109
129
  if (key.length > 100) throw new Error("Your Key can only be 100 chars");
110
130
  await this._query({
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import async from "async";
3
3
  import * as pg from "pg";
4
4
  //#region databases/postgres_db.ts
@@ -85,6 +85,27 @@ var postgres_db_default = class extends AbstractDatabase {
85
85
  callback(err, value);
86
86
  });
87
87
  }
88
+ findKeysPaged(key, notKey, options, callback) {
89
+ if (!options || !Number.isInteger(options.limit) || options.limit <= 0) return callback(/* @__PURE__ */ new Error("findKeysPaged requires a positive integer limit"), []);
90
+ let query = "SELECT key FROM store WHERE key LIKE $1";
91
+ const params = [key.replace(/\*/g, "%")];
92
+ let n = 2;
93
+ if (notKey != null) {
94
+ query += ` AND key NOT LIKE $${n++}`;
95
+ params.push(notKey.replace(/\*/g, "%"));
96
+ }
97
+ if (options.after != null) {
98
+ query += ` AND key > $${n++}`;
99
+ params.push(options.after);
100
+ }
101
+ query += ` ORDER BY key ASC LIMIT $${n}`;
102
+ params.push(options.limit);
103
+ this.db.query(query, params, (err, results) => {
104
+ const value = [];
105
+ if (!err && results.rows.length > 0) for (const row of results.rows) value.push(row.key);
106
+ callback(err, value);
107
+ });
108
+ }
88
109
  set(key, value, callback) {
89
110
  if (key.length > 100) callback(Error("Your Key can only be 100 chars"), "");
90
111
  else if (this.upsertStatement != null) this.db.query(this.upsertStatement, [key, value], callback);
@@ -1,4 +1,4 @@
1
- import postgres_db_default from "./postgres_db-7Hiezhpi.js";
1
+ import postgres_db_default from "./postgres_db-BzDKMRC5.js";
2
2
  //#region databases/postgrespool_db.ts
3
3
  var PostgresDB = class extends postgres_db_default {
4
4
  constructor(settings) {
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import { createClient } from "redis";
3
3
  //#region databases/redis_db.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import async from "async";
3
3
  import r from "rethinkdb";
4
4
  //#region databases/rethink_db.ts
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import { KeyValueDB } from "rusty-store-kv";
3
3
  //#region databases/rusty_db.ts
4
4
  var Rusty_db = class extends AbstractDatabase {
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import { SQLite } from "rusty-store-kv";
3
3
  //#region databases/sqlite_db.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as AbstractDatabase } from "./AbstractDatabase-DfQ39Ry6.js";
1
+ import { t as AbstractDatabase } from "./AbstractDatabase-WBFqc8ye.js";
2
2
  import { Surreal } from "surrealdb";
3
3
  //#region databases/surrealdb_db.ts
4
4
  /**
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Transform every database into a object key value store",
4
4
  "url": "https://github.com/ether/ueberDB",
5
5
  "type": "module",
6
- "version": "6.0.3",
6
+ "version": "6.1.2",
7
7
  "keywords": [
8
8
  "database",
9
9
  "keyvalue"
@@ -100,28 +100,28 @@
100
100
  "@elastic/elasticsearch": "^9.4.0",
101
101
  "@types/async": "^3.2.25",
102
102
  "@types/mssql": "^12.3.0",
103
- "@types/node": "^25.7.0",
103
+ "@types/node": "^25.9.1",
104
104
  "@types/pg": "^8.20.0",
105
105
  "@types/rethinkdb": "^2.3.21",
106
106
  "@types/wtfnode": "^0.10.0",
107
107
  "cassandra-driver": "^4.9.0",
108
108
  "cli-table3": "^0.6.5",
109
109
  "mongodb": "^7.2.0",
110
- "mssql": "^12.5.2",
110
+ "mssql": "^12.5.4",
111
111
  "mysql2": "^3.22.3",
112
112
  "nano": "^11.0.5",
113
- "oxfmt": "^0.49.0",
114
- "oxlint": "^1.64.0",
115
- "pg": "^8.20.0",
113
+ "oxfmt": "^0.51.0",
114
+ "oxlint": "^1.66.0",
115
+ "pg": "^8.21.0",
116
116
  "randexp-ts": "^1.0.5",
117
117
  "redis": "^5.12.1",
118
118
  "rethinkdb": "^2.4.2",
119
- "rolldown": "^1.0.0",
119
+ "rolldown": "^1.0.2",
120
120
  "semver": "^7.8.0",
121
121
  "surrealdb": "^2.0.3",
122
122
  "testcontainers": "^11.14.0",
123
123
  "typescript": "^6.0.3",
124
- "vitest": "^4.1.6",
124
+ "vitest": "^4.1.7",
125
125
  "wtfnode": "^0.10.1"
126
126
  },
127
127
  "repository": {
@@ -143,7 +143,7 @@
143
143
  }
144
144
  ],
145
145
  "engines": {
146
- "node": ">=22.0.0"
146
+ "node": ">=24.0.0"
147
147
  },
148
148
  "scripts": {
149
149
  "lint": "oxlint",