descript-redis-cache 4.1.0 → 5.0.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/README.md CHANGED
@@ -6,16 +6,21 @@ Plugin to use Redis as a cache in Descript
6
6
  ```js
7
7
  import de from 'descript';
8
8
  import { Cache } from 'descript-redis-cache';
9
+ import { createSentinel } from '@redis/client';
9
10
 
10
- const redisCache = new Cache(options);
11
+ const sentinel = await createSentinel({
12
+ name: 'sentinel-db',
13
+ sentinelRootNodes: [{
14
+ host: 'localhost',
15
+ port: 1234
16
+ }]
17
+ })
18
+ // subscribe to events if necessary
19
+ .on('error', err => console.error('Redis Sentinel Error', err))
20
+ .connect();
11
21
 
12
- // subscribe to events if necessary
13
- // @see https://github.com/luin/ioredis#connection-events
14
- redisCache.getClient()
15
- .on('reconnecting', () => {/* ... */})
16
- .on('error', () => {/* ... */})
17
- .on('close', () => {/* ... */})
18
- .on('end', () => {/* ... */});
22
+
23
+ const redisCache = new Cache({ client: sentinel });
19
24
 
20
25
  const myBlock = de.http({
21
26
  block: { /* ... */ },
@@ -38,7 +43,7 @@ export interface Options {
38
43
  generation?: number;
39
44
  // read timeout in milliseconds (default: 100)
40
45
  readTimeout?: number;
41
- redis: RedisOptions | { startupNodes: ClusterNode[], options?: ClusterOptions };
46
+ client: `client fron @redis/client`;
42
47
  }
43
48
  ```
44
49
 
