@parsrun/cache 0.1.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.
@@ -0,0 +1,783 @@
1
+ // src/adapters/memory.ts
2
+ var MemoryCacheAdapter = class {
3
+ type = "memory";
4
+ cache = /* @__PURE__ */ new Map();
5
+ tagIndex = /* @__PURE__ */ new Map();
6
+ maxEntries;
7
+ cleanupInterval;
8
+ cleanupTimer = null;
9
+ constructor(config) {
10
+ this.maxEntries = config?.maxEntries ?? 1e4;
11
+ this.cleanupInterval = config?.cleanupInterval ?? 6e4;
12
+ if (this.cleanupInterval > 0) {
13
+ this.cleanupTimer = setInterval(() => this.cleanup(), this.cleanupInterval);
14
+ }
15
+ }
16
+ async get(key, options) {
17
+ const entry = this.cache.get(key);
18
+ if (!entry) {
19
+ return null;
20
+ }
21
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
22
+ this.cache.delete(key);
23
+ this.removeFromTagIndex(key, entry.tags);
24
+ return null;
25
+ }
26
+ if (options?.refresh && entry.expiresAt && entry.ttlSeconds) {
27
+ entry.expiresAt = Date.now() + entry.ttlSeconds * 1e3;
28
+ }
29
+ return entry.value;
30
+ }
31
+ async set(key, value, options) {
32
+ if (this.cache.size >= this.maxEntries && !this.cache.has(key)) {
33
+ const oldestKey = this.cache.keys().next().value;
34
+ if (oldestKey) {
35
+ const oldEntry = this.cache.get(oldestKey);
36
+ this.cache.delete(oldestKey);
37
+ if (oldEntry?.tags) {
38
+ this.removeFromTagIndex(oldestKey, oldEntry.tags);
39
+ }
40
+ }
41
+ }
42
+ const entry = {
43
+ value,
44
+ metadata: options?.metadata
45
+ };
46
+ if (options?.ttl) {
47
+ entry.expiresAt = Date.now() + options.ttl * 1e3;
48
+ entry.ttlSeconds = options.ttl;
49
+ }
50
+ if (options?.tags && options.tags.length > 0) {
51
+ entry.tags = options.tags;
52
+ this.addToTagIndex(key, options.tags);
53
+ }
54
+ this.cache.set(key, entry);
55
+ }
56
+ async delete(key) {
57
+ const entry = this.cache.get(key);
58
+ if (entry?.tags) {
59
+ this.removeFromTagIndex(key, entry.tags);
60
+ }
61
+ this.cache.delete(key);
62
+ }
63
+ async has(key) {
64
+ const entry = this.cache.get(key);
65
+ if (!entry) {
66
+ return false;
67
+ }
68
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
69
+ this.cache.delete(key);
70
+ this.removeFromTagIndex(key, entry.tags);
71
+ return false;
72
+ }
73
+ return true;
74
+ }
75
+ async clear() {
76
+ this.cache.clear();
77
+ this.tagIndex.clear();
78
+ }
79
+ async getMany(keys) {
80
+ const result = /* @__PURE__ */ new Map();
81
+ for (const key of keys) {
82
+ result.set(key, await this.get(key));
83
+ }
84
+ return result;
85
+ }
86
+ async setMany(entries, options) {
87
+ for (const [key, value] of entries) {
88
+ await this.set(key, value, options);
89
+ }
90
+ }
91
+ async deleteMany(keys) {
92
+ for (const key of keys) {
93
+ await this.delete(key);
94
+ }
95
+ }
96
+ async invalidateByTags(tags) {
97
+ const keysToDelete = /* @__PURE__ */ new Set();
98
+ for (const tag of tags) {
99
+ const keys = this.tagIndex.get(tag);
100
+ if (keys) {
101
+ for (const key of keys) {
102
+ keysToDelete.add(key);
103
+ }
104
+ }
105
+ }
106
+ for (const key of keysToDelete) {
107
+ await this.delete(key);
108
+ }
109
+ }
110
+ async ttl(key) {
111
+ const entry = this.cache.get(key);
112
+ if (!entry) {
113
+ return -2;
114
+ }
115
+ if (!entry.expiresAt) {
116
+ return -1;
117
+ }
118
+ const remaining = entry.expiresAt - Date.now();
119
+ if (remaining <= 0) {
120
+ return -2;
121
+ }
122
+ return Math.ceil(remaining / 1e3);
123
+ }
124
+ async close() {
125
+ if (this.cleanupTimer) {
126
+ clearInterval(this.cleanupTimer);
127
+ this.cleanupTimer = null;
128
+ }
129
+ await this.clear();
130
+ }
131
+ /**
132
+ * Get cache statistics
133
+ */
134
+ getStats() {
135
+ return {
136
+ size: this.cache.size,
137
+ maxEntries: this.maxEntries
138
+ };
139
+ }
140
+ addToTagIndex(key, tags) {
141
+ for (const tag of tags) {
142
+ let keys = this.tagIndex.get(tag);
143
+ if (!keys) {
144
+ keys = /* @__PURE__ */ new Set();
145
+ this.tagIndex.set(tag, keys);
146
+ }
147
+ keys.add(key);
148
+ }
149
+ }
150
+ removeFromTagIndex(key, tags) {
151
+ if (!tags) return;
152
+ for (const tag of tags) {
153
+ const keys = this.tagIndex.get(tag);
154
+ if (keys) {
155
+ keys.delete(key);
156
+ if (keys.size === 0) {
157
+ this.tagIndex.delete(tag);
158
+ }
159
+ }
160
+ }
161
+ }
162
+ cleanup() {
163
+ const now = Date.now();
164
+ for (const [key, entry] of this.cache) {
165
+ if (entry.expiresAt && now > entry.expiresAt) {
166
+ this.removeFromTagIndex(key, entry.tags);
167
+ this.cache.delete(key);
168
+ }
169
+ }
170
+ }
171
+ };
172
+ function createMemoryCacheAdapter(config) {
173
+ return new MemoryCacheAdapter(config);
174
+ }
175
+
176
+ // src/types.ts
177
+ import {
178
+ type,
179
+ cacheSetOptions,
180
+ cacheGetResult,
181
+ cacheStats,
182
+ memoryCacheConfig,
183
+ redisCacheConfig,
184
+ upstashCacheConfig,
185
+ cloudflareKvConfig,
186
+ multiTierCacheConfig,
187
+ cacheConfig
188
+ } from "@parsrun/types";
189
+ var CacheError = class extends Error {
190
+ constructor(message, code, cause) {
191
+ super(message);
192
+ this.code = code;
193
+ this.cause = cause;
194
+ this.name = "CacheError";
195
+ }
196
+ };
197
+ var CacheErrorCodes = {
198
+ CONNECTION_FAILED: "CONNECTION_FAILED",
199
+ OPERATION_FAILED: "OPERATION_FAILED",
200
+ SERIALIZATION_ERROR: "SERIALIZATION_ERROR",
201
+ INVALID_CONFIG: "INVALID_CONFIG",
202
+ NOT_IMPLEMENTED: "NOT_IMPLEMENTED"
203
+ };
204
+
205
+ // src/adapters/redis.ts
206
+ var RedisCacheAdapter = class {
207
+ type = "redis";
208
+ client;
209
+ keyPrefix;
210
+ isExternalClient;
211
+ constructor(config) {
212
+ this.client = config.client;
213
+ this.keyPrefix = config.keyPrefix ?? "";
214
+ this.isExternalClient = true;
215
+ }
216
+ prefixKey(key) {
217
+ return this.keyPrefix ? `${this.keyPrefix}:${key}` : key;
218
+ }
219
+ async get(key, _options) {
220
+ try {
221
+ const data = await this.client.get(this.prefixKey(key));
222
+ if (!data) {
223
+ return null;
224
+ }
225
+ const parsed = JSON.parse(data);
226
+ return parsed.value;
227
+ } catch (err) {
228
+ throw new CacheError(
229
+ `Redis get failed: ${err instanceof Error ? err.message : "Unknown error"}`,
230
+ CacheErrorCodes.OPERATION_FAILED,
231
+ err
232
+ );
233
+ }
234
+ }
235
+ async set(key, value, options) {
236
+ try {
237
+ const data = JSON.stringify({
238
+ value,
239
+ tags: options?.tags,
240
+ metadata: options?.metadata
241
+ });
242
+ const prefixedKey = this.prefixKey(key);
243
+ if (options?.ttl) {
244
+ await this.client.set(prefixedKey, data, "EX", options.ttl);
245
+ } else {
246
+ await this.client.set(prefixedKey, data);
247
+ }
248
+ if (options?.tags && options.tags.length > 0) {
249
+ const pipeline = this.client.pipeline();
250
+ for (const tag of options.tags) {
251
+ const tagKey = this.prefixKey(`__tag:${tag}`);
252
+ pipeline.set(tagKey, JSON.stringify([...await this.getTagKeys(tag), key]));
253
+ }
254
+ await pipeline.exec();
255
+ }
256
+ } catch (err) {
257
+ throw new CacheError(
258
+ `Redis set failed: ${err instanceof Error ? err.message : "Unknown error"}`,
259
+ CacheErrorCodes.OPERATION_FAILED,
260
+ err
261
+ );
262
+ }
263
+ }
264
+ async delete(key) {
265
+ try {
266
+ await this.client.del(this.prefixKey(key));
267
+ } catch (err) {
268
+ throw new CacheError(
269
+ `Redis delete failed: ${err instanceof Error ? err.message : "Unknown error"}`,
270
+ CacheErrorCodes.OPERATION_FAILED,
271
+ err
272
+ );
273
+ }
274
+ }
275
+ async has(key) {
276
+ try {
277
+ const exists = await this.client.exists(this.prefixKey(key));
278
+ return exists > 0;
279
+ } catch (err) {
280
+ throw new CacheError(
281
+ `Redis exists failed: ${err instanceof Error ? err.message : "Unknown error"}`,
282
+ CacheErrorCodes.OPERATION_FAILED,
283
+ err
284
+ );
285
+ }
286
+ }
287
+ async clear() {
288
+ try {
289
+ if (this.keyPrefix) {
290
+ const keys = await this.client.keys(`${this.keyPrefix}:*`);
291
+ if (keys.length > 0) {
292
+ await this.client.del(...keys);
293
+ }
294
+ } else {
295
+ await this.client.flushdb();
296
+ }
297
+ } catch (err) {
298
+ throw new CacheError(
299
+ `Redis clear failed: ${err instanceof Error ? err.message : "Unknown error"}`,
300
+ CacheErrorCodes.OPERATION_FAILED,
301
+ err
302
+ );
303
+ }
304
+ }
305
+ async getMany(keys) {
306
+ try {
307
+ const prefixedKeys = keys.map((k) => this.prefixKey(k));
308
+ const results = await this.client.mget(...prefixedKeys);
309
+ const map = /* @__PURE__ */ new Map();
310
+ for (let i = 0; i < keys.length; i++) {
311
+ const data = results[i];
312
+ if (data) {
313
+ const parsed = JSON.parse(data);
314
+ map.set(keys[i] ?? "", parsed.value);
315
+ } else {
316
+ map.set(keys[i] ?? "", null);
317
+ }
318
+ }
319
+ return map;
320
+ } catch (err) {
321
+ throw new CacheError(
322
+ `Redis mget failed: ${err instanceof Error ? err.message : "Unknown error"}`,
323
+ CacheErrorCodes.OPERATION_FAILED,
324
+ err
325
+ );
326
+ }
327
+ }
328
+ async setMany(entries, options) {
329
+ try {
330
+ const pipeline = this.client.pipeline();
331
+ for (const [key, value] of entries) {
332
+ const data = JSON.stringify({
333
+ value,
334
+ tags: options?.tags,
335
+ metadata: options?.metadata
336
+ });
337
+ const prefixedKey = this.prefixKey(key);
338
+ if (options?.ttl) {
339
+ pipeline.set(prefixedKey, data, "EX", options.ttl);
340
+ } else {
341
+ pipeline.set(prefixedKey, data);
342
+ }
343
+ }
344
+ await pipeline.exec();
345
+ } catch (err) {
346
+ throw new CacheError(
347
+ `Redis mset failed: ${err instanceof Error ? err.message : "Unknown error"}`,
348
+ CacheErrorCodes.OPERATION_FAILED,
349
+ err
350
+ );
351
+ }
352
+ }
353
+ async deleteMany(keys) {
354
+ try {
355
+ const prefixedKeys = keys.map((k) => this.prefixKey(k));
356
+ await this.client.del(...prefixedKeys);
357
+ } catch (err) {
358
+ throw new CacheError(
359
+ `Redis mdel failed: ${err instanceof Error ? err.message : "Unknown error"}`,
360
+ CacheErrorCodes.OPERATION_FAILED,
361
+ err
362
+ );
363
+ }
364
+ }
365
+ async invalidateByTags(tags) {
366
+ try {
367
+ const keysToDelete = [];
368
+ for (const tag of tags) {
369
+ const keys = await this.getTagKeys(tag);
370
+ keysToDelete.push(...keys);
371
+ }
372
+ if (keysToDelete.length > 0) {
373
+ await this.deleteMany(keysToDelete);
374
+ }
375
+ const tagKeys = tags.map((tag) => this.prefixKey(`__tag:${tag}`));
376
+ await this.client.del(...tagKeys);
377
+ } catch (err) {
378
+ throw new CacheError(
379
+ `Redis invalidate by tags failed: ${err instanceof Error ? err.message : "Unknown error"}`,
380
+ CacheErrorCodes.OPERATION_FAILED,
381
+ err
382
+ );
383
+ }
384
+ }
385
+ async ttl(key) {
386
+ try {
387
+ return await this.client.ttl(this.prefixKey(key));
388
+ } catch (err) {
389
+ throw new CacheError(
390
+ `Redis ttl failed: ${err instanceof Error ? err.message : "Unknown error"}`,
391
+ CacheErrorCodes.OPERATION_FAILED,
392
+ err
393
+ );
394
+ }
395
+ }
396
+ async close() {
397
+ if (!this.isExternalClient) {
398
+ await this.client.quit();
399
+ }
400
+ }
401
+ async getTagKeys(tag) {
402
+ const tagKey = this.prefixKey(`__tag:${tag}`);
403
+ const data = await this.client.get(tagKey);
404
+ if (data) {
405
+ return JSON.parse(data);
406
+ }
407
+ return [];
408
+ }
409
+ };
410
+ function createRedisCacheAdapter(config) {
411
+ return new RedisCacheAdapter(config);
412
+ }
413
+
414
+ // src/adapters/upstash.ts
415
+ var UpstashCacheAdapter = class {
416
+ type = "upstash";
417
+ url;
418
+ token;
419
+ keyPrefix;
420
+ constructor(config) {
421
+ this.url = config.url.replace(/\/$/, "");
422
+ this.token = config.token;
423
+ this.keyPrefix = config.keyPrefix ?? "";
424
+ }
425
+ prefixKey(key) {
426
+ return this.keyPrefix ? `${this.keyPrefix}:${key}` : key;
427
+ }
428
+ async command(...args) {
429
+ try {
430
+ const response = await fetch(this.url, {
431
+ method: "POST",
432
+ headers: {
433
+ Authorization: `Bearer ${this.token}`,
434
+ "Content-Type": "application/json"
435
+ },
436
+ body: JSON.stringify(args)
437
+ });
438
+ if (!response.ok) {
439
+ const error = await response.text();
440
+ throw new Error(`Upstash API error: ${error}`);
441
+ }
442
+ const data = await response.json();
443
+ if (data.error) {
444
+ throw new Error(data.error);
445
+ }
446
+ return data.result;
447
+ } catch (err) {
448
+ throw new CacheError(
449
+ `Upstash command failed: ${err instanceof Error ? err.message : "Unknown error"}`,
450
+ CacheErrorCodes.OPERATION_FAILED,
451
+ err
452
+ );
453
+ }
454
+ }
455
+ async pipeline(commands) {
456
+ try {
457
+ const response = await fetch(`${this.url}/pipeline`, {
458
+ method: "POST",
459
+ headers: {
460
+ Authorization: `Bearer ${this.token}`,
461
+ "Content-Type": "application/json"
462
+ },
463
+ body: JSON.stringify(commands)
464
+ });
465
+ if (!response.ok) {
466
+ const error = await response.text();
467
+ throw new Error(`Upstash API error: ${error}`);
468
+ }
469
+ const data = await response.json();
470
+ return data.map((item) => {
471
+ if (item.error) {
472
+ throw new Error(item.error);
473
+ }
474
+ return item.result;
475
+ });
476
+ } catch (err) {
477
+ throw new CacheError(
478
+ `Upstash pipeline failed: ${err instanceof Error ? err.message : "Unknown error"}`,
479
+ CacheErrorCodes.OPERATION_FAILED,
480
+ err
481
+ );
482
+ }
483
+ }
484
+ async get(key, _options) {
485
+ const data = await this.command("GET", this.prefixKey(key));
486
+ if (!data) {
487
+ return null;
488
+ }
489
+ try {
490
+ const parsed = JSON.parse(data);
491
+ return parsed.value;
492
+ } catch {
493
+ return data;
494
+ }
495
+ }
496
+ async set(key, value, options) {
497
+ const data = JSON.stringify({
498
+ value,
499
+ tags: options?.tags,
500
+ metadata: options?.metadata
501
+ });
502
+ const prefixedKey = this.prefixKey(key);
503
+ if (options?.ttl) {
504
+ await this.command("SET", prefixedKey, data, "EX", options.ttl);
505
+ } else {
506
+ await this.command("SET", prefixedKey, data);
507
+ }
508
+ if (options?.tags && options.tags.length > 0) {
509
+ const commands = [];
510
+ for (const tag of options.tags) {
511
+ commands.push(["SADD", this.prefixKey(`__tag:${tag}`), key]);
512
+ }
513
+ await this.pipeline(commands);
514
+ }
515
+ }
516
+ async delete(key) {
517
+ await this.command("DEL", this.prefixKey(key));
518
+ }
519
+ async has(key) {
520
+ const exists = await this.command("EXISTS", this.prefixKey(key));
521
+ return exists > 0;
522
+ }
523
+ async clear() {
524
+ if (this.keyPrefix) {
525
+ let cursor = "0";
526
+ do {
527
+ const result = await this.command(
528
+ "SCAN",
529
+ cursor,
530
+ "MATCH",
531
+ `${this.keyPrefix}:*`,
532
+ "COUNT",
533
+ 100
534
+ );
535
+ cursor = result[0];
536
+ const keys = result[1];
537
+ if (keys.length > 0) {
538
+ await this.command("DEL", ...keys);
539
+ }
540
+ } while (cursor !== "0");
541
+ } else {
542
+ await this.command("FLUSHDB");
543
+ }
544
+ }
545
+ async getMany(keys) {
546
+ const prefixedKeys = keys.map((k) => this.prefixKey(k));
547
+ const results = await this.command("MGET", ...prefixedKeys);
548
+ const map = /* @__PURE__ */ new Map();
549
+ for (let i = 0; i < keys.length; i++) {
550
+ const data = results[i];
551
+ const key = keys[i];
552
+ if (key !== void 0) {
553
+ if (data) {
554
+ try {
555
+ const parsed = JSON.parse(data);
556
+ map.set(key, parsed.value);
557
+ } catch {
558
+ map.set(key, data);
559
+ }
560
+ } else {
561
+ map.set(key, null);
562
+ }
563
+ }
564
+ }
565
+ return map;
566
+ }
567
+ async setMany(entries, options) {
568
+ const commands = [];
569
+ for (const [key, value] of entries) {
570
+ const data = JSON.stringify({
571
+ value,
572
+ tags: options?.tags,
573
+ metadata: options?.metadata
574
+ });
575
+ const prefixedKey = this.prefixKey(key);
576
+ if (options?.ttl) {
577
+ commands.push(["SET", prefixedKey, data, "EX", options.ttl]);
578
+ } else {
579
+ commands.push(["SET", prefixedKey, data]);
580
+ }
581
+ }
582
+ await this.pipeline(commands);
583
+ }
584
+ async deleteMany(keys) {
585
+ const prefixedKeys = keys.map((k) => this.prefixKey(k));
586
+ await this.command("DEL", ...prefixedKeys);
587
+ }
588
+ async invalidateByTags(tags) {
589
+ const keysToDelete = [];
590
+ for (const tag of tags) {
591
+ const keys = await this.command("SMEMBERS", this.prefixKey(`__tag:${tag}`));
592
+ keysToDelete.push(...keys);
593
+ }
594
+ if (keysToDelete.length > 0) {
595
+ await this.deleteMany(keysToDelete);
596
+ }
597
+ const tagKeys = tags.map((tag) => this.prefixKey(`__tag:${tag}`));
598
+ await this.command("DEL", ...tagKeys);
599
+ }
600
+ async ttl(key) {
601
+ return await this.command("TTL", this.prefixKey(key));
602
+ }
603
+ async close() {
604
+ }
605
+ };
606
+ function createUpstashCacheAdapter(config) {
607
+ return new UpstashCacheAdapter(config);
608
+ }
609
+
610
+ // src/adapters/cloudflare-kv.ts
611
+ var CloudflareKVCacheAdapter = class {
612
+ type = "cloudflare-kv";
613
+ kv;
614
+ keyPrefix;
615
+ constructor(config) {
616
+ this.kv = config.namespace;
617
+ this.keyPrefix = config.keyPrefix ?? "";
618
+ }
619
+ prefixKey(key) {
620
+ return this.keyPrefix ? `${this.keyPrefix}:${key}` : key;
621
+ }
622
+ async get(key, _options) {
623
+ try {
624
+ const data = await this.kv.get(this.prefixKey(key), { type: "json" });
625
+ if (!data) {
626
+ return null;
627
+ }
628
+ return data.value;
629
+ } catch (err) {
630
+ throw new CacheError(
631
+ `Cloudflare KV get failed: ${err instanceof Error ? err.message : "Unknown error"}`,
632
+ CacheErrorCodes.OPERATION_FAILED,
633
+ err
634
+ );
635
+ }
636
+ }
637
+ async set(key, value, options) {
638
+ try {
639
+ const data = {
640
+ value,
641
+ tags: options?.tags,
642
+ metadata: options?.metadata
643
+ };
644
+ const putOptions = {};
645
+ if (options?.ttl) {
646
+ putOptions.expirationTtl = options.ttl;
647
+ }
648
+ if (options?.tags || options?.metadata) {
649
+ putOptions.metadata = {
650
+ tags: options.tags,
651
+ ...options.metadata
652
+ };
653
+ }
654
+ await this.kv.put(this.prefixKey(key), JSON.stringify(data), putOptions);
655
+ if (options?.tags && options.tags.length > 0) {
656
+ for (const tag of options.tags) {
657
+ const tagKey = this.prefixKey(`__tag:${tag}`);
658
+ const existing = await this.kv.get(tagKey, { type: "json" });
659
+ const keys = existing ? [.../* @__PURE__ */ new Set([...existing, key])] : [key];
660
+ await this.kv.put(tagKey, JSON.stringify(keys));
661
+ }
662
+ }
663
+ } catch (err) {
664
+ throw new CacheError(
665
+ `Cloudflare KV set failed: ${err instanceof Error ? err.message : "Unknown error"}`,
666
+ CacheErrorCodes.OPERATION_FAILED,
667
+ err
668
+ );
669
+ }
670
+ }
671
+ async delete(key) {
672
+ try {
673
+ await this.kv.delete(this.prefixKey(key));
674
+ } catch (err) {
675
+ throw new CacheError(
676
+ `Cloudflare KV delete failed: ${err instanceof Error ? err.message : "Unknown error"}`,
677
+ CacheErrorCodes.OPERATION_FAILED,
678
+ err
679
+ );
680
+ }
681
+ }
682
+ async has(key) {
683
+ try {
684
+ const value = await this.kv.get(this.prefixKey(key));
685
+ return value !== null;
686
+ } catch (err) {
687
+ throw new CacheError(
688
+ `Cloudflare KV has failed: ${err instanceof Error ? err.message : "Unknown error"}`,
689
+ CacheErrorCodes.OPERATION_FAILED,
690
+ err
691
+ );
692
+ }
693
+ }
694
+ async clear() {
695
+ try {
696
+ const prefix = this.keyPrefix ? `${this.keyPrefix}:` : "";
697
+ let cursor;
698
+ do {
699
+ const result = await this.kv.list({
700
+ prefix,
701
+ limit: 1e3,
702
+ cursor
703
+ });
704
+ for (const key of result.keys) {
705
+ await this.kv.delete(key.name);
706
+ }
707
+ cursor = result.list_complete ? void 0 : result.cursor;
708
+ } while (cursor);
709
+ } catch (err) {
710
+ throw new CacheError(
711
+ `Cloudflare KV clear failed: ${err instanceof Error ? err.message : "Unknown error"}`,
712
+ CacheErrorCodes.OPERATION_FAILED,
713
+ err
714
+ );
715
+ }
716
+ }
717
+ async getMany(keys) {
718
+ const map = /* @__PURE__ */ new Map();
719
+ const promises = keys.map(async (key) => {
720
+ const value = await this.get(key);
721
+ return { key, value };
722
+ });
723
+ const results = await Promise.all(promises);
724
+ for (const { key, value } of results) {
725
+ map.set(key, value);
726
+ }
727
+ return map;
728
+ }
729
+ async setMany(entries, options) {
730
+ const promises = [];
731
+ for (const [key, value] of entries) {
732
+ promises.push(this.set(key, value, options));
733
+ }
734
+ await Promise.all(promises);
735
+ }
736
+ async deleteMany(keys) {
737
+ const promises = keys.map((key) => this.delete(key));
738
+ await Promise.all(promises);
739
+ }
740
+ async invalidateByTags(tags) {
741
+ try {
742
+ const keysToDelete = /* @__PURE__ */ new Set();
743
+ for (const tag of tags) {
744
+ const tagKey = this.prefixKey(`__tag:${tag}`);
745
+ const keys = await this.kv.get(tagKey, { type: "json" });
746
+ if (keys) {
747
+ for (const key of keys) {
748
+ keysToDelete.add(key);
749
+ }
750
+ await this.kv.delete(tagKey);
751
+ }
752
+ }
753
+ if (keysToDelete.size > 0) {
754
+ await this.deleteMany([...keysToDelete]);
755
+ }
756
+ } catch (err) {
757
+ throw new CacheError(
758
+ `Cloudflare KV invalidate by tags failed: ${err instanceof Error ? err.message : "Unknown error"}`,
759
+ CacheErrorCodes.OPERATION_FAILED,
760
+ err
761
+ );
762
+ }
763
+ }
764
+ async ttl(_key) {
765
+ return -1;
766
+ }
767
+ async close() {
768
+ }
769
+ };
770
+ function createCloudflareKVCacheAdapter(config) {
771
+ return new CloudflareKVCacheAdapter(config);
772
+ }
773
+ export {
774
+ CloudflareKVCacheAdapter,
775
+ MemoryCacheAdapter,
776
+ RedisCacheAdapter,
777
+ UpstashCacheAdapter,
778
+ createCloudflareKVCacheAdapter,
779
+ createMemoryCacheAdapter,
780
+ createRedisCacheAdapter,
781
+ createUpstashCacheAdapter
782
+ };
783
+ //# sourceMappingURL=index.js.map