@pantheon-systems/nextjs-cache-handler 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.
Files changed (54) hide show
  1. package/README.md +256 -0
  2. package/dist/edge/edge-cache-clear.d.ts +64 -0
  3. package/dist/edge/edge-cache-clear.d.ts.map +1 -0
  4. package/dist/edge/edge-cache-clear.js +245 -0
  5. package/dist/edge/edge-cache-clear.js.map +1 -0
  6. package/dist/handlers/base.d.ts +69 -0
  7. package/dist/handlers/base.d.ts.map +1 -0
  8. package/dist/handlers/base.js +278 -0
  9. package/dist/handlers/base.js.map +1 -0
  10. package/dist/handlers/file.d.ts +62 -0
  11. package/dist/handlers/file.d.ts.map +1 -0
  12. package/dist/handlers/file.js +332 -0
  13. package/dist/handlers/file.js.map +1 -0
  14. package/dist/handlers/gcs.d.ts +66 -0
  15. package/dist/handlers/gcs.d.ts.map +1 -0
  16. package/dist/handlers/gcs.js +407 -0
  17. package/dist/handlers/gcs.js.map +1 -0
  18. package/dist/handlers/index.d.ts +4 -0
  19. package/dist/handlers/index.d.ts.map +1 -0
  20. package/dist/handlers/index.js +4 -0
  21. package/dist/handlers/index.js.map +1 -0
  22. package/dist/index.d.ts +47 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +73 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/types.d.ts +119 -0
  27. package/dist/types.d.ts.map +1 -0
  28. package/dist/types.js +2 -0
  29. package/dist/types.js.map +1 -0
  30. package/dist/utils/build-detection.d.ts +10 -0
  31. package/dist/utils/build-detection.d.ts.map +1 -0
  32. package/dist/utils/build-detection.js +57 -0
  33. package/dist/utils/build-detection.js.map +1 -0
  34. package/dist/utils/index.d.ts +5 -0
  35. package/dist/utils/index.d.ts.map +1 -0
  36. package/dist/utils/index.js +5 -0
  37. package/dist/utils/index.js.map +1 -0
  38. package/dist/utils/logger.d.ts +34 -0
  39. package/dist/utils/logger.d.ts.map +1 -0
  40. package/dist/utils/logger.js +54 -0
  41. package/dist/utils/logger.js.map +1 -0
  42. package/dist/utils/serialization.d.ts +12 -0
  43. package/dist/utils/serialization.d.ts.map +1 -0
  44. package/dist/utils/serialization.js +137 -0
  45. package/dist/utils/serialization.js.map +1 -0
  46. package/dist/utils/static-routes.d.ts +7 -0
  47. package/dist/utils/static-routes.d.ts.map +1 -0
  48. package/dist/utils/static-routes.js +52 -0
  49. package/dist/utils/static-routes.js.map +1 -0
  50. package/dist/utils/tags-buffer.d.ts +63 -0
  51. package/dist/utils/tags-buffer.d.ts.map +1 -0
  52. package/dist/utils/tags-buffer.js +181 -0
  53. package/dist/utils/tags-buffer.js.map +1 -0
  54. package/package.json +58 -0
