ioredis-toolkit 0.0.9 → 0.0.10

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/cache.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { RedisClientWrapper } from './client.js';
2
- import { CacheOptions, CacheInputConfig } from './types.js';
3
- import { LoggerLike } from './logger.js';
1
+ import { RedisClientWrapper } from "./client.js";
2
+ import { CacheOptions, CacheInputConfig } from "./types.js";
3
+ import { LoggerLike } from "./logger.js";
4
4
  /**
5
5
  * Cache layer on top of {@link RedisClientWrapper} with JSON serialization,
6
6
  * optional gzip compression and namespace support.
@@ -32,7 +32,7 @@ export declare class Cache {
32
32
  * applied when no per-call TTL is specified.
33
33
  * - `compressionThreshold` (number, optional, default: `1024`) - Byte threshold
34
34
  * above which values are gzip-compressed transparently.
35
- * - `namespace` (string, optional, default: `cache`) - Namespace prefix for all keys.
35
+ * - `namespace` (string, optional, default: `''`) - Namespace prefix for all keys.
36
36
  * - `logger` - Optional pino-compatible logger. Supports `trace/debug/info/warn/error/fatal`
37
37
  * levels and `child()` for namespace logging. Defaults to `console`.
38
38
  *
@@ -41,12 +41,13 @@ export declare class Cache {
41
41
  *
42
42
  * **Example:**
43
43
  * ```ts
44
- * const cache = new Cache(client, { defaultTTL: 600, compressionThreshold: 2048, namespace: "myapp" });
44
+ * const cache = new Cache(client, { defaultTTL: 600, compressionThreshold: 2048, namespace: 'myapp' });
45
45
  * ```
46
46
  */
47
47
  constructor(client: RedisClientWrapper, config: CacheInputConfig, logger?: LoggerLike);
48
48
  private serialize;
49
49
  private deserialize;
50
+ private get getNamespace();
50
51
  private getKey;
51
52
  /**
52
53
  * Reads a cached value.
@@ -134,7 +135,7 @@ export declare class Cache {
134
135
  *
135
136
  * **Type Parameters:**
136
137
  * - `T` - The type of the value being stored. Can be any serializable JavaScript value.
137
- *
138
+ *
138
139
  * **Returns:**
139
140
  * - `true` when the value was stored successfully (`result === 'OK'`).
140
141
  *
@@ -268,36 +269,36 @@ export declare class Cache {
268
269
  * ```
269
270
  */
270
271
  /**
271
- * Reads multiple cache keys in one call.
272
- *
273
- * **Behavior:**
274
- * - Cluster-safe: keys are grouped by hash slot under the hood, avoiding CROSS-SLOT errors.
275
- * - Values are deserialized from JSON when stored as JSON. Strings/numbers/buffers
276
- * are returned as-is.
277
- * - Missing keys return `null` in the corresponding position.
278
- *
279
- * **Type Parameters:**
280
- * - `T` - The expected type of each returned value. When the stored value is JSON,
281
- * it will be parsed and coerced to `T`.
282
- *
283
- * **Returns:**
284
- * - An array of values in the same order as the input `keys`. Each element is `T | null`.
285
- * `null` indicates the key did not exist.
286
- *
287
- * **Example:**
288
- * ```ts
289
- * const [a, b] = await cache.mget(['user:1', 'user:2']);
290
- * // a === { name: 'alice' }, b === { name: 'bob' }
291
- * ```
292
- *
293
- * **Parameters:**
294
- * - `keys` - Cache keys to read. Will have the namespace prefix applied automatically
295
- * if a namespace is configured.
296
- * - `namespace` - Optional namespace prefix applied to every key. When provided,
297
- * each key is internally transformed to `${namespace}:${key}`.
298
- *
299
- * @returns Values in input order; `null` for missing keys.
300
- */
272
+ * Reads multiple cache keys in one call.
273
+ *
274
+ * **Behavior:**
275
+ * - Cluster-safe: keys are grouped by hash slot under the hood, avoiding CROSS-SLOT errors.
276
+ * - Values are deserialized from JSON when stored as JSON. Strings/numbers/buffers
277
+ * are returned as-is.
278
+ * - Missing keys return `null` in the corresponding position.
279
+ *
280
+ * **Type Parameters:**
281
+ * - `T` - The expected type of each returned value. When the stored value is JSON,
282
+ * it will be parsed and coerced to `T`.
283
+ *
284
+ * **Returns:**
285
+ * - An array of values in the same order as the input `keys`. Each element is `T | null`.
286
+ * `null` indicates the key did not exist.
287
+ *
288
+ * **Example:**
289
+ * ```ts
290
+ * const [a, b] = await cache.mget(['user:1', 'user:2']);
291
+ * // a === { name: 'alice' }, b === { name: 'bob' }
292
+ * ```
293
+ *
294
+ * **Parameters:**
295
+ * - `keys` - Cache keys to read. Will have the namespace prefix applied automatically
296
+ * if a namespace is configured.
297
+ * - `namespace` - Optional namespace prefix applied to every key. When provided,
298
+ * each key is internally transformed to `${namespace}:${key}`.
299
+ *
300
+ * @returns Values in input order; `null` for missing keys.
301
+ */
301
302
  mget<T = any>(keys: string[], namespace?: string): Promise<(T | null)[]>;
