@pantheon-systems/nextjs-cache-handler 0.1.0 → 0.2.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 (58) hide show
  1. package/README.md +110 -0
  2. package/dist/handlers/base.d.ts +9 -0
  3. package/dist/handlers/base.d.ts.map +1 -1
  4. package/dist/handlers/base.js +22 -0
  5. package/dist/handlers/base.js.map +1 -1
  6. package/dist/index.d.ts +5 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +15 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/middleware/index.d.ts +2 -0
  11. package/dist/middleware/index.d.ts.map +1 -0
  12. package/dist/middleware/index.js +2 -0
  13. package/dist/middleware/index.js.map +1 -0
  14. package/dist/middleware/surrogate-key.d.ts +29 -0
  15. package/dist/middleware/surrogate-key.d.ts.map +1 -0
  16. package/dist/middleware/surrogate-key.js +66 -0
  17. package/dist/middleware/surrogate-key.js.map +1 -0
  18. package/dist/use-cache/file-handler.d.ts +71 -0
  19. package/dist/use-cache/file-handler.d.ts.map +1 -0
  20. package/dist/use-cache/file-handler.js +366 -0
  21. package/dist/use-cache/file-handler.js.map +1 -0
  22. package/dist/use-cache/gcs-handler.d.ts +64 -0
  23. package/dist/use-cache/gcs-handler.d.ts.map +1 -0
  24. package/dist/use-cache/gcs-handler.js +406 -0
  25. package/dist/use-cache/gcs-handler.js.map +1 -0
  26. package/dist/use-cache/index.d.ts +58 -0
  27. package/dist/use-cache/index.d.ts.map +1 -0
  28. package/dist/use-cache/index.js +87 -0
  29. package/dist/use-cache/index.js.map +1 -0
  30. package/dist/use-cache/stream-serialization.d.ts +34 -0
  31. package/dist/use-cache/stream-serialization.d.ts.map +1 -0
  32. package/dist/use-cache/stream-serialization.js +96 -0
  33. package/dist/use-cache/stream-serialization.js.map +1 -0
  34. package/dist/use-cache/types.d.ts +202 -0
  35. package/dist/use-cache/types.d.ts.map +1 -0
  36. package/dist/use-cache/types.js +9 -0
  37. package/dist/use-cache/types.js.map +1 -0
  38. package/dist/utils/cache-tag-context.d.ts +66 -0
  39. package/dist/utils/cache-tag-context.d.ts.map +1 -0
  40. package/dist/utils/cache-tag-context.js +126 -0
  41. package/dist/utils/cache-tag-context.js.map +1 -0
  42. package/dist/utils/index.d.ts +3 -0
  43. package/dist/utils/index.d.ts.map +1 -1
  44. package/dist/utils/index.js +3 -0
  45. package/dist/utils/index.js.map +1 -1
  46. package/dist/utils/request-context.d.ts +28 -0
  47. package/dist/utils/request-context.d.ts.map +1 -0
  48. package/dist/utils/request-context.js +54 -0
  49. package/dist/utils/request-context.js.map +1 -0
  50. package/dist/utils/request-context.test.d.ts +2 -0
  51. package/dist/utils/request-context.test.d.ts.map +1 -0
  52. package/dist/utils/request-context.test.js +65 -0
  53. package/dist/utils/request-context.test.js.map +1 -0
  54. package/dist/utils/with-surrogate-key.d.ts +32 -0
  55. package/dist/utils/with-surrogate-key.d.ts.map +1 -0
  56. package/dist/utils/with-surrogate-key.js +113 -0
  57. package/dist/utils/with-surrogate-key.js.map +1 -0
  58. package/package.json +15 -1
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Convert a ReadableStream<Uint8Array> to a Uint8Array.
3
+ * Consumes the entire stream and concatenates all chunks.
4
+ *
5
+ * @param stream - The stream to consume
6
+ * @returns A single Uint8Array containing all the stream data
7
+ */
8
+ export async function streamToBytes(stream) {
9
+ const reader = stream.getReader();
10
+ const chunks = [];
11
+ while (true) {
12
+ const { done, value } = await reader.read();
13
+ if (done)
14
+ break;
15
+ if (value) {
16
+ chunks.push(value);
17
+ }
18
+ }
19
+ // Handle empty stream
20
+ if (chunks.length === 0) {
21
+ return new Uint8Array(0);
22
+ }
23
+ // Single chunk optimization
24
+ if (chunks.length === 1) {
25
+ return chunks[0];
26
+ }
27
+ // Concatenate all chunks
28
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
29
+ const result = new Uint8Array(totalLength);
30
+ let offset = 0;
31
+ for (const chunk of chunks) {
32
+ result.set(chunk, offset);
33
+ offset += chunk.length;
34
+ }
35
+ return result;
36
+ }
37
+ /**
38
+ * Convert a Uint8Array to a ReadableStream<Uint8Array>.
39
+ * Creates a stream that emits the entire array as a single chunk.
40
+ *
41
+ * @param bytes - The bytes to convert to a stream
42
+ * @returns A ReadableStream that emits the bytes
43
+ */
44
+ export function bytesToStream(bytes) {
45
+ return new ReadableStream({
46
+ start(controller) {
47
+ controller.enqueue(bytes);
48
+ controller.close();
49
+ },
50
+ });
51
+ }
52
+ /**
53
+ * Serialize a UseCacheEntry for persistent storage.
54
+ * Converts the ReadableStream value to a base64-encoded string.
55
+ *
56
+ * @param entry - The cache entry to serialize
57
+ * @returns A serialized entry suitable for JSON storage
58
+ */
59
+ export async function serializeUseCacheEntry(entry) {
60
+ // Convert stream to bytes
61
+ const bytes = await streamToBytes(entry.value);
62
+ // Convert bytes to base64 for JSON-safe storage
63
+ const base64Value = Buffer.from(bytes).toString('base64');
64
+ return {
65
+ value: base64Value,
66
+ tags: entry.tags,
67
+ stale: entry.stale,
68
+ timestamp: entry.timestamp,
69
+ expire: entry.expire,
70
+ revalidate: entry.revalidate,
71
+ };
72
+ }
73
+ /**
74
+ * Deserialize a stored cache entry back to UseCacheEntry.
75
+ * Converts the base64-encoded value back to a ReadableStream.
76
+ *
77
+ * @param stored - The serialized entry from storage
78
+ * @returns A UseCacheEntry with a ReadableStream value
79
+ */
80
+ export function deserializeUseCacheEntry(stored) {
81
+ // Convert base64 back to bytes
82
+ const bytes = stored.value ? Buffer.from(stored.value, 'base64') : new Uint8Array(0);
83
+ // Convert bytes to Uint8Array (Buffer is a subclass, but be explicit)
84
+ const uint8Array = new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
85
+ // Create stream from bytes
86
+ const stream = bytesToStream(uint8Array);
87
+ return {
88
+ value: stream,
89
+ tags: stored.tags,
90
+ stale: stored.stale,
91
+ timestamp: stored.timestamp,
92
+ expire: stored.expire,
93
+ revalidate: stored.revalidate,
94
+ };
95
+ }
96
+ //# sourceMappingURL=stream-serialization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-serialization.js","sourceRoot":"","sources":["../../src/use-cache/stream-serialization.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Cache entry structure for 'use cache' directive.
3
+ *
4
+ * Key differences from the legacy cacheHandler interface:
5
+ * - value is a ReadableStream<Uint8Array> instead of a serializable object
6
+ * - Includes timing metadata: stale, expire, revalidate
7
+ * - timestamp is in milliseconds (creation time)
8
+ */
9
+ export interface UseCacheEntry {
10
+ /**
11
+ * The cached value as a stream.
12
+ * Must be consumed or tee()'d if needed for multiple reads.
13
+ */
14
+ value: ReadableStream<Uint8Array>;
15
+ /**
16
+ * Cache tags for on-demand revalidation.
17
+ * Used with cacheTag() and revalidateTag().
18
+ */
19
+ tags: string[];
20
+ /**
21
+ * Duration in seconds for client-side staleness.
22
+ * Controls how long the entry can be served as stale while revalidating.
23
+ */
24
+ stale: number;
25
+ /**
26
+ * Creation timestamp in milliseconds.
27
+ * Used to determine cache age.
28
+ */
29
+ timestamp: number;
30
+ /**
31
+ * How long (in seconds) the entry is allowed to be used.
32
+ * After this time, the entry should not be served.
33
+ */
34
+ expire: number;
35
+ /**
36
+ * How long (in seconds) until the entry should be revalidated.
37
+ * After this time, the entry is considered stale but may still be served.
38
+ */
39
+ revalidate: number;
40
+ }
41
+ /**
42
+ * Serialized format for storing UseCacheEntry to persistent storage.
43
+ * The ReadableStream is converted to a base64 string.
44
+ */
45
+ export interface SerializedUseCacheEntry {
46
+ /**
47
+ * Base64-encoded bytes from the stream.
48
+ */
49
+ value: string;
50
+ /**
51
+ * Cache tags for on-demand revalidation.
52
+ */
53
+ tags: string[];
54
+ /**
55
+ * Duration in seconds for client-side staleness.
56
+ */
57
+ stale: number;
58
+ /**
59
+ * Creation timestamp in milliseconds.
60
+ */
61
+ timestamp: number;
62
+ /**
63
+ * How long (in seconds) the entry is allowed to be used.
64
+ */
65
+ expire: number;
66
+ /**
67
+ * How long (in seconds) until the entry should be revalidated.
68
+ */
69
+ revalidate: number;
70
+ }
71
+ /**
72
+ * Cache handler interface for 'use cache' directive (cacheHandlers plural).
73
+ *
74
+ * Key differences from the legacy CacheHandler interface:
75
+ * - get() receives softTags parameter
76
+ * - set() receives a Promise that must be awaited
77
+ * - Includes refreshTags(), getExpiration(), and updateTags() methods
78
+ */
79
+ export interface UseCacheHandler {
80
+ /**
81
+ * Retrieve a cache entry.
82
+ *
83
+ * @param cacheKey - The cache key to look up
84
+ * @param softTags - Framework-provided tags for additional filtering
85
+ * @returns The cache entry if found and valid, undefined otherwise
86
+ *
87
+ * Implementation notes:
88
+ * - Check expiration based on entry.revalidate and entry.timestamp
89
+ * - Return undefined if missing or expired
90
+ */
91
+ get(cacheKey: string, softTags: string[]): Promise<UseCacheEntry | undefined>;
92
+ /**
93
+ * Store a cache entry.
94
+ *
95
+ * @param cacheKey - The cache key to store under
96
+ * @param pendingEntry - A Promise that MUST be awaited before storage
97
+ *
98
+ * Implementation notes:
99
+ * - CRITICAL: Must await pendingEntry before storing
100
+ * - entry.value is a ReadableStream that may need .tee() if reading
101
+ * - For persistent storage, convert stream to bytes before storing
102
+ */
103
+ set(cacheKey: string, pendingEntry: Promise<UseCacheEntry>): Promise<void>;
104
+ /**
105
+ * Synchronize tag state from external source.
106
+ *
107
+ * Implementation notes:
108
+ * - Can be no-op for in-memory caches
109
+ * - For distributed caches, sync tag invalidation state from shared storage
110
+ */
111
+ refreshTags(): Promise<void>;
112
+ /**
113
+ * Return maximum revalidation timestamp for given tags.
114
+ *
115
+ * @param tags - Array of tag names to check
116
+ * @returns The most recent invalidation timestamp, or 0 if no cached info
117
+ *
118
+ * Implementation notes:
119
+ * - Used to determine if cached entries are still valid
120
+ * - Return 0 if no tags have been invalidated
121
+ */
122
+ getExpiration(tags: string[]): Promise<number>;
123
+ /**
124
+ * Invalidate cache entries with matching tags.
125
+ *
126
+ * @param tags - Array of tag names to invalidate
127
+ * @param durations - Corresponding invalidation durations (currently unused by Next.js)
128
+ *
129
+ * Implementation notes:
130
+ * - Store invalidation timestamps for each tag
131
+ * - Entries with matching tags should be considered invalid
132
+ */
133
+ updateTags(tags: string[], durations: number[]): Promise<void>;
134
+ }
135
+ /**
136
+ * Configuration options for creating a use cache handler instance.
137
+ */
138
+ export interface UseCacheHandlerConfig {
139
+ /**
140
+ * Handler type selection:
141
+ * - 'auto': Automatically detect based on environment (GCS if CACHE_BUCKET is set, otherwise file)
142
+ * - 'file': Use file-based caching (local development)
143
+ * - 'gcs': Use Google Cloud Storage (production/Pantheon)
144
+ */
145
+ type?: 'auto' | 'file' | 'gcs';
146
+ }
147
+ /**
148
+ * Information about a single use-cache entry for stats reporting.
149
+ */
150
+ export interface UseCacheEntryInfo {
151
+ /**
152
+ * The cache key.
153
+ */
154
+ key: string;
155
+ /**
156
+ * Cache tags associated with this entry.
157
+ */
158
+ tags: string[];
159
+ /**
160
+ * Type identifier for stats reporting.
161
+ * Always 'use-cache' for entries from cacheHandlers (plural).
162
+ */
163
+ type: 'use-cache';
164
+ /**
165
+ * When the entry was created (ISO timestamp).
166
+ */
167
+ lastModified?: string;
168
+ /**
169
+ * Approximate size in bytes (if available).
170
+ */
171
+ size?: number;
172
+ /**
173
+ * Revalidation time in seconds.
174
+ */
175
+ revalidate?: number;
176
+ /**
177
+ * Stale time in seconds.
178
+ */
179
+ stale?: number;
180
+ /**
181
+ * Expire time in seconds.
182
+ */
183
+ expire?: number;
184
+ }
185
+ /**
186
+ * Cache statistics for use-cache entries.
187
+ */
188
+ export interface UseCacheStats {
189
+ /**
190
+ * Number of cache entries.
191
+ */
192
+ size: number;
193
+ /**
194
+ * Detailed information about each entry.
195
+ */
196
+ entries: UseCacheEntryInfo[];
197
+ /**
198
+ * List of cache keys.
199
+ */
200
+ keys: string[];
201
+ }
202
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/use-cache/types.ts"],"names":[],"mappings":"AAQA;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IAElC;;;OAGG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;;OAUG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;IAE9E;;;;;;;;;;OAUG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3E;;;;;;OAMG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7B;;;;;;;;;OASG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE/C;;;;;;;;;OASG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;CAChC;AAMD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf;;;OAGG;IACH,IAAI,EAAE,WAAW,CAAC;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAE7B;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB"}
@@ -0,0 +1,9 @@
1
+ // ============================================================================
2
+ // Next.js 16 'use cache' Handler Types
3
+ // ============================================================================
4
+ // These types implement the cacheHandlers (plural) interface for the
5
+ // 'use cache' directive introduced in Next.js 16.
6
+ // See: https://nextjs.org/docs/app/api-reference/config/next-config-js/cacheHandlers
7
+ // ============================================================================
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/use-cache/types.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,uCAAuC;AACvC,+EAA+E;AAC/E,qEAAqE;AACrE,kDAAkD;AAClD,qFAAqF;AACrF,+EAA+E"}
@@ -0,0 +1,66 @@
1
+ interface CacheTagContextData {
2
+ tags: string[];
3
+ requestId: string;
4
+ startTime: number;
5
+ }
6
+ /**
7
+ * Request-scoped context for tracking cache tags using the Symbol.for pattern.
8
+ *
9
+ * This approach mirrors Next.js's @next/request-context pattern, which is known
10
+ * to propagate through Next.js's internal mechanisms (used by `after()`).
11
+ *
12
+ * The key difference from direct AsyncLocalStorage usage is that cache handlers
13
+ * can access this context via `globalThis[Symbol.for('@nextjs-cache-handler/tag-context')]`
14
+ * rather than importing a module directly.
15
+ */
16
+ export declare class CacheTagContext {
17
+ /**
18
+ * Add tags to the current request context.
19
+ * Called by cache handler during cache hits.
20
+ */
21
+ static addTags(tags: string[]): void;
22
+ /**
23
+ * Get all unique tags accumulated during the current request.
24
+ * Called by middleware before sending response.
25
+ */
26
+ static getTags(): string[];
27
+ /**
28
+ * Get the current request ID.
29
+ */
30
+ static getRequestId(): string | undefined;
31
+ /**
32
+ * Run a callback within a cache tag context.
33
+ * Must be called by withSurrogateKey to initialize tracking.
34
+ */
35
+ static run<T>(callback: () => T): T;
36
+ /**
37
+ * Check if running within a cache tag context.
38
+ */
39
+ static isActive(): boolean;
40
+ /**
41
+ * Get the well-known symbol for accessing this context from cache handlers.
42
+ * Cache handlers should use: globalThis[CacheTagContext.symbol]?.get()
43
+ */
44
+ static get symbol(): symbol;
45
+ }
46
+ /**
47
+ * Helper function for cache handlers to access the cache tag context.
48
+ * This can be called from any module without importing CacheTagContext directly.
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * // In cache handler (use-cache-handler.mjs)
53
+ * const context = globalThis[Symbol.for('@nextjs-cache-handler/tag-context')]?.get();
54
+ * if (context) {
55
+ * context.tags.push(...entry.tags);
56
+ * }
57
+ * ```
58
+ */
59
+ export declare function getCacheTagContextFromGlobal(): CacheTagContextData | undefined;
60
+ /**
61
+ * Helper function for cache handlers to add tags to the cache tag context.
62
+ * This can be called from any module without importing CacheTagContext directly.
63
+ */
64
+ export declare function addTagsToCacheTagContext(tags: string[]): boolean;
65
+ export {};
66
+ //# sourceMappingURL=cache-tag-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-tag-context.d.ts","sourceRoot":"","sources":["../../src/utils/cache-tag-context.ts"],"names":[],"mappings":"AAYA,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AA0BD;;;;;;;;;GASG;AACH,qBAAa,eAAe;IAC1B;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAUpC;;;OAGG;IACH,MAAM,CAAC,OAAO,IAAI,MAAM,EAAE;IAQ1B;;OAEG;IACH,MAAM,CAAC,YAAY,IAAI,MAAM,GAAG,SAAS;IAIzC;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC;IAcnC;;OAEG;IACH,MAAM,CAAC,QAAQ,IAAI,OAAO;IAI1B;;;OAGG;IACH,MAAM,KAAK,MAAM,IAAI,MAAM,CAE1B;CACF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,IAAI,mBAAmB,GAAG,SAAS,CAK9E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAQhE"}
@@ -0,0 +1,126 @@
1
+ import { AsyncLocalStorage } from 'async_hooks';
2
+ import { createLogger } from './logger.js';
3
+ const log = createLogger('CacheTagContext');
4
+ /**
5
+ * Symbol used to store the cache tag context accessor on globalThis.
6
+ * Uses Symbol.for() to ensure the same symbol is used across module boundaries,
7
+ * similar to Next.js's @next/request-context pattern.
8
+ */
9
+ const CACHE_TAG_CONTEXT_SYMBOL = Symbol.for('@nextjs-cache-handler/tag-context');
10
+ /**
11
+ * AsyncLocalStorage instance for request-scoped context.
12
+ * This is created once and registered globally via Symbol.for().
13
+ */
14
+ const cacheTagContextStorage = new AsyncLocalStorage();
15
+ /**
16
+ * The accessor object that will be stored on globalThis.
17
+ * Cache handlers can retrieve this via globalThis[Symbol.for('@nextjs-cache-handler/tag-context')].
18
+ */
19
+ const cacheTagContextAccessor = {
20
+ get() {
21
+ return cacheTagContextStorage.getStore();
22
+ },
23
+ };
24
+ // Register the accessor on globalThis using the well-known symbol
25
+ // This allows cache handlers (which run in a different module context) to access it
26
+ globalThis[CACHE_TAG_CONTEXT_SYMBOL] = cacheTagContextAccessor;
27
+ /**
28
+ * Request-scoped context for tracking cache tags using the Symbol.for pattern.
29
+ *
30
+ * This approach mirrors Next.js's @next/request-context pattern, which is known
31
+ * to propagate through Next.js's internal mechanisms (used by `after()`).
32
+ *
33
+ * The key difference from direct AsyncLocalStorage usage is that cache handlers
34
+ * can access this context via `globalThis[Symbol.for('@nextjs-cache-handler/tag-context')]`
35
+ * rather than importing a module directly.
36
+ */
37
+ export class CacheTagContext {
38
+ /**
39
+ * Add tags to the current request context.
40
+ * Called by cache handler during cache hits.
41
+ */
42
+ static addTags(tags) {
43
+ const context = cacheTagContextStorage.getStore();
44
+ if (context) {
45
+ context.tags.push(...tags);
46
+ log.debug(`Added ${tags.length} tags to CacheTagContext: ${tags.join(', ')}`);
47
+ }
48
+ else {
49
+ log.debug('No CacheTagContext available - tags will not be captured via Symbol.for');
50
+ }
51
+ }
52
+ /**
53
+ * Get all unique tags accumulated during the current request.
54
+ * Called by middleware before sending response.
55
+ */
56
+ static getTags() {
57
+ const context = cacheTagContextStorage.getStore();
58
+ if (!context) {
59
+ return [];
60
+ }
61
+ return [...new Set(context.tags)];
62
+ }
63
+ /**
64
+ * Get the current request ID.
65
+ */
66
+ static getRequestId() {
67
+ return cacheTagContextStorage.getStore()?.requestId;
68
+ }
69
+ /**
70
+ * Run a callback within a cache tag context.
71
+ * Must be called by withSurrogateKey to initialize tracking.
72
+ */
73
+ static run(callback) {
74
+ const requestId = crypto.randomUUID();
75
+ log.debug(`Starting CacheTagContext with requestId: ${requestId}`);
76
+ return cacheTagContextStorage.run({
77
+ tags: [],
78
+ requestId,
79
+ startTime: Date.now(),
80
+ }, callback);
81
+ }
82
+ /**
83
+ * Check if running within a cache tag context.
84
+ */
85
+ static isActive() {
86
+ return cacheTagContextStorage.getStore() !== undefined;
87
+ }
88
+ /**
89
+ * Get the well-known symbol for accessing this context from cache handlers.
90
+ * Cache handlers should use: globalThis[CacheTagContext.symbol]?.get()
91
+ */
92
+ static get symbol() {
93
+ return CACHE_TAG_CONTEXT_SYMBOL;
94
+ }
95
+ }
96
+ /**
97
+ * Helper function for cache handlers to access the cache tag context.
98
+ * This can be called from any module without importing CacheTagContext directly.
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * // In cache handler (use-cache-handler.mjs)
103
+ * const context = globalThis[Symbol.for('@nextjs-cache-handler/tag-context')]?.get();
104
+ * if (context) {
105
+ * context.tags.push(...entry.tags);
106
+ * }
107
+ * ```
108
+ */
109
+ export function getCacheTagContextFromGlobal() {
110
+ const accessor = globalThis[CACHE_TAG_CONTEXT_SYMBOL];
111
+ return accessor?.get();
112
+ }
113
+ /**
114
+ * Helper function for cache handlers to add tags to the cache tag context.
115
+ * This can be called from any module without importing CacheTagContext directly.
116
+ */
117
+ export function addTagsToCacheTagContext(tags) {
118
+ const context = getCacheTagContextFromGlobal();
119
+ if (context && tags.length > 0) {
120
+ context.tags.push(...tags);
121
+ log.debug(`Added ${tags.length} tags via global accessor: ${tags.join(', ')}`);
122
+ return true;
123
+ }
124
+ return false;
125
+ }
126
+ //# sourceMappingURL=cache-tag-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-tag-context.js","sourceRoot":"","sources":["../../src/utils/cache-tag-context.ts"],"names":[],"mappings":"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"}
@@ -2,4 +2,7 @@ export { serializeForStorage, deserializeFromStorage } from './serialization.js'
2
2
  export { getBuildId, isBuildPhase } from './build-detection.js';
