@harperfast/rocksdb-js 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -36,16 +36,21 @@ interface DBIteratorValue<T> {
36
36
  value: T;
37
37
  }
38
38
  /**
39
- * Wraps an iterator, namely the `NativeIterator` class, and decodes the key
40
- * and value.
39
+ * Wraps the `NativeIterator` C++ binding, decoding keys and values from the
40
+ * shared key/value buffers (fast path) or from per-iteration buffers (slow
41
+ * fallback path used for oversized data or stable-buffer decoders).
42
+ *
43
+ * The native `next()` returns a primitive signal (and writes lengths to the
44
+ * shared `ITERATOR_STATE` buffer) instead of constructing a JS result object,
45
+ * so this class is responsible for building the `IteratorResult`.
41
46
  */
42
47
  declare class DBIterator<T> implements Iterator<DBIteratorValue<T>> {
43
48
  #private;
44
- iterator: Iterator<DBIteratorValue<T>>;
49
+ iterator: InstanceType<typeof NativeIteratorCls>;
45
50
  store: Store;
46
- constructor(iterator: Iterator<DBIteratorValue<T>>, store: Store, options?: IteratorOptions & T);
51
+ constructor(iterator: InstanceType<typeof NativeIteratorCls>, store: Store, includeValues: boolean);
47
52
  [Symbol.iterator](): Iterator<DBIteratorValue<T>>;
48
- next(...[_value]: [] | [any]): IteratorResult<DBIteratorValue<T>>;
53
+ next(): IteratorResult<DBIteratorValue<T>>;
49
54
  return(value?: any): IteratorResult<DBIteratorValue<T>, any>;
50
55
  throw(err: unknown): IteratorResult<DBIteratorValue<T>, any>;
51
56
  }
@@ -57,6 +62,10 @@ type StoreIteratorOptions = IteratorOptions & DBITransactional;
57
62
  type StorePutOptions = PutOptions & DBITransactional;
58
63
  type StoreRangeOptions = RangeOptions & DBITransactional;
59
64
  type StoreRemoveOptions = DBITransactional | unknown;
65
+ type CompactOptions = {
66
+ start?: Key;
67
+ end?: Key;
68
+ };
60
69
  /**
61
70
  * Options for the `Store` class.
62
71
  */