package/build/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { CacheInterface, LoggerInterface } from 'descript';
2
- import type { ClusterNode, ClusterOptions, RedisOptions } from 'ioredis';
3
- import { Cluster, Redis } from 'ioredis';
2
+ import type { RedisClientType, RedisClusterType, RedisSentinelType } from '@redis/client';
3
+ type RedisClient = RedisClientType | RedisSentinelType | RedisClusterType;
4
4
  export interface Options {
5
5
  /** key TTL in seconds (default: 60 * 60 * 24) */
6
6
  defaultKeyTTL?: number;
@@ -8,13 +8,8 @@ export interface Options {
8
8
  generation?: number;
9
9
  /** read timeout in milliseconds (default: 100) */
10
10
  readTimeout?: number;
11
- /** use two clients (reader and writer) with Sentinel (default: false) */
12
- useReaderAndWriterWithSentinel?: boolean;
13
- /** redis config */
14
- redis: RedisOptions | {
15
- startupNodes: ClusterNode[];
16
- options?: ClusterOptions;
17
- };
11
+ /** @redis/client */
12
+ client: RedisClient;
18
13
  }
19
14
  type Logger = LoggerInterface<LoggerEvent>;
20
15
  interface Timers {
@@ -22,65 +17,65 @@ interface Timers {
22
17
  end: number;
23
18
  }
24
19
  export type LoggerEvent = ({
25
- type: EVENT.REDIS_CACHE_INITIALIZED;
20
+ 'type': EVENT.REDIS_CACHE_INITIALIZED;
26
21
  options: Options;
27
22
  } | {
28
- type: EVENT.REDIS_CACHE_READ_START;
23
+ 'type': EVENT.REDIS_CACHE_READ_START;
29
24
  key: string;
30
25
  normalizedKey: string;
31
26
  } | {
32
- type: EVENT.REDIS_CACHE_READ_KEY_NOT_FOUND;
27
+ 'type': EVENT.REDIS_CACHE_READ_KEY_NOT_FOUND;
33
28
  key: string;
34
29
  normalizedKey: string;
35
30
  timers: Timers;
36
31
  } | {
37
- type: EVENT.REDIS_CACHE_READ_TIMEOUT;
32
+ 'type': EVENT.REDIS_CACHE_READ_TIMEOUT;
38
33
  key: string;
39
34
  normalizedKey: string;
40
35
  timers: Timers;
41
36
  } | {
42
- type: EVENT.REDIS_CACHE_READ_ERROR;
37
+ 'type': EVENT.REDIS_CACHE_READ_ERROR;
43
38
  error: Error;
44
39
  key: string;
45
40
  normalizedKey: string;
46
41
  timers: Timers;
47
42
  } | {
48
- type: EVENT.REDIS_CACHE_JSON_PARSING_FAILED;
43
+ 'type': EVENT.REDIS_CACHE_JSON_PARSING_FAILED;
49
44
  data: unknown;
50
45
  error: unknown;
51
46
  key: string;
52
47
  normalizedKey: string;
53
48
  timers: Timers;
54
49
  } | {
55
- type: EVENT.REDIS_CACHE_READ_DONE;
50
+ 'type': EVENT.REDIS_CACHE_READ_DONE;
56
51
  data: unknown;
57
52
  key: string;
58
53
  normalizedKey: string;
59
54
  timers: Timers;
60
55
  } | {
61
- type: EVENT.REDIS_CACHE_WRITE_START;
56
+ 'type': EVENT.REDIS_CACHE_WRITE_START;
62
57
  key: string;
63
58
  normalizedKey: string;
64
59
  } | {
65
- type: EVENT.REDIS_CACHE_JSON_STRINGIFY_FAILED;
60
+ 'type': EVENT.REDIS_CACHE_JSON_STRINGIFY_FAILED;
66
61
  data: unknown;
67
62
  error: unknown;
68
63
  key: string;
69
64
  normalizedKey: string;
70
65
  timers: Timers;
71
66
  } | {
72
- type: EVENT.REDIS_CACHE_WRITE_ERROR;
67
+ 'type': EVENT.REDIS_CACHE_WRITE_ERROR;
73
68
  error: Error;
74
69
  key: string;
75
70
  normalizedKey: string;
76
71
  timers: Timers;
77
72
  } | {
78
- type: EVENT.REDIS_CACHE_WRITE_FAILED;
73
+ 'type': EVENT.REDIS_CACHE_WRITE_FAILED;
79
74
  key: string;
80
75
  normalizedKey: string;
81
76
  timers: Timers;
82
77
  } | {
83
- type: EVENT.REDIS_CACHE_WRITE_DONE;
78
+ 'type': EVENT.REDIS_CACHE_WRITE_DONE;
84
79
  data: string;
85
80
  key: string;
86
81
  normalizedKey: string;
@@ -89,10 +84,6 @@ export type LoggerEvent = ({
89
84
  export declare class Cache<Result> implements CacheInterface<Result> {
90
85
  #private;
91
86
  constructor(options: Options, logger?: Logger);
92
- getClient(): {
93
- reader: Cluster | Redis;
94
- writer: Cluster | Redis;
95
- };
96
87
  get({ key }: {
97
88
  key: string;
98
89
  }): Promise<Result | undefined>;
package/build/index.js CHANGED
@@ -10,17 +10,15 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _Cache_instances, _Cache_writer, _Cache_reader, _Cache_logger, _Cache_options, _Cache_normalizeKey, _Cache_log;
13
+ var _Cache_instances, _Cache_client, _Cache_logger, _Cache_options, _Cache_normalizeKey, _Cache_log;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.EVENT = exports.Cache = void 0;
16
16
  const node_crypto_1 = require("node:crypto");
17
17
  const descript_1 = require("descript");
18
- const ioredis_1 = require("ioredis");
19
18
  class Cache {
20
19
  constructor(options, logger) {
21
20
  _Cache_instances.add(this);
22
- _Cache_writer.set(this, void 0);
23
- _Cache_reader.set(this, void 0);
21
+ _Cache_client.set(this, void 0);
24
22
  _Cache_logger.set(this, void 0);
25
23
  _Cache_options.set(this, void 0);
26
24
  __classPrivateFieldSet(this, _Cache_options, {
@@ -30,45 +28,17 @@ class Cache {
30
28
  ...options,
31
29
  }, "f");
32
30
  __classPrivateFieldSet(this, _Cache_logger, logger, "f");
33
- if ('startupNodes' in __classPrivateFieldGet(this, _Cache_options, "f").redis) {
34
- __classPrivateFieldSet(this, _Cache_reader, new ioredis_1.Cluster(__classPrivateFieldGet(this, _Cache_options, "f").redis.startupNodes, __classPrivateFieldGet(this, _Cache_options, "f").redis.options), "f");
35
- __classPrivateFieldSet(this, _Cache_writer, __classPrivateFieldGet(this, _Cache_reader, "f"), "f");
36
- }
37
- else {
38
- if (__classPrivateFieldGet(this, _Cache_options, "f").useReaderAndWriterWithSentinel) {
39
- // Client for write (always on master)
40
- __classPrivateFieldSet(this, _Cache_writer, new ioredis_1.Redis({
41
- ...__classPrivateFieldGet(this, _Cache_options, "f").redis,
42
- role: 'master',
43
- }), "f");
44
- // Client for read (replica, only read-only commands)
45
- __classPrivateFieldSet(this, _Cache_reader, new ioredis_1.Redis({
46
- ...__classPrivateFieldGet(this, _Cache_options, "f").redis,
47
- role: 'slave',
48
- readOnly: true,
49
- }), "f");
50
- }
51
- else {
52
- __classPrivateFieldSet(this, _Cache_reader, new ioredis_1.Redis(__classPrivateFieldGet(this, _Cache_options, "f").redis), "f");
53
- __classPrivateFieldSet(this, _Cache_writer, __classPrivateFieldGet(this, _Cache_reader, "f"), "f");
54
- }
55
- }
31
+ __classPrivateFieldSet(this, _Cache_client, options.client, "f");
56
32
  __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
57
- type: EVENT.REDIS_CACHE_INITIALIZED,
33
+ 'type': EVENT.REDIS_CACHE_INITIALIZED,
58
34
  options: { ...__classPrivateFieldGet(this, _Cache_options, "f") },
59
35
  });
60
36
  }
61
- getClient() {
62
- return {
63
- reader: __classPrivateFieldGet(this, _Cache_reader, "f"),
64
- writer: __classPrivateFieldGet(this, _Cache_writer, "f"),
65
- };
66
- }
67
37
  get({ key }) {
68
38
  const normalizedKey = __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_normalizeKey).call(this, key);
69
39
  return new Promise((resolve, reject) => {
70
40
  __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
71
- type: EVENT.REDIS_CACHE_READ_START,
41
+ 'type': EVENT.REDIS_CACHE_READ_START,
72
42
  key,
73
43
  normalizedKey,
74
44
  });
@@ -77,7 +47,7 @@ class Cache {
77
47
  const timer = setTimeout(() => {
78
48
  isTimeout = true;
79
49
  __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
80
- type: EVENT.REDIS_CACHE_READ_TIMEOUT,
50
+ 'type': EVENT.REDIS_CACHE_READ_TIMEOUT,
81
51
  key,
82
52
  normalizedKey,
83
53
  timers: {
@@ -89,29 +59,15 @@ class Cache {
89
59
  id: EVENT.REDIS_CACHE_READ_TIMEOUT,
90
60
  }));
91
61
  }, __classPrivateFieldGet(this, _Cache_options, "f").readTimeout);
92
- __classPrivateFieldGet(this, _Cache_reader, "f").get(normalizedKey, (error, data) => {
62
+ __classPrivateFieldGet(this, _Cache_client, "f").get(normalizedKey)
63
+ .then((data) => {
64
+ clearTimeout(timer);
93
65
  if (isTimeout) {
94
66
  return;
95
67
  }
96
- clearTimeout(timer);
97
- if (error) {
98
- __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
99
- type: EVENT.REDIS_CACHE_READ_ERROR,
100
- error,
101
- key,
102
- normalizedKey,
103
- timers: {
104
- start,
105
- end: Date.now(),
106
- },
107
- });
108
- reject((0, descript_1.error)({
109
- id: EVENT.REDIS_CACHE_READ_ERROR,
110
- }));
111
- }
112
- else if (!data) {
68
+ if (!data) {
113
69
  __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
114
- type: EVENT.REDIS_CACHE_READ_KEY_NOT_FOUND,
70
+ 'type': EVENT.REDIS_CACHE_READ_KEY_NOT_FOUND,
115
71
  key,
116
72
  normalizedKey,
117
73
  timers: {
@@ -122,32 +78,17 @@ class Cache {
122
78
  reject((0, descript_1.error)({
123
79
  id: EVENT.REDIS_CACHE_READ_KEY_NOT_FOUND,
124
80
  }));
81
+ return;
125
82
  }
126
- else {
127
- let parsedValue;
128
- try {
129
- parsedValue = JSON.parse(data);
130
- }
131
- catch (error) {
132
- __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
133
- type: EVENT.REDIS_CACHE_JSON_PARSING_FAILED,
134
- data,
135
- error,
136
- key,
137
- normalizedKey,
138
- timers: {
139
- start,
140
- end: Date.now(),
141
- },
142
- });
143
- reject((0, descript_1.error)({
144
- id: EVENT.REDIS_CACHE_JSON_PARSING_FAILED,
145
- }));
146
- return;
147
- }
83
+ let parsedValue;
84
+ try {
85
+ parsedValue = JSON.parse(data);
86
+ }
87
+ catch (error) {
148
88
  __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
149
- type: EVENT.REDIS_CACHE_READ_DONE,
89
+ 'type': EVENT.REDIS_CACHE_JSON_PARSING_FAILED,
150
90
  data,
91
+ error,
151
92
  key,
152
93
  normalizedKey,
153
94
  timers: {
@@ -155,8 +96,38 @@ class Cache {
155
96
  end: Date.now(),
156
97
  },
157
98
  });
158
- resolve(parsedValue);
99
+ reject((0, descript_1.error)({
100
+ id: EVENT.REDIS_CACHE_JSON_PARSING_FAILED,
101
+ }));
102
+ return;
159
103
  }
104
+ __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
105
+ 'type': EVENT.REDIS_CACHE_READ_DONE,
106
+ data,
107
+ key,
108
+ normalizedKey,
109
+ timers: {
110
+ start,
111
+ end: Date.now(),
112
+ },
113
+ });
114
+ resolve(parsedValue);
115
+ })
116
+ .catch((error) => {
117
+ clearTimeout(timer);
118
+ __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
119
+ 'type': EVENT.REDIS_CACHE_READ_ERROR,
120
+ error,
121
+ key,
122
+ normalizedKey,
123
+ timers: {
124
+ start,
125
+ end: Date.now(),
126
+ },
127
+ });
128
+ reject((0, descript_1.error)({
129
+ id: EVENT.REDIS_CACHE_READ_ERROR,
130
+ }));
160
131
  });
161
132
  });
162
133
  }
@@ -168,7 +139,7 @@ class Cache {
168
139
  const normalizedKey = __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_normalizeKey).call(this, key);
169
140
  return new Promise((resolve, reject) => {
170
141
  __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
171
- type: EVENT.REDIS_CACHE_WRITE_START,
142
+ 'type': EVENT.REDIS_CACHE_WRITE_START,
172
143
  key,
173
144
  normalizedKey,
174
145
  });
@@ -178,7 +149,7 @@ class Cache {
178
149
  }
179
150
  catch (error) {
180
151
  __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
181
- type: EVENT.REDIS_CACHE_JSON_STRINGIFY_FAILED,
152
+ 'type': EVENT.REDIS_CACHE_JSON_STRINGIFY_FAILED,
182
153
  data: value,
183
154
  error,
184
155
  key,
@@ -193,26 +164,13 @@ class Cache {
193
164
  }));
