@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,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":"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"}
@@ -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"}