@@ -245,6 +254,28 @@ declare class Store {
245
254
  */
246
255
  close(): void;
247
256
  /**
257
+ * Compacts the entire key range of the database asynchronously.
258
+ * This triggers manual compaction which removes tombstones and reclaims space.
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * const db = RocksDatabase.open('/path/to/database');
263
+ * await db.compact();
264
+ * ```
265
+ */
266
+ compact(options?: CompactOptions): Promise<void>;
267
+ /**
268
+ * Compacts the entire key range of the database synchronously.
269
+ * This triggers manual compaction which removes tombstones and reclaims space.
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * const db = RocksDatabase.open('/path/to/database');
274
+ * db.compactSync();
275
+ * ```
276
+ */
277
+ compactSync(options?: CompactOptions): void;
278
+ /**
248
279
  * Decodes a key from the database.
249
280
  *
250
281
  * @param key - The key to decode.
@@ -429,6 +460,36 @@ type TransactionLog = {
429
460
  _lastCommittedPosition: Float64Array;
430
461
  _logBuffers: Map<number, WeakRef<LogBuffer>>;
431
462
  };
463
+ /**
464
+ * Shape of options that can be passed to the native iterator constructor for
465
+ * the rare case of advanced RocksDB ReadOptions overrides. Common iterator
466
+ * options are passed via the bitmask `flags` argument instead.
467
+ */
468
+ type NativeIteratorAdvancedOptions = {
469
+ adaptiveReadahead?: boolean;
470
+ asyncIO?: boolean;
471
+ autoReadaheadSize?: boolean;
472
+ backgroundPurgeOnIteratorCleanup?: boolean;
473
+ fillCache?: boolean;
474
+ readaheadSize?: number;
475
+ tailing?: boolean;
476
+ };
477
+ /**
478
+ * The result of a single native iterator step. A number value matches one of
479
+ * the `ITERATOR_RESULT_*` constants. The slow-path object is returned when
480
+ * the data does not fit in the shared key/value buffers, or when the decoder
481
+ * needs a stable value buffer.
482
+ */
483
+ type NativeIteratorResult = number | {
484
+ key: Buffer;
485
+ value?: Buffer;
486
+ };
487
+ declare class NativeIteratorCls {
488
+ constructor(context: StoreContext, flags: number, startKeyEnd: number, endKeyStart: number, endKeyEnd: number, options?: NativeIteratorAdvancedOptions);
489
+ next(): NativeIteratorResult;
490
+ return(): void;
491
+ throw(err?: unknown): void;
492
+ }
432
493
  type NativeDatabaseMode = "optimistic" | "pessimistic";
433
494
  type NativeDatabaseOptions = {
434
495
  disableWAL?: boolean;
@@ -469,6 +530,8 @@ type NativeDatabase = {
469
530
  clear(resolve: ResolveCallback<void>, reject: RejectCallback): void;
470
531
  clearSync(): void;
471
532
  close(): void;
533
+ compact(resolve: ResolveCallback<void>, reject: RejectCallback, start?: Key, end?: Key): void;
534
+ compactSync(start?: Key, end?: Key): void;
472
535
  columns: string[];
473
536
  destroy(): void;
474
537
  drop(resolve: ResolveCallback<void>, reject: RejectCallback): void;
@@ -497,6 +560,7 @@ type NativeDatabase = {
497
560
  removeSync(key: BufferWithDataView, txnId?: number): void;
498
561
  setDefaultKeyBuffer(buffer: Buffer | Uint8Array | null): void;
499
562
  setDefaultValueBuffer(buffer: Buffer | Uint8Array | null): void;
563
+ setIteratorState(buffer: Buffer | Uint8Array): void;
500
564
  tryLock(key: BufferWithDataView, callback?: () => void): boolean;
501
565
  unlock(key: BufferWithDataView): void;
502
566
  useLog(name: string): TransactionLog;
@@ -504,6 +568,7 @@ type NativeDatabase = {
504
568
  };
505
569
  type RocksDatabaseConfig = {
506
570
  blockCacheSize?: number;
571
+ compactOnClose?: boolean;
507
572
  };
508
573
  type RegistryStatusDB = {
509
574
  path: string;
@@ -523,6 +588,14 @@ declare const constants: {
523
588
  TRANSACTION_LOG_TOKEN: number;
524
589
  TRANSACTION_LOG_ENTRY_HEADER_SIZE: number;
525
590
  TRANSACTION_LOG_FILE_HEADER_SIZE: number;
591
+ ITERATOR_REVERSE_FLAG: number;
592
+ ITERATOR_INCLUSIVE_END_FLAG: number;
593
+ ITERATOR_EXCLUSIVE_START_FLAG: number;
594
+ ITERATOR_INCLUDE_VALUES_FLAG: number;
595
+ ITERATOR_NEEDS_STABLE_VALUE_BUFFER_FLAG: number;
596
+ ITERATOR_CONTEXT_IS_TRANSACTION_FLAG: number;
597
+ ITERATOR_RESULT_DONE: number;
598
+ ITERATOR_RESULT_FAST: number;
526
599
  };
527
600
  declare const NativeDatabase: NativeDatabase;
528
601
  declare const NativeTransaction: NativeTransaction;
@@ -975,6 +1048,28 @@ declare class RocksDatabase extends DBI<DBITransactional> {
975
1048
  */
976
1049
  close(): void;
977
1050
  /**
1051
+ * Compacts the entire key range of the database asynchronously.
1052
+ * This triggers manual compaction which removes tombstones and reclaims space.
1053
+ *
1054
+ * @example
1055
+ * ```typescript
1056
+ * const db = RocksDatabase.open('/path/to/database');
1057
+ * await db.compact();
1058
+ * ```
1059
+ */
1060
+ compact(options?: CompactOptions): Promise<void>;
1061
+ /**
1062
+ * Compacts the entire key range of the database synchronously.
1063
+ * This triggers manual compaction which removes tombstones and reclaims space.
1064
+ *
1065
+ * @example
1066
+ * ```typescript
1067
+ * const db = RocksDatabase.open('/path/to/database');
1068
+ * db.compactSync();
1069
+ * ```
1070
+ */
1071
+ compactSync(options?: CompactOptions): void;
1072
+ /**
978
1073
  * Returns the list of column families in the RocksDB database.
979
1074
  */
980
1075
  get columns(): string[];
@@ -1034,6 +1129,17 @@ declare class RocksDatabase extends DBI<DBITransactional> {
1034
1129
  */
1035
1130
  getDBProperty(propertyName: string): string | undefined;
1036
1131
  /**
1132
+ * Retrieves the estimated number of keys in the database.
1133
+ *
1134
+ * @example
1135
+ * ```typescript
1136
+ * const db = RocksDatabase.open('/path/to/database');
1137
+ * const estimated = db.getEstimatedKeyCount();
1138
+ * console.log(estimated);
1139
+ * ```
1140
+ */
1141
+ getEstimatedKeyCount(): number;
1142
+ /**
1037
1143
  * Returns the current timestamp as a monotonically increasing timestamp in
1038
1144
  * milliseconds represented as a decimal number.
1039
1145
  *
package/dist/index.d.mts CHANGED
@@ -36,16 +36,21 @@ interface DBIteratorValue<T> {
36
36
  value: T;
37
37
  }
38
38
  /**
39
- * Wraps an iterator, namely the `NativeIterator` class, and decodes the key
40
- * and value.
39
+ * Wraps the `NativeIterator` C++ binding, decoding keys and values from the
40
+ * shared key/value buffers (fast path) or from per-iteration buffers (slow
41
+ * fallback path used for oversized data or stable-buffer decoders).
42
+ *
43
+ * The native `next()` returns a primitive signal (and writes lengths to the
44
+ * shared `ITERATOR_STATE` buffer) instead of constructing a JS result object,
45
+ * so this class is responsible for building the `IteratorResult`.
41
46
  */
42
47
  declare class DBIterator<T> implements Iterator<DBIteratorValue<T>> {
43
48
  #private;
44
- iterator: Iterator<DBIteratorValue<T>>;
49
+ iterator: InstanceType<typeof NativeIteratorCls>;
45
50
  store: Store;
46
- constructor(iterator: Iterator<DBIteratorValue<T>>, store: Store, options?: IteratorOptions & T);
51
+ constructor(iterator: InstanceType<typeof NativeIteratorCls>, store: Store, includeValues: boolean);
47
52
  [Symbol.iterator](): Iterator<DBIteratorValue<T>>;
48
- next(...[_value]: [] | [any]): IteratorResult<DBIteratorValue<T>>;
53
+ next(): IteratorResult<DBIteratorValue<T>>;
49
54
  return(value?: any): IteratorResult<DBIteratorValue<T>, any>;
50
55
  throw(err: unknown): IteratorResult<DBIteratorValue<T>, any>;
51
56
  }
@@ -57,6 +62,10 @@ type StoreIteratorOptions = IteratorOptions & DBITransactional;
57
62
  type StorePutOptions = PutOptions & DBITransactional;
58
63
  type StoreRangeOptions = RangeOptions & DBITransactional;
59
64
  type StoreRemoveOptions = DBITransactional | unknown;
65
+ type CompactOptions = {
66
+ start?: Key;
67
+ end?: Key;
68
+ };
60
69
  /**
61
70
  * Options for the `Store` class.
62
71
  */
@@ -245,6 +254,28 @@ declare class Store {
245
254
  */
246
255
  close(): void;
247
256
  /**
257
+ * Compacts the entire key range of the database asynchronously.
258
+ * This triggers manual compaction which removes tombstones and reclaims space.
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * const db = RocksDatabase.open('/path/to/database');
263
+ * await db.compact();
264
+ * ```
265
+ */
266
+ compact(options?: CompactOptions): Promise<void>;
267
+ /**
268
+ * Compacts the entire key range of the database synchronously.
269
+ * This triggers manual compaction which removes tombstones and reclaims space.
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * const db = RocksDatabase.open('/path/to/database');
274
+ * db.compactSync();
275
+ * ```
276
+ */
277
+ compactSync(options?: CompactOptions): void;
278
+ /**
248
279
  * Decodes a key from the database.
249
280
  *
250
281
  * @param key - The key to decode.
@@ -429,6 +460,36 @@ type TransactionLog = {
429
460
  _lastCommittedPosition: Float64Array;
430
461
  _logBuffers: Map<number, WeakRef<LogBuffer>>;
431
462
  };
463
+ /**
464
+ * Shape of options that can be passed to the native iterator constructor for
465
+ * the rare case of advanced RocksDB ReadOptions overrides. Common iterator
466
+ * options are passed via the bitmask `flags` argument instead.
467
+ */
468
+ type NativeIteratorAdvancedOptions = {
469
+ adaptiveReadahead?: boolean;
470
+ asyncIO?: boolean;
471
+ autoReadaheadSize?: boolean;
472
+ backgroundPurgeOnIteratorCleanup?: boolean;
473
+ fillCache?: boolean;
474
+ readaheadSize?: number;
475
+ tailing?: boolean;
476
+ };
477
+ /**
478
+ * The result of a single native iterator step. A number value matches one of
479
+ * the `ITERATOR_RESULT_*` constants. The slow-path object is returned when
480
+ * the data does not fit in the shared key/value buffers, or when the decoder
481
+ * needs a stable value buffer.
482
+ */
483
+ type NativeIteratorResult = number | {
484
+ key: Buffer;
485
+ value?: Buffer;
486
+ };
487
+ declare class NativeIteratorCls {
488
+ constructor(context: StoreContext, flags: number, startKeyEnd: number, endKeyStart: number, endKeyEnd: number, options?: NativeIteratorAdvancedOptions);
489
+ next(): NativeIteratorResult;
490
+ return(): void;
491
+ throw(err?: unknown): void;
492
+ }
432
493
  type NativeDatabaseMode = "optimistic" | "pessimistic";
433
494
  type NativeDatabaseOptions = {
434
495
  disableWAL?: boolean;
@@ -469,6 +530,8 @@ type NativeDatabase = {
469
530
  clear(resolve: ResolveCallback<void>, reject: RejectCallback): void;
470
531
  clearSync(): void;
471
532
  close(): void;
533
+ compact(resolve: ResolveCallback<void>, reject: RejectCallback, start?: Key, end?: Key): void;
534
+ compactSync(start?: Key, end?: Key): void;
472
535
  columns: string[];
473
536
  destroy(): void;
474
537
  drop(resolve: ResolveCallback<void>, reject: RejectCallback): void;
@@ -497,6 +560,7 @@ type NativeDatabase = {
497
560
  removeSync(key: BufferWithDataView, txnId?: number): void;
498
561
  setDefaultKeyBuffer(buffer: Buffer | Uint8Array | null): void;
499
562
  setDefaultValueBuffer(buffer: Buffer | Uint8Array | null): void;
563
+ setIteratorState(buffer: Buffer | Uint8Array): void;
500
564
  tryLock(key: BufferWithDataView, callback?: () => void): boolean;
501
565
  unlock(key: BufferWithDataView): void;
502
566
  useLog(name: string): TransactionLog;
@@ -504,6 +568,7 @@ type NativeDatabase = {
504
568
  };
505
569
  type RocksDatabaseConfig = {
506
570
  blockCacheSize?: number;
571
+ compactOnClose?: boolean;
507
572
  };
508
573
  type RegistryStatusDB = {
509
574
  path: string;
@@ -523,6 +588,14 @@ declare const constants: {
523
588
  TRANSACTION_LOG_TOKEN: number;
524
589
  TRANSACTION_LOG_ENTRY_HEADER_SIZE: number;
525
590
  TRANSACTION_LOG_FILE_HEADER_SIZE: number;
591
+ ITERATOR_REVERSE_FLAG: number;
592
+ ITERATOR_INCLUSIVE_END_FLAG: number;
593
+ ITERATOR_EXCLUSIVE_START_FLAG: number;
594
+ ITERATOR_INCLUDE_VALUES_FLAG: number;
595
+ ITERATOR_NEEDS_STABLE_VALUE_BUFFER_FLAG: number;
596
+ ITERATOR_CONTEXT_IS_TRANSACTION_FLAG: number;
597
+ ITERATOR_RESULT_DONE: number;
598
+ ITERATOR_RESULT_FAST: number;
526
599
  };
527
600
  declare const NativeDatabase: NativeDatabase;
528
601
  declare const NativeTransaction: NativeTransaction;
@@ -975,6 +1048,28 @@ declare class RocksDatabase extends DBI<DBITransactional> {
975
1048
  */
976
1049
  close(): void;
977
1050
  /**
1051
+ * Compacts the entire key range of the database asynchronously.
1052
+ * This triggers manual compaction which removes tombstones and reclaims space.
1053
+ *
1054
+ * @example
1055
+ * ```typescript
1056
+ * const db = RocksDatabase.open('/path/to/database');
1057
+ * await db.compact();
1058
+ * ```
1059
+ */
1060
+ compact(options?: CompactOptions): Promise<void>;
1061
+ /**
1062
+ * Compacts the entire key range of the database synchronously.
1063
+ * This triggers manual compaction which removes tombstones and reclaims space.
1064
+ *
1065
+ * @example
1066
+ * ```typescript
1067
+ * const db = RocksDatabase.open('/path/to/database');
1068
+ * db.compactSync();
1069
+ * ```
1070
+ */
1071
+ compactSync(options?: CompactOptions): void;
1072
+ /**
978
1073
  * Returns the list of column families in the RocksDB database.
979
1074
  */
980
1075
  get columns(): string[];
@@ -1034,6 +1129,17 @@ declare class RocksDatabase extends DBI<DBITransactional> {
1034
1129
  */
1035
1130
  getDBProperty(propertyName: string): string | undefined;
1036
1131
  /**
1132
+ * Retrieves the estimated number of keys in the database.
1133
+ *
1134
+ * @example
1135
+ * ```typescript
1136
+ * const db = RocksDatabase.open('/path/to/database');
1137
+ * const estimated = db.getEstimatedKeyCount();
1138
+ * console.log(estimated);
1139
+ * ```
1140
+ */
1141
+ getEstimatedKeyCount(): number;
1142
+ /**
1037
1143
  * Returns the current timestamp as a monotonically increasing timestamp in
1038
1144
  * milliseconds represented as a decimal number.
1039
1145
  *
package/dist/index.mjs CHANGED
@@ -428,42 +428,62 @@ var DBI = class DBI {
428
428
 
429
429
  //#endregion
430
430
  //#region src/dbi-iterator.ts
431
+ const { ITERATOR_RESULT_DONE, ITERATOR_RESULT_FAST } = constants;
432
+ const DONE_RESULT = Object.freeze({
433
+ done: true,
434
+ value: void 0
435
+ });
431
436
  /**
432
- * Wraps an iterator, namely the `NativeIterator` class, and decodes the key
433
- * and value.
437
+ * Wraps the `NativeIterator` C++ binding, decoding keys and values from the
438
+ * shared key/value buffers (fast path) or from per-iteration buffers (slow
439
+ * fallback path used for oversized data or stable-buffer decoders).
440
+ *
441
+ * The native `next()` returns a primitive signal (and writes lengths to the
442
+ * shared `ITERATOR_STATE` buffer) instead of constructing a JS result object,
443
+ * so this class is responsible for building the `IteratorResult`.
434
444
  */
435
445
  var DBIterator = class {
436
446
  iterator;
437
447
  store;
438
448
  #includeValues;
439
- constructor(iterator, store, options) {
449
+ constructor(iterator, store, includeValues) {
440
450
  this.iterator = iterator;
441
451
  this.store = store;
442
- this.#includeValues = options?.values ?? true;
452
+ this.#includeValues = includeValues;
443
453
  }
444
454
  [Symbol.iterator]() {
445
455
  return this;
446
456
  }
447
- next(...[_value]) {
457
+ next() {
448
458
  const result = this.iterator.next();
449
- if (result.done) return result;
459
+ if (result === ITERATOR_RESULT_DONE) return DONE_RESULT;
460
+ const includeValues = this.#includeValues;
450
461
  const value = {};
451
- value.key = this.store.decodeKey(result.value.key);
452
- if (this.#includeValues) value.value = this.store.decodeValue(result.value.value);
462
+ if (result === ITERATOR_RESULT_FAST) {
463
+ value.key = this.store.readKey(KEY_BUFFER, 0, ITERATOR_STATE[0]);
464
+ if (includeValues) {
465
+ VALUE_BUFFER.end = ITERATOR_STATE[1];
466
+ value.value = this.store.decodeValue(VALUE_BUFFER);
467
+ }
468
+ } else {
469
+ const slow = result;
470
+ value.key = this.store.decodeKey(slow.key);
471
+ if (includeValues && slow.value !== void 0) value.value = this.store.decodeValue(slow.value);
472
+ }
453
473
  return {
454
474
  done: false,
455
475
  value
456
476
  };
457
477
  }
458
478
  return(value) {
459
- if (this.iterator.return) return this.iterator.return(value);
479
+ this.iterator.return?.();
460
480
  return {
461
481
  done: true,
462
482
  value
463
483
  };
464
484
  }
465
485
  throw(err) {
466
- if (this.iterator.throw) return this.iterator.throw(err);
486
+ this.iterator.throw?.(err);
467
487
  throw err;
468
488
  }
469
489
  };
@@ -538,10 +558,17 @@ function createFixedBuffer(size) {
538
558
 
539
559
  //#endregion
540
560
  //#region src/store.ts
541
- const { ONLY_IF_IN_MEMORY_CACHE_FLAG, NOT_IN_MEMORY_CACHE_FLAG, ALWAYS_CREATE_NEW_BUFFER_FLAG } = constants;
561
+ const { ONLY_IF_IN_MEMORY_CACHE_FLAG, NOT_IN_MEMORY_CACHE_FLAG, ALWAYS_CREATE_NEW_BUFFER_FLAG, ITERATOR_REVERSE_FLAG, ITERATOR_INCLUSIVE_END_FLAG, ITERATOR_EXCLUSIVE_START_FLAG, ITERATOR_INCLUDE_VALUES_FLAG, ITERATOR_NEEDS_STABLE_VALUE_BUFFER_FLAG, ITERATOR_CONTEXT_IS_TRANSACTION_FLAG } = constants;
542
562
  const KEY_BUFFER_SIZE = 4096;
543
563
  const KEY_BUFFER = createFixedBuffer(KEY_BUFFER_SIZE);
544
564
  const VALUE_BUFFER = createFixedBuffer(64 * 1024);
565
+ /**
566
+ * Backing buffer for the shared iterator state. Layout (Uint32Array view):
567
+ * [0] = key length written into KEY_BUFFER by the most recent iterator step
568
+ * [1] = value length written into VALUE_BUFFER by the most recent step
569
+ */
570
+ const ITERATOR_STATE_BUFFER = Buffer.allocUnsafeSlow(8);
571
+ const ITERATOR_STATE = new Uint32Array(ITERATOR_STATE_BUFFER.buffer, ITERATOR_STATE_BUFFER.byteOffset, 2);
545
572
  const MAX_KEY_SIZE = 1024 * 1024;
546
573
  const RESET_BUFFER_MODE = 1024;
547
574
  const REUSE_BUFFER_MODE = 512;
@@ -720,6 +747,52 @@ var Store = class {
720
747
  this.db.close();
721
748
  }
722
749
  /**
750
+ * Compacts the entire key range of the database asynchronously.
751
+ * This triggers manual compaction which removes tombstones and reclaims space.
752
+ *
753
+ * @example
754
+ * ```typescript
755
+ * const db = RocksDatabase.open('/path/to/database');
756
+ * await db.compact();
757
+ * ```
758
+ */
759
+ compact(options) {
760
+ let startBuffer;
761
+ let endBuffer;
762
+ if (options?.start !== void 0) {
763
+ const start = this.encodeKey(options.start);
764
+ startBuffer = Buffer.from(start.subarray(start.start, start.end));
765
+ }
766
+ if (options?.end !== void 0) {
767
+ const end = this.encodeKey(options.end);
768
+ endBuffer = Buffer.from(end.subarray(end.start, end.end));
769
+ }
770
+ return new Promise((resolve, reject) => this.db.compact(resolve, reject, startBuffer, endBuffer));
771
+ }
772
+ /**
773
+ * Compacts the entire key range of the database synchronously.
774
+ * This triggers manual compaction which removes tombstones and reclaims space.
775
+ *
776
+ * @example
777
+ * ```typescript
778
+ * const db = RocksDatabase.open('/path/to/database');
779
+ * db.compactSync();
780
+ * ```
781
+ */
782
+ compactSync(options) {
783
+ let startBuffer;
784
+ let endBuffer;
785
+ if (options?.start !== void 0) {
786
+ const start = this.encodeKey(options.start);
787
+ startBuffer = Buffer.from(start.subarray(start.start, start.end));
788
+ }
789
+ if (options?.end !== void 0) {
790
+ const end = this.encodeKey(options.end);
791
+ endBuffer = Buffer.from(end.subarray(end.start, end.end));
792
+ }
793
+ this.db.compactSync(startBuffer, endBuffer);
794
+ }
795
+ /**
723
796
  * Decodes a key from the database.
724
797
  *
725
798
  * @param key - The key to decode.
@@ -807,27 +880,45 @@ var Store = class {
807
880
  }
808
881
  getRange(context, options) {
809
882
  if (!this.db.opened) throw new Error("Database not open");
810
- options = { ...options };
811
- const unencodedStartKey = options.key ?? options.start;
812
- if (unencodedStartKey !== void 0) {
813
- const start = this.encodeKey(unencodedStartKey);
814
- options.start = Buffer.from(start.subarray(start.start, start.end));
883
+ let startUnencoded = options?.key ?? options?.start;
884
+ let endUnencoded = options?.key ?? options?.end;
885
+ const includeValues = options?.values ?? true;
886
+ const reverse = options?.reverse ?? false;
887
+ let exclusiveStart = options?.exclusiveStart ?? false;
888
+ let inclusiveEnd = options?.inclusiveEnd ?? false;
889
+ if (options?.key !== void 0) inclusiveEnd = true;
890
+ if (reverse) {
891
+ const tmp = startUnencoded;
892
+ startUnencoded = endUnencoded;
893
+ endUnencoded = tmp;
894
+ exclusiveStart = options?.exclusiveStart ?? true;
895
+ inclusiveEnd = options?.inclusiveEnd ?? true;
815
896
  }
816
- if (options.key !== void 0) {
817
- options.end = options.start;
818
- options.inclusiveEnd = true;
819
- } else if (options.end !== void 0) {
820
- const end = this.encodeKey(options.end);
821
- options.end = Buffer.from(end.subarray(end.start, end.end));
897
+ const keyBuffer = this.keyBuffer;
898
+ let startKeyEnd = 0;
899
+ let endKeyStart = 0;
900
+ let endKeyEnd = 0;
901
+ if (startUnencoded !== void 0) {
902
+ startKeyEnd = this.writeKey(startUnencoded, keyBuffer, 0);
903
+ if (startKeyEnd === 0) throw new Error("Zero length key is not allowed");
822
904
  }
823
- if (options.reverse) {
824
- const start = options.start;
825
- options.start = options.end;
826
- options.end = start;
827
- options.exclusiveStart = options.exclusiveStart ?? true;
828
- options.inclusiveEnd = options.inclusiveEnd ?? true;
905
+ if (endUnencoded !== void 0) if (endUnencoded === startUnencoded) {
906
+ endKeyStart = 0;
907
+ endKeyEnd = startKeyEnd;
908
+ } else {
909
+ endKeyStart = startKeyEnd;
910
+ endKeyEnd = this.writeKey(endUnencoded, keyBuffer, endKeyStart);
911
+ if (endKeyEnd === endKeyStart) throw new Error("Zero length key is not allowed");
829
912
  }
830
- return new ExtendedIterable(new DBIterator(new NativeIterator(context, options), this, options));
913
+ let flags = 0;
914
+ if (reverse) flags |= ITERATOR_REVERSE_FLAG;
915
+ if (exclusiveStart) flags |= ITERATOR_EXCLUSIVE_START_FLAG;
916
+ if (inclusiveEnd) flags |= ITERATOR_INCLUSIVE_END_FLAG;
917
+ if (includeValues) flags |= ITERATOR_INCLUDE_VALUES_FLAG;
918
+ if (includeValues && !this.decoderCopies) flags |= ITERATOR_NEEDS_STABLE_VALUE_BUFFER_FLAG;
919
+ if (context !== this.db) flags |= ITERATOR_CONTEXT_IS_TRANSACTION_FLAG;
920
+ const advancedOptions = options !== void 0 && (options.adaptiveReadahead !== void 0 || options.asyncIO !== void 0 || options.autoReadaheadSize !== void 0 || options.backgroundPurgeOnIteratorCleanup !== void 0 || options.fillCache !== void 0 || options.readaheadSize !== void 0 || options.tailing !== void 0) ? options : void 0;
921
+ return new ExtendedIterable(new DBIterator(new NativeIterator(context, flags, startKeyEnd, endKeyStart, endKeyEnd, advancedOptions), this, includeValues));
831
922
  }
832
923
  getSync(context, key, alwaysCreateNewBuffer = false, options) {
833
924
  const keyParam = getKeyParam(this.encodeKey(key));
@@ -1194,6 +1285,32 @@ var RocksDatabase = class RocksDatabase extends DBI {
1194
1285
  this.store.close();
1195
1286
  }
1196
1287
  /**
1288
+ * Compacts the entire key range of the database asynchronously.
1289
+ * This triggers manual compaction which removes tombstones and reclaims space.
1290
+ *
1291
+ * @example
1292
+ * ```typescript
1293
+ * const db = RocksDatabase.open('/path/to/database');
1294
+ * await db.compact();
1295
+ * ```
1296
+ */
1297
+ compact(options) {
1298
+ return this.store.compact(options);
1299
+ }
1300
+ /**
1301
+ * Compacts the entire key range of the database synchronously.
1302
+ * This triggers manual compaction which removes tombstones and reclaims space.
1303
+ *
1304
+ * @example
1305
+ * ```typescript
1306
+ * const db = RocksDatabase.open('/path/to/database');
1307
+ * db.compactSync();
1308
+ * ```
1309
+ */
1310
+ compactSync(options) {
1311
+ return this.store.compactSync(options);
1312
+ }
1313
+ /**
1197
1314
  * Returns the list of column families in the RocksDB database.
1198
1315
  */
1199
1316
  get columns() {
@@ -1275,6 +1392,19 @@ var RocksDatabase = class RocksDatabase extends DBI {
1275
1392
  return this.store.db.getDBProperty(propertyName);
1276
1393
  }
1277
1394
  /**
1395
+ * Retrieves the estimated number of keys in the database.
1396
+ *
1397
+ * @example
1398
+ * ```typescript
1399
+ * const db = RocksDatabase.open('/path/to/database');
1400
+ * const estimated = db.getEstimatedKeyCount();
1401
+ * console.log(estimated);
1402
+ * ```
1403
+ */
1404
+ getEstimatedKeyCount() {
1405
+ return this.getDBIntProperty("rocksdb.estimate-num-keys") ?? 0;
1406
+ }
1407
+ /**
1278
1408
  * Returns the current timestamp as a monotonically increasing timestamp in
1279
1409
  * milliseconds represented as a decimal number.
1280
1410
  *
@@ -1413,6 +1543,7 @@ var RocksDatabase = class RocksDatabase extends DBI {
1413
1543
  if (store.open()) return this;
1414
1544
  store.db.setDefaultValueBuffer(VALUE_BUFFER);
1415
1545
  store.db.setDefaultKeyBuffer(KEY_BUFFER);
1546
+ store.db.setIteratorState(ITERATOR_STATE_BUFFER);
1416
1547
  /**
1417
1548
  * The encoder initialization precedence is:
1418
1549
  * 1. encoder.Encoder
@@ -1784,6 +1915,7 @@ Object.defineProperty(TransactionLog.prototype, "query", { value({ start, end, e
1784
1915
  logBuffer.logId = 0;
1785
1916
  logBuffer.size = 0;
1786
1917
  logBuffer.dataView = new DataView(logBuffer.buffer);
1918
+ size = 0;
1787
1919
  }
1788
1920
  }
1789
1921
  dataView = logBuffer.dataView;
@@ -1911,7 +2043,7 @@ function loadLastPosition(transactionLog, readUncommitted) {
1911
2043
  //#region src/index.ts
1912
2044
  const versions = {
1913
2045
  rocksdb: version,
1914
- "rocksdb-js": "1.1.1"
2046
+ "rocksdb-js": "1.2.0"
1915
2047
  };
1916
2048
 
1917
2049
  //#endregion