@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.
- package/README.md +110 -0
- package/dist/handlers/base.d.ts +9 -0
- package/dist/handlers/base.d.ts.map +1 -1
- package/dist/handlers/base.js +22 -0
- package/dist/handlers/base.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +2 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/surrogate-key.d.ts +29 -0
- package/dist/middleware/surrogate-key.d.ts.map +1 -0
- package/dist/middleware/surrogate-key.js +66 -0
- package/dist/middleware/surrogate-key.js.map +1 -0
- package/dist/use-cache/file-handler.d.ts +71 -0
- package/dist/use-cache/file-handler.d.ts.map +1 -0
- package/dist/use-cache/file-handler.js +366 -0
- package/dist/use-cache/file-handler.js.map +1 -0
- package/dist/use-cache/gcs-handler.d.ts +64 -0
- package/dist/use-cache/gcs-handler.d.ts.map +1 -0
- package/dist/use-cache/gcs-handler.js +406 -0
- package/dist/use-cache/gcs-handler.js.map +1 -0
- package/dist/use-cache/index.d.ts +58 -0
- package/dist/use-cache/index.d.ts.map +1 -0
- package/dist/use-cache/index.js +87 -0
- package/dist/use-cache/index.js.map +1 -0
- package/dist/use-cache/stream-serialization.d.ts +34 -0
- package/dist/use-cache/stream-serialization.d.ts.map +1 -0
- package/dist/use-cache/stream-serialization.js +96 -0
- package/dist/use-cache/stream-serialization.js.map +1 -0
- package/dist/use-cache/types.d.ts +202 -0
- package/dist/use-cache/types.d.ts.map +1 -0
- package/dist/use-cache/types.js +9 -0
- package/dist/use-cache/types.js.map +1 -0
- package/dist/utils/cache-tag-context.d.ts +66 -0
- package/dist/utils/cache-tag-context.d.ts.map +1 -0
- package/dist/utils/cache-tag-context.js +126 -0
- package/dist/utils/cache-tag-context.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/request-context.d.ts +28 -0
- package/dist/utils/request-context.d.ts.map +1 -0
- package/dist/utils/request-context.js +54 -0
- package/dist/utils/request-context.js.map +1 -0
- package/dist/utils/request-context.test.d.ts +2 -0
- package/dist/utils/request-context.test.d.ts.map +1 -0
- package/dist/utils/request-context.test.js +65 -0
- package/dist/utils/request-context.test.js.map +1 -0
- package/dist/utils/with-surrogate-key.d.ts +32 -0
- package/dist/utils/with-surrogate-key.d.ts.map +1 -0
- package/dist/utils/with-surrogate-key.js +113 -0
- package/dist/utils/with-surrogate-key.js.map +1 -0
- package/package.json +15 -1
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { serializeUseCacheEntry, deserializeUseCacheEntry, } from './stream-serialization.js';
|
|
4
|
+
import { createLogger } from '../utils/logger.js';
|
|
5
|
+
import { createEdgeCacheClearer } from '../edge/edge-cache-clear.js';
|
|
6
|
+
const log = createLogger('UseCacheFileHandler');
|
|
7
|
+
/**
|
|
8
|
+
* Next.js internal prefix for path-based cache tags.
|
|
9
|
+
*/
|
|
10
|
+
const NEXTJS_PATH_TAG_PREFIX = '_N_T_';
|
|
11
|
+
/**
|
|
12
|
+
* Symbol for path→surrogate-key registry on globalThis.
|
|
13
|
+
*/
|
|
14
|
+
const PATH_TAGS_REGISTRY_SYMBOL = Symbol.for('@nextjs-cache-handler/path-tags-registry');
|
|
15
|
+
/**
|
|
16
|
+
* Symbol used to access CacheTagContext from globalThis.
|
|
17
|
+
* This matches the Symbol.for pattern used by Next.js for @next/request-context.
|
|
18
|
+
*/
|
|
19
|
+
const CACHE_TAG_CONTEXT_SYMBOL = Symbol.for('@nextjs-cache-handler/tag-context');
|
|
20
|
+
/**
|
|
21
|
+
* Access the CacheTagContext via globalThis using Symbol.for.
|
|
22
|
+
* This allows cross-context access without direct module imports.
|
|
23
|
+
*/
|
|
24
|
+
function getCacheTagContext() {
|
|
25
|
+
const accessor = globalThis[CACHE_TAG_CONTEXT_SYMBOL];
|
|
26
|
+
return accessor?.get();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Add tags to the CacheTagContext if available.
|
|
30
|
+
* Falls back to global store if CacheTagContext is not active.
|
|
31
|
+
*/
|
|
32
|
+
function captureTags(tags) {
|
|
33
|
+
if (tags.length === 0) {
|
|
34
|
+
return { captured: false, source: 'none' };
|
|
35
|
+
}
|
|
36
|
+
// Primary: Try CacheTagContext (Symbol.for pattern)
|
|
37
|
+
const context = getCacheTagContext();
|
|
38
|
+
if (context) {
|
|
39
|
+
context.tags.push(...tags);
|
|
40
|
+
log.debug(`Captured ${tags.length} tags via CacheTagContext: ${tags.join(', ')}`);
|
|
41
|
+
return { captured: true, source: 'CacheTagContext' };
|
|
42
|
+
}
|
|
43
|
+
// Fallback: Use global store (for environments where Symbol.for doesn't propagate)
|
|
44
|
+
let globalTags = globalThis.__pantheonSurrogateKeyTags;
|
|
45
|
+
if (!globalTags) {
|
|
46
|
+
globalTags = [];
|
|
47
|
+
globalThis.__pantheonSurrogateKeyTags = globalTags;
|
|
48
|
+
}
|
|
49
|
+
globalTags.push(...tags);
|
|
50
|
+
log.debug(`Captured ${tags.length} tags via globalStore fallback: ${tags.join(', ')}`);
|
|
51
|
+
return { captured: true, source: 'globalStore' };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* File-based cache handler for Next.js 16 'use cache' directive.
|
|
55
|
+
* Implements the cacheHandlers (plural) interface.
|
|
56
|
+
*
|
|
57
|
+
* Suitable for:
|
|
58
|
+
* - Local development
|
|
59
|
+
* - Single-instance deployments
|
|
60
|
+
* - Testing
|
|
61
|
+
*/
|
|
62
|
+
export class UseCacheFileHandler {
|
|
63
|
+
constructor(config = {}) {
|
|
64
|
+
this.tagTimestamps = new Map();
|
|
65
|
+
this.pathToSurrogateKeys = new Map();
|
|
66
|
+
this.cacheDir = config.cacheDir ?? path.join(process.cwd(), '.next', 'cache', 'use-cache');
|
|
67
|
+
this.tagsFile = path.join(this.cacheDir, '_tags.json');
|
|
68
|
+
this.ensureCacheDir();
|
|
69
|
+
this.loadTagTimestamps();
|
|
70
|
+
// Initialize edge cache clearer if OUTBOUND_PROXY_ENDPOINT is configured
|
|
71
|
+
this.edgeCacheClearer = createEdgeCacheClearer();
|
|
72
|
+
if (this.edgeCacheClearer) {
|
|
73
|
+
log.debug('Edge cache clearing enabled');
|
|
74
|
+
}
|
|
75
|
+
// Expose registerPathTags on globalThis for withSurrogateKey integration
|
|
76
|
+
globalThis[PATH_TAGS_REGISTRY_SYMBOL] =
|
|
77
|
+
(p, t) => this.registerPathTags(p, t);
|
|
78
|
+
log.debug('Initialized with cache dir:', this.cacheDir);
|
|
79
|
+
}
|
|
80
|
+
ensureCacheDir() {
|
|
81
|
+
try {
|
|
82
|
+
fs.mkdirSync(this.cacheDir, { recursive: true });
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error.code !== 'EEXIST') {
|
|
86
|
+
log.error('Error creating cache directory:', error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
loadTagTimestamps() {
|
|
91
|
+
try {
|
|
92
|
+
if (fs.existsSync(this.tagsFile)) {
|
|
93
|
+
const data = fs.readFileSync(this.tagsFile, 'utf-8');
|
|
94
|
+
const parsed = JSON.parse(data);
|
|
95
|
+
this.tagTimestamps = new Map(Object.entries(parsed));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
log.warn('Error loading tag timestamps:', error);
|
|
100
|
+
this.tagTimestamps = new Map();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
saveTagTimestamps() {
|
|
104
|
+
try {
|
|
105
|
+
const obj = Object.fromEntries(this.tagTimestamps);
|
|
106
|
+
fs.writeFileSync(this.tagsFile, JSON.stringify(obj, null, 2), 'utf-8');
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
log.error('Error saving tag timestamps:', error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
getCacheFilePath(cacheKey) {
|
|
113
|
+
// Sanitize cache key for filesystem
|
|
114
|
+
const safeKey = cacheKey.replace(/[^a-zA-Z0-9-]/g, '_');
|
|
115
|
+
return path.join(this.cacheDir, `${safeKey}.json`);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Check if an entry is expired based on revalidate time.
|
|
119
|
+
*/
|
|
120
|
+
isExpired(entry) {
|
|
121
|
+
const now = Date.now();
|
|
122
|
+
const age = now - entry.timestamp;
|
|
123
|
+
const revalidateMs = entry.revalidate * 1000;
|
|
124
|
+
// Entry is expired if it's older than revalidate time
|
|
125
|
+
if (age > revalidateMs) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
// Also check if any of the entry's tags have been invalidated
|
|
129
|
+
for (const tag of entry.tags) {
|
|
130
|
+
const tagTimestamp = this.tagTimestamps.get(tag);
|
|
131
|
+
if (tagTimestamp && tagTimestamp > entry.timestamp) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Retrieve a cache entry.
|
|
139
|
+
*/
|
|
140
|
+
async get(cacheKey, softTags) {
|
|
141
|
+
log.debug(`GET: ${cacheKey}`);
|
|
142
|
+
try {
|
|
143
|
+
const filePath = this.getCacheFilePath(cacheKey);
|
|
144
|
+
if (!fs.existsSync(filePath)) {
|
|
145
|
+
log.debug(`MISS: ${cacheKey} (not found)`);
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
const data = fs.readFileSync(filePath, 'utf-8');
|
|
149
|
+
const stored = JSON.parse(data);
|
|
150
|
+
const entry = deserializeUseCacheEntry(stored);
|
|
151
|
+
// Check expiration
|
|
152
|
+
if (this.isExpired(entry)) {
|
|
153
|
+
log.debug(`MISS: ${cacheKey} (expired)`);
|
|
154
|
+
// Optionally delete expired entry
|
|
155
|
+
try {
|
|
156
|
+
fs.unlinkSync(filePath);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// Ignore deletion errors
|
|
160
|
+
}
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
log.debug(`HIT: ${cacheKey}`);
|
|
164
|
+
// Capture tags for Surrogate-Key header propagation
|
|
165
|
+
// Uses Symbol.for pattern to access PantheonContext across async boundaries
|
|
166
|
+
const storedTags = entry.tags ?? [];
|
|
167
|
+
const { captured, source } = captureTags(storedTags);
|
|
168
|
+
if (captured) {
|
|
169
|
+
log.debug(`HIT ${cacheKey}: Captured ${storedTags.length} tags via ${source}`);
|
|
170
|
+
}
|
|
171
|
+
else if (storedTags.length === 0) {
|
|
172
|
+
// TODO: Remove this diagnostic logging once Next.js fixes the empty tags bug
|
|
173
|
+
// See: https://github.com/vercel/next.js/issues/78864
|
|
174
|
+
log.info(`HIT ${cacheKey}: No tags to capture (Next.js empty tags bug)`);
|
|
175
|
+
}
|
|
176
|
+
return entry;
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
log.error(`Error reading cache for key ${cacheKey}:`, error);
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Store a cache entry.
|
|
185
|
+
* CRITICAL: Must await pendingEntry before storing.
|
|
186
|
+
*/
|
|
187
|
+
async set(cacheKey, pendingEntry) {
|
|
188
|
+
log.debug(`SET: ${cacheKey}`);
|
|
189
|
+
try {
|
|
190
|
+
// CRITICAL: Await the pending entry
|
|
191
|
+
const entry = await pendingEntry;
|
|
192
|
+
// TODO: Remove this diagnostic logging once Next.js fixes the empty tags bug
|
|
193
|
+
// Diagnostic logging for empty tags issue
|
|
194
|
+
// See: https://github.com/vercel/next.js/issues/78864
|
|
195
|
+
// See: docs/known-issues-nextjs16.md
|
|
196
|
+
const tagsLength = entry.tags?.length ?? 0;
|
|
197
|
+
if (tagsLength === 0) {
|
|
198
|
+
// Use info level so this is gated behind CACHE_DEBUG
|
|
199
|
+
log.info(`[EMPTY_TAGS_BUG] SET ${cacheKey}: Next.js passed empty tags array. ` +
|
|
200
|
+
`This is a known Next.js bug - cacheTag() values are not propagated to cacheHandlers.set(). ` +
|
|
201
|
+
`See: https://github.com/vercel/next.js/issues/78864`);
|
|
202
|
+
}
|
|
203
|
+
log.info(`SET entry structure for ${cacheKey}:`, {
|
|
204
|
+
hasTags: !!entry.tags,
|
|
205
|
+
tags: entry.tags,
|
|
206
|
+
tagsLength,
|
|
207
|
+
stale: entry.stale,
|
|
208
|
+
revalidate: entry.revalidate,
|
|
209
|
+
expire: entry.expire,
|
|
210
|
+
timestamp: entry.timestamp,
|
|
211
|
+
hasValue: !!entry.value,
|
|
212
|
+
entryKeys: Object.keys(entry),
|
|
213
|
+
});
|
|
214
|
+
const serialized = await serializeUseCacheEntry(entry);
|
|
215
|
+
const filePath = this.getCacheFilePath(cacheKey);
|
|
216
|
+
fs.writeFileSync(filePath, JSON.stringify(serialized, null, 2), 'utf-8');
|
|
217
|
+
log.debug(`Cached ${cacheKey}`);
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
log.error(`Error setting cache for key ${cacheKey}:`, error);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Synchronize tag state from external source.
|
|
225
|
+
* For file-based handler, this reloads from disk.
|
|
226
|
+
*/
|
|
227
|
+
async refreshTags() {
|
|
228
|
+
log.debug('REFRESH TAGS');
|
|
229
|
+
this.loadTagTimestamps();
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Return maximum revalidation timestamp for given tags.
|
|
233
|
+
*/
|
|
234
|
+
async getExpiration(tags) {
|
|
235
|
+
let maxTimestamp = 0;
|
|
236
|
+
for (const tag of tags) {
|
|
237
|
+
const timestamp = this.tagTimestamps.get(tag) ?? 0;
|
|
238
|
+
if (timestamp > maxTimestamp) {
|
|
239
|
+
maxTimestamp = timestamp;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
log.debug(`GET EXPIRATION for [${tags.join(', ')}]: ${maxTimestamp}`);
|
|
243
|
+
return maxTimestamp;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Register the surrogate keys associated with a path.
|
|
247
|
+
* Called by withSurrogateKey via globalThis Symbol.
|
|
248
|
+
*/
|
|
249
|
+
registerPathTags(path, surrogateKeys) {
|
|
250
|
+
this.pathToSurrogateKeys.set(path, surrogateKeys);
|
|
251
|
+
log.debug(`Registered path tags: ${path} → [${surrogateKeys.join(', ')}]`);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Invalidate cache entries with matching tags.
|
|
255
|
+
* Also triggers CDN edge cache clearing via Surrogate-Key if configured.
|
|
256
|
+
*/
|
|
257
|
+
async updateTags(tags, durations) {
|
|
258
|
+
log.debug(`UPDATE TAGS: [${tags.join(', ')}]`);
|
|
259
|
+
if (tags.length === 0) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const now = Date.now();
|
|
263
|
+
for (const tag of tags) {
|
|
264
|
+
this.tagTimestamps.set(tag, now);
|
|
265
|
+
}
|
|
266
|
+
this.saveTagTimestamps();
|
|
267
|
+
// Clear edge cache if configured
|
|
268
|
+
if (this.edgeCacheClearer) {
|
|
269
|
+
const explicitTags = [];
|
|
270
|
+
const pathTags = [];
|
|
271
|
+
for (const tag of tags) {
|
|
272
|
+
if (tag.startsWith(NEXTJS_PATH_TAG_PREFIX)) {
|
|
273
|
+
pathTags.push(tag);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
explicitTags.push(tag);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (explicitTags.length > 0) {
|
|
280
|
+
this.edgeCacheClearer.clearKeysInBackground(explicitTags, `use-cache tag invalidation: ${explicitTags.join(', ')}`);
|
|
281
|
+
}
|
|
282
|
+
if (pathTags.length > 0) {
|
|
283
|
+
const resolvedKeys = [];
|
|
284
|
+
const unresolvedPaths = [];
|
|
285
|
+
for (const pathTag of pathTags) {
|
|
286
|
+
const p = pathTag.substring(NEXTJS_PATH_TAG_PREFIX.length);
|
|
287
|
+
const surrogateKeys = this.pathToSurrogateKeys.get(p);
|
|
288
|
+
if (surrogateKeys && surrogateKeys.length > 0) {
|
|
289
|
+
resolvedKeys.push(...surrogateKeys);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
unresolvedPaths.push(p);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (resolvedKeys.length > 0) {
|
|
296
|
+
this.edgeCacheClearer.clearKeysInBackground(resolvedKeys, `path revalidation (resolved): ${resolvedKeys.join(', ')}`);
|
|
297
|
+
}
|
|
298
|
+
if (unresolvedPaths.length > 0) {
|
|
299
|
+
this.edgeCacheClearer.clearPathsInBackground(unresolvedPaths, `path revalidation (fallback): ${unresolvedPaths.join(', ')}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Get cache statistics for the use-cache entries.
|
|
306
|
+
* Returns information about all valid (non-expired) cache entries.
|
|
307
|
+
*/
|
|
308
|
+
async getStats() {
|
|
309
|
+
log.debug('GET STATS');
|
|
310
|
+
const entries = [];
|
|
311
|
+
const keys = [];
|
|
312
|
+
try {
|
|
313
|
+
if (!fs.existsSync(this.cacheDir)) {
|
|
314
|
+
return { size: 0, entries: [], keys: [] };
|
|
315
|
+
}
|
|
316
|
+
const files = fs.readdirSync(this.cacheDir);
|
|
317
|
+
for (const file of files) {
|
|
318
|
+
// Skip tags file and non-JSON files
|
|
319
|
+
if (file === '_tags.json' || !file.endsWith('.json')) {
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
try {
|
|
323
|
+
const filePath = path.join(this.cacheDir, file);
|
|
324
|
+
const data = fs.readFileSync(filePath, 'utf-8');
|
|
325
|
+
const stored = JSON.parse(data);
|
|
326
|
+
// Reconstruct the key from the filename (reverse of sanitization)
|
|
327
|
+
const key = file.replace('.json', '');
|
|
328
|
+
// Deserialize to check expiration
|
|
329
|
+
const entry = deserializeUseCacheEntry(stored);
|
|
330
|
+
// Skip expired entries
|
|
331
|
+
if (this.isExpired(entry)) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
// Get file stats for size
|
|
335
|
+
const fileStat = fs.statSync(filePath);
|
|
336
|
+
const entryInfo = {
|
|
337
|
+
key,
|
|
338
|
+
tags: stored.tags || [],
|
|
339
|
+
type: 'use-cache',
|
|
340
|
+
lastModified: new Date(entry.timestamp).toISOString(),
|
|
341
|
+
size: fileStat.size,
|
|
342
|
+
revalidate: entry.revalidate,
|
|
343
|
+
stale: entry.stale,
|
|
344
|
+
expire: entry.expire,
|
|
345
|
+
};
|
|
346
|
+
entries.push(entryInfo);
|
|
347
|
+
keys.push(key);
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
log.warn(`Error reading cache file ${file}:`, error);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
log.error('Error getting cache stats:', error);
|
|
356
|
+
}
|
|
357
|
+
log.debug(`Found ${entries.length} valid cache entries`);
|
|
358
|
+
return {
|
|
359
|
+
size: entries.length,
|
|
360
|
+
entries,
|
|
361
|
+
keys,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
export default UseCacheFileHandler;
|
|
366
|
+
//# sourceMappingURL=file-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-handler.js","sourceRoot":"","sources":["../../src/use-cache/file-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EACL,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAuB,MAAM,6BAA6B,CAAC;AAE1F,MAAM,GAAG,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;AAEhD;;GAEG;AACH,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;AAEzF;;;GAGG;AACH,MAAM,wBAAwB,GAAG,MAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;AAYjF;;;GAGG;AACH,SAAS,kBAAkB;IACzB,MAAM,QAAQ,GAAI,UAAsC,CAAC,wBAAwB,CAEpE,CAAC;IACd,OAAO,QAAQ,EAAE,GAAG,EAAE,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAC,IAAc;IACjC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC7C,CAAC;IAED,oDAAoD;IACpD,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3B,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,MAAM,8BAA8B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACvD,CAAC;IAED,mFAAmF;IACnF,IAAI,UAAU,GAAI,UAAsC,CAAC,0BAE5C,CAAC;IACd,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,UAAU,GAAG,EAAE,CAAC;QACf,UAAsC,CAAC,0BAA0B,GAAG,UAAU,CAAC;IAClF,CAAC;IACD,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,MAAM,mCAAmC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AACnD,CAAC;AAaD;;;;;;;;GAQG;AACH,MAAM,OAAO,mBAAmB;IAO9B,YAAY,SAAoC,EAAE;QAJ1C,kBAAa,GAAwB,IAAI,GAAG,EAAE,CAAC;QAC/C,wBAAmB,GAA0B,IAAI,GAAG,EAAE,CAAC;QAI7D,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QAC3F,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAEvD,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,yEAAyE;QACzE,IAAI,CAAC,gBAAgB,GAAG,sBAAsB,EAAE,CAAC;QACjD,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,GAAG,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC3C,CAAC;QAED,yEAAyE;QACxE,UAAsC,CAAC,yBAAyB,CAAC;YAChE,CAAC,CAAS,EAAE,CAAW,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAE1D,GAAG,CAAC,KAAK,CAAC,6BAA6B,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACvD,GAAG,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;IACH,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjC,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACrD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAChC,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,IAAI,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;YACjD,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,EAAE,CAAC;QACjC,CAAC;IACH,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACnD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,QAAgB;QACvC,oCAAoC;QACpC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACK,SAAS,CAAC,KAAoB;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC;QAClC,MAAM,YAAY,GAAG,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;QAE7C,sDAAsD;QACtD,IAAI,GAAG,GAAG,YAAY,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,8DAA8D;QAC9D,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjD,IAAI,YAAY,IAAI,YAAY,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;gBACnD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,QAAgB,EAAE,QAAkB;QAC5C,GAAG,CAAC,KAAK,CAAC,QAAQ,QAAQ,EAAE,CAAC,CAAC;QAE9B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAEjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC7B,GAAG,CAAC,KAAK,CAAC,SAAS,QAAQ,cAAc,CAAC,CAAC;gBAC3C,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,KAAK,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;YAE/C,mBAAmB;YACnB,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1B,GAAG,CAAC,KAAK,CAAC,SAAS,QAAQ,YAAY,CAAC,CAAC;gBACzC,kCAAkC;gBAClC,IAAI,CAAC;oBACH,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBAC1B,CAAC;gBAAC,MAAM,CAAC;oBACP,yBAAyB;gBAC3B,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,GAAG,CAAC,KAAK,CAAC,QAAQ,QAAQ,EAAE,CAAC,CAAC;YAE9B,oDAAoD;YACpD,4EAA4E;YAC5E,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;YACpC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;YAErD,IAAI,QAAQ,EAAE,CAAC;gBACb,GAAG,CAAC,KAAK,CAAC,OAAO,QAAQ,cAAc,UAAU,CAAC,MAAM,aAAa,MAAM,EAAE,CAAC,CAAC;YACjF,CAAC;iBAAM,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,6EAA6E;gBAC7E,sDAAsD;gBACtD,GAAG,CAAC,IAAI,CAAC,OAAO,QAAQ,+CAA+C,CAAC,CAAC;YAC3E,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,KAAK,CAAC,+BAA+B,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;YAC7D,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAG,CAAC,QAAgB,EAAE,YAAoC;QAC9D,GAAG,CAAC,KAAK,CAAC,QAAQ,QAAQ,EAAE,CAAC,CAAC;QAE9B,IAAI,CAAC;YACH,oCAAoC;YACpC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC;YAEjC,6EAA6E;YAC7E,0CAA0C;YAC1C,sDAAsD;YACtD,qCAAqC;YACrC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC;YAC3C,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;gBACrB,qDAAqD;gBACrD,GAAG,CAAC,IAAI,CAAC,wBAAwB,QAAQ,qCAAqC;oBAC5E,6FAA6F;oBAC7F,qDAAqD,CAAC,CAAC;YAC3D,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,2BAA2B,QAAQ,GAAG,EAAE;gBAC/C,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI;gBACrB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,UAAU;gBACV,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK;gBACvB,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;aAC9B,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;YACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAEjD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEzE,GAAG,CAAC,KAAK,CAAC,UAAU,QAAQ,EAAE,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,KAAK,CAAC,+BAA+B,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW;QACf,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC1B,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,IAAc;QAChC,IAAI,YAAY,GAAG,CAAC,CAAC;QAErB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACnD,IAAI,SAAS,GAAG,YAAY,EAAE,CAAC;gBAC7B,YAAY,GAAG,SAAS,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,GAAG,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,YAAY,EAAE,CAAC,CAAC;QACtE,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;;OAGG;IACH,gBAAgB,CAAC,IAAY,EAAE,aAAuB;QACpD,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QAClD,GAAG,CAAC,KAAK,CAAC,yBAAyB,IAAI,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7E,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,IAAc,EAAE,SAAmB;QAClD,GAAG,CAAC,KAAK,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAE/C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,iCAAiC;QACjC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAa,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAa,EAAE,CAAC;YAE9B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,IAAI,GAAG,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;oBAC3C,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrB,CAAC;qBAAM,CAAC;oBACN,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;YAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,YAAY,EAAE,+BAA+B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtH,CAAC;YAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,YAAY,GAAa,EAAE,CAAC;gBAClC,MAAM,eAAe,GAAa,EAAE,CAAC;gBAErC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;oBAC3D,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBAEtD,IAAI,aAAa,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC9C,YAAY,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;oBACtC,CAAC;yBAAM,CAAC;wBACN,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBAC1B,CAAC;gBACH,CAAC;gBAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5B,IAAI,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,YAAY,EAAE,iCAAiC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACxH,CAAC;gBAED,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC/B,IAAI,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,eAAe,EAAE,iCAAiC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC/H,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,QAAQ;QACZ,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAEvB,MAAM,OAAO,GAAwB,EAAE,CAAC;QACxC,MAAM,IAAI,GAAa,EAAE,CAAC;QAE1B,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClC,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;YAC5C,CAAC;YAED,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAE5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,oCAAoC;gBACpC,IAAI,IAAI,KAAK,YAAY,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBACrD,SAAS;gBACX,CAAC;gBAED,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;oBAChD,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;oBAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAEhC,kEAAkE;oBAClE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;oBAEtC,kCAAkC;oBAClC,MAAM,KAAK,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;oBAE/C,uBAAuB;oBACvB,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC1B,SAAS;oBACX,CAAC;oBAED,0BAA0B;oBAC1B,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBAEvC,MAAM,SAAS,GAAsB;wBACnC,GAAG;wBACH,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;wBACvB,IAAI,EAAE,WAAW;wBACjB,YAAY,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE;wBACrD,IAAI,EAAE,QAAQ,CAAC,IAAI;wBACnB,UAAU,EAAE,KAAK,CAAC,UAAU;wBAC5B,KAAK,EAAE,KAAK,CAAC,KAAK;wBAClB,MAAM,EAAE,KAAK,CAAC,MAAM;qBACrB,CAAC;oBAEF,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACxB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACjB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,GAAG,CAAC,IAAI,CAAC,4BAA4B,IAAI,GAAG,EAAE,KAAK,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC;QAED,GAAG,CAAC,KAAK,CAAC,SAAS,OAAO,CAAC,MAAM,sBAAsB,CAAC,CAAC;QAEzD,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,MAAM;YACpB,OAAO;YACP,IAAI;SACL,CAAC;IACJ,CAAC;CACF;AAED,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { UseCacheEntry, UseCacheHandler, UseCacheStats } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Google Cloud Storage cache handler for Next.js 16 'use cache' directive.
|
|
4
|
+
* Implements the cacheHandlers (plural) interface.
|
|
5
|
+
*
|
|
6
|
+
* Suitable for:
|
|
7
|
+
* - Production/Pantheon environments
|
|
8
|
+
* - Multi-instance deployments requiring shared cache
|
|
9
|
+
*/
|
|
10
|
+
export declare class UseCacheGcsHandler implements UseCacheHandler {
|
|
11
|
+
private readonly bucket;
|
|
12
|
+
private readonly cachePrefix;
|
|
13
|
+
private readonly tagsKey;
|
|
14
|
+
private readonly edgeCacheClearer;
|
|
15
|
+
private tagTimestamps;
|
|
16
|
+
private pathToSurrogateKeys;
|
|
17
|
+
private initialized;
|
|
18
|
+
private initPromise;
|
|
19
|
+
constructor();
|
|
20
|
+
private initialize;
|
|
21
|
+
private ensureInitialized;
|
|
22
|
+
private loadTagTimestamps;
|
|
23
|
+
private saveTagTimestamps;
|
|
24
|
+
private getCacheKey;
|
|
25
|
+
/**
|
|
26
|
+
* Check if an entry is expired based on revalidate time.
|
|
27
|
+
*/
|
|
28
|
+
private isExpired;
|
|
29
|
+
/**
|
|
30
|
+
* Retrieve a cache entry.
|
|
31
|
+
*/
|
|
32
|
+
get(cacheKey: string, softTags: string[]): Promise<UseCacheEntry | undefined>;
|
|
33
|
+
/**
|
|
34
|
+
* Store a cache entry.
|
|
35
|
+
* CRITICAL: Must await pendingEntry before storing.
|
|
36
|
+
*/
|
|
37
|
+
set(cacheKey: string, pendingEntry: Promise<UseCacheEntry>): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Synchronize tag state from external source.
|
|
40
|
+
* Reloads tag timestamps from GCS.
|
|
41
|
+
*/
|
|
42
|
+
refreshTags(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Return maximum revalidation timestamp for given tags.
|
|
45
|
+
*/
|
|
46
|
+
getExpiration(tags: string[]): Promise<number>;
|
|
47
|
+
/**
|
|
48
|
+
* Register the surrogate keys (explicit cacheTag values) associated with a path.
|
|
49
|
+
* Called by withSurrogateKey when tags are captured during a cache HIT,
|
|
50
|
+
* enabling revalidatePath to resolve the correct CDN surrogate keys.
|
|
51
|
+
*/
|
|
52
|
+
registerPathTags(path: string, surrogateKeys: string[]): void;
|
|
53
|
+
/**
|
|
54
|
+
* Invalidate cache entries with matching tags.
|
|
55
|
+
*/
|
|
56
|
+
updateTags(tags: string[], durations: number[]): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Get cache statistics for the use-cache entries in GCS.
|
|
59
|
+
* Returns information about all valid (non-expired) cache entries.
|
|
60
|
+
*/
|
|
61
|
+
getStats(): Promise<UseCacheStats>;
|
|
62
|
+
}
|
|
63
|
+
export default UseCacheGcsHandler;
|
|
64
|
+
//# sourceMappingURL=gcs-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gcs-handler.d.ts","sourceRoot":"","sources":["../../src/use-cache/gcs-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAqB,MAAM,YAAY,CAAC;AAiFnG;;;;;;;GAOG;AACH,qBAAa,kBAAmB,YAAW,eAAe;IACxD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAwB;IACzD,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,WAAW,CAA8B;;YA2BnC,UAAU;YAMV,iBAAiB;YAOjB,iBAAiB;YA6BjB,iBAAiB;IAY/B,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACH,OAAO,CAAC,SAAS;IAqBjB;;OAEG;IACG,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAmDnF;;;OAGG;IACG,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA4ChF;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAKlC;;OAEG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAcpD;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI;IAK7D;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAiEpE;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,aAAa,CAAC;CAsEzC;AAED,eAAe,kBAAkB,CAAC"}
|