@mrjasonroy/cache-components-cache-handler 16.0.0-alpha.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.
Files changed (50) hide show
  1. package/README.md +437 -0
  2. package/dist/data-cache/memory.d.ts +47 -0
  3. package/dist/data-cache/memory.d.ts.map +1 -0
  4. package/dist/data-cache/memory.js +310 -0
  5. package/dist/data-cache/memory.js.map +1 -0
  6. package/dist/data-cache/redis.d.ts +83 -0
  7. package/dist/data-cache/redis.d.ts.map +1 -0
  8. package/dist/data-cache/redis.js +240 -0
  9. package/dist/data-cache/redis.js.map +1 -0
  10. package/dist/data-cache/types.d.ts +85 -0
  11. package/dist/data-cache/types.d.ts.map +1 -0
  12. package/dist/data-cache/types.js +7 -0
  13. package/dist/data-cache/types.js.map +1 -0
  14. package/dist/handlers/composite.d.ts +70 -0
  15. package/dist/handlers/composite.d.ts.map +1 -0
  16. package/dist/handlers/composite.js +123 -0
  17. package/dist/handlers/composite.js.map +1 -0
  18. package/dist/handlers/memory.d.ts +77 -0
  19. package/dist/handlers/memory.d.ts.map +1 -0
  20. package/dist/handlers/memory.js +145 -0
  21. package/dist/handlers/memory.js.map +1 -0
  22. package/dist/handlers/redis.d.ts +80 -0
  23. package/dist/handlers/redis.d.ts.map +1 -0
  24. package/dist/handlers/redis.js +210 -0
  25. package/dist/handlers/redis.js.map +1 -0
  26. package/dist/helpers/buffer.d.ts +25 -0
  27. package/dist/helpers/buffer.d.ts.map +1 -0
  28. package/dist/helpers/buffer.js +45 -0
  29. package/dist/helpers/buffer.js.map +1 -0
  30. package/dist/helpers/is-implicit-tag.d.ts +9 -0
  31. package/dist/helpers/is-implicit-tag.d.ts.map +1 -0
  32. package/dist/helpers/is-implicit-tag.js +16 -0
  33. package/dist/helpers/is-implicit-tag.js.map +1 -0
  34. package/dist/helpers/lifespan.d.ts +18 -0
  35. package/dist/helpers/lifespan.d.ts.map +1 -0
  36. package/dist/helpers/lifespan.js +43 -0
  37. package/dist/helpers/lifespan.js.map +1 -0
  38. package/dist/helpers/next-config.d.ts +97 -0
  39. package/dist/helpers/next-config.d.ts.map +1 -0
  40. package/dist/helpers/next-config.js +96 -0
  41. package/dist/helpers/next-config.js.map +1 -0
  42. package/dist/index.d.ts +17 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +23 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/types.d.ts +163 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +9 -0
  49. package/dist/types.js.map +1 -0
  50. package/package.json +67 -0
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Next.js Data Cache Handler Types
3
+ * For "use cache" directive support
4
+ * Source: next.js/packages/next/src/server/lib/cache-handlers/types.ts
5
+ */
6
+ /**
7
+ * A timestamp in milliseconds elapsed since the epoch
8
+ */
9
+ export type Timestamp = number;
10
+ /**
11
+ * Cache entry for data cache (used by "use cache" directive)
12
+ * Uses ReadableStream for streaming responses
13
+ */
14
+ export interface DataCacheEntry {
15
+ /**
16
+ * The ReadableStream can error and only have partial data so any cache
17
+ * handlers need to handle this case and decide to keep the partial cache
18
+ * around or not.
19
+ */
20
+ value: ReadableStream<Uint8Array>;
21
+ /**
22
+ * The tags configured for the entry excluding soft tags
23
+ */
24
+ tags: string[];
25
+ /**
26
+ * This is for the client, not used to calculate cache entry expiration
27
+ * [duration in seconds]
28
+ */
29
+ stale: number;
30
+ /**
31
+ * When the cache entry was created [timestamp in milliseconds]
32
+ */
33
+ timestamp: Timestamp;
34
+ /**
35
+ * How long the entry is allowed to be used (should be longer than revalidate)
36
+ * [duration in seconds]
37
+ */
38
+ expire: number;
39
+ /**
40
+ * How long until the entry should be revalidated [duration in seconds]
41
+ */
42
+ revalidate: number;
43
+ }
44
+ /**
45
+ * Data cache handler interface that must be implemented
46
+ * This is for "use cache" directive support
47
+ */
48
+ export interface DataCacheHandler {
49
+ /**
50
+ * Retrieve a cache entry for the given cache key, if available. Will return
51
+ * undefined if there's no valid entry, or if the given soft tags are stale.
52
+ */
53
+ get(cacheKey: string, softTags: string[]): Promise<undefined | DataCacheEntry>;
54
+ /**
55
+ * Store a cache entry for the given cache key. When this is called, the entry
56
+ * may still be pending, i.e. its value stream may still be written to. So it
57
+ * needs to be awaited first. If a `get` for the same cache key is called,
58
+ * before the pending entry is complete, the cache handler must wait for the
59
+ * `set` operation to finish, before returning the entry, instead of returning
60
+ * undefined.
61
+ */
62
+ set(cacheKey: string, pendingEntry: Promise<DataCacheEntry>): Promise<void>;
63
+ /**
64
+ * This function may be called periodically, but always before starting a new
65
+ * request. If applicable, it should communicate with the tags service to
66
+ * refresh the local tags manifest accordingly.
67
+ */
68
+ refreshTags(): Promise<void>;
69
+ /**
70
+ * This function is called for each set of soft tags that are relevant at the
71
+ * start of a request. The result is the maximum timestamp of a revalidate
72
+ * event for the tags. Returns `0` if none of the tags were ever revalidated.
73
+ * Returns `Infinity` if the soft tags are supposed to be passed into the
74
+ * `get` method instead to be checked for expiration.
75
+ */
76
+ getExpiration(tags: string[]): Promise<Timestamp>;
77
+ /**
78
+ * This function is called when tags are revalidated/expired. If applicable,
79
+ * it should update the tags manifest accordingly.
80
+ */
81
+ updateTags(tags: string[], durations?: {
82
+ expire?: number;
83
+ }): Promise<void>;
84
+ }
85
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/data-cache/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IAElC;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,SAAS,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,GAAG,cAAc,CAAC,CAAC;IAE/E;;;;;;;OAOG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5E;;;;OAIG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7B;;;;;;OAMG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAElD;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5E"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Next.js Data Cache Handler Types
3
+ * For "use cache" directive support
4
+ * Source: next.js/packages/next/src/server/lib/cache-handlers/types.ts
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/data-cache/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,70 @@
1
+ import type { CacheHandler, CacheHandlerContext, CacheHandlerGetMeta, CacheHandlerOptions, CacheHandlerValue, CacheValue } from "../types.js";
2
+ export interface CompositeHandlerOptions extends CacheHandlerOptions {
3
+ /**
4
+ * Array of cache handlers to use (ordered by priority)
5
+ * First handler is checked first for reads
6
+ */
7
+ handlers: CacheHandler[];
8
+ /**
9
+ * Strategy function to determine which handler to use for set operations
10
+ * Returns the index of the handler to use
11
+ *
12
+ * @default - Write to all handlers
13
+ */
14
+ setStrategy?: (data: CacheHandlerValue) => number;
15
+ }
16
+ /**
17
+ * Composite cache handler that orchestrates multiple cache handlers
18
+ * Enables multi-tier caching strategies (e.g., memory -> Redis)
19
+ *
20
+ * Features:
21
+ * - First-match read strategy (fast fallback)
22
+ * - Configurable write strategy
23
+ * - Fault tolerance with Promise.allSettled()
24
+ * - Parallel revalidation across all handlers
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * // Memory + Redis two-tier cache
29
+ * const handler = createCompositeHandler({
30
+ * handlers: [memoryHandler, redisHandler],
31
+ * // Only cache small items in memory, everything in Redis
32
+ * setStrategy: (data) => {
33
+ * const size = JSON.stringify(data).length;
34
+ * return size < 10000 ? 0 : 1; // 0 = memory, 1 = redis
35
+ * }
36
+ * });
37
+ * ```
38
+ */
39
+ export declare class CompositeHandler implements CacheHandler {
40
+ readonly name = "composite";
41
+ private readonly handlers;
42
+ private readonly setStrategy?;
43
+ constructor(options: CompositeHandlerOptions);
44
+ get(key: string, meta?: CacheHandlerGetMeta): Promise<CacheValue | null>;
45
+ set(key: string, value: CacheValue, context?: CacheHandlerContext): Promise<void>;
46
+ revalidateTag(tag: string, profile?: string | {
47
+ expire?: number;
48
+ }): Promise<void>;
49
+ delete(key: string): Promise<void>;
50
+ }
51
+ /**
52
+ * Create a composite cache handler instance
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * // Route based on tags
57
+ * const handler = createCompositeHandler({
58
+ * handlers: [memoryHandler, redisHandler],
59
+ * setStrategy: (data) => {
60
+ * // Use memory for items tagged with "memory-cache"
61
+ * if (data.tags.includes("memory-cache")) {
62
+ * return 0; // memory handler
63
+ * }
64
+ * return 1; // redis handler
65
+ * }
66
+ * });
67
+ * ```
68
+ */
69
+ export declare function createCompositeHandler(options: CompositeHandlerOptions): CompositeHandler;
70
+ //# sourceMappingURL=composite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composite.d.ts","sourceRoot":"","sources":["../../src/handlers/composite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACX,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IAClE;;;OAGG;IACH,QAAQ,EAAE,YAAY,EAAE,CAAC;IAEzB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,MAAM,CAAC;CACnD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,gBAAiB,YAAW,YAAY;IACnD,SAAgB,IAAI,eAAe;IAEnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAsC;gBAEvD,OAAO,EAAE,uBAAuB;IAStC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAiBxE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BjF,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAcjF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAezC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB,CAEzF"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Composite cache handler that orchestrates multiple cache handlers
3
+ * Enables multi-tier caching strategies (e.g., memory -> Redis)
4
+ *
5
+ * Features:
6
+ * - First-match read strategy (fast fallback)
7
+ * - Configurable write strategy
8
+ * - Fault tolerance with Promise.allSettled()
9
+ * - Parallel revalidation across all handlers
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // Memory + Redis two-tier cache
14
+ * const handler = createCompositeHandler({
15
+ * handlers: [memoryHandler, redisHandler],
16
+ * // Only cache small items in memory, everything in Redis
17
+ * setStrategy: (data) => {
18
+ * const size = JSON.stringify(data).length;
19
+ * return size < 10000 ? 0 : 1; // 0 = memory, 1 = redis
20
+ * }
21
+ * });
22
+ * ```
23
+ */
24
+ export class CompositeHandler {
25
+ name = "composite";
26
+ handlers;
27
+ setStrategy;
28
+ constructor(options) {
29
+ if (!options.handlers || options.handlers.length === 0) {
30
+ throw new Error("CompositeHandler requires at least one handler");
31
+ }
32
+ this.handlers = options.handlers;
33
+ this.setStrategy = options.setStrategy;
34
+ }
35
+ async get(key, meta) {
36
+ // Try handlers in order, return first hit
37
+ for (const handler of this.handlers) {
38
+ try {
39
+ const value = await handler.get(key, meta);
40
+ if (value !== null) {
41
+ return value;
42
+ }
43
+ }
44
+ catch (error) {
45
+ // Log error but continue to next handler
46
+ console.error(`Handler ${handler.name} failed:`, error);
47
+ }
48
+ }
49
+ return null;
50
+ }
51
+ async set(key, value, context) {
52
+ // Build the full cache handler value for strategy function
53
+ const now = Date.now();
54
+ const cacheHandlerValue = {
55
+ lastModified: now,
56
+ lifespan: null, // Simplified - handlers will calculate their own
57
+ tags: context?.tags ?? [],
58
+ value,
59
+ };
60
+ // Determine which handler(s) to write to
61
+ if (this.setStrategy) {
62
+ const handlerIndex = this.setStrategy(cacheHandlerValue);
63
+ if (handlerIndex >= 0 && handlerIndex < this.handlers.length) {
64
+ await this.handlers[handlerIndex].set(key, value, context);
65
+ }
66
+ }
67
+ else {
68
+ // Default: write to all handlers with fault tolerance
69
+ const results = await Promise.allSettled(this.handlers.map((handler) => handler.set(key, value, context)));
70
+ // Log failures but don't throw (fault tolerance)
71
+ results.forEach((result, index) => {
72
+ if (result.status === "rejected") {
73
+ console.error(`Handler ${this.handlers[index].name} set failed:`, result.reason);
74
+ }
75
+ });
76
+ }
77
+ }
78
+ async revalidateTag(tag, profile) {
79
+ // Revalidate on all handlers in parallel with fault tolerance
80
+ const results = await Promise.allSettled(this.handlers.map((handler) => handler.revalidateTag(tag, profile)));
81
+ // Log failures but don't throw
82
+ results.forEach((result, index) => {
83
+ if (result.status === "rejected") {
84
+ console.error(`Handler ${this.handlers[index].name} revalidateTag failed:`, result.reason);
85
+ }
86
+ });
87
+ }
88
+ async delete(key) {
89
+ // Delete from all handlers that support it
90
+ const deletePromises = this.handlers
91
+ .filter((handler) => typeof handler.delete === "function")
92
+ .map((handler) => handler.delete?.(key));
93
+ const results = await Promise.allSettled(deletePromises);
94
+ // Log failures but don't throw
95
+ results.forEach((result, index) => {
96
+ if (result.status === "rejected") {
97
+ console.error(`Handler ${this.handlers[index].name} delete failed:`, result.reason);
98
+ }
99
+ });
100
+ }
101
+ }
102
+ /**
103
+ * Create a composite cache handler instance
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * // Route based on tags
108
+ * const handler = createCompositeHandler({
109
+ * handlers: [memoryHandler, redisHandler],
110
+ * setStrategy: (data) => {
111
+ * // Use memory for items tagged with "memory-cache"
112
+ * if (data.tags.includes("memory-cache")) {
113
+ * return 0; // memory handler
114
+ * }
115
+ * return 1; // redis handler
116
+ * }
117
+ * });
118
+ * ```
119
+ */
120
+ export function createCompositeHandler(options) {
121
+ return new CompositeHandler(options);
122
+ }
123
+ //# sourceMappingURL=composite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composite.js","sourceRoot":"","sources":["../../src/handlers/composite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import type { CacheHandler, CacheHandlerContext, CacheHandlerGetMeta, CacheHandlerOptions, CacheValue } from "../types.js";
2
+ export interface MemoryCacheHandlerOptions extends CacheHandlerOptions {
3
+ /**
4
+ * Maximum number of items to store (LRU eviction when exceeded)
5
+ * @default 1000
6
+ */
7
+ maxItemsNumber?: number;
8
+ /**
9
+ * Maximum size in bytes for a single item
10
+ * @default 104857600 (100MB)
11
+ */
12
+ maxItemSizeBytes?: number;
13
+ /**
14
+ * Default TTL in seconds for entries without explicit revalidate
15
+ * @default undefined (no expiration)
16
+ */
17
+ defaultTTL?: number;
18
+ }
19
+ /**
20
+ * In-memory LRU cache handler for Next.js 16+
21
+ * Suitable for development and single-instance deployments
22
+ *
23
+ * Features:
24
+ * - LRU eviction based on item count and size
25
+ * - Implicit tag tracking for ISR
26
+ * - Proper expiration handling
27
+ * - Tag-based revalidation
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const handler = createMemoryCacheHandler({
32
+ * maxItemsNumber: 1000,
33
+ * maxItemSizeBytes: 100 * 1024 * 1024, // 100MB
34
+ * defaultTTL: 3600 // 1 hour
35
+ * });
36
+ * ```
37
+ */
38
+ export declare class MemoryCacheHandler implements CacheHandler {
39
+ readonly name = "local-lru";
40
+ private cache;
41
+ private revalidatedTags;
42
+ private readonly maxItemsNumber;
43
+ private readonly maxItemSizeBytes;
44
+ private readonly defaultTTL?;
45
+ constructor(options?: MemoryCacheHandlerOptions);
46
+ get(key: string, meta?: CacheHandlerGetMeta): Promise<CacheValue | null>;
47
+ set(key: string, value: CacheValue, context?: CacheHandlerContext): Promise<void>;
48
+ revalidateTag(tag: string, _profile?: string | {
49
+ expire?: number;
50
+ }): Promise<void>;
51
+ delete(key: string): Promise<void>;
52
+ /**
53
+ * Clear all cache entries (useful for testing)
54
+ */
55
+ clear(): Promise<void>;
56
+ /**
57
+ * Get cache statistics
58
+ */
59
+ getStats(): {
60
+ size: number;
61
+ maxSize: number;
62
+ revalidatedTags: number;
63
+ };
64
+ }
65
+ /**
66
+ * Create a memory cache handler instance
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const handler = createMemoryCacheHandler({
71
+ * maxItemsNumber: 500,
72
+ * defaultTTL: 3600
73
+ * });
74
+ * ```
75
+ */
76
+ export declare function createMemoryCacheHandler(options?: MemoryCacheHandlerOptions): MemoryCacheHandler;
77
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/handlers/memory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EAEnB,UAAU,EACX,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,yBAA0B,SAAQ,mBAAmB;IACpE;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,kBAAmB,YAAW,YAAY;IACrD,SAAgB,IAAI,eAAe;IAEnC,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAS;gBAEzB,OAAO,GAAE,yBAA8B;IAQ7C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAiCxE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCjF,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BlF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;OAEG;IACH,QAAQ;;;;;CAOT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE,yBAAyB,GAAG,kBAAkB,CAEhG"}
@@ -0,0 +1,145 @@
1
+ import { isImplicitTag } from "../helpers/is-implicit-tag.js";
2
+ import { calculateLifespan, isExpired } from "../helpers/lifespan.js";
3
+ /**
4
+ * In-memory LRU cache handler for Next.js 16+
5
+ * Suitable for development and single-instance deployments
6
+ *
7
+ * Features:
8
+ * - LRU eviction based on item count and size
9
+ * - Implicit tag tracking for ISR
10
+ * - Proper expiration handling
11
+ * - Tag-based revalidation
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const handler = createMemoryCacheHandler({
16
+ * maxItemsNumber: 1000,
17
+ * maxItemSizeBytes: 100 * 1024 * 1024, // 100MB
18
+ * defaultTTL: 3600 // 1 hour
19
+ * });
20
+ * ```
21
+ */
22
+ export class MemoryCacheHandler {
23
+ name = "local-lru";
24
+ cache;
25
+ revalidatedTags; // tag -> timestamp (milliseconds)
26
+ maxItemsNumber;
27
+ maxItemSizeBytes;
28
+ defaultTTL;
29
+ constructor(options = {}) {
30
+ this.cache = new Map();
31
+ this.revalidatedTags = new Map();
32
+ this.maxItemsNumber = options.maxItemsNumber ?? 1000;
33
+ this.maxItemSizeBytes = options.maxItemSizeBytes ?? 104857600; // 100MB
34
+ this.defaultTTL = options.defaultTTL;
35
+ }
36
+ async get(key, meta) {
37
+ const entry = this.cache.get(key);
38
+ if (!entry) {
39
+ return null;
40
+ }
41
+ // Check if expired based on lifespan
42
+ if (entry.lifespan && isExpired(entry.lifespan)) {
43
+ await this.delete(key);
44
+ return null;
45
+ }
46
+ // Check if any tag (explicit or implicit) has been revalidated
47
+ const allTags = [...entry.tags, ...(meta?.implicitTags ?? [])];
48
+ for (const tag of allTags) {
49
+ const revalidatedAt = this.revalidatedTags.get(tag);
50
+ // If tag was revalidated after entry was last modified, entry is stale
51
+ if (revalidatedAt && revalidatedAt > entry.lastModified) {
52
+ await this.delete(key);
53
+ return null;
54
+ }
55
+ }
56
+ // Move to end for LRU (delete and re-add)
57
+ this.cache.delete(key);
58
+ this.cache.set(key, entry);
59
+ return entry.value;
60
+ }
61
+ async set(key, value, context) {
62
+ // Calculate size of the entry
63
+ const size = JSON.stringify(value).length;
64
+ // Check if entry exceeds max size
65
+ if (size > this.maxItemSizeBytes) {
66
+ // Skip storing oversized entries
67
+ return;
68
+ }
69
+ // Enforce max items (LRU eviction)
70
+ if (this.cache.size >= this.maxItemsNumber) {
71
+ // Delete the oldest entry (first in Map)
72
+ const firstKey = this.cache.keys().next().value;
73
+ if (firstKey) {
74
+ await this.delete(firstKey);
75
+ }
76
+ }
77
+ // Calculate lifespan
78
+ const lifespan = calculateLifespan(context?.revalidate, this.defaultTTL);
79
+ // Combine tags (explicit user tags only - implicit tags are passed in get())
80
+ const tags = context?.tags ?? [];
81
+ const entry = {
82
+ lastModified: Date.now(),
83
+ lifespan,
84
+ tags,
85
+ value,
86
+ };
87
+ this.cache.set(key, entry);
88
+ }
89
+ async revalidateTag(tag, _profile) {
90
+ // Store revalidation timestamp
91
+ // Note: profile parameter is used by Next.js for cache-life configuration
92
+ // but for memory handler we just invalidate immediately
93
+ this.revalidatedTags.set(tag, Date.now());
94
+ // For explicit tags (non-implicit), we can directly delete entries
95
+ if (!isImplicitTag(tag)) {
96
+ const keysToDelete = [];
97
+ for (const [key, entry] of this.cache.entries()) {
98
+ if (entry.tags.includes(tag)) {
99
+ keysToDelete.push(key);
100
+ }
101
+ }
102
+ // Delete all entries with this tag
103
+ for (const key of keysToDelete) {
104
+ await this.delete(key);
105
+ }
106
+ }
107
+ // For implicit tags, we rely on the get() method to check revalidation
108
+ // This is because implicit tags are passed dynamically in meta.implicitTags
109
+ }
110
+ async delete(key) {
111
+ this.cache.delete(key);
112
+ }
113
+ /**
114
+ * Clear all cache entries (useful for testing)
115
+ */
116
+ async clear() {
117
+ this.cache.clear();
118
+ this.revalidatedTags.clear();
119
+ }
120
+ /**
121
+ * Get cache statistics
122
+ */
123
+ getStats() {
124
+ return {
125
+ size: this.cache.size,
126
+ maxSize: this.maxItemsNumber,
127
+ revalidatedTags: this.revalidatedTags.size,
128
+ };
129
+ }
130
+ }
131
+ /**
132
+ * Create a memory cache handler instance
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * const handler = createMemoryCacheHandler({
137
+ * maxItemsNumber: 500,
138
+ * defaultTTL: 3600
139
+ * });
140
+ * ```
141
+ */
142
+ export function createMemoryCacheHandler(options) {
143
+ return new MemoryCacheHandler(options);
144
+ }
145
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/handlers/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { type RedisOptions } from "ioredis";
2
+ import type { CacheHandler, CacheHandlerContext, CacheHandlerGetMeta, CacheHandlerOptions, CacheValue } from "../types.js";
3
+ export interface RedisCacheHandlerOptions extends CacheHandlerOptions {
4
+ /**
5
+ * Redis connection options (ioredis)
6
+ * Can be a URL string or RedisOptions object
7
+ */
8
+ redis?: string | RedisOptions;
9
+ /**
10
+ * Key prefix for all cache entries
11
+ * @default "nextjs:cache:"
12
+ */
13
+ keyPrefix?: string;
14
+ /**
15
+ * Key prefix for tag tracking
16
+ * @default "nextjs:tags:"
17
+ */
18
+ tagPrefix?: string;
19
+ /**
20
+ * Default TTL in seconds for entries without explicit revalidate
21
+ * @default undefined (no expiration)
22
+ */
23
+ defaultTTL?: number;
24
+ /**
25
+ * Enable debug logging
26
+ * @default false
27
+ */
28
+ debug?: boolean;
29
+ }
30
+ /**
31
+ * Redis cache handler for Next.js 16+ with Cache Components support
32
+ *
33
+ * Features:
34
+ * - Persistent caching across server restarts
35
+ * - Tag-based revalidation with Redis Sets
36
+ * - TTL support with automatic expiration
37
+ * - Compatible with Redis, ElastiCache, and Valkey
38
+ * - Connection pooling via ioredis
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * // In cache-handler.mjs or data-cache-handler.mjs
43
+ * import { RedisCacheHandler } from "@mrjasonroy/cache-components-cache-handler/handlers/redis";
44
+ *
45
+ * export default class NextCacheHandler extends RedisCacheHandler {
46
+ * constructor(options) {
47
+ * super({
48
+ * ...options,
49
+ * redis: process.env.REDIS_URL || "redis://localhost:6379",
50
+ * keyPrefix: "nextjs:cache:",
51
+ * defaultTTL: 3600
52
+ * });
53
+ * }
54
+ * }
55
+ * ```
56
+ */
57
+ export declare class RedisCacheHandler implements CacheHandler {
58
+ readonly name = "redis";
59
+ private redis;
60
+ private readonly keyPrefix;
61
+ private readonly tagPrefix;
62
+ private readonly defaultTTL?;
63
+ private readonly debug;
64
+ constructor(options?: RedisCacheHandlerOptions);
65
+ private log;
66
+ private getCacheKey;
67
+ private getTagKey;
68
+ get(key: string, meta?: CacheHandlerGetMeta): Promise<CacheValue | null>;
69
+ set(key: string, value: CacheValue, context?: CacheHandlerContext): Promise<void>;
70
+ revalidateTag(tag: string, _profile?: string | {
71
+ expire?: number;
72
+ }): Promise<void>;
73
+ delete(key: string): Promise<void>;
74
+ /**
75
+ * Close the Redis connection
76
+ * Call this when shutting down your application
77
+ */
78
+ close(): Promise<void>;
79
+ }
80
+ //# sourceMappingURL=redis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/handlers/redis.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EAEnB,UAAU,EACX,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB;IACnE;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAE9B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,iBAAkB,YAAW,YAAY;IACpD,SAAgB,IAAI,WAAW;IAE/B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;gBAEpB,OAAO,GAAE,wBAA6B;IA2BlD,OAAO,CAAC,GAAG;IAMX,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,SAAS;IAIX,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA8CxE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2DjF,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BlF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxC;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}