@sebspark/promise-cache 3.3.3 → 3.4.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 +126 -8
- package/dist/index.d.mts +221 -2
- package/dist/index.d.ts +221 -2
- package/dist/index.js +283 -36
- package/dist/index.mjs +284 -35
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Simple caching wrapper
|
|
4
4
|
|
|
5
|
+
# PromiseCache implementation
|
|
6
|
+
|
|
5
7
|
## **Features**
|
|
6
8
|
|
|
7
9
|
- **PromiseCache**: Simple caching wraper for promises
|
|
@@ -18,14 +20,14 @@ yarn install @sebspark/promise-cache
|
|
|
18
20
|
|
|
19
21
|
### **PromiseCache Class**
|
|
20
22
|
|
|
21
|
-
| Params | Type
|
|
22
|
-
|
|
23
|
-
| redis | RedisClientOptions
|
|
24
|
-
| ttlInSeconds | number
|
|
25
|
-
| caseSensituve | boolean
|
|
26
|
-
| onSuccess | function
|
|
27
|
-
| onError | function
|
|
28
|
-
| logger | winston Logger
|
|
23
|
+
| Params | Type | Default | Description |
|
|
24
|
+
|---------------|---------------------|-----------|-----------------------------------------------|
|
|
25
|
+
| redis | RedisClientOptions | undefined | Redis instance url, skip if use local memory |
|
|
26
|
+
| ttlInSeconds | number | undefined | Persist time in Seconds |
|
|
27
|
+
| caseSensituve | boolean | false | Retrieving cache with case sensitive |
|
|
28
|
+
| onSuccess | function | undefined | Callback function if connection is success |
|
|
29
|
+
| onError | function | undefined | Callback function if there is an error |
|
|
30
|
+
| logger | winston Logger | undefined | Logger |
|
|
29
31
|
|
|
30
32
|
```typescript
|
|
31
33
|
import { PromiseCache } from '@sebspark/promise-cache'
|
|
@@ -161,3 +163,119 @@ expect(cached).toBe({
|
|
|
161
163
|
await store.delete('MyKey')
|
|
162
164
|
expect(await store.get('MyKey').toBe(null)
|
|
163
165
|
```
|
|
166
|
+
|
|
167
|
+
# Cache implementation
|
|
168
|
+
|
|
169
|
+
The basic functionality of this new implementation is:
|
|
170
|
+
|
|
171
|
+
1. You create a persistor to store your cached data. This can be the built in `InMemoryPersistor` or a `Redis` client
|
|
172
|
+
2. You create a cache by calling `createCache(persistor, 'optional-prefix')`
|
|
173
|
+
3. You call the cache's wrap function to wrap your original function(s)
|
|
174
|
+
4. You call the wrapped function(s) instead of the originals
|
|
175
|
+
|
|
176
|
+
** Why the change? **
|
|
177
|
+
|
|
178
|
+
When trying to add support for caching _to_ a specified time in addition to _for_ a specified time, it tuyrned out to be hard given the original implementation. Changing the implementation proved hard without breaking changes. So a new implementation is is.
|
|
179
|
+
|
|
180
|
+
## How to use it
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { createClient } from 'redis'
|
|
184
|
+
import { createCache } from '@sebspark/promise-cache'
|
|
185
|
+
import { myFunction } from './some_function'
|
|
186
|
+
|
|
187
|
+
const run = async () => {
|
|
188
|
+
// Create your persistor
|
|
189
|
+
const persistor = createClient({ url: 'redis' })
|
|
190
|
+
await persistor.connect() // This is not handled by the cache
|
|
191
|
+
|
|
192
|
+
// Create your cache and give it a prefix
|
|
193
|
+
const cache = createCache(persistor, 'my-prefix')
|
|
194
|
+
|
|
195
|
+
// wrap your function
|
|
196
|
+
const myCachedFunction = cache.wrap(myFunction, {
|
|
197
|
+
key: 'my-function', // cached data will be stored with the key 'my-prefix:my-function'
|
|
198
|
+
expiry: 100, // ttl will be 100 ms
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
// call the wrapped function
|
|
202
|
+
const response = await myCachedFunction() // the wrapped function will have the same signature as the original
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
run()
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Keys
|
|
209
|
+
|
|
210
|
+
Keys can be constructed in two ways: as a fixed string or as a function that generates a string. The generator will accept the arguments of the wrapped function.
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
const cache = createCache(persistor, 'api')
|
|
214
|
+
|
|
215
|
+
const getById = async (id: string): Promise<Data> => {
|
|
216
|
+
// Something gets called
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const cachedGetById = cache.wrap(myApiCall, {
|
|
220
|
+
key: (id) => `getById:${id}`
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
const result = await cachedGetById('foo')
|
|
224
|
+
|
|
225
|
+
// key will be 'api:getById:foo'
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Expiry
|
|
229
|
+
|
|
230
|
+
Expiration can be set as either a number (number of milliseconds from now) or a Date (exact expiry time). It can be set either as a value (`number | Date`) or as a function that generates a value (`number | Date`). The generator will accept the arguments _and_ the response of the wrapped function.
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
const cache = createCache(persistor, 'api')
|
|
234
|
+
|
|
235
|
+
type Data = {
|
|
236
|
+
value: number
|
|
237
|
+
expires: string // ISO6501 date time string
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const getById = async (id: string): Promise<Data> => {
|
|
241
|
+
// Something gets called
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const cachedGetById = cache.wrap(myApiCall, {
|
|
245
|
+
key: (id) => `getById:${id}`,
|
|
246
|
+
expires: ([id], data) => new Date(data.expires),
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
const result = await cachedGetById('foo')
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
There are also helpers for setting time or manipulating dates
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import { createCache, time } from '@sebspark/promise-cache'
|
|
256
|
+
|
|
257
|
+
const cache = createCache(persistor, 'api')
|
|
258
|
+
|
|
259
|
+
type Data = {
|
|
260
|
+
value: number
|
|
261
|
+
lastUpdated: string // ISO6501 date time string. Data is updated every 30 minutes.
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const getById = async (id: string): Promise<Data> => {
|
|
265
|
+
// Something gets called
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Computed from response
|
|
269
|
+
const cachedGetById = cache.wrap(myApiCall, {
|
|
270
|
+
key: (id) => `getById:${id}`,
|
|
271
|
+
expires: ([id], data) => time.add(new Date(data.lastUpdated), { minutes: 30 })
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
// Fixed at 20 seconds
|
|
275
|
+
const cachedGetById = cache.wrap(myApiCall, {
|
|
276
|
+
key: (id) => `getById:${id}`,
|
|
277
|
+
expires: time.seconds(100),
|
|
278
|
+
})
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
If expiry is not set or yields an unusable value, it will default to 1 sec.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { RedisClientOptions, createClient } from 'redis';
|
|
1
|
+
import { RedisClientOptions, createClient, SetOptions } from 'redis';
|
|
2
2
|
export { RedisClientOptions } from 'redis';
|
|
3
3
|
import { Logger } from 'winston';
|
|
4
4
|
import { UUID } from 'node:crypto';
|
|
5
|
+
import { add } from 'date-fns';
|
|
5
6
|
|
|
6
7
|
type GetType<T> = {
|
|
7
8
|
value: T;
|
|
@@ -101,4 +102,222 @@ declare class PromiseCache<U> {
|
|
|
101
102
|
wrap(key: string, delegate: () => Promise<U>, ttlInSeconds?: number, ttlKeyInSeconds?: string): Promise<U>;
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Defines the expiration strategy for cached values.
|
|
107
|
+
*
|
|
108
|
+
* - A `number` is interpreted as a TTL (time-to-live) in **milliseconds**.
|
|
109
|
+
* - A `Date` represents an **exact expiration timestamp**.
|
|
110
|
+
* - If omitted, the cache entry **never expires**.
|
|
111
|
+
*/
|
|
112
|
+
type Expiry = number | Date;
|
|
113
|
+
/**
|
|
114
|
+
* Options for caching a function's result.
|
|
115
|
+
* @template A - Argument types of the function.
|
|
116
|
+
*/
|
|
117
|
+
type CachingOptions<A extends unknown[], R> = {
|
|
118
|
+
/**
|
|
119
|
+
* A fixed key or a function that generates a key based on function arguments.
|
|
120
|
+
*/
|
|
121
|
+
key: string | ((...args: A) => string);
|
|
122
|
+
/**
|
|
123
|
+
* Defines how long the cached value remains valid before expiring.
|
|
124
|
+
*
|
|
125
|
+
* - A **number** is treated as a TTL (time-to-live) in **milliseconds**.
|
|
126
|
+
* - A **Date** sets an **exact expiration timestamp**.
|
|
127
|
+
* - A **function** dynamically determines the expiration based on:
|
|
128
|
+
* - `args` - The function arguments.
|
|
129
|
+
* - `response` - The function result.
|
|
130
|
+
* - If omitted, the cache entry **does not expire**.
|
|
131
|
+
*/
|
|
132
|
+
expiry?: Expiry | ((args: A, response: R) => Expiry);
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Represents a caching system that wraps asynchronous functions.
|
|
136
|
+
*/
|
|
137
|
+
type Cache = {
|
|
138
|
+
/**
|
|
139
|
+
* The underlying persistor used for caching.
|
|
140
|
+
*/
|
|
141
|
+
persistor: IPersistor;
|
|
142
|
+
/**
|
|
143
|
+
* Wraps an asynchronous function to enable caching.
|
|
144
|
+
* @template A - Argument types.
|
|
145
|
+
* @template R - Return type.
|
|
146
|
+
* @param {Delegate<A, R>} delegate - The function to wrap.
|
|
147
|
+
* @param {CachingOptions<A>} options - Caching options, including key strategy.
|
|
148
|
+
* @returns {Delegate<A, R>} A new function that caches results.
|
|
149
|
+
*/
|
|
150
|
+
wrap: <A extends unknown[], R>(delegate: (...args: A) => Promise<R>, options: CachingOptions<A, R>) => (...args: A) => Promise<R>;
|
|
151
|
+
};
|
|
152
|
+
interface IPersistor {
|
|
153
|
+
/**
|
|
154
|
+
* Stores a value in Redis or Memory with an optional expiration.
|
|
155
|
+
* @param key - The storage key.
|
|
156
|
+
* @param value - The string value to store.
|
|
157
|
+
* @param options - Expiration options.
|
|
158
|
+
* @returns Resolves to `"OK"` if successful.
|
|
159
|
+
*/
|
|
160
|
+
set: (key: string, value: string, options?: SetOptions) => Promise<string | null>;
|
|
161
|
+
/**
|
|
162
|
+
* Retrieves a value from Redis or Memory.
|
|
163
|
+
* @param key - The storage key.
|
|
164
|
+
* @returns Resolves to the stored value or `null` if not found.
|
|
165
|
+
*/
|
|
166
|
+
get: (key: string) => Promise<string | null>;
|
|
167
|
+
/**
|
|
168
|
+
* Deletes a key from Redis or Memory.
|
|
169
|
+
* @param key - The storage key.
|
|
170
|
+
* @returns Resolves to the number of keys removed (1 if deleted, 0 if not found).
|
|
171
|
+
*/
|
|
172
|
+
del: (key: string) => Promise<number>;
|
|
173
|
+
/**
|
|
174
|
+
* Sets a time-to-live (TTL) in seconds for a key.
|
|
175
|
+
* @param key - The storage key.
|
|
176
|
+
* @param seconds - TTL in seconds.
|
|
177
|
+
* @returns Resolves to true if successful, false if key does not exist.
|
|
178
|
+
*/
|
|
179
|
+
expire: (key: string, seconds: number) => Promise<boolean>;
|
|
180
|
+
/**
|
|
181
|
+
* Gets the remaining TTL of a key in seconds.
|
|
182
|
+
* @param key - The storage key.
|
|
183
|
+
* @returns Remaining TTL in seconds, `-1` if no TTL is set, or `-2` if key does not exist.
|
|
184
|
+
*/
|
|
185
|
+
ttl: (key: string) => Promise<number>;
|
|
186
|
+
/**
|
|
187
|
+
* Clears all keys in Redis or Memory.
|
|
188
|
+
* @returns Resolves to `"OK"` when complete.
|
|
189
|
+
*/
|
|
190
|
+
flushAll: () => Promise<string>;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Creates a cache instance using a given persistor.
|
|
195
|
+
* @param {IPersistor} persistor - The underlying storage for caching.
|
|
196
|
+
* @param {string?} prefix - An optional prefix that will be prepended to the key, formatted as `prefix:key`.
|
|
197
|
+
* @returns {Cache} A cache instance.
|
|
198
|
+
*/
|
|
199
|
+
declare const createCache: (persistor: IPersistor, prefix?: string) => Cache;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* An in-memory key-value store with Redis-like behavior.
|
|
203
|
+
* Supports basic operations like `set`, `get`, `del`, `expire`, `ttl`, and `flushAll`.
|
|
204
|
+
* Implements expiration using `setTimeout` for automatic key deletion.
|
|
205
|
+
*/
|
|
206
|
+
declare class InMemoryPersistor implements IPersistor {
|
|
207
|
+
/**
|
|
208
|
+
* Internal key-value store for caching string values.
|
|
209
|
+
* @private
|
|
210
|
+
*/
|
|
211
|
+
private readonly store;
|
|
212
|
+
/**
|
|
213
|
+
* Tracks active timeouts for expiring keys.
|
|
214
|
+
* Each key maps to a `setTimeout` reference that deletes the key when triggered.
|
|
215
|
+
* @private
|
|
216
|
+
*/
|
|
217
|
+
private readonly expirations;
|
|
218
|
+
/**
|
|
219
|
+
* Stores absolute expiration timestamps (in milliseconds since epoch) for each key.
|
|
220
|
+
* Used to compute remaining TTL.
|
|
221
|
+
* @private
|
|
222
|
+
*/
|
|
223
|
+
private readonly expiryTimestamps;
|
|
224
|
+
/**
|
|
225
|
+
* Creates a new instance of `InMemoryPersistor`.
|
|
226
|
+
* Initializes an empty store, expiration map, and TTL tracker.
|
|
227
|
+
*/
|
|
228
|
+
constructor();
|
|
229
|
+
/**
|
|
230
|
+
* Stores a key-value pair with optional expiration settings.
|
|
231
|
+
* If an expiration is provided (`EX`, `PX`, `EXAT`, `PXAT`), the key is automatically removed when TTL expires.
|
|
232
|
+
*
|
|
233
|
+
* @param {string} key - The key to store.
|
|
234
|
+
* @param {string} value - The string value to associate with the key.
|
|
235
|
+
* @param {SetOptions} [options] - Optional Redis-style expiration settings.
|
|
236
|
+
* @returns {Promise<'OK' | null>} Resolves to `'OK'` on success, or `null` if a conditional set (`NX`) fails.
|
|
237
|
+
*/
|
|
238
|
+
set(key: string, value: string, options?: SetOptions): Promise<'OK' | null>;
|
|
239
|
+
/**
|
|
240
|
+
* Retrieves the value associated with a key.
|
|
241
|
+
*
|
|
242
|
+
* @param {string} key - The key to retrieve.
|
|
243
|
+
* @returns {Promise<string | null>} Resolves to the string value, or `null` if the key does not exist.
|
|
244
|
+
*/
|
|
245
|
+
get(key: string): Promise<string | null>;
|
|
246
|
+
/**
|
|
247
|
+
* Deletes a key from the store.
|
|
248
|
+
* If the key exists, it is removed along with any associated expiration.
|
|
249
|
+
*
|
|
250
|
+
* @param {string} key - The key to delete.
|
|
251
|
+
* @returns {Promise<number>} Resolves to `1` if the key was deleted, or `0` if the key did not exist.
|
|
252
|
+
*/
|
|
253
|
+
del(key: string): Promise<number>;
|
|
254
|
+
/**
|
|
255
|
+
* Sets a time-to-live (TTL) in seconds for a key.
|
|
256
|
+
* If the key exists, it will be deleted after the specified duration.
|
|
257
|
+
*
|
|
258
|
+
* @param {string} key - The key to set an expiration on.
|
|
259
|
+
* @param {number} seconds - The TTL in seconds.
|
|
260
|
+
* @returns {Promise<number>} Resolves to `1` if the TTL was set, or `0` if the key does not exist.
|
|
261
|
+
*/
|
|
262
|
+
expire(key: string, seconds: number): Promise<boolean>;
|
|
263
|
+
/**
|
|
264
|
+
* Retrieves the remaining time-to-live (TTL) of a key in seconds.
|
|
265
|
+
*
|
|
266
|
+
* @param {string} key - The key to check.
|
|
267
|
+
* @returns {Promise<number>} Resolves to:
|
|
268
|
+
* - Remaining TTL in **seconds** if the key exists and has an expiration.
|
|
269
|
+
* - `-1` if the key exists but has no expiration.
|
|
270
|
+
* - `-2` if the key does not exist.
|
|
271
|
+
*/
|
|
272
|
+
ttl(key: string): Promise<number>;
|
|
273
|
+
/**
|
|
274
|
+
* Removes all keys from the store and clears all active expirations.
|
|
275
|
+
*
|
|
276
|
+
* @returns {Promise<'OK'>} Resolves to `'OK'` after all data is cleared.
|
|
277
|
+
*/
|
|
278
|
+
flushAll(): Promise<'OK'>;
|
|
279
|
+
/**
|
|
280
|
+
* Sets an expiration timeout for a key.
|
|
281
|
+
* Cancels any existing expiration before setting a new one.
|
|
282
|
+
*
|
|
283
|
+
* @private
|
|
284
|
+
* @param {string} key - The key to expire.
|
|
285
|
+
* @param {number} ttlMs - Time-to-live in milliseconds.
|
|
286
|
+
*/
|
|
287
|
+
private setExpiration;
|
|
288
|
+
/**
|
|
289
|
+
* Cancels an active expiration timeout for a key and removes its TTL record.
|
|
290
|
+
*
|
|
291
|
+
* @private
|
|
292
|
+
* @param {string} key - The key whose expiration should be cleared.
|
|
293
|
+
*/
|
|
294
|
+
private clearExpiration;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
declare const SECOND = 1000;
|
|
298
|
+
declare const MINUTE: number;
|
|
299
|
+
declare const HOUR: number;
|
|
300
|
+
declare const DAY: number;
|
|
301
|
+
declare const WEEK: number;
|
|
302
|
+
declare const seconds: (num: number) => number;
|
|
303
|
+
declare const minutes: (num: number) => number;
|
|
304
|
+
declare const hours: (num: number) => number;
|
|
305
|
+
declare const days: (num: number) => number;
|
|
306
|
+
declare const weeks: (num: number) => number;
|
|
307
|
+
|
|
308
|
+
declare const time_DAY: typeof DAY;
|
|
309
|
+
declare const time_HOUR: typeof HOUR;
|
|
310
|
+
declare const time_MINUTE: typeof MINUTE;
|
|
311
|
+
declare const time_SECOND: typeof SECOND;
|
|
312
|
+
declare const time_WEEK: typeof WEEK;
|
|
313
|
+
declare const time_add: typeof add;
|
|
314
|
+
declare const time_days: typeof days;
|
|
315
|
+
declare const time_hours: typeof hours;
|
|
316
|
+
declare const time_minutes: typeof minutes;
|
|
317
|
+
declare const time_seconds: typeof seconds;
|
|
318
|
+
declare const time_weeks: typeof weeks;
|
|
319
|
+
declare namespace time {
|
|
320
|
+
export { time_DAY as DAY, time_HOUR as HOUR, time_MINUTE as MINUTE, time_SECOND as SECOND, time_WEEK as WEEK, time_add as add, time_days as days, time_hours as hours, time_minutes as minutes, time_seconds as seconds, time_weeks as weeks };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export { type Cache, type CachingOptions, type IPersistor, InMemoryPersistor, Persistor, type PersistorConstructorType, PromiseCache, type PromiseCacheOptions, createCache, time };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { RedisClientOptions, createClient } from 'redis';
|
|
1
|
+
import { RedisClientOptions, createClient, SetOptions } from 'redis';
|
|
2
2
|
export { RedisClientOptions } from 'redis';
|
|
3
3
|
import { Logger } from 'winston';
|
|
4
4
|
import { UUID } from 'node:crypto';
|
|
5
|
+
import { add } from 'date-fns';
|
|
5
6
|
|
|
6
7
|
type GetType<T> = {
|
|
7
8
|
value: T;
|
|
@@ -101,4 +102,222 @@ declare class PromiseCache<U> {
|
|
|
101
102
|
wrap(key: string, delegate: () => Promise<U>, ttlInSeconds?: number, ttlKeyInSeconds?: string): Promise<U>;
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Defines the expiration strategy for cached values.
|
|
107
|
+
*
|
|
108
|
+
* - A `number` is interpreted as a TTL (time-to-live) in **milliseconds**.
|
|
109
|
+
* - A `Date` represents an **exact expiration timestamp**.
|
|
110
|
+
* - If omitted, the cache entry **never expires**.
|
|
111
|
+
*/
|
|
112
|
+
type Expiry = number | Date;
|
|
113
|
+
/**
|
|
114
|
+
* Options for caching a function's result.
|
|
115
|
+
* @template A - Argument types of the function.
|
|
116
|
+
*/
|
|
117
|
+
type CachingOptions<A extends unknown[], R> = {
|
|
118
|
+
/**
|
|
119
|
+
* A fixed key or a function that generates a key based on function arguments.
|
|
120
|
+
*/
|
|
121
|
+
key: string | ((...args: A) => string);
|
|
122
|
+
/**
|
|
123
|
+
* Defines how long the cached value remains valid before expiring.
|
|
124
|
+
*
|
|
125
|
+
* - A **number** is treated as a TTL (time-to-live) in **milliseconds**.
|
|
126
|
+
* - A **Date** sets an **exact expiration timestamp**.
|
|
127
|
+
* - A **function** dynamically determines the expiration based on:
|
|
128
|
+
* - `args` - The function arguments.
|
|
129
|
+
* - `response` - The function result.
|
|
130
|
+
* - If omitted, the cache entry **does not expire**.
|
|
131
|
+
*/
|
|
132
|
+
expiry?: Expiry | ((args: A, response: R) => Expiry);
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Represents a caching system that wraps asynchronous functions.
|
|
136
|
+
*/
|
|
137
|
+
type Cache = {
|
|
138
|
+
/**
|
|
139
|
+
* The underlying persistor used for caching.
|
|
140
|
+
*/
|
|
141
|
+
persistor: IPersistor;
|
|
142
|
+
/**
|
|
143
|
+
* Wraps an asynchronous function to enable caching.
|
|
144
|
+
* @template A - Argument types.
|
|
145
|
+
* @template R - Return type.
|
|
146
|
+
* @param {Delegate<A, R>} delegate - The function to wrap.
|
|
147
|
+
* @param {CachingOptions<A>} options - Caching options, including key strategy.
|
|
148
|
+
* @returns {Delegate<A, R>} A new function that caches results.
|
|
149
|
+
*/
|
|
150
|
+
wrap: <A extends unknown[], R>(delegate: (...args: A) => Promise<R>, options: CachingOptions<A, R>) => (...args: A) => Promise<R>;
|
|
151
|
+
};
|
|
152
|
+
interface IPersistor {
|
|
153
|
+
/**
|
|
154
|
+
* Stores a value in Redis or Memory with an optional expiration.
|
|
155
|
+
* @param key - The storage key.
|
|
156
|
+
* @param value - The string value to store.
|
|
157
|
+
* @param options - Expiration options.
|
|
158
|
+
* @returns Resolves to `"OK"` if successful.
|
|
159
|
+
*/
|
|
160
|
+
set: (key: string, value: string, options?: SetOptions) => Promise<string | null>;
|
|
161
|
+
/**
|
|
162
|
+
* Retrieves a value from Redis or Memory.
|
|
163
|
+
* @param key - The storage key.
|
|
164
|
+
* @returns Resolves to the stored value or `null` if not found.
|
|
165
|
+
*/
|
|
166
|
+
get: (key: string) => Promise<string | null>;
|
|
167
|
+
/**
|
|
168
|
+
* Deletes a key from Redis or Memory.
|
|
169
|
+
* @param key - The storage key.
|
|
170
|
+
* @returns Resolves to the number of keys removed (1 if deleted, 0 if not found).
|
|
171
|
+
*/
|
|
172
|
+
del: (key: string) => Promise<number>;
|
|
173
|
+
/**
|
|
174
|
+
* Sets a time-to-live (TTL) in seconds for a key.
|
|
175
|
+
* @param key - The storage key.
|
|
176
|
+
* @param seconds - TTL in seconds.
|
|
177
|
+
* @returns Resolves to true if successful, false if key does not exist.
|
|
178
|
+
*/
|
|
179
|
+
expire: (key: string, seconds: number) => Promise<boolean>;
|
|
180
|
+
/**
|
|
181
|
+
* Gets the remaining TTL of a key in seconds.
|
|
182
|
+
* @param key - The storage key.
|
|
183
|
+
* @returns Remaining TTL in seconds, `-1` if no TTL is set, or `-2` if key does not exist.
|
|
184
|
+
*/
|
|
185
|
+
ttl: (key: string) => Promise<number>;
|
|
186
|
+
/**
|
|
187
|
+
* Clears all keys in Redis or Memory.
|
|
188
|
+
* @returns Resolves to `"OK"` when complete.
|
|
189
|
+
*/
|
|
190
|
+
flushAll: () => Promise<string>;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Creates a cache instance using a given persistor.
|
|
195
|
+
* @param {IPersistor} persistor - The underlying storage for caching.
|
|
196
|
+
* @param {string?} prefix - An optional prefix that will be prepended to the key, formatted as `prefix:key`.
|
|
197
|
+
* @returns {Cache} A cache instance.
|
|
198
|
+
*/
|
|
199
|
+
declare const createCache: (persistor: IPersistor, prefix?: string) => Cache;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* An in-memory key-value store with Redis-like behavior.
|
|
203
|
+
* Supports basic operations like `set`, `get`, `del`, `expire`, `ttl`, and `flushAll`.
|
|
204
|
+
* Implements expiration using `setTimeout` for automatic key deletion.
|
|
205
|
+
*/
|
|
206
|
+
declare class InMemoryPersistor implements IPersistor {
|
|
207
|
+
/**
|
|
208
|
+
* Internal key-value store for caching string values.
|
|
209
|
+
* @private
|
|
210
|
+
*/
|
|
211
|
+
private readonly store;
|
|
212
|
+
/**
|
|
213
|
+
* Tracks active timeouts for expiring keys.
|
|
214
|
+
* Each key maps to a `setTimeout` reference that deletes the key when triggered.
|
|
215
|
+
* @private
|
|
216
|
+
*/
|
|
217
|
+
private readonly expirations;
|
|
218
|
+
/**
|
|
219
|
+
* Stores absolute expiration timestamps (in milliseconds since epoch) for each key.
|
|
220
|
+
* Used to compute remaining TTL.
|
|
221
|
+
* @private
|
|
222
|
+
*/
|
|
223
|
+
private readonly expiryTimestamps;
|
|
224
|
+
/**
|
|
225
|
+
* Creates a new instance of `InMemoryPersistor`.
|
|
226
|
+
* Initializes an empty store, expiration map, and TTL tracker.
|
|
227
|
+
*/
|
|
228
|
+
constructor();
|
|
229
|
+
/**
|
|
230
|
+
* Stores a key-value pair with optional expiration settings.
|
|
231
|
+
* If an expiration is provided (`EX`, `PX`, `EXAT`, `PXAT`), the key is automatically removed when TTL expires.
|
|
232
|
+
*
|
|
233
|
+
* @param {string} key - The key to store.
|
|
234
|
+
* @param {string} value - The string value to associate with the key.
|
|
235
|
+
* @param {SetOptions} [options] - Optional Redis-style expiration settings.
|
|
236
|
+
* @returns {Promise<'OK' | null>} Resolves to `'OK'` on success, or `null` if a conditional set (`NX`) fails.
|
|
237
|
+
*/
|
|
238
|
+
set(key: string, value: string, options?: SetOptions): Promise<'OK' | null>;
|
|
239
|
+
/**
|
|
240
|
+
* Retrieves the value associated with a key.
|
|
241
|
+
*
|
|
242
|
+
* @param {string} key - The key to retrieve.
|
|
243
|
+
* @returns {Promise<string | null>} Resolves to the string value, or `null` if the key does not exist.
|
|
244
|
+
*/
|
|
245
|
+
get(key: string): Promise<string | null>;
|
|
246
|
+
/**
|
|
247
|
+
* Deletes a key from the store.
|
|
248
|
+
* If the key exists, it is removed along with any associated expiration.
|
|
249
|
+
*
|
|
250
|
+
* @param {string} key - The key to delete.
|
|
251
|
+
* @returns {Promise<number>} Resolves to `1` if the key was deleted, or `0` if the key did not exist.
|
|
252
|
+
*/
|
|
253
|
+
del(key: string): Promise<number>;
|
|
254
|
+
/**
|
|
255
|
+
* Sets a time-to-live (TTL) in seconds for a key.
|
|
256
|
+
* If the key exists, it will be deleted after the specified duration.
|
|
257
|
+
*
|
|
258
|
+
* @param {string} key - The key to set an expiration on.
|
|
259
|
+
* @param {number} seconds - The TTL in seconds.
|
|
260
|
+
* @returns {Promise<number>} Resolves to `1` if the TTL was set, or `0` if the key does not exist.
|
|
261
|
+
*/
|
|
262
|
+
expire(key: string, seconds: number): Promise<boolean>;
|
|
263
|
+
/**
|
|
264
|
+
* Retrieves the remaining time-to-live (TTL) of a key in seconds.
|
|
265
|
+
*
|
|
266
|
+
* @param {string} key - The key to check.
|
|
267
|
+
* @returns {Promise<number>} Resolves to:
|
|
268
|
+
* - Remaining TTL in **seconds** if the key exists and has an expiration.
|
|
269
|
+
* - `-1` if the key exists but has no expiration.
|
|
270
|
+
* - `-2` if the key does not exist.
|
|
271
|
+
*/
|
|
272
|
+
ttl(key: string): Promise<number>;
|
|
273
|
+
/**
|
|
274
|
+
* Removes all keys from the store and clears all active expirations.
|
|
275
|
+
*
|
|
276
|
+
* @returns {Promise<'OK'>} Resolves to `'OK'` after all data is cleared.
|
|
277
|
+
*/
|
|
278
|
+
flushAll(): Promise<'OK'>;
|
|
279
|
+
/**
|
|
280
|
+
* Sets an expiration timeout for a key.
|
|
281
|
+
* Cancels any existing expiration before setting a new one.
|
|
282
|
+
*
|
|
283
|
+
* @private
|
|
284
|
+
* @param {string} key - The key to expire.
|
|
285
|
+
* @param {number} ttlMs - Time-to-live in milliseconds.
|
|
286
|
+
*/
|
|
287
|
+
private setExpiration;
|
|
288
|
+
/**
|
|
289
|
+
* Cancels an active expiration timeout for a key and removes its TTL record.
|
|
290
|
+
*
|
|
291
|
+
* @private
|
|
292
|
+
* @param {string} key - The key whose expiration should be cleared.
|
|
293
|
+
*/
|
|
294
|
+
private clearExpiration;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
declare const SECOND = 1000;
|
|
298
|
+
declare const MINUTE: number;
|
|
299
|
+
declare const HOUR: number;
|
|
300
|
+
declare const DAY: number;
|
|
301
|
+
declare const WEEK: number;
|
|
302
|
+
declare const seconds: (num: number) => number;
|
|
303
|
+
declare const minutes: (num: number) => number;
|
|
304
|
+
declare const hours: (num: number) => number;
|
|
305
|
+
declare const days: (num: number) => number;
|
|
306
|
+
declare const weeks: (num: number) => number;
|
|
307
|
+
|
|
308
|
+
declare const time_DAY: typeof DAY;
|
|
309
|
+
declare const time_HOUR: typeof HOUR;
|
|
310
|
+
declare const time_MINUTE: typeof MINUTE;
|
|
311
|
+
declare const time_SECOND: typeof SECOND;
|
|
312
|
+
declare const time_WEEK: typeof WEEK;
|
|
313
|
+
declare const time_add: typeof add;
|
|
314
|
+
declare const time_days: typeof days;
|
|
315
|
+
declare const time_hours: typeof hours;
|
|
316
|
+
declare const time_minutes: typeof minutes;
|
|
317
|
+
declare const time_seconds: typeof seconds;
|
|
318
|
+
declare const time_weeks: typeof weeks;
|
|
319
|
+
declare namespace time {
|
|
320
|
+
export { time_DAY as DAY, time_HOUR as HOUR, time_MINUTE as MINUTE, time_SECOND as SECOND, time_WEEK as WEEK, time_add as add, time_days as days, time_hours as hours, time_minutes as minutes, time_seconds as seconds, time_weeks as weeks };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export { type Cache, type CachingOptions, type IPersistor, InMemoryPersistor, Persistor, type PersistorConstructorType, PromiseCache, type PromiseCacheOptions, createCache, time };
|