194
165
  return;
195
166
  }
167
+ // https://redis.io/docs/latest/commands/getex/
196
168
  // maxage - seconds
197
- __classPrivateFieldGet(this, _Cache_writer, "f").set(normalizedKey, json, 'EX', maxage, (error, done) => {
198
- if (error) {
199
- __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
200
- type: EVENT.REDIS_CACHE_WRITE_ERROR,
201
- error,
202
- key,
203
- normalizedKey,
204
- timers: {
205
- start,
206
- end: Date.now(),
207
- },
208
- });
209
- reject((0, descript_1.error)({
210
- id: EVENT.REDIS_CACHE_WRITE_ERROR,
211
- }));
212
- }
213
- else if (!done) {
169
+ __classPrivateFieldGet(this, _Cache_client, "f").set(normalizedKey, json, { expiration: { 'type': 'EX', value: maxage } })
170
+ .then((done) => {
171
+ if (!done) {
214
172
  __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
215
- type: EVENT.REDIS_CACHE_WRITE_FAILED,
173
+ 'type': EVENT.REDIS_CACHE_WRITE_FAILED,
216
174
  key,
217
175
  normalizedKey,
218
176
  timers: {
@@ -223,26 +181,40 @@ class Cache {
223
181
  reject((0, descript_1.error)({
224
182
  id: EVENT.REDIS_CACHE_WRITE_FAILED,
225
183
  }));
184
+ return;
226
185
  }
227
- else {
228
- __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
229
- type: EVENT.REDIS_CACHE_WRITE_DONE,
230
- data: json,
231
- key,
232
- normalizedKey,
233
- timers: {
234
- start,
235
- end: Date.now(),
236
- },
237
- });
238
- resolve();
239
- }
186
+ __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
187
+ 'type': EVENT.REDIS_CACHE_WRITE_DONE,
188
+ data: json,
189
+ key,
190
+ normalizedKey,
191
+ timers: {
192
+ start,
193
+ end: Date.now(),
194
+ },
195
+ });
196
+ resolve();
197
+ })
198
+ .catch((error) => {
199
+ __classPrivateFieldGet(this, _Cache_instances, "m", _Cache_log).call(this, {
200
+ 'type': EVENT.REDIS_CACHE_WRITE_ERROR,
201
+ error,
202
+ key,
203
+ normalizedKey,
204
+ timers: {
205
+ start,
206
+ end: Date.now(),
207
+ },
208
+ });
209
+ reject((0, descript_1.error)({
210
+ id: EVENT.REDIS_CACHE_WRITE_ERROR,
211
+ }));
240
212
  });
