layercache 1.2.1 → 1.2.2
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 +40 -4
- package/dist/{chunk-GF47Y3XR.js → chunk-IXCMHVHP.js} +55 -24
- package/dist/cli.cjs +55 -24
- package/dist/cli.js +1 -1
- package/dist/{edge-C1sBhTfv.d.cts → edge-DLpdQN0W.d.cts} +5 -0
- package/dist/{edge-C1sBhTfv.d.ts → edge-DLpdQN0W.d.ts} +5 -0
- package/dist/edge.d.cts +1 -1
- package/dist/edge.d.ts +1 -1
- package/dist/index.cjs +238 -60
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +185 -38
- package/package.json +2 -2
- package/packages/nestjs/dist/index.cjs +100 -28
- package/packages/nestjs/dist/index.d.cts +5 -0
- package/packages/nestjs/dist/index.d.ts +5 -0
- package/packages/nestjs/dist/index.js +100 -28
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# layercache
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Production-ready multi-layer caching for Node.js — memory, Redis, persistence, invalidation, and resilience in one API.**
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/layercache)
|
|
6
6
|
[](https://www.npmjs.com/package/layercache)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://www.typescriptlang.org/)
|
|
9
|
-
[](https://github.com/flyingsquirrel0419/layercache)
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
L1 hit ~0.01 ms ← served from memory, zero network
|
|
@@ -26,6 +26,8 @@ Most Node.js services end up with the same problem:
|
|
|
26
26
|
|
|
27
27
|
layercache solves all three. You declare your layers once and call `get`. Everything else is handled.
|
|
28
28
|
|
|
29
|
+
It is designed for production services that need predictable cache behavior under load: stampede prevention, cross-instance invalidation, layered TTL control, operational metrics, and safer persistence defaults.
|
|
30
|
+
|
|
29
31
|
```ts
|
|
30
32
|
const user = await cache.get('user:123', () => db.findUser(123))
|
|
31
33
|
// ↑ only called on a full miss
|
|
@@ -452,13 +454,14 @@ const cache = new CacheStack(
|
|
|
452
454
|
{
|
|
453
455
|
singleFlightCoordinator: coordinator,
|
|
454
456
|
singleFlightLeaseMs: 30_000,
|
|
457
|
+
singleFlightRenewIntervalMs: 10_000,
|
|
455
458
|
singleFlightTimeoutMs: 5_000,
|
|
456
459
|
singleFlightPollMs: 50
|
|
457
460
|
}
|
|
458
461
|
)
|
|
459
462
|
```
|
|
460
463
|
|
|
461
|
-
When another instance already owns the miss, the current process waits for the value to appear in the shared layer instead of running the fetcher again.
|
|
464
|
+
When another instance already owns the miss, the current process waits for the value to appear in the shared layer instead of running the fetcher again. `RedisSingleFlightCoordinator` also renews its Redis lease while the worker is still running, so long fetches are less likely to expire their lock mid-flight. Keep `singleFlightLeaseMs` comfortably above your expected fetch latency, and use `singleFlightRenewIntervalMs` if you need tighter control over renewal cadence.
|
|
462
465
|
|
|
463
466
|
### Cross-server L1 invalidation
|
|
464
467
|
|
|
@@ -494,7 +497,8 @@ import { RedisTagIndex } from 'layercache'
|
|
|
494
497
|
|
|
495
498
|
const sharedTagIndex = new RedisTagIndex({
|
|
496
499
|
client: redis,
|
|
497
|
-
prefix: 'myapp:tag-index' // namespaced so it doesn't collide with other data
|
|
500
|
+
prefix: 'myapp:tag-index', // namespaced so it doesn't collide with other data
|
|
501
|
+
knownKeysShards: 8
|
|
498
502
|
})
|
|
499
503
|
|
|
500
504
|
// Every CacheStack instance should use the same Redis-backed tag index config
|
|
@@ -528,6 +532,38 @@ new RedisLayer({
|
|
|
528
532
|
})
|
|
529
533
|
```
|
|
530
534
|
|
|
535
|
+
For production Redis, also set an explicit `prefix`, enforce Redis authentication/network isolation, and configure Redis `maxmemory` / eviction policy so cache growth cannot starve unrelated workloads.
|
|
536
|
+
|
|
537
|
+
### DiskLayer safety
|
|
538
|
+
|
|
539
|
+
`DiskLayer` is best used with an application-controlled directory and an explicit `maxFiles` bound.
|
|
540
|
+
|
|
541
|
+
```ts
|
|
542
|
+
import { resolve } from 'node:path'
|
|
543
|
+
|
|
544
|
+
const disk = new DiskLayer({
|
|
545
|
+
directory: resolve('./var/cache/layercache'),
|
|
546
|
+
maxFiles: 10_000
|
|
547
|
+
})
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
The library hashes cache keys before turning them into filenames, validates the configured directory, uses atomic temp-file writes, and removes malformed on-disk entries. You should still keep the directory outside any user-controlled path and set filesystem permissions so only your app can read or write it.
|
|
551
|
+
|
|
552
|
+
### Scoped fetcher rate limiting
|
|
553
|
+
|
|
554
|
+
Rate limits are global by default, but you can scope them per cache key or per fetcher function when different backends should not throttle each other.
|
|
555
|
+
|
|
556
|
+
```ts
|
|
557
|
+
await cache.get('user:123', fetchUser, {
|
|
558
|
+
fetcherRateLimit: {
|
|
559
|
+
maxConcurrent: 1,
|
|
560
|
+
scope: 'key'
|
|
561
|
+
}
|
|
562
|
+
})
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Use `scope: 'fetcher'` to share a bucket across calls using the same fetcher function reference, or `bucketKey: 'billing-api'` for a custom named bucket.
|
|
566
|
+
|
|
531
567
|
---
|
|
532
568
|
|
|
533
569
|
## Per-layer TTL overrides
|
|
@@ -7,19 +7,21 @@ var RedisTagIndex = class {
|
|
|
7
7
|
client;
|
|
8
8
|
prefix;
|
|
9
9
|
scanCount;
|
|
10
|
+
knownKeysShards;
|
|
10
11
|
constructor(options) {
|
|
11
12
|
this.client = options.client;
|
|
12
13
|
this.prefix = options.prefix ?? "layercache:tag-index";
|
|
13
14
|
this.scanCount = options.scanCount ?? 100;
|
|
15
|
+
this.knownKeysShards = normalizeKnownKeysShards(options.knownKeysShards);
|
|
14
16
|
}
|
|
15
17
|
async touch(key) {
|
|
16
|
-
await this.client.sadd(this.
|
|
18
|
+
await this.client.sadd(this.knownKeysKeyFor(key), key);
|
|
17
19
|
}
|
|
18
20
|
async track(key, tags) {
|
|
19
21
|
const keyTagsKey = this.keyTagsKey(key);
|
|
20
22
|
const existingTags = await this.client.smembers(keyTagsKey);
|
|
21
23
|
const pipeline = this.client.pipeline();
|
|
22
|
-
pipeline.sadd(this.
|
|
24
|
+
pipeline.sadd(this.knownKeysKeyFor(key), key);
|
|
23
25
|
for (const tag of existingTags) {
|
|
24
26
|
pipeline.srem(this.tagKeysKey(tag), key);
|
|
25
27
|
}
|
|
@@ -36,7 +38,7 @@ var RedisTagIndex = class {
|
|
|
36
38
|
const keyTagsKey = this.keyTagsKey(key);
|
|
37
39
|
const existingTags = await this.client.smembers(keyTagsKey);
|
|
38
40
|
const pipeline = this.client.pipeline();
|
|
39
|
-
pipeline.srem(this.
|
|
41
|
+
pipeline.srem(this.knownKeysKeyFor(key), key);
|
|
40
42
|
pipeline.del(keyTagsKey);
|
|
41
43
|
for (const tag of existingTags) {
|
|
42
44
|
pipeline.srem(this.tagKeysKey(tag), key);
|
|
@@ -48,12 +50,14 @@ var RedisTagIndex = class {
|
|
|
48
50
|
}
|
|
49
51
|
async keysForPrefix(prefix) {
|
|
50
52
|
const matches = [];
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
for (const knownKeysKey of this.knownKeysKeys()) {
|
|
54
|
+
let cursor = "0";
|
|
55
|
+
do {
|
|
56
|
+
const [nextCursor, keys] = await this.client.sscan(knownKeysKey, cursor, "COUNT", this.scanCount);
|
|
57
|
+
cursor = nextCursor;
|
|
58
|
+
matches.push(...keys.filter((key) => key.startsWith(prefix)));
|
|
59
|
+
} while (cursor !== "0");
|
|
60
|
+
}
|
|
57
61
|
return matches;
|
|
58
62
|
}
|
|
59
63
|
async tagsForKey(key) {
|
|
@@ -61,19 +65,21 @@ var RedisTagIndex = class {
|
|
|
61
65
|
}
|
|
62
66
|
async matchPattern(pattern) {
|
|
63
67
|
const matches = [];
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
this.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
for (const knownKeysKey of this.knownKeysKeys()) {
|
|
69
|
+
let cursor = "0";
|
|
70
|
+
do {
|
|
71
|
+
const [nextCursor, keys] = await this.client.sscan(
|
|
72
|
+
knownKeysKey,
|
|
73
|
+
cursor,
|
|
74
|
+
"MATCH",
|
|
75
|
+
pattern,
|
|
76
|
+
"COUNT",
|
|
77
|
+
this.scanCount
|
|
78
|
+
);
|
|
79
|
+
cursor = nextCursor;
|
|
80
|
+
matches.push(...keys.filter((key) => PatternMatcher.matches(pattern, key)));
|
|
81
|
+
} while (cursor !== "0");
|
|
82
|
+
}
|
|
77
83
|
return matches;
|
|
78
84
|
}
|
|
79
85
|
async clear() {
|
|
@@ -94,8 +100,17 @@ var RedisTagIndex = class {
|
|
|
94
100
|
} while (cursor !== "0");
|
|
95
101
|
return matches;
|
|
96
102
|
}
|
|
97
|
-
|
|
98
|
-
|
|
103
|
+
knownKeysKeyFor(key) {
|
|
104
|
+
if (this.knownKeysShards === 1) {
|
|
105
|
+
return `${this.prefix}:keys`;
|
|
106
|
+
}
|
|
107
|
+
return `${this.prefix}:keys:${simpleHash(key) % this.knownKeysShards}`;
|
|
108
|
+
}
|
|
109
|
+
knownKeysKeys() {
|
|
110
|
+
if (this.knownKeysShards === 1) {
|
|
111
|
+
return [`${this.prefix}:keys`];
|
|
112
|
+
}
|
|
113
|
+
return Array.from({ length: this.knownKeysShards }, (_, index) => `${this.prefix}:keys:${index}`);
|
|
99
114
|
}
|
|
100
115
|
keyTagsKey(key) {
|
|
101
116
|
return `${this.prefix}:key:${encodeURIComponent(key)}`;
|
|
@@ -104,6 +119,22 @@ var RedisTagIndex = class {
|
|
|
104
119
|
return `${this.prefix}:tag:${encodeURIComponent(tag)}`;
|
|
105
120
|
}
|
|
106
121
|
};
|
|
122
|
+
function normalizeKnownKeysShards(value) {
|
|
123
|
+
if (value === void 0) {
|
|
124
|
+
return 1;
|
|
125
|
+
}
|
|
126
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
127
|
+
throw new Error("RedisTagIndex.knownKeysShards must be a positive integer.");
|
|
128
|
+
}
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
function simpleHash(value) {
|
|
132
|
+
let hash = 0;
|
|
133
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
134
|
+
hash = hash * 31 + value.charCodeAt(index) >>> 0;
|
|
135
|
+
}
|
|
136
|
+
return hash;
|
|
137
|
+
}
|
|
107
138
|
|
|
108
139
|
export {
|
|
109
140
|
RedisTagIndex
|
package/dist/cli.cjs
CHANGED
|
@@ -118,19 +118,21 @@ var RedisTagIndex = class {
|
|
|
118
118
|
client;
|
|
119
119
|
prefix;
|
|
120
120
|
scanCount;
|
|
121
|
+
knownKeysShards;
|
|
121
122
|
constructor(options) {
|
|
122
123
|
this.client = options.client;
|
|
123
124
|
this.prefix = options.prefix ?? "layercache:tag-index";
|
|
124
125
|
this.scanCount = options.scanCount ?? 100;
|
|
126
|
+
this.knownKeysShards = normalizeKnownKeysShards(options.knownKeysShards);
|
|
125
127
|
}
|
|
126
128
|
async touch(key) {
|
|
127
|
-
await this.client.sadd(this.
|
|
129
|
+
await this.client.sadd(this.knownKeysKeyFor(key), key);
|
|
128
130
|
}
|
|
129
131
|
async track(key, tags) {
|
|
130
132
|
const keyTagsKey = this.keyTagsKey(key);
|
|
131
133
|
const existingTags = await this.client.smembers(keyTagsKey);
|
|
132
134
|
const pipeline = this.client.pipeline();
|
|
133
|
-
pipeline.sadd(this.
|
|
135
|
+
pipeline.sadd(this.knownKeysKeyFor(key), key);
|
|
134
136
|
for (const tag of existingTags) {
|
|
135
137
|
pipeline.srem(this.tagKeysKey(tag), key);
|
|
136
138
|
}
|
|
@@ -147,7 +149,7 @@ var RedisTagIndex = class {
|
|
|
147
149
|
const keyTagsKey = this.keyTagsKey(key);
|
|
148
150
|
const existingTags = await this.client.smembers(keyTagsKey);
|
|
149
151
|
const pipeline = this.client.pipeline();
|
|
150
|
-
pipeline.srem(this.
|
|
152
|
+
pipeline.srem(this.knownKeysKeyFor(key), key);
|
|
151
153
|
pipeline.del(keyTagsKey);
|
|
152
154
|
for (const tag of existingTags) {
|
|
153
155
|
pipeline.srem(this.tagKeysKey(tag), key);
|
|
@@ -159,12 +161,14 @@ var RedisTagIndex = class {
|
|
|
159
161
|
}
|
|
160
162
|
async keysForPrefix(prefix) {
|
|
161
163
|
const matches = [];
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
for (const knownKeysKey of this.knownKeysKeys()) {
|
|
165
|
+
let cursor = "0";
|
|
166
|
+
do {
|
|
167
|
+
const [nextCursor, keys] = await this.client.sscan(knownKeysKey, cursor, "COUNT", this.scanCount);
|
|
168
|
+
cursor = nextCursor;
|
|
169
|
+
matches.push(...keys.filter((key) => key.startsWith(prefix)));
|
|
170
|
+
} while (cursor !== "0");
|
|
171
|
+
}
|
|
168
172
|
return matches;
|
|
169
173
|
}
|
|
170
174
|
async tagsForKey(key) {
|
|
@@ -172,19 +176,21 @@ var RedisTagIndex = class {
|
|
|
172
176
|
}
|
|
173
177
|
async matchPattern(pattern) {
|
|
174
178
|
const matches = [];
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
this.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
179
|
+
for (const knownKeysKey of this.knownKeysKeys()) {
|
|
180
|
+
let cursor = "0";
|
|
181
|
+
do {
|
|
182
|
+
const [nextCursor, keys] = await this.client.sscan(
|
|
183
|
+
knownKeysKey,
|
|
184
|
+
cursor,
|
|
185
|
+
"MATCH",
|
|
186
|
+
pattern,
|
|
187
|
+
"COUNT",
|
|
188
|
+
this.scanCount
|
|
189
|
+
);
|
|
190
|
+
cursor = nextCursor;
|
|
191
|
+
matches.push(...keys.filter((key) => PatternMatcher.matches(pattern, key)));
|
|
192
|
+
} while (cursor !== "0");
|
|
193
|
+
}
|
|
188
194
|
return matches;
|
|
189
195
|
}
|
|
190
196
|
async clear() {
|
|
@@ -205,8 +211,17 @@ var RedisTagIndex = class {
|
|
|
205
211
|
} while (cursor !== "0");
|
|
206
212
|
return matches;
|
|
207
213
|
}
|
|
208
|
-
|
|
209
|
-
|
|
214
|
+
knownKeysKeyFor(key) {
|
|
215
|
+
if (this.knownKeysShards === 1) {
|
|
216
|
+
return `${this.prefix}:keys`;
|
|
217
|
+
}
|
|
218
|
+
return `${this.prefix}:keys:${simpleHash(key) % this.knownKeysShards}`;
|
|
219
|
+
}
|
|
220
|
+
knownKeysKeys() {
|
|
221
|
+
if (this.knownKeysShards === 1) {
|
|
222
|
+
return [`${this.prefix}:keys`];
|
|
223
|
+
}
|
|
224
|
+
return Array.from({ length: this.knownKeysShards }, (_, index) => `${this.prefix}:keys:${index}`);
|
|
210
225
|
}
|
|
211
226
|
keyTagsKey(key) {
|
|
212
227
|
return `${this.prefix}:key:${encodeURIComponent(key)}`;
|
|
@@ -215,6 +230,22 @@ var RedisTagIndex = class {
|
|
|
215
230
|
return `${this.prefix}:tag:${encodeURIComponent(tag)}`;
|
|
216
231
|
}
|
|
217
232
|
};
|
|
233
|
+
function normalizeKnownKeysShards(value) {
|
|
234
|
+
if (value === void 0) {
|
|
235
|
+
return 1;
|
|
236
|
+
}
|
|
237
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
238
|
+
throw new Error("RedisTagIndex.knownKeysShards must be a positive integer.");
|
|
239
|
+
}
|
|
240
|
+
return value;
|
|
241
|
+
}
|
|
242
|
+
function simpleHash(value) {
|
|
243
|
+
let hash = 0;
|
|
244
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
245
|
+
hash = hash * 31 + value.charCodeAt(index) >>> 0;
|
|
246
|
+
}
|
|
247
|
+
return hash;
|
|
248
|
+
}
|
|
218
249
|
|
|
219
250
|
// src/cli.ts
|
|
220
251
|
var CONNECT_TIMEOUT_MS = 5e3;
|
package/dist/cli.js
CHANGED
|
@@ -165,6 +165,7 @@ interface CacheSingleFlightExecutionOptions {
|
|
|
165
165
|
leaseMs: number;
|
|
166
166
|
waitTimeoutMs: number;
|
|
167
167
|
pollIntervalMs: number;
|
|
168
|
+
renewIntervalMs?: number;
|
|
168
169
|
}
|
|
169
170
|
interface CacheSingleFlightCoordinator {
|
|
170
171
|
execute<T>(key: string, options: CacheSingleFlightExecutionOptions, worker: () => Promise<T>, waiter: () => Promise<T>): Promise<T>;
|
|
@@ -198,6 +199,7 @@ interface CacheStackOptions {
|
|
|
198
199
|
singleFlightLeaseMs?: number;
|
|
199
200
|
singleFlightTimeoutMs?: number;
|
|
200
201
|
singleFlightPollMs?: number;
|
|
202
|
+
singleFlightRenewIntervalMs?: number;
|
|
201
203
|
/**
|
|
202
204
|
* Maximum number of entries in `accessProfiles` and `circuitBreakers` maps
|
|
203
205
|
* before the oldest entries are pruned. Prevents unbounded memory growth.
|
|
@@ -228,6 +230,8 @@ interface CacheRateLimitOptions {
|
|
|
228
230
|
maxConcurrent?: number;
|
|
229
231
|
intervalMs?: number;
|
|
230
232
|
maxPerInterval?: number;
|
|
233
|
+
scope?: 'global' | 'key' | 'fetcher';
|
|
234
|
+
bucketKey?: string;
|
|
231
235
|
}
|
|
232
236
|
interface CacheWriteBehindOptions {
|
|
233
237
|
flushIntervalMs?: number;
|
|
@@ -627,6 +631,7 @@ declare class CacheStack extends EventEmitter {
|
|
|
627
631
|
private validateWriteOptions;
|
|
628
632
|
private validateLayerNumberOption;
|
|
629
633
|
private validatePositiveNumber;
|
|
634
|
+
private validateRateLimitOptions;
|
|
630
635
|
private validateNonNegativeNumber;
|
|
631
636
|
private validateCacheKey;
|
|
632
637
|
private validateTtlPolicy;
|
|
@@ -165,6 +165,7 @@ interface CacheSingleFlightExecutionOptions {
|
|
|
165
165
|
leaseMs: number;
|
|
166
166
|
waitTimeoutMs: number;
|
|
167
167
|
pollIntervalMs: number;
|
|
168
|
+
renewIntervalMs?: number;
|
|
168
169
|
}
|
|
169
170
|
interface CacheSingleFlightCoordinator {
|
|
170
171
|
execute<T>(key: string, options: CacheSingleFlightExecutionOptions, worker: () => Promise<T>, waiter: () => Promise<T>): Promise<T>;
|
|
@@ -198,6 +199,7 @@ interface CacheStackOptions {
|
|
|
198
199
|
singleFlightLeaseMs?: number;
|
|
199
200
|
singleFlightTimeoutMs?: number;
|
|
200
201
|
singleFlightPollMs?: number;
|
|
202
|
+
singleFlightRenewIntervalMs?: number;
|
|
201
203
|
/**
|
|
202
204
|
* Maximum number of entries in `accessProfiles` and `circuitBreakers` maps
|
|
203
205
|
* before the oldest entries are pruned. Prevents unbounded memory growth.
|
|
@@ -228,6 +230,8 @@ interface CacheRateLimitOptions {
|
|
|
228
230
|
maxConcurrent?: number;
|
|
229
231
|
intervalMs?: number;
|
|
230
232
|
maxPerInterval?: number;
|
|
233
|
+
scope?: 'global' | 'key' | 'fetcher';
|
|
234
|
+
bucketKey?: string;
|
|
231
235
|
}
|
|
232
236
|
interface CacheWriteBehindOptions {
|
|
233
237
|
flushIntervalMs?: number;
|
|
@@ -627,6 +631,7 @@ declare class CacheStack extends EventEmitter {
|
|
|
627
631
|
private validateWriteOptions;
|
|
628
632
|
private validateLayerNumberOption;
|
|
629
633
|
private validatePositiveNumber;
|
|
634
|
+
private validateRateLimitOptions;
|
|
630
635
|
private validateNonNegativeNumber;
|
|
631
636
|
private validateCacheKey;
|
|
632
637
|
private validateTtlPolicy;
|
package/dist/edge.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-
|
|
1
|
+
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-DLpdQN0W.cjs';
|
|
2
2
|
import 'node:events';
|
package/dist/edge.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-
|
|
1
|
+
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-DLpdQN0W.js';
|
|
2
2
|
import 'node:events';
|