302
303
  /**
303
304
  * Stores multiple key/value entries in one call.
@@ -368,7 +369,7 @@ export declare class Cache {
368
369
  *
369
370
  * **Returns:**
370
371
  * - `true` if the key existed and was deleted.
371
- *
372
+ *
372
373
  * **Example:**
373
374
  * ```ts
374
375
  * const removed = await cache.delete('user:1');
package/dist/cache.js CHANGED
@@ -1,6 +1,6 @@
1
- import zlib from 'node:zlib';
2
- import { promisify } from 'node:util';
3
- import { defaultLogger } from './logger.js';
1
+ import zlib from "node:zlib";
2
+ import { promisify } from "node:util";
3
+ import { defaultLogger } from "./logger.js";
4
4
  const gzip = promisify(zlib.gzip);
5
5
  const gunzip = promisify(zlib.gunzip);
6
6
  /**
@@ -35,7 +35,7 @@ export class Cache {
35
35
  * applied when no per-call TTL is specified.
36
36
  * - `compressionThreshold` (number, optional, default: `1024`) - Byte threshold
37
37
  * above which values are gzip-compressed transparently.
38
- * - `namespace` (string, optional, default: `cache`) - Namespace prefix for all keys.
38
+ * - `namespace` (string, optional, default: `''`) - Namespace prefix for all keys.
39
39
  * - `logger` - Optional pino-compatible logger. Supports `trace/debug/info/warn/error/fatal`
40
40
  * levels and `child()` for namespace logging. Defaults to `console`.
41
41
  *
@@ -44,16 +44,16 @@ export class Cache {
44
44
  *
45
45
  * **Example:**
46
46
  * ```ts
47
- * const cache = new Cache(client, { defaultTTL: 600, compressionThreshold: 2048, namespace: "myapp" });
47
+ * const cache = new Cache(client, { defaultTTL: 600, compressionThreshold: 2048, namespace: 'myapp' });
48
48
  * ```
49
49
  */
50
50
  constructor(client, config, logger = defaultLogger) {
51
51
  this.client = client;
52
- this.logger = logger.child({ component: 'Cache' });
52
+ this.logger = logger.child({ component: "Cache" });
53
53
  // this.config = config;
54
54
  this.defaultTTL = config.defaultTTL || 3600;
55
55
  this.compressionThreshold = config.compressionThreshold || 1024;
56
- this.namespace = config.namespace?.trim() || "cache";
56
+ this.namespace = config.namespace || "";
57
57
  }