241
213
  });
242
214
  }
243
215
  }
244
216
  exports.Cache = Cache;
245
- _Cache_writer = new WeakMap(), _Cache_reader = new WeakMap(), _Cache_logger = new WeakMap(), _Cache_options = new WeakMap(), _Cache_instances = new WeakSet(), _Cache_normalizeKey = function _Cache_normalizeKey(key) {
217
+ _Cache_client = new WeakMap(), _Cache_logger = new WeakMap(), _Cache_options = new WeakMap(), _Cache_instances = new WeakSet(), _Cache_normalizeKey = function _Cache_normalizeKey(key) {
246
218
  const value = `g${__classPrivateFieldGet(this, _Cache_options, "f").generation}:${key}`;
247
219
  return (0, node_crypto_1.hash)('sha512', value);
248
220
  }, _Cache_log = function _Cache_log(event) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "descript-redis-cache",
3
- "version": "4.1.0",
3
+ "version": "5.0.0",
4
4
  "description": "plugin for descript to use redis as cache",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -30,21 +30,20 @@
30
30
  "files": [
31
31
  "build"
32
32
  ],
33
- "dependencies": {
34
- "ioredis": "^5.4.1"
35
- },
36
33
  "peerDependencies": {
34
+ "@redis/client": "^5",
37
35
  "descript": ">=4"
38
36
  },
39
37
  "devDependencies": {
40
38
  "@eslint/js": "^9.14.0",
41
- "@stylistic/eslint-plugin-ts": "^2.11.0",
39
+ "@redis/client": "^5.8.2",
40
+ "@stylistic/eslint-plugin": "^5.3.1",
42
41
  "@types/eslint__js": "^8.42.3",
43
- "@types/node": "^22.10.0",
44
- "descript": "^4.0.6",
45
- "eslint": "^9.15.0",
46
- "typescript": "^5.7.2",
47
- "typescript-eslint": "^8.16.0",
48
- "vitest": "^2.1.6"
42
+ "@types/node": "^22.18.1",
43
+ "descript": "^4.0.16",
44
+ "eslint": "^9.35.0",
45
+ "typescript": "^5.9.2",
46
+ "typescript-eslint": "^8.42.0",
47
+ "vitest": "^3.2.4"
49
48
  }
50
49
  }