@dotpress/cache 0.0.0-stage → 2.0.0-alpha.1
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/LICENSE +21 -0
- package/README.md +305 -2
- package/dist/als.d.ts +36 -0
- package/dist/als.js +35 -0
- package/dist/als.js.map +1 -0
- package/dist/chunk-2IEBMYSF.js +27 -0
- package/dist/chunk-2IEBMYSF.js.map +1 -0
- package/dist/chunk-6ZNJJARH.js +281 -0
- package/dist/chunk-6ZNJJARH.js.map +1 -0
- package/dist/cloudflare-kv.d.ts +52 -0
- package/dist/cloudflare-kv.js +75 -0
- package/dist/cloudflare-kv.js.map +1 -0
- package/dist/duration-2mZnG0_i.d.ts +8 -0
- package/dist/index.d.ts +384 -0
- package/dist/index.js +696 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +51 -0
- package/dist/plugin.js +49 -0
- package/dist/plugin.js.map +1 -0
- package/dist/redis.d.ts +39 -0
- package/dist/redis.js +73 -0
- package/dist/redis.js.map +1 -0
- package/dist/store-D0BfLqyM.d.ts +56 -0
- package/dist/upstash.d.ts +30 -0
- package/dist/upstash.js +88 -0
- package/dist/upstash.js.map +1 -0
- package/package.json +89 -3
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { D as Duration } from './duration-2mZnG0_i.js';
|
|
2
|
+
import { C as CacheStore } from './store-D0BfLqyM.js';
|
|
3
|
+
export { M as MemoryStore, a as MemoryStoreOptions, c as createMemoryStore } from './store-D0BfLqyM.js';
|
|
4
|
+
|
|
5
|
+
/** Options shared by every memo. */
|
|
6
|
+
interface BaseMemoOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Name of the memo, used in errors: letters, digits, `.`, `_`, `:` and
|
|
9
|
+
* `-`.
|
|
10
|
+
*/
|
|
11
|
+
name: string;
|
|
12
|
+
}
|
|
13
|
+
/** Options of a memo that loads one value at a time. */
|
|
14
|
+
interface LoadMemoOptions<A extends readonly unknown[], T> extends BaseMemoOptions {
|
|
15
|
+
/** Loads the value of the arguments. */
|
|
16
|
+
load: (...args: A) => T | Promise<T>;
|
|
17
|
+
/**
|
|
18
|
+
* Key of the arguments. Defaults to the arguments themselves: strings,
|
|
19
|
+
* numbers, booleans, `null`, `undefined`, bigints, dates, arrays and
|
|
20
|
+
* plain objects.
|
|
21
|
+
*/
|
|
22
|
+
key?: ((...args: A) => unknown) | undefined;
|
|
23
|
+
batch?: never;
|
|
24
|
+
}
|
|
25
|
+
/** Options of a memo that loads the values of several keys at once. */
|
|
26
|
+
interface BatchMemoOptions<K, R> extends BaseMemoOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Loads the values of the keys requested in the same tick, without
|
|
29
|
+
* duplicates. Returns their values in the order of the keys (an `Error`
|
|
30
|
+
* fails its key only), or a `Map` by key (a missing key gives
|
|
31
|
+
* `undefined`).
|
|
32
|
+
*/
|
|
33
|
+
batch: (keys: readonly K[]) => R | Promise<R>;
|
|
34
|
+
/** Key of a requested key, for keys that are objects. */
|
|
35
|
+
key?: ((key: K) => unknown) | undefined;
|
|
36
|
+
/** Keys per call of `batch`. Defaults to no limit. */
|
|
37
|
+
maxBatchSize?: number | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Schedules a batch. Defaults to a timer (`setTimeout(run, 0)`): the
|
|
40
|
+
* batch receives every key requested before it.
|
|
41
|
+
*/
|
|
42
|
+
schedule?: ((run: () => void) => void) | undefined;
|
|
43
|
+
load?: never;
|
|
44
|
+
}
|
|
45
|
+
declare const memoTypes: unique symbol;
|
|
46
|
+
/** A memoized loader, created by `defineMemo()`. */
|
|
47
|
+
interface MemoDefinition<A extends readonly unknown[], T> {
|
|
48
|
+
readonly name: string;
|
|
49
|
+
/** Types only. */
|
|
50
|
+
readonly [memoTypes]?: {
|
|
51
|
+
args: A;
|
|
52
|
+
value: T;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Memoized values of a unit of work: a request, a message, a job. */
|
|
56
|
+
interface Memo {
|
|
57
|
+
/**
|
|
58
|
+
* Loads the value of the arguments once per memo: later calls, and
|
|
59
|
+
* calls made while it loads, share the result. Failures are shared by
|
|
60
|
+
* the calls in progress, not kept.
|
|
61
|
+
*/
|
|
62
|
+
<A extends readonly unknown[], T>(memo: MemoDefinition<A, T>, ...args: A): Promise<T>;
|
|
63
|
+
/** Sets the value of the arguments, after an update for instance. */
|
|
64
|
+
set<A extends readonly unknown[], T>(memo: MemoDefinition<A, T>, ...argsAndValue: [...A, T]): void;
|
|
65
|
+
/** Forgets the value of the arguments: the next call loads it again. */
|
|
66
|
+
delete<A extends readonly unknown[], T>(memo: MemoDefinition<A, T>, ...args: A): void;
|
|
67
|
+
/** Forgets the values of a memo, or of every memo. */
|
|
68
|
+
clear<A extends readonly unknown[], T>(memo?: MemoDefinition<A, T>): void;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Defines a memoized loader: `memo(loadUser, id)` loads a user once per
|
|
72
|
+
* memo (request, message, job), and calls made while it loads share the
|
|
73
|
+
* same load (single flight). With `batch`, the keys requested in the same
|
|
74
|
+
* tick are loaded in one call.
|
|
75
|
+
*
|
|
76
|
+
* ```ts
|
|
77
|
+
* const loadUser = defineMemo({
|
|
78
|
+
* name: 'user',
|
|
79
|
+
* load: (id: string) => db.users.findById(id),
|
|
80
|
+
* })
|
|
81
|
+
*
|
|
82
|
+
* const loadOrder = defineMemo({
|
|
83
|
+
* name: 'order',
|
|
84
|
+
* batch: (ids: readonly string[]) => db.orders.findManyById(ids), // a Map by id
|
|
85
|
+
* })
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
declare function defineMemo<K, T>(options: BatchMemoOptions<K, ReadonlyMap<K, T>>): MemoDefinition<[key: K], T | undefined>;
|
|
89
|
+
declare function defineMemo<K, T>(options: BatchMemoOptions<K, readonly (T | Error)[]>): MemoDefinition<[key: K], T>;
|
|
90
|
+
declare function defineMemo<A extends readonly unknown[], T>(options: LoadMemoOptions<A, T>): MemoDefinition<A, T>;
|
|
91
|
+
/**
|
|
92
|
+
* Creates a memo: one per request, message or job. Plugins provide
|
|
93
|
+
* `ctx.memo`; create one yourself elsewhere.
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* const memo = createMemo()
|
|
97
|
+
* const [ada, grace] = await Promise.all([memo(loadUser, '1'), memo(loadUser, '2')])
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
declare const createMemo: () => Memo;
|
|
101
|
+
|
|
102
|
+
/** Base class of the errors thrown by `@dotpress/cache`. */
|
|
103
|
+
declare class CacheError extends Error {
|
|
104
|
+
name: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The `batch` function of a memo returned a result that does not match
|
|
108
|
+
* the keys: every call of the batch fails with this error.
|
|
109
|
+
*/
|
|
110
|
+
declare class MemoBatchError extends CacheError {
|
|
111
|
+
/** Name of the memo. */
|
|
112
|
+
readonly memo: string;
|
|
113
|
+
name: string;
|
|
114
|
+
constructor(
|
|
115
|
+
/** Name of the memo. */
|
|
116
|
+
memo: string, message: string);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Operation of a cache store: `invalidate` writes the tokens of tags,
|
|
120
|
+
* `lock` and `unlock` hold the distributed lock of a load.
|
|
121
|
+
*/
|
|
122
|
+
type StoreOperation = 'get' | 'set' | 'delete' | 'invalidate' | 'lock' | 'unlock';
|
|
123
|
+
/** A cache store failed or did not answer in time (`failOpen: false`). */
|
|
124
|
+
declare class CacheStoreError extends CacheError {
|
|
125
|
+
/** Name of the store. */
|
|
126
|
+
readonly store: string;
|
|
127
|
+
readonly operation: StoreOperation;
|
|
128
|
+
/** Key of the store. */
|
|
129
|
+
readonly key: string;
|
|
130
|
+
name: string;
|
|
131
|
+
constructor(
|
|
132
|
+
/** Name of the store. */
|
|
133
|
+
store: string, operation: StoreOperation,
|
|
134
|
+
/** Key of the store. */
|
|
135
|
+
key: string, options: {
|
|
136
|
+
cause: unknown;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The loader of `getOrSet()` did not finish within `hardTimeout`, and no
|
|
141
|
+
* stale value could be served. The load goes on, and caches its value.
|
|
142
|
+
*/
|
|
143
|
+
declare class CacheTimeoutError extends CacheError {
|
|
144
|
+
/** Name of the entry. */
|
|
145
|
+
readonly entry: string;
|
|
146
|
+
/** Key of the store. */
|
|
147
|
+
readonly key: string;
|
|
148
|
+
/** Timeout, in milliseconds. */
|
|
149
|
+
readonly timeout: number;
|
|
150
|
+
name: string;
|
|
151
|
+
constructor(
|
|
152
|
+
/** Name of the entry. */
|
|
153
|
+
entry: string,
|
|
154
|
+
/** Key of the store. */
|
|
155
|
+
key: string,
|
|
156
|
+
/** Timeout, in milliseconds. */
|
|
157
|
+
timeout: number);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Logger of the cache. A Dotpress or Pino logger fits; `cachePlugin` uses
|
|
162
|
+
* the logger of the request.
|
|
163
|
+
*/
|
|
164
|
+
interface CacheLogger {
|
|
165
|
+
debug?(data: object, message: string): void;
|
|
166
|
+
info(data: object, message: string): void;
|
|
167
|
+
warn(data: object, message: string): void;
|
|
168
|
+
error(data: object, message: string): void;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* A schema that validates cached values when they are read: a Zod schema,
|
|
173
|
+
* or anything with the same `safeParseAsync()`.
|
|
174
|
+
*/
|
|
175
|
+
interface CacheSchema<T> {
|
|
176
|
+
safeParseAsync(value: unknown): Promise<{
|
|
177
|
+
success: true;
|
|
178
|
+
data: T;
|
|
179
|
+
} | {
|
|
180
|
+
success: false;
|
|
181
|
+
}>;
|
|
182
|
+
}
|
|
183
|
+
declare const untyped: unique symbol;
|
|
184
|
+
/** Value type of an entry without schema: given by the loader. */
|
|
185
|
+
interface Untyped {
|
|
186
|
+
readonly [untyped]: true;
|
|
187
|
+
}
|
|
188
|
+
declare const entryTypes: unique symbol;
|
|
189
|
+
/** A kind of cached value, created by `defineCacheEntry()`. */
|
|
190
|
+
interface CacheEntry<A extends readonly unknown[], T> {
|
|
191
|
+
readonly name: string;
|
|
192
|
+
readonly version: number;
|
|
193
|
+
/** Types only. */
|
|
194
|
+
readonly [entryTypes]?: {
|
|
195
|
+
args: A;
|
|
196
|
+
value: (value: T) => T;
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/** Value of an entry: `unknown` without schema. */
|
|
200
|
+
type CacheValue<T> = T extends Untyped ? unknown : T;
|
|
201
|
+
/**
|
|
202
|
+
* Lifetime and resilience of values: options of an entry, or defaults of
|
|
203
|
+
* the cache.
|
|
204
|
+
*/
|
|
205
|
+
interface CachePolicy {
|
|
206
|
+
/** Lifetime of the values. Defaults to 1 hour. */
|
|
207
|
+
ttl?: Duration | undefined;
|
|
208
|
+
/**
|
|
209
|
+
* Stale-if-error: how long after expiry a value can still be served when
|
|
210
|
+
* the loader fails (or times out). Defaults to 0 (disabled).
|
|
211
|
+
*/
|
|
212
|
+
grace?: Duration | undefined;
|
|
213
|
+
/**
|
|
214
|
+
* After a failed load served from the grace period, the loader is not
|
|
215
|
+
* called again before this delay: the stale value is served. Defaults to
|
|
216
|
+
* 10 seconds.
|
|
217
|
+
*/
|
|
218
|
+
graceBackoff?: Duration | undefined;
|
|
219
|
+
/**
|
|
220
|
+
* How long after expiry a value is still served while a background load
|
|
221
|
+
* refreshes it. Defaults to 0 (disabled).
|
|
222
|
+
*/
|
|
223
|
+
staleWhileRevalidate?: Duration | undefined;
|
|
224
|
+
/**
|
|
225
|
+
* Soft timeout: a load slower than this serves the stale value of the
|
|
226
|
+
* grace period, if any, and goes on in the background.
|
|
227
|
+
*/
|
|
228
|
+
timeout?: Duration | undefined;
|
|
229
|
+
/**
|
|
230
|
+
* Hard timeout: a load slower than this fails (`CacheTimeoutError`), or
|
|
231
|
+
* serves the stale value of the grace period, if any. It goes on in the
|
|
232
|
+
* background.
|
|
233
|
+
*/
|
|
234
|
+
hardTimeout?: Duration | undefined;
|
|
235
|
+
/**
|
|
236
|
+
* Distributed single flight: before loading a missing value, takes a
|
|
237
|
+
* lock in the store (Redis…) for at most this duration; the other
|
|
238
|
+
* instances wait for the value meanwhile, then load it themselves.
|
|
239
|
+
* Ignored by stores without locks. Disabled by default.
|
|
240
|
+
*/
|
|
241
|
+
lock?: Duration | undefined;
|
|
242
|
+
}
|
|
243
|
+
/** Options of `defineCacheEntry()`. */
|
|
244
|
+
interface CacheEntryOptions<A extends readonly unknown[], T> extends CachePolicy {
|
|
245
|
+
/**
|
|
246
|
+
* Name of the entry, in keys and logs: letters, digits, `.`, `_` and
|
|
247
|
+
* `-`.
|
|
248
|
+
*/
|
|
249
|
+
name: string;
|
|
250
|
+
/**
|
|
251
|
+
* Key of the arguments: a string, a number, or a value compared like the
|
|
252
|
+
* arguments of a memo. Defaults to the argument (or the arguments).
|
|
253
|
+
*/
|
|
254
|
+
key?: ((...args: A) => unknown) | undefined;
|
|
255
|
+
/**
|
|
256
|
+
* Validates cached values when they are read (entries from an older
|
|
257
|
+
* version of the app) and written. JSON turns dates into strings: use
|
|
258
|
+
* `z.coerce.date()`.
|
|
259
|
+
*/
|
|
260
|
+
schema?: CacheSchema<T> | undefined;
|
|
261
|
+
/**
|
|
262
|
+
* Version of the values, in the key: increase it when their shape
|
|
263
|
+
* changes, to ignore the values written before. Defaults to 1.
|
|
264
|
+
*/
|
|
265
|
+
version?: number | undefined;
|
|
266
|
+
/**
|
|
267
|
+
* Tags of the arguments: `invalidateTags()` expires every value with one
|
|
268
|
+
* of them.
|
|
269
|
+
*/
|
|
270
|
+
tags?: ((...args: A) => readonly string[]) | undefined;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Defines a kind of cached value: its key, its lifetime, and optionally
|
|
274
|
+
* its schema.
|
|
275
|
+
*
|
|
276
|
+
* ```ts
|
|
277
|
+
* export const userCache = defineCacheEntry({
|
|
278
|
+
* name: 'user',
|
|
279
|
+
* key: (id: string) => id,
|
|
280
|
+
* schema: userSchema,
|
|
281
|
+
* ttl: '1h',
|
|
282
|
+
* })
|
|
283
|
+
* ```
|
|
284
|
+
*/
|
|
285
|
+
declare function defineCacheEntry<A extends readonly unknown[], T>(options: CacheEntryOptions<A, T> & {
|
|
286
|
+
schema: CacheSchema<T>;
|
|
287
|
+
}): CacheEntry<A, T>;
|
|
288
|
+
declare function defineCacheEntry<A extends readonly unknown[]>(options: CacheEntryOptions<A, never> & {
|
|
289
|
+
schema?: undefined;
|
|
290
|
+
}): CacheEntry<A, Untyped>;
|
|
291
|
+
declare function defineCacheEntry<A extends readonly unknown[], T>(options: CacheEntryOptions<A, T>): CacheEntry<A, T>;
|
|
292
|
+
/** Turns values into strings for the store, and back. */
|
|
293
|
+
interface CacheSerializer {
|
|
294
|
+
serialize(value: unknown): string;
|
|
295
|
+
deserialize(text: string): unknown;
|
|
296
|
+
}
|
|
297
|
+
/** Details of a store failure, for `onError`. */
|
|
298
|
+
interface CacheErrorInfo {
|
|
299
|
+
readonly operation: StoreOperation;
|
|
300
|
+
/** Key of the store. */
|
|
301
|
+
readonly key: string;
|
|
302
|
+
/** Name of the entry. */
|
|
303
|
+
readonly entry: string;
|
|
304
|
+
}
|
|
305
|
+
/** Something that happened to a value, for `onEvent`. */
|
|
306
|
+
interface CacheEvent {
|
|
307
|
+
/**
|
|
308
|
+
* `hit`: fresh value; `miss`: loaded; `stale`: a value past its `ttl`
|
|
309
|
+
* served, for the `reason`.
|
|
310
|
+
*/
|
|
311
|
+
readonly type: 'hit' | 'miss' | 'stale';
|
|
312
|
+
readonly reason?: 'revalidate' | 'error' | 'timeout' | 'backoff';
|
|
313
|
+
/** Name of the entry. */
|
|
314
|
+
readonly entry: string;
|
|
315
|
+
/** Key of the store. */
|
|
316
|
+
readonly key: string;
|
|
317
|
+
}
|
|
318
|
+
/** Options of `createCache()`: the policy is the default of the entries. */
|
|
319
|
+
interface CacheOptions extends CachePolicy {
|
|
320
|
+
store: CacheStore;
|
|
321
|
+
/** Prefix of every key, like the name of the app. */
|
|
322
|
+
prefix?: string | undefined;
|
|
323
|
+
/** Defaults to JSON. */
|
|
324
|
+
serializer?: CacheSerializer | undefined;
|
|
325
|
+
logger?: CacheLogger | undefined;
|
|
326
|
+
/**
|
|
327
|
+
* Called for each store failure, besides the log: metrics, alerts. Its
|
|
328
|
+
* own errors are logged and ignored.
|
|
329
|
+
*/
|
|
330
|
+
onError?: ((error: CacheStoreError, info: CacheErrorInfo) => void | Promise<void>) | undefined;
|
|
331
|
+
/**
|
|
332
|
+
* When the store fails, behaves as a cache miss (reads) or ignores the
|
|
333
|
+
* write, after logging it. Set false to throw a `CacheStoreError`.
|
|
334
|
+
* Defaults to true.
|
|
335
|
+
*/
|
|
336
|
+
failOpen?: boolean | undefined;
|
|
337
|
+
/** A store operation slower than this counts as a failure. */
|
|
338
|
+
storeTimeout?: Duration | undefined;
|
|
339
|
+
/**
|
|
340
|
+
* Called for each hit, miss and stale value served: metrics. Its errors
|
|
341
|
+
* are logged and ignored.
|
|
342
|
+
*/
|
|
343
|
+
onEvent?: ((event: CacheEvent) => void) | undefined;
|
|
344
|
+
}
|
|
345
|
+
/** A cache, created by `createCache()`. */
|
|
346
|
+
interface Cache {
|
|
347
|
+
/**
|
|
348
|
+
* The fresh value of the arguments, or undefined when missing, expired
|
|
349
|
+
* or invalidated.
|
|
350
|
+
*/
|
|
351
|
+
get<A extends readonly unknown[], T>(entry: CacheEntry<A, T>, ...args: A): Promise<CacheValue<T> | undefined>;
|
|
352
|
+
/** Sets the value of the arguments (the last argument). */
|
|
353
|
+
set<A extends readonly unknown[], T>(entry: CacheEntry<A, T>, ...argsAndValue: [...A, CacheValue<T>]): Promise<void>;
|
|
354
|
+
/** Removes the value of the arguments. */
|
|
355
|
+
delete<A extends readonly unknown[], T>(entry: CacheEntry<A, T>, ...args: A): Promise<void>;
|
|
356
|
+
/**
|
|
357
|
+
* The value of the arguments, loaded by the last argument when missing
|
|
358
|
+
* and cached. Calls made while it loads share the load. Applies the
|
|
359
|
+
* grace period, stale-while-revalidate and timeouts of the entry.
|
|
360
|
+
*/
|
|
361
|
+
getOrSet<A extends readonly unknown[], R>(entry: CacheEntry<A, Untyped>, ...argsAndLoader: [...A, () => R | Promise<R>]): Promise<R>;
|
|
362
|
+
getOrSet<A extends readonly unknown[], T>(entry: CacheEntry<A, T>, ...argsAndLoader: [...A, () => T | Promise<T>]): Promise<T>;
|
|
363
|
+
/**
|
|
364
|
+
* Expires every value with one of the tags (they can still be served by
|
|
365
|
+
* the grace period when the loader fails).
|
|
366
|
+
*/
|
|
367
|
+
invalidateTags(tags: readonly string[]): Promise<void>;
|
|
368
|
+
/** The same cache, logging with another logger. */
|
|
369
|
+
withLogger(logger: CacheLogger): Cache;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Creates a cache on a store. Reads and writes fail open by default: a
|
|
373
|
+
* store failure is logged (and passed to `onError`), and the app keeps
|
|
374
|
+
* working without cache.
|
|
375
|
+
*
|
|
376
|
+
* ```ts
|
|
377
|
+
* const cache = createCache({ store: createMemoryStore(), prefix: 'app', ttl: '10m' })
|
|
378
|
+
* const user = await cache.getOrSet(userCache, id, () => db.users.findById(id))
|
|
379
|
+
* ```
|
|
380
|
+
*/
|
|
381
|
+
declare const createCache: (options: CacheOptions) => Cache;
|
|
382
|
+
|
|
383
|
+
export { CacheError, CacheStore, CacheStoreError, CacheTimeoutError, Duration, MemoBatchError, createCache, createMemo, defineCacheEntry, defineMemo };
|
|
384
|
+
export type { BatchMemoOptions, Cache, CacheEntry, CacheEntryOptions, CacheErrorInfo, CacheEvent, CacheLogger, CacheOptions, CachePolicy, CacheSchema, CacheSerializer, CacheValue, LoadMemoOptions, Memo, MemoDefinition, StoreOperation, Untyped };
|