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 +14 -9
- package/build/index.d.ts +16 -25
- package/build/index.js +85 -113
- package/package.json +10 -11
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
|
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
|
-
|
13
|
-
|
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
|
-
|
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 {
|
3
|
-
|
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
|
-
/**
|
12
|
-
|
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,
|
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
|
-
|
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
|
-
|
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,
|
62
|
+
__classPrivateFieldGet(this, _Cache_client, "f").get(normalizedKey)
|
63
|
+
.then((data) => {
|
64
|
+
clearTimeout(timer);
|
93
65
|
if (isTimeout) {
|
94
66
|
return;
|
95
67
|
}
|
96
|
-
|
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
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
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.
|
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
|
-
|
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,
|
198
|
-
|
199
|
-
|
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
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
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
|
-
|
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": "
|
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
|
-
"@
|
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.
|
44
|
-
"descript": "^4.0.
|
45
|
-
"eslint": "^9.
|
46
|
-
"typescript": "^5.
|
47
|
-
"typescript-eslint": "^8.
|
48
|
-
"vitest": "^2.
|
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
|
}
|