58
58
  async serialize(value) {
59
59
  // Convert to Buffer
@@ -61,10 +61,10 @@ export class Cache {
61
61
  if (Buffer.isBuffer(value)) {
62
62
  data = value;
63
63
  }
64
- else if (typeof value === 'string') {
64
+ else if (typeof value === "string") {
65
65
  data = Buffer.from(value);
66
66
  }
67
- else if (typeof value === 'number' || typeof value === 'boolean') {
67
+ else if (typeof value === "number" || typeof value === "boolean") {
68
68
  data = Buffer.from(String(value));
69
69
  }
70
70
  else {
@@ -78,7 +78,7 @@ export class Cache {
78
78
  return { data: compressed, compressed: true };
79
79
  }
80
80
  catch (error) {
81
- this.logger.warn('Compression failed, storing uncompressed');
81
+ this.logger.warn("Compression failed, storing uncompressed");
82
82
  return { data, compressed: false };
83
83
  }
84
84
  }
@@ -91,14 +91,14 @@ export class Cache {
91
91
  buffer = await gunzip(data);
92
92
  }
93
93
  catch (error) {
94
- this.logger.warn('Decompression failed, trying raw data');
94
+ this.logger.warn("Decompression failed, trying raw data");
95
95
  // Attempt to use raw data if decompression fails
96
96
  }
97
97
  }
98
98
  // Try to parse as JSON if it looks like JSON
99
99
  const str = buffer.toString();
100
100
  try {
101
- if (str.startsWith('{') || str.startsWith('[')) {
101
+ if (str.startsWith("{") || str.startsWith("[")) {
102
102
  return JSON.parse(str);
103
103
  }
104
104
  }
@@ -107,11 +107,14 @@ export class Cache {
107
107
  }
108
108
  return str;
109
109
  }
110
+ get getNamespace() {
111
+ return this.namespace?.trim() ? `${this.namespace}:` : "";
112
+ }
110
113
  getKey(key, namespace) {
111
114
  if (namespace?.trim()) {
112
- return `${this.namespace}:${namespace.trim()}:${key}`;
115
+ return `${this.getNamespace}${namespace.trim()}:${key}`;
113
116
  }
114
- return `${this.namespace}:${key}`;
117
+ return `${this.getNamespace}${key}`;
115
118
  }
116
119
  /**
117
120
  * Reads a cached value.
@@ -176,7 +179,7 @@ export class Cache {
176
179
  // Check if stored with metadata
177
180
  const parsed = JSON.parse(raw);
178
181
  if (parsed._compressed && parsed._data) {
179
- const data = Buffer.from(parsed._data, 'base64');
182
+ const data = Buffer.from(parsed._data, "base64");
180
183
  return this.deserialize(data, parsed._compressed);
181
184
  }
182
185
  // Legacy format - try to parse as JSON
@@ -218,7 +221,7 @@ export class Cache {
218
221
  *
219
222
  * **Type Parameters:**
220
223
  * - `T` - The type of the value being stored. Can be any serializable JavaScript value.
221
- *
224
+ *
222
225
  * **Returns:**
223
226
  * - `true` when the value was stored successfully (`result === 'OK'`).
224
227
  *
@@ -256,7 +259,7 @@ export class Cache {
256
259
  // Store with metadata
257
260
  rawValue = JSON.stringify({
258
261
  _compressed: true,
259
- _data: data.toString('base64'),
262
+ _data: data.toString("base64"),
260
263
  });
261
264
  }
262
265
  else {
@@ -264,7 +267,7 @@ export class Cache {
264
267
  }
265
268
  }
266
269
  else {
267
- if (typeof value === 'string') {
270
+ if (typeof value === "string") {
268
271
  rawValue = value;
269
272
  }
270
273
  else if (Buffer.isBuffer(value)) {
@@ -275,11 +278,15 @@ export class Cache {
275
278
  }
276
279
  }
277
280
  const result = await this.client.set(fullKey, rawValue, ttl);
278
- this.logger.debug('Cache set', { key: fullKey, ttl, compressed: shouldCompress });
279
- return result === 'OK';
281
+ this.logger.debug("Cache set", {
282
+ key: fullKey,
283
+ ttl,
284
+ compressed: shouldCompress,
285
+ });
286
+ return result === "OK";
280
287
  }
281
288
  catch (error) {
282
- this.logger.error('Cache set failed:', error);
289
+ this.logger.error("Cache set failed:", error);
283
290
  return false;
284
291
  }
285
292
  }
@@ -330,12 +337,12 @@ export class Cache {
330
337
  const fullKey = this.getKey(key, options.namespace);
331
338
  const ttl = options.ttl || this.defaultTTL;
332
339
  try {
333
- const rawValue = typeof value === 'string' ? value : JSON.stringify(value);
340
+ const rawValue = typeof value === "string" ? value : JSON.stringify(value);
334
341
  const result = await this.client.setnx(fullKey, rawValue, ttl);
335
342
  return result === 1;
336
343
  }
337
344
  catch (error) {
338
- this.logger.error('Cache setNX failed:', error);
345
+ this.logger.error("Cache setNX failed:", error);
339
346
  return false;
340
347
  }
341
348
  }
@@ -390,12 +397,12 @@ export class Cache {
390
397
  const fullKey = this.getKey(key, options.namespace);
391
398
  const ttl = options.ttl || this.defaultTTL;
392
399
  try {
393
- const rawValue = typeof value === 'string' ? value : JSON.stringify(value);
400
+ const rawValue = typeof value === "string" ? value : JSON.stringify(value);
394
401
  const result = await this.client.setexnx(fullKey, rawValue, ttl);
395
- return result === 'OK';
402
+ return result === "OK";
396
403
  }
397
404
  catch (error) {
398
- this.logger.error('Cache setEXNX failed:', error);
405
+ this.logger.error("Cache setEXNX failed:", error);
399
406
  return false;
400
407
  }
401
408
  }
@@ -436,38 +443,38 @@ export class Cache {
436
443
  * ```
437
444
  */
438
445
  /**
439
- * Reads multiple cache keys in one call.
440
- *
441
- * **Behavior:**
442
- * - Cluster-safe: keys are grouped by hash slot under the hood, avoiding CROSS-SLOT errors.
443
- * - Values are deserialized from JSON when stored as JSON. Strings/numbers/buffers
444
- * are returned as-is.
445
- * - Missing keys return `null` in the corresponding position.
446
- *
447
- * **Type Parameters:**
448
- * - `T` - The expected type of each returned value. When the stored value is JSON,
449
- * it will be parsed and coerced to `T`.
450
- *
451
- * **Returns:**
452
- * - An array of values in the same order as the input `keys`. Each element is `T | null`.
453
- * `null` indicates the key did not exist.
454
- *
455
- * **Example:**
456
- * ```ts
457
- * const [a, b] = await cache.mget(['user:1', 'user:2']);
458
- * // a === { name: 'alice' }, b === { name: 'bob' }
459
- * ```
460
- *
461
- * **Parameters:**
462
- * - `keys` - Cache keys to read. Will have the namespace prefix applied automatically
463
- * if a namespace is configured.
464
- * - `namespace` - Optional namespace prefix applied to every key. When provided,
465
- * each key is internally transformed to `${namespace}:${key}`.
466
- *
467
- * @returns Values in input order; `null` for missing keys.
468
- */
446
+ * Reads multiple cache keys in one call.
447
+ *
448
+ * **Behavior:**
449
+ * - Cluster-safe: keys are grouped by hash slot under the hood, avoiding CROSS-SLOT errors.
450
+ * - Values are deserialized from JSON when stored as JSON. Strings/numbers/buffers
451
+ * are returned as-is.
452
+ * - Missing keys return `null` in the corresponding position.
453
+ *
454
+ * **Type Parameters:**
455
+ * - `T` - The expected type of each returned value. When the stored value is JSON,
456
+ * it will be parsed and coerced to `T`.
457
+ *
458
+ * **Returns:**
459
+ * - An array of values in the same order as the input `keys`. Each element is `T | null`.
460
+ * `null` indicates the key did not exist.
461
+ *
462
+ * **Example:**
463
+ * ```ts
464
+ * const [a, b] = await cache.mget(['user:1', 'user:2']);
465
+ * // a === { name: 'alice' }, b === { name: 'bob' }
466
+ * ```
467
+ *
468
+ * **Parameters:**
469
+ * - `keys` - Cache keys to read. Will have the namespace prefix applied automatically
470
+ * if a namespace is configured.
471
+ * - `namespace` - Optional namespace prefix applied to every key. When provided,
472
+ * each key is internally transformed to `${namespace}:${key}`.
473
+ *
474
+ * @returns Values in input order; `null` for missing keys.
475
+ */
469
476
  async mget(keys, namespace) {
470
- const fullKeys = keys.map(k => this.getKey(k, namespace));
477
+ const fullKeys = keys.map((k) => this.getKey(k, namespace));
471
478
  const raw = await this.client.mgetClusterAware(fullKeys);
472
479
  return Promise.all(raw.map(async (item) => {
473
480
  if (!item)
@@ -475,7 +482,7 @@ export class Cache {
475
482
  try {
476
483
  const parsed = JSON.parse(item);
477
484
  if (parsed._compressed && parsed._data) {
478
- const data = Buffer.from(parsed._data, 'base64');
485
+ const data = Buffer.from(parsed._data, "base64");
479
486
  return this.deserialize(data, parsed._compressed);
480
487
  }
481
488
  return parsed;
@@ -564,7 +571,7 @@ export class Cache {
564
571
  const groups = new Map();
565
572
  for (const [key, value] of Object.entries(entries)) {
566
573
  const fullKey = this.getKey(key, namespace);
567
- const rawValue = typeof value === 'string' ? value : JSON.stringify(value);
574
+ const rawValue = typeof value === "string" ? value : JSON.stringify(value);
568
575
  const slot = this.client.calculateSlot(fullKey);
569
576
  if (!groups.has(slot)) {
570
577
  groups.set(slot, []);
@@ -574,17 +581,17 @@ export class Cache {
574
581
  for (const group of groups.values()) {
575
582
  const pipeline = this.client.pipeline();
576
583
  for (const [fullKey, rawValue] of group) {
577
- pipeline.set(fullKey, rawValue, 'EX', ttl);
584
+ pipeline.set(fullKey, rawValue, "EX", ttl);
578
585
  }
579
586
  const results = await pipeline.exec();
580
- if (!results?.every((result) => result[1] === 'OK')) {
587
+ if (!results?.every((result) => result[1] === "OK")) {
581
588
  return false;
582
589
  }
583
590
  }
584
591
  return true;
585
592
  }
586
593
  catch (error) {
587
- this.logger.error('Cache mset failed:', error);
594
+ this.logger.error("Cache mset failed:", error);
588
595
  return false;
589
596
  }
590
597
  }
@@ -609,7 +616,7 @@ export class Cache {
609
616
  *
610
617
  * **Returns:**
611
618
  * - `true` if the key existed and was deleted.
612
- *
619
+ *
613
620
  * **Example:**
614
621
  * ```ts
615
622
  * const removed = await cache.delete('user:1');
@@ -918,7 +925,7 @@ export class Cache {
918
925
  */
919
926
  async hset(key, field, value, namespace) {
920
927
  const fullKey = this.getKey(key, namespace);
921
- const rawValue = typeof value === 'string' ? value : JSON.stringify(value);
928
+ const rawValue = typeof value === "string" ? value : JSON.stringify(value);
922
929
  const result = await this.client.hset(fullKey, field, rawValue);
923
930
  return result === 1;
924
931
  }
@@ -1012,13 +1019,7 @@ export class Cache {
1012
1019
  * @returns The number of deleted keys.
1013
1020
  */
1014
1021
  async deletePattern(pattern, namespace) {
1015
- let fullPattern;
1016
- if (namespace?.trim()) {
1017
- fullPattern = `${this.namespace}:${namespace.trim()}:${pattern}`;
1018
- }
1019
- else {
1020
- fullPattern = `${this.namespace}:${pattern}`;
1021
- }
1022
+ const fullPattern = this.getKey(pattern, namespace);
1022
1023
  let deleted = 0;
1023
1024
  for await (const key of this.client.scanIterator(fullPattern)) {
1024
1025
  const result = await this.client.del(key);
@@ -1067,13 +1068,7 @@ export class Cache {
1067
1068
  * @returns Matching keys.
1068
1069
  */
1069
1070
  async keys(pattern, namespace) {
1070
- let fullPattern;
1071
- if (namespace?.trim()) {
1072
- fullPattern = `${this.namespace}:${namespace.trim()}:${pattern}`;
1073
- }
1074
- else {
1075
- fullPattern = `${this.namespace}:${pattern}`;
1076
- }
1071
+ const fullPattern = this.getKey(pattern, namespace);
1077
1072
  const keys = [];
1078
1073
  for await (const key of this.client.scanIterator(fullPattern)) {
1079
1074
  keys.push(key);
@@ -1115,6 +1110,6 @@ export class Cache {
1115
1110
  * @returns The number of deleted keys.
1116
1111
  */
1117
1112
  async clearNamespace(namespace) {
1118
- return this.deletePattern('*', namespace);
1113
+ return this.deletePattern("*", namespace);
1119
1114
  }
1120
1115
  }
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Cluster, Redis as RedisClient } from "ioredis";
2
- import { RateLimitOptionsInput, type ClusterInfo, type ClusterSlotRange, type ConnectionStatus, type RedisConfigInput, type RedisMode, DistributedLockInputOptions, CacheInputConfig } from "./types.js";
2
+ import { RateLimitOptionsInput, type ClusterInfo, type ClusterRedisConfig, type ClusterSlotRange, type ConnectionStatus, type RedisConfig, type RedisConfigInput, type RedisMode, type SentinelRedisConfig, type StandaloneRedisConfig, DistributedLockInputOptions, CacheInputConfig } from "./types.js";
3
3
  import { type LoggerLike } from "./logger.js";
4
4
  import { Cache } from "./cache.js";
5
5
  import { PubSub } from "./pubsub.js";
@@ -48,6 +48,9 @@ type DeletePatternOptions = {
48
48
  batchSize?: number;
49
49
  scanCount?: number;
50
50
  };
51
+ export declare function isClusterConfig(config: RedisConfig): config is ClusterRedisConfig;
52
+ export declare function isSentinelConfig(config: RedisConfig): config is SentinelRedisConfig;
53
+ export declare function isStandaloneConfig(config: RedisConfig): config is StandaloneRedisConfig;
51
54
  /**
52
55
  * Production-grade Redis client wrapper supporting:
53
56
  *
package/dist/client.js CHANGED
@@ -15,13 +15,13 @@ import { deepMerge } from "./utils/deepmerge.js";
15
15
  // ============================================================================
16
16
  // Type Guards
17
17
  // ============================================================================
18
- function isClusterConfig(config) {
18
+ export function isClusterConfig(config) {
19
19
  return config.mode === "cluster";
20
20
  }
21
- function isSentinelConfig(config) {
21
+ export function isSentinelConfig(config) {
22
22
  return config.mode === "sentinel";
23
23
  }
24
- function isStandaloneConfig(config) {
24
+ export function isStandaloneConfig(config) {
25
25
  return config.mode === "standalone";
26
26
  }
27
27
  // ============================================================================
@@ -295,7 +295,6 @@ export class RedisClientWrapper {
295
295
  revocationStore: options.revocationStore ?? this.revocationStore,
296
296
  };
297
297
  this._session = createSessionManager(params);
298
- void this._session.init();
299
298
  this.config.sessionOptions = params;
300
299
  }
301
300
  return this._session;
package/dist/lock.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { RedisClientWrapper } from './client.js';
2
2
  import { LoggerLike } from './logger.js';
3
+ import { DistributedLockOptions, LockInfo } from './types.js';
3
4
  /**
4
5
  * Information about a distributed lock.
5
6
  *
@@ -14,14 +15,6 @@ import { LoggerLike } from './logger.js';
14
15
  * // { locked: true, ttl: 29, lockId: 'a1b2c3...' }
15
16
  * ```
16
17
  */
17
- export type LockInfo = {
18
- /** Whether the lock is currently held. */
19
- locked: boolean;
20
- /** Remaining TTL in seconds (when held and TTL set). */
21
- ttl?: number;
22
- /** Unique owner id of the lock. */
23
- lockId?: string;
24
- };
25
18
  /**
26
19
  * Options for the distributed lock.
27
20
  *
@@ -35,14 +28,6 @@ export type LockInfo = {
35
28
  * const lock = new DistributedLock(client, { ttl: 10000, retryCount: 5 });
36
29
  * ```
37
30
  */
38
- export interface DistributedLockOptions {
39
- /** Lock TTL in milliseconds. Default: `30000`. */
40
- ttl?: number;
41
- /** Number of acquisition attempts. Default: `3`. */
42
- retryCount?: number;
43
- /** Base delay between retries in ms (grows exponentially). Default: `200`. */
44
- retryDelay?: number;
45
- }
46
31
  /**
47
32
  * Distributed mutual-exclusion lock backed by Redis.
48
33
  *
package/dist/lock.js CHANGED
@@ -1,6 +1,49 @@
1
1
  import { RedisError } from './errors.js';
2
2
  import { randomBytes } from 'node:crypto';
3
3
  import { defaultLogger } from './logger.js';
4
+ /**
5
+ * Information about a distributed lock.
6
+ *
7
+ * **Fields:**
8
+ * - `locked`: Whether the lock is currently held.
9
+ * - `ttl`: Remaining TTL in seconds (when held and TTL set).
10
+ * - `lockId`: Unique owner id of the lock.
11
+ *
12
+ * **Example:**
13
+ * ```ts
14
+ * const info = await lock.getLockInfo('order:42');
15
+ * // { locked: true, ttl: 29, lockId: 'a1b2c3...' }
16
+ * ```
17
+ */
18
+ // export type LockInfo = {
19
+ // /** Whether the lock is currently held. */
20
+ // locked: boolean;
21
+ // /** Remaining TTL in seconds (when held and TTL set). */
22
+ // ttl?: number;
23
+ // /** Unique owner id of the lock. */
24
+ // lockId?: string;
25
+ // };
26
+ /**
27
+ * Options for the distributed lock.
28
+ *
29
+ * **Fields:**
30
+ * - `ttl`: Lock TTL in milliseconds. Default: `30000`.
31
+ * - `retryCount`: Number of acquisition attempts. Default: `3`.
32
+ * - `retryDelay`: Base delay between retries in ms (grows exponentially). Default: `200`.
33
+ *
34
+ * **Example:**
35
+ * ```ts
36
+ * const lock = new DistributedLock(client, { ttl: 10000, retryCount: 5 });
37
+ * ```
38
+ */
39
+ // export interface DistributedLockOptions {
40
+ // /** Lock TTL in milliseconds. Default: `30000`. */
41
+ // ttl?: number;
42
+ // /** Number of acquisition attempts. Default: `3`. */
43
+ // retryCount?: number;
44
+ // /** Base delay between retries in ms (grows exponentially). Default: `200`. */
45
+ // retryDelay?: number;
46
+ // }
4
47
  /**
5
48
  * Distributed mutual-exclusion lock backed by Redis.
6
49
  *