3
3
  export { getStaticRoutes } from './static-routes.js';
4
4
  export { createLogger, type Logger } from './logger.js';
5
+ export { RequestContext } from './request-context.js';
6
+ export { CacheTagContext, getCacheTagContextFromGlobal, addTagsToCacheTagContext, } from './cache-tag-context.js';
7
+ export { withSurrogateKey, type SurrogateKeyOptions } from './with-surrogate-key.js';
5
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,eAAe,EACf,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -2,4 +2,7 @@ export { serializeForStorage, deserializeFromStorage } from './serialization.js'
2
2
  export { getBuildId, isBuildPhase } from './build-detection.js';
3
3
  export { getStaticRoutes } from './static-routes.js';
4
4
  export { createLogger } from './logger.js';
5
+ export { RequestContext } from './request-context.js';
6
+ export { CacheTagContext, getCacheTagContextFromGlobal, addTagsToCacheTagContext, } from './cache-tag-context.js';
7
+ export { withSurrogateKey } from './with-surrogate-key.js';
5
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,eAAe,EACf,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAA4B,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Request-scoped context for tracking cache tags during SSR.
3
+ * Uses AsyncLocalStorage to maintain isolation between concurrent requests.
4
+ */
5
+ export declare class RequestContext {
6
+ private static storage;
7
+ /**
8
+ * Add tags to the current request context.
9
+ * Called by cache handler during cache hits.
10
+ */
11
+ static addTags(tags: string[]): void;
12
+ /**
13
+ * Get all unique tags accumulated during the current request.
14
+ * Called by middleware before sending response.
15
+ */
16
+ static getTags(): string[];
17
+ /**
18
+ * Run a callback within a request context.
19
+ * Must be called by middleware to initialize tracking.
20
+ */
21
+ static run<T>(callback: () => T): T;
22
+ /**
23
+ * Check if running within a request context.
24
+ * Useful for debugging and conditional logic.
25
+ */
26
+ static isActive(): boolean;
27
+ }
28
+ //# sourceMappingURL=request-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/utils/request-context.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,OAAO,CAA+C;IAErE;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAUpC;;;OAGG;IACH,MAAM,CAAC,OAAO,IAAI,MAAM,EAAE;IAS1B;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC;IAUnC;;;OAGG;IACH,MAAM,CAAC,QAAQ,IAAI,OAAO;CAG3B"}
@@ -0,0 +1,54 @@
1
+ import { AsyncLocalStorage } from 'async_hooks';
2
+ import { createLogger } from './logger.js';
3
+ const log = createLogger('RequestContext');
4
+ /**
5
+ * Request-scoped context for tracking cache tags during SSR.
6
+ * Uses AsyncLocalStorage to maintain isolation between concurrent requests.
7
+ */
8
+ export class RequestContext {
9
+ /**
10
+ * Add tags to the current request context.
11
+ * Called by cache handler during cache hits.
12
+ */
13
+ static addTags(tags) {
14
+ const context = this.storage.getStore();
15
+ if (context) {
16
+ context.tags.push(...tags);
17
+ log.debug(`Added ${tags.length} tags to request context: ${tags.join(', ')}`);
18
+ }
19
+ else {
20
+ log.warn('No request context available - tags will not be captured');
21
+ }
22
+ }
23
+ /**
24
+ * Get all unique tags accumulated during the current request.
25
+ * Called by middleware before sending response.
26
+ */
27
+ static getTags() {
28
+ const context = this.storage.getStore();
29
+ if (!context) {
30
+ return [];
31
+ }
32
+ // Remove duplicates using Set
33
+ return [...new Set(context.tags)];
34
+ }
35
+ /**
36
+ * Run a callback within a request context.
37
+ * Must be called by middleware to initialize tracking.
38
+ */
39
+ static run(callback) {
40
+ return this.storage.run({
41
+ tags: [],
42
+ startTime: Date.now(),
43
+ }, callback);
44
+ }
45
+ /**
46
+ * Check if running within a request context.
47
+ * Useful for debugging and conditional logic.
48
+ */
49
+ static isActive() {
50
+ return this.storage.getStore() !== undefined;
51
+ }
52
+ }
53
+ RequestContext.storage = new AsyncLocalStorage();
54
+ //# sourceMappingURL=request-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context.js","sourceRoot":"","sources":["../../src/utils/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,GAAG,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAC;AAO3C;;;GAGG;AACH,MAAM,OAAO,cAAc;IAGzB;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAc;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACxC,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;YAC3B,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,MAAM,6BAA6B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,OAAO;QACZ,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,8BAA8B;QAC9B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAI,QAAiB;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CACrB;YACE,IAAI,EAAE,EAAE;YACR,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,EACD,QAAQ,CACT,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,QAAQ;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,SAAS,CAAC;IAC/C,CAAC;;AAjDc,sBAAO,GAAG,IAAI,iBAAiB,EAAsB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=request-context.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context.test.d.ts","sourceRoot":"","sources":["../../src/utils/request-context.test.ts"],"names":[],"mappings":""}