@@ -0,0 +1,407 @@
1
+ import { Storage } from '@google-cloud/storage';
2
+ import { BaseCacheHandler } from './base.js';
3
+ import { createEdgeCacheClearer } from '../edge/edge-cache-clear.js';
4
+ import { getStaticRoutes } from '../utils/static-routes.js';
5
+ import { TagsBuffer } from '../utils/tags-buffer.js';
6
+ import { createLogger } from '../utils/logger.js';
7
+ const gcsLog = createLogger('GcsCacheHandler');
8
+ /**
9
+ * Google Cloud Storage cache handler for production/Pantheon environments.
10
+ * Stores cache entries in a GCS bucket.
11
+ */
12
+ export class GcsCacheHandler extends BaseCacheHandler {
13
+ constructor(context) {
14
+ super(context, 'GcsCacheHandler');
15
+ const bucketName = process.env.CACHE_BUCKET;
16
+ if (!bucketName) {
17
+ throw new Error('CACHE_BUCKET environment variable is required for GCS cache handler');
18
+ }
19
+ const storage = new Storage();
20
+ this.bucket = storage.bucket(bucketName);
21
+ this.fetchCachePrefix = 'fetch-cache/';
22
+ this.routeCachePrefix = 'route-cache/';
23
+ this.buildMetaKey = 'build-meta.json';
24
+ this.tagsPrefix = 'cache/tags/';
25
+ this.tagsMapKey = `${this.tagsPrefix}tags.json`;
26
+ this.edgeCacheClearer = createEdgeCacheClearer();
27
+ // Create tags buffer for rate-limited writes
28
+ this.tagsBuffer = new TagsBuffer({
29
+ flushIntervalMs: 1000, // GCS rate limit is 1 write/second per object
30
+ readTagsMapping: () => this.readTagsMappingDirect(),
31
+ writeTagsMapping: (mapping) => this.writeTagsMapping(mapping),
32
+ handlerName: 'GcsCacheHandler',
33
+ });
34
+ // Initialize asynchronously (don't await to avoid blocking constructor)
35
+ this.initialize().catch(() => { });
36
+ }
37
+ // ============================================================================
38
+ // Tags mapping implementation (buffered for GCS rate limiting)
39
+ // ============================================================================
40
+ async initializeTagsMapping() {
41
+ try {
42
+ const file = this.bucket.file(this.tagsMapKey);
43
+ const [exists] = await file.exists();
44
+ if (!exists) {
45
+ await file.save(JSON.stringify({}), {
46
+ metadata: { contentType: 'application/json' },
47
+ });
48
+ }
49
+ }
50
+ catch (error) {
51
+ this.log.error('Error initializing tags mapping:', error);
52
+ // Don't throw - tags mapping will be created on first write
53
+ }
54
+ }
55
+ /**
56
+ * Read tags mapping, flushing any pending updates first to ensure accuracy.
57
+ */
58
+ async readTagsMapping() {
59
+ // Flush pending updates before reading to ensure we have accurate data
60
+ await this.tagsBuffer.flush();
61
+ return this.readTagsMappingDirect();
62
+ }
63
+ /**
64
+ * Direct read from GCS without flushing buffer.
65
+ * Used internally by the buffer.
66
+ */
67
+ async readTagsMappingDirect() {
68
+ try {
69
+ const file = this.bucket.file(this.tagsMapKey);
70
+ const [exists] = await file.exists();
71
+ if (!exists) {
72
+ return {};
73
+ }
74
+ const [data] = await file.download();
75
+ return JSON.parse(data.toString());
76
+ }
77
+ catch (error) {
78
+ this.log.warn('Error reading tags mapping:', error);
79
+ return {};
80
+ }
81
+ }
82
+ /**
83
+ * Write tags mapping directly to GCS.
84
+ * Used by the buffer for batched writes.
85
+ */
86
+ async writeTagsMapping(tagsMapping) {
87
+ try {
88
+ const file = this.bucket.file(this.tagsMapKey);
89
+ await file.save(JSON.stringify(tagsMapping, null, 2), {
90
+ metadata: { contentType: 'application/json' },
91
+ });
92
+ }
93
+ catch (error) {
94
+ this.log.error('Error writing tags mapping:', error);
95
+ throw error; // Re-throw so buffer can retry
96
+ }
97
+ }
98
+ /**
99
+ * Override to use buffered updates instead of immediate writes.
100
+ */
101
+ async updateTagsMapping(cacheKey, tags, isDelete = false) {
102
+ if (isDelete) {
103
+ this.tagsBuffer.deleteKey(cacheKey);
104
+ }
105
+ else if (tags.length > 0) {
106
+ this.tagsBuffer.addTags(cacheKey, tags);
107
+ }
108
+ // Updates are queued and will be flushed automatically
109
+ this.log.debug(`Queued tags update for ${cacheKey} (pending: ${this.tagsBuffer.pendingCount})`);
110
+ }
111
+ /**
112
+ * Override to use buffered deletes instead of immediate writes.
113
+ */
114
+ async updateTagsMappingBulkDelete(cacheKeysToDelete, _tagsMapping) {
115
+ this.tagsBuffer.deleteKeys(cacheKeysToDelete);
116
+ // Force flush after bulk delete to ensure consistency for revalidation
117
+ await this.tagsBuffer.flush();
118
+ }
119
+ // ============================================================================
120
+ // Cache entry implementation
121
+ // ============================================================================
122
+ getCacheKey(cacheKey, cacheType) {
123
+ const safeKey = cacheKey.replace(/[^a-zA-Z0-9-]/g, '_');
124
+ const prefix = cacheType === 'fetch' ? this.fetchCachePrefix : this.routeCachePrefix;
125
+ return `${prefix}${safeKey}.json`;
126
+ }
127
+ async readCacheEntry(cacheKey, cacheType) {
128
+ try {
129
+ const gcsKey = this.getCacheKey(cacheKey, cacheType);
130
+ const file = this.bucket.file(gcsKey);
131
+ const [exists] = await file.exists();
132
+ if (!exists) {
133
+ return null;
134
+ }
135
+ const [data] = await file.download();
136
+ const parsedData = JSON.parse(data.toString());
137
+ return this.deserializeFromStorage({ [cacheKey]: parsedData })[cacheKey] || null;
138
+ }
139
+ catch {
140
+ return null;
141
+ }
142
+ }
143
+ async writeCacheEntry(cacheKey, cacheValue, cacheType) {
144
+ try {
145
+ const gcsKey = this.getCacheKey(cacheKey, cacheType);
146
+ const file = this.bucket.file(gcsKey);
147
+ const serializedData = this.serializeForStorage({ [cacheKey]: cacheValue });
148
+ await file.save(JSON.stringify(serializedData[cacheKey], null, 2), {
149
+ metadata: { contentType: 'application/json' },
150
+ });
151
+ }
152
+ catch (error) {
153
+ this.log.error(`Error writing cache entry ${cacheKey}:`, error);
154
+ }
155
+ }
156
+ async deleteCacheEntry(cacheKey, cacheType) {
157
+ try {
158
+ const gcsKey = this.getCacheKey(cacheKey, cacheType);
159
+ const file = this.bucket.file(gcsKey);
160
+ await file.delete();
161
+ }
162
+ catch (error) {
163
+ if (!error || typeof error !== 'object' || !('code' in error) || error.code !== 404) {
164
+ this.log.error(`Error deleting cache entry ${cacheKey}:`, error);
165
+ }
166
+ throw error;
167
+ }
168
+ }
169
+ // ============================================================================
170
+ // Build meta implementation
171
+ // ============================================================================
172
+ async readBuildMeta() {
173
+ const file = this.bucket.file(this.buildMetaKey);
174
+ const [data] = await file.download();
175
+ return JSON.parse(data.toString());
176
+ }
177
+ async writeBuildMeta(meta) {
178
+ const file = this.bucket.file(this.buildMetaKey);
179
+ await file.save(JSON.stringify(meta), {
180
+ metadata: { contentType: 'application/json' },
181
+ });
182
+ }
183
+ async invalidateRouteCache() {
184
+ try {
185
+ const [files] = await this.bucket.getFiles({ prefix: this.routeCachePrefix });
186
+ const deletePromises = files.map((file) => file.delete());
187
+ await Promise.all(deletePromises);
188
+ // Also clear the edge cache since route cache was invalidated
189
+ this.clearEdgeCache('route cache invalidation on new build');
190
+ }
191
+ catch {
192
+ // Silently fail - cache invalidation is best effort
193
+ }
194
+ }
195
+ // ============================================================================
196
+ // Edge cache integration
197
+ // ============================================================================
198
+ clearEdgeCache(context) {
199
+ if (!this.edgeCacheClearer) {
200
+ this.log.debug(`Edge cache clearer not configured, skipping edge cache clear for: ${context}`);
201
+ return;
202
+ }
203
+ this.edgeCacheClearer.nukeCacheInBackground(context);
204
+ }
205
+ async onRevalidateComplete(tags, deletedKeys) {
206
+ if (deletedKeys.length === 0 || !this.edgeCacheClearer) {
207
+ return;
208
+ }
209
+ // Clear by tags/keys
210
+ this.edgeCacheClearer.clearKeysInBackground(tags, `tag revalidation: ${tags.join(', ')}`);
211
+ // Also clear by route paths for routes that may not have tags (e.g., ISR routes)
212
+ const routePaths = this.extractRoutePaths(deletedKeys);
213
+ if (routePaths.length > 0) {
214
+ this.edgeCacheClearer.clearPathsInBackground(routePaths, `path revalidation: ${routePaths.join(', ')}`);
215
+ }
216
+ }
217
+ /**
218
+ * Called when a route cache entry is set (ISR page update).
219
+ * Clears the edge cache for this specific route so users get the fresh version.
220
+ */
221
+ onRouteCacheSet(cacheKey) {
222
+ if (!this.edgeCacheClearer) {
223
+ return;
224
+ }
225
+ const routePath = this.cacheKeyToRoutePath(cacheKey);
226
+ this.edgeCacheClearer.clearPathInBackground(routePath, `ISR route update: ${routePath}`);
227
+ }
228
+ cacheKeyToRoutePath(cacheKey) {
229
+ // Cache keys may be encoded (e.g., underscores for slashes)
230
+ // Convert to a proper path format
231
+ if (cacheKey.startsWith('/')) {
232
+ return cacheKey;
233
+ }
234
+ // Handle encoded paths (underscores represent slashes in some cases)
235
+ if (cacheKey.startsWith('_')) {
236
+ return cacheKey.replace(/_/g, '/');
237
+ }
238
+ return `/${cacheKey}`;
239
+ }
240
+ extractRoutePaths(keys) {
241
+ return keys
242
+ .filter((key) => key.startsWith('/') || key.startsWith('_'))
243
+ .map((key) => {
244
+ if (key.startsWith('_')) {
245
+ return key.replace(/_/g, '/');
246
+ }
247
+ return key.startsWith('/') ? key : `/${key}`;
248
+ });
249
+ }
250
+ }
251
+ // ============================================================================
252
+ // Standalone functions for API usage
253
+ // ============================================================================
254
+ /**
255
+ * Get cache statistics for the GCS-based cache.
256
+ */
257
+ export async function getSharedCacheStats() {
258
+ const bucketName = process.env.CACHE_BUCKET;
259
+ if (!bucketName) {
260
+ gcsLog.debug('CACHE_BUCKET environment variable not found');
261
+ return { size: 0, keys: [], entries: [] };
262
+ }
263
+ const storage = new Storage();
264
+ const bucket = storage.bucket(bucketName);
265
+ const fetchCachePrefix = 'fetch-cache/';
266
+ const routeCachePrefix = 'route-cache/';
267
+ const keys = [];
268
+ const entries = [];
269
+ try {
270
+ await processGcsCachePrefix(bucket, fetchCachePrefix, 'fetch', keys, entries);
271
+ await processGcsCachePrefix(bucket, routeCachePrefix, 'route', keys, entries);
272
+ gcsLog.debug(`Found ${keys.length} cache entries ` +
273
+ `(${keys.filter((k) => k.startsWith('fetch:')).length} fetch, ` +
274
+ `${keys.filter((k) => k.startsWith('route:')).length} route)`);
275
+ return { size: keys.length, keys, entries };
276
+ }
277
+ catch (error) {
278
+ gcsLog.error('Error reading cache:', error);
279
+ return { size: 0, keys: [], entries: [] };
280
+ }
281
+ }
282
+ async function processGcsCachePrefix(bucket, prefix, cacheType, keys, entries) {
283
+ try {
284
+ const [files] = await bucket.getFiles({ prefix });
285
+ const jsonFiles = files.filter((file) => file.name.endsWith('.json'));
286
+ for (const file of jsonFiles) {
287
+ await processGcsFile(file, prefix, cacheType, keys, entries);
288
+ }
289
+ }
290
+ catch (error) {
291
+ gcsLog.warn(`Error reading ${cacheType} cache:`, error);
292
+ }
293
+ }
294
+ async function processGcsFile(file, prefix, cacheType, keys, entries) {
295
+ const cacheKey = file.name.replace(prefix, '').replace('.json', '').replace(/_/g, '-');
296
+ const displayKey = `${cacheType}:${cacheKey}`;
297
+ keys.push(displayKey);
298
+ try {
299
+ const [data] = await file.download();
300
+ const cacheData = JSON.parse(data.toString());
301
+ entries.push({
302
+ key: displayKey,
303
+ tags: cacheData.tags || [],
304
+ lastModified: cacheData.lastModified || Date.now(),
305
+ type: cacheType,
306
+ });
307
+ }
308
+ catch {
309
+ entries.push({
310
+ key: displayKey,
311
+ tags: [],
312
+ type: cacheType,
313
+ });
314
+ }
315
+ }
316
+ /**
317
+ * Clear all cache entries for the GCS-based cache.
318
+ */
319
+ export async function clearSharedCache() {
320
+ const bucketName = process.env.CACHE_BUCKET;
321
+ if (!bucketName) {
322
+ gcsLog.debug('CACHE_BUCKET environment variable not found');
323
+ return 0;
324
+ }
325
+ const storage = new Storage();
326
+ const bucket = storage.bucket(bucketName);
327
+ const fetchCachePrefix = 'fetch-cache/';
328
+ const routeCachePrefix = 'route-cache/';
329
+ const tagsFilePath = 'cache/tags/tags.json';
330
+ const staticRoutes = getStaticRoutes();
331
+ let clearedCount = 0;
332
+ try {
333
+ // Clear fetch cache (data cache - always clearable)
334
+ clearedCount += await clearGcsFetchCache(bucket, fetchCachePrefix);
335
+ // Clear route cache (skip static routes)
336
+ const routeResult = await clearGcsRouteCache(bucket, routeCachePrefix, staticRoutes);
337
+ clearedCount += routeResult.cleared;
338
+ // Clear tags mapping
339
+ await clearGcsTagsMapping(bucket, tagsFilePath);
340
+ gcsLog.info(`Total cleared: ${clearedCount} cache entries`);
341
+ // Clear edge cache if configured and entries were cleared
342
+ if (clearedCount > 0) {
343
+ const edgeCacheClearer = createEdgeCacheClearer();
344
+ if (edgeCacheClearer) {
345
+ edgeCacheClearer.nukeCacheInBackground('shared cache clear');
346
+ }
347
+ }
348
+ return clearedCount;
349
+ }
350
+ catch (error) {
351
+ gcsLog.error('Error clearing cache:', error);
352
+ return 0;
353
+ }
354
+ }
355
+ async function clearGcsFetchCache(bucket, prefix) {
356
+ try {
357
+ const [files] = await bucket.getFiles({ prefix });
358
+ const jsonFiles = files.filter((file) => file.name.endsWith('.json'));
359
+ const deletePromises = jsonFiles.map((file) => file.delete());
360
+ await Promise.all(deletePromises);
361
+ gcsLog.debug(`Cleared ${jsonFiles.length} fetch cache entries`);
362
+ return jsonFiles.length;
363
+ }
364
+ catch (error) {
365
+ gcsLog.warn('Error clearing fetch cache:', error);
366
+ return 0;
367
+ }
368
+ }
369
+ async function clearGcsRouteCache(bucket, prefix, staticRoutes) {
370
+ let cleared = 0;
371
+ let preserved = 0;
372
+ try {
373
+ const [files] = await bucket.getFiles({ prefix });
374
+ const jsonFiles = files.filter((file) => file.name.endsWith('.json'));
375
+ const filesToDelete = [];
376
+ for (const file of jsonFiles) {
377
+ const cacheKey = file.name.replace(prefix, '').replace('.json', '');
378
+ if (staticRoutes.has(cacheKey)) {
379
+ preserved++;
380
+ continue;
381
+ }
382
+ filesToDelete.push(file);
383
+ }
384
+ const deletePromises = filesToDelete.map((file) => file.delete());
385
+ await Promise.all(deletePromises);
386
+ cleared = filesToDelete.length;
387
+ gcsLog.debug(`Route cache: cleared ${cleared}, preserved ${preserved} static routes`);
388
+ }
389
+ catch (error) {
390
+ gcsLog.warn('Error clearing route cache:', error);
391
+ }
392
+ return { cleared, preserved };
393
+ }
394
+ async function clearGcsTagsMapping(bucket, tagsFilePath) {
395
+ try {
396
+ const tagsFile = bucket.file(tagsFilePath);
397
+ const [exists] = await tagsFile.exists();
398
+ if (exists) {
399
+ await tagsFile.delete();
400
+ }
401
+ }
402
+ catch {
403
+ // Ignore errors
404
+ }
405
+ }
406
+ export default GcsCacheHandler;
407
+ //# sourceMappingURL=gcs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcs.js","sourceRoot":"","sources":["../../src/handlers/gcs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { FileCacheHandler, getSharedCacheStats as getFileSharedCacheStats, clearSharedCache as clearFileSharedCache } from './file.js';
2
+ export { GcsCacheHandler, getSharedCacheStats as getGcsSharedCacheStats, clearSharedCache as clearGcsSharedCache } from './gcs.js';
3
+ export { BaseCacheHandler } from './base.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,IAAI,uBAAuB,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACvI,OAAO,EAAE,eAAe,EAAE,mBAAmB,IAAI,sBAAsB,EAAE,gBAAgB,IAAI,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACnI,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { FileCacheHandler, getSharedCacheStats as getFileSharedCacheStats, clearSharedCache as clearFileSharedCache } from './file.js';
2
+ export { GcsCacheHandler, getSharedCacheStats as getGcsSharedCacheStats, clearSharedCache as clearGcsSharedCache } from './gcs.js';
3
+ export { BaseCacheHandler } from './base.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,IAAI,uBAAuB,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACvI,OAAO,EAAE,eAAe,EAAE,mBAAmB,IAAI,sBAAsB,EAAE,gBAAgB,IAAI,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACnI,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { CacheHandlerConfig, CacheStats } from './types.js';
2
+ import { FileCacheHandler } from './handlers/file.js';
3
+ import { GcsCacheHandler } from './handlers/gcs.js';
4
+ /**
5
+ * Factory function to create a cache handler based on configuration.
6
+ *
7
+ * @param config - Configuration options for the cache handler
8
+ * @returns A cache handler class that can be used with Next.js
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // In your cacheHandler.ts file:
13
+ * import { createCacheHandler } from '@pantheon-systems/nextjs-cache-handler';
14
+ *
15
+ * const CacheHandler = createCacheHandler({
16
+ * type: 'auto', // Auto-detect: GCS if CACHE_BUCKET exists, else file-based
17
+ * });
18
+ *
19
+ * export default CacheHandler;
20
+ * ```
21
+ *
22
+ * @example
23
+ * ```javascript
24
+ * // In your next.config.mjs:
25
+ * const nextConfig = {
26
+ * cacheHandler: require.resolve('./cacheHandler'),
27
+ * cacheMaxMemorySize: 0,
28
+ * };
29
+ *
30
+ * export default nextConfig;
31
+ * ```
32
+ */
33
+ export declare function createCacheHandler(config?: CacheHandlerConfig): typeof FileCacheHandler | typeof GcsCacheHandler;
34
+ /**
35
+ * Get cache statistics for the current environment.
36
+ * Automatically detects whether to use file-based or GCS cache stats.
37
+ */
38
+ export declare function getSharedCacheStats(): Promise<CacheStats>;
39
+ /**
40
+ * Clear all cache entries for the current environment.
41
+ * Automatically detects whether to use file-based or GCS cache clearing.
42
+ */
43
+ export declare function clearSharedCache(): Promise<number>;
44
+ export { FileCacheHandler } from './handlers/file.js';
45
+ export { GcsCacheHandler } from './handlers/gcs.js';
46
+ export type { CacheHandlerConfig, CacheStats, CacheEntryInfo, CacheContext, CacheEntry, CacheData, CacheHandlerValue, CacheHandlerParametersGet, CacheHandlerParametersSet, CacheHandlerParametersRevalidateTag, FileSystemCacheContext, Revalidate, LifespanParameters, SerializedBuffer, SerializedMap, SerializableValue, SerializedCacheData, } from './types.js';
47
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAgF,MAAM,oBAAoB,CAAC;AACpI,OAAO,EAAE,eAAe,EAA8E,MAAM,mBAAmB,CAAC;AAEhI;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,gBAAgB,GAAG,OAAO,eAAe,CAQhH;AAcD;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,UAAU,CAAC,CAK/D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAKxD;AAMD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAMpD,YAAY,EACV,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,yBAAyB,EACzB,yBAAyB,EACzB,mCAAmC,EACnC,sBAAsB,EACtB,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,73 @@
1
+ import { FileCacheHandler, getSharedCacheStats as getFileCacheStats, clearSharedCache as clearFileCache } from './handlers/file.js';
2
+ import { GcsCacheHandler, getSharedCacheStats as getGcsCacheStats, clearSharedCache as clearGcsCache } from './handlers/gcs.js';
3
+ /**
4
+ * Factory function to create a cache handler based on configuration.
5
+ *
6
+ * @param config - Configuration options for the cache handler
7
+ * @returns A cache handler class that can be used with Next.js
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * // In your cacheHandler.ts file:
12
+ * import { createCacheHandler } from '@pantheon-systems/nextjs-cache-handler';
13
+ *
14
+ * const CacheHandler = createCacheHandler({
15
+ * type: 'auto', // Auto-detect: GCS if CACHE_BUCKET exists, else file-based
16
+ * });
17
+ *
18
+ * export default CacheHandler;
19
+ * ```
20
+ *
21
+ * @example
22
+ * ```javascript
23
+ * // In your next.config.mjs:
24
+ * const nextConfig = {
25
+ * cacheHandler: require.resolve('./cacheHandler'),
26
+ * cacheMaxMemorySize: 0,
27
+ * };
28
+ *
29
+ * export default nextConfig;
30
+ * ```
31
+ */
32
+ export function createCacheHandler(config) {
33
+ const type = config?.type ?? 'auto';
34
+ if (shouldUseGcs(type)) {
35
+ return GcsCacheHandler;
36
+ }
37
+ return FileCacheHandler;
38
+ }
39
+ function shouldUseGcs(type) {
40
+ if (type === 'gcs') {
41
+ return true;
42
+ }
43
+ if (type === 'auto') {
44
+ return !!process.env.CACHE_BUCKET;
45
+ }
46
+ return false;
47
+ }
48
+ /**
49
+ * Get cache statistics for the current environment.
50
+ * Automatically detects whether to use file-based or GCS cache stats.
51
+ */
52
+ export async function getSharedCacheStats() {
53
+ if (process.env.CACHE_BUCKET) {
54
+ return getGcsCacheStats();
55
+ }
56
+ return getFileCacheStats();
57
+ }
58
+ /**
59
+ * Clear all cache entries for the current environment.
60
+ * Automatically detects whether to use file-based or GCS cache clearing.
61
+ */
62
+ export async function clearSharedCache() {
63
+ if (process.env.CACHE_BUCKET) {
64
+ return clearGcsCache();
65
+ }
66
+ return clearFileCache();
67
+ }
68
+ // ============================================================================
69
+ // Direct handler exports for advanced users
70
+ // ============================================================================
71
+ export { FileCacheHandler } from './handlers/file.js';
72
+ export { GcsCacheHandler } from './handlers/gcs.js';
73
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,IAAI,iBAAiB,EAAE,gBAAgB,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpI,OAAO,EAAE,eAAe,EAAE,mBAAmB,IAAI,gBAAgB,EAAE,gBAAgB,IAAI,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEhI;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA2B;IAC5D,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC;IAEpC,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,IAA6B;IACjD,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IACpC,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC7B,OAAO,gBAAgB,EAAE,CAAC;IAC5B,CAAC;IACD,OAAO,iBAAiB,EAAE,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC7B,OAAO,aAAa,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,cAAc,EAAE,CAAC;AAC1B,CAAC;AAED,+EAA+E;AAC/E,4CAA4C;AAC5C,+EAA+E;AAE/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}