@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.
- package/README.md +256 -0
- package/dist/edge/edge-cache-clear.d.ts +64 -0
- package/dist/edge/edge-cache-clear.d.ts.map +1 -0
- package/dist/edge/edge-cache-clear.js +245 -0
- package/dist/edge/edge-cache-clear.js.map +1 -0
- package/dist/handlers/base.d.ts +69 -0
- package/dist/handlers/base.d.ts.map +1 -0
- package/dist/handlers/base.js +278 -0
- package/dist/handlers/base.js.map +1 -0
- package/dist/handlers/file.d.ts +62 -0
- package/dist/handlers/file.d.ts.map +1 -0
- package/dist/handlers/file.js +332 -0
- package/dist/handlers/file.js.map +1 -0
- package/dist/handlers/gcs.d.ts +66 -0
- package/dist/handlers/gcs.d.ts.map +1 -0
- package/dist/handlers/gcs.js +407 -0
- package/dist/handlers/gcs.js.map +1 -0
- package/dist/handlers/index.d.ts +4 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +4 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +119 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/build-detection.d.ts +10 -0
- package/dist/utils/build-detection.d.ts.map +1 -0
- package/dist/utils/build-detection.js +57 -0
- package/dist/utils/build-detection.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +34 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +54 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/serialization.d.ts +12 -0
- package/dist/utils/serialization.d.ts.map +1 -0
- package/dist/utils/serialization.js +137 -0
- package/dist/utils/serialization.js.map +1 -0
- package/dist/utils/static-routes.d.ts +7 -0
- package/dist/utils/static-routes.d.ts.map +1 -0
- package/dist/utils/static-routes.js +52 -0
- package/dist/utils/static-routes.js.map +1 -0
- package/dist/utils/tags-buffer.d.ts +63 -0
- package/dist/utils/tags-buffer.d.ts.map +1 -0
- package/dist/utils/tags-buffer.js +181 -0
- package/dist/utils/tags-buffer.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { serializeForStorage, deserializeFromStorage } from '../utils/serialization.js';
|
|
2
|
+
import { getBuildId, isBuildPhase } from '../utils/build-detection.js';
|
|
3
|
+
import { createLogger } from '../utils/logger.js';
|
|
4
|
+
// Global singleton to track if build invalidation has been checked for this process
|
|
5
|
+
let buildInvalidationChecked = false;
|
|
6
|
+
/**
|
|
7
|
+
* Reset the build invalidation check flag.
|
|
8
|
+
* Useful for testing purposes.
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export function resetBuildInvalidationCheck() {
|
|
12
|
+
buildInvalidationChecked = false;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Abstract base class for cache handlers.
|
|
16
|
+
* Provides shared functionality for tag mapping, serialization, and build invalidation.
|
|
17
|
+
*/
|
|
18
|
+
export class BaseCacheHandler {
|
|
19
|
+
constructor(context, handlerName) {
|
|
20
|
+
this.context = context;
|
|
21
|
+
this.handlerName = handlerName;
|
|
22
|
+
this.log = createLogger(handlerName);
|
|
23
|
+
// Only log during server runtime, not during build (too noisy with parallel workers)
|
|
24
|
+
if (!isBuildPhase()) {
|
|
25
|
+
this.log.info('Initializing cache handler');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Initialize the handler. Should be called after construction.
|
|
30
|
+
* Handles build invalidation check and tags mapping initialization.
|
|
31
|
+
*/
|
|
32
|
+
async initialize() {
|
|
33
|
+
await this.initializeTagsMapping();
|
|
34
|
+
// Only check build invalidation once per process
|
|
35
|
+
// Skip during build phase to avoid race conditions with parallel workers
|
|
36
|
+
if (!buildInvalidationChecked && !isBuildPhase()) {
|
|
37
|
+
await this.checkBuildInvalidation();
|
|
38
|
+
buildInvalidationChecked = true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// Shared tag mapping methods
|
|
43
|
+
// ============================================================================
|
|
44
|
+
async updateTagsMapping(cacheKey, tags, isDelete = false) {
|
|
45
|
+
try {
|
|
46
|
+
const tagsMapping = await this.readTagsMapping();
|
|
47
|
+
if (isDelete) {
|
|
48
|
+
this.removeKeysFromAllTags(tagsMapping, [cacheKey]);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.addKeyToTags(tagsMapping, cacheKey, tags);
|
|
52
|
+
}
|
|
53
|
+
await this.writeTagsMapping(tagsMapping);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
this.log.error('Error updating tags mapping:', error);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async updateTagsMappingBulkDelete(cacheKeysToDelete, tagsMapping) {
|
|
60
|
+
try {
|
|
61
|
+
this.removeKeysFromAllTags(tagsMapping, cacheKeysToDelete);
|
|
62
|
+
await this.writeTagsMapping(tagsMapping);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
this.log.error('Error bulk updating tags mapping:', error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Removes cache keys from all tag mappings they're associated with.
|
|
70
|
+
* This is used when cache entries are deleted to keep the tag mapping consistent.
|
|
71
|
+
* Empty tags are cleaned up automatically.
|
|
72
|
+
*/
|
|
73
|
+
removeKeysFromAllTags(tagsMapping, keysToRemove) {
|
|
74
|
+
const keysSet = new Set(keysToRemove);
|
|
75
|
+
for (const tag of Object.keys(tagsMapping)) {
|
|
76
|
+
tagsMapping[tag] = tagsMapping[tag].filter((key) => !keysSet.has(key));
|
|
77
|
+
if (tagsMapping[tag].length === 0) {
|
|
78
|
+
delete tagsMapping[tag];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
addKeyToTags(tagsMapping, cacheKey, tags) {
|
|
83
|
+
for (const tag of tags) {
|
|
84
|
+
if (!tagsMapping[tag]) {
|
|
85
|
+
tagsMapping[tag] = [];
|
|
86
|
+
}
|
|
87
|
+
if (!tagsMapping[tag].includes(cacheKey)) {
|
|
88
|
+
tagsMapping[tag].push(cacheKey);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// ============================================================================
|
|
93
|
+
// Build invalidation
|
|
94
|
+
// ============================================================================
|
|
95
|
+
async checkBuildInvalidation() {
|
|
96
|
+
const currentBuildId = getBuildId();
|
|
97
|
+
try {
|
|
98
|
+
const buildMeta = await this.readBuildMeta();
|
|
99
|
+
if (buildMeta.buildId !== currentBuildId) {
|
|
100
|
+
this.log.info(`New build detected (${buildMeta.buildId} -> ${currentBuildId}), invalidating route cache`);
|
|
101
|
+
await this.invalidateRouteCache();
|
|
102
|
+
await this.writeBuildMeta({
|
|
103
|
+
buildId: currentBuildId,
|
|
104
|
+
timestamp: Date.now(),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// No previous build metadata - first run, just save current build ID
|
|
110
|
+
await this.writeBuildMeta({
|
|
111
|
+
buildId: currentBuildId,
|
|
112
|
+
timestamp: Date.now(),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// ============================================================================
|
|
117
|
+
// Serialization helpers
|
|
118
|
+
// ============================================================================
|
|
119
|
+
serializeForStorage(data) {
|
|
120
|
+
return serializeForStorage(data);
|
|
121
|
+
}
|
|
122
|
+
deserializeFromStorage(data) {
|
|
123
|
+
return deserializeFromStorage(data);
|
|
124
|
+
}
|
|
125
|
+
// ============================================================================
|
|
126
|
+
// Cache type determination
|
|
127
|
+
// ============================================================================
|
|
128
|
+
determineCacheType(ctx) {
|
|
129
|
+
if (!ctx) {
|
|
130
|
+
return 'route';
|
|
131
|
+
}
|
|
132
|
+
if ('fetchCache' in ctx && ctx.fetchCache === true) {
|
|
133
|
+
return 'fetch';
|
|
134
|
+
}
|
|
135
|
+
if ('fetchUrl' in ctx) {
|
|
136
|
+
return 'fetch';
|
|
137
|
+
}
|
|
138
|
+
if ('fetchIdx' in ctx) {
|
|
139
|
+
return 'fetch';
|
|
140
|
+
}
|
|
141
|
+
return 'route';
|
|
142
|
+
}
|
|
143
|
+
determineCacheTypeFromValue(incrementalCacheValue) {
|
|
144
|
+
if (incrementalCacheValue &&
|
|
145
|
+
typeof incrementalCacheValue === 'object' &&
|
|
146
|
+
'kind' in incrementalCacheValue &&
|
|
147
|
+
incrementalCacheValue.kind === 'FETCH') {
|
|
148
|
+
return 'fetch';
|
|
149
|
+
}
|
|
150
|
+
return 'route';
|
|
151
|
+
}
|
|
152
|
+
// ============================================================================
|
|
153
|
+
// CacheHandler interface implementation
|
|
154
|
+
// ============================================================================
|
|
155
|
+
async get(cacheKey, ctx) {
|
|
156
|
+
this.log.debug(`GET: ${cacheKey}`);
|
|
157
|
+
try {
|
|
158
|
+
const cacheType = this.determineCacheType(ctx);
|
|
159
|
+
const entry = await this.readCacheEntry(cacheKey, cacheType);
|
|
160
|
+
if (!entry) {
|
|
161
|
+
this.log.debug(`MISS: ${cacheKey} (${cacheType})`);
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
this.log.debug(`HIT: ${cacheKey} (${cacheType})`, {
|
|
165
|
+
entryType: typeof entry,
|
|
166
|
+
hasValue: entry && typeof entry === 'object' && 'value' in entry,
|
|
167
|
+
});
|
|
168
|
+
return entry;
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
this.log.error(`Error reading cache for key ${cacheKey}:`, error);
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async set(cacheKey, incrementalCacheValue, ctx) {
|
|
176
|
+
const cacheType = this.determineCacheTypeFromValue(incrementalCacheValue);
|
|
177
|
+
this.log.debug(`SET: ${cacheKey} (${cacheType})`, {
|
|
178
|
+
valueType: typeof incrementalCacheValue,
|
|
179
|
+
hasKind: incrementalCacheValue && typeof incrementalCacheValue === 'object' && 'kind' in incrementalCacheValue,
|
|
180
|
+
});
|
|
181
|
+
try {
|
|
182
|
+
const { tags = [] } = ctx;
|
|
183
|
+
const cacheHandlerValue = {
|
|
184
|
+
value: incrementalCacheValue,
|
|
185
|
+
lastModified: Date.now(),
|
|
186
|
+
tags: Object.freeze(tags),
|
|
187
|
+
};
|
|
188
|
+
await this.writeCacheEntry(cacheKey, cacheHandlerValue, cacheType);
|
|
189
|
+
if (tags.length > 0) {
|
|
190
|
+
await this.updateTagsMapping(cacheKey, tags);
|
|
191
|
+
this.log.debug(`Updated tags mapping for ${cacheKey} with tags:`, tags);
|
|
192
|
+
}
|
|
193
|
+
// For route cache updates (ISR), trigger edge cache invalidation
|
|
194
|
+
if (cacheType === 'route') {
|
|
195
|
+
this.onRouteCacheSet(cacheKey);
|
|
196
|
+
}
|
|
197
|
+
this.log.debug(`Cached ${cacheKey} in ${cacheType} cache`);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
this.log.error(`Error setting cache for key ${cacheKey}:`, error);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
async revalidateTag(tag) {
|
|
204
|
+
this.log.debug(`REVALIDATE TAG: ${tag}`);
|
|
205
|
+
const tagArray = [tag].flat();
|
|
206
|
+
const deletedKeys = [];
|
|
207
|
+
let tagsMapping;
|
|
208
|
+
try {
|
|
209
|
+
tagsMapping = await this.readTagsMapping();
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
this.log.error('Error reading tags mapping during revalidateTag:', error);
|
|
213
|
+
tagsMapping = {};
|
|
214
|
+
}
|
|
215
|
+
for (const currentTag of tagArray) {
|
|
216
|
+
const cacheKeysForTag = tagsMapping[currentTag] || [];
|
|
217
|
+
if (cacheKeysForTag.length === 0) {
|
|
218
|
+
this.log.debug(`No cache entries found for tag: ${currentTag}`);
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
this.log.debug(`Found ${cacheKeysForTag.length} cache entries for tag: ${currentTag}`);
|
|
222
|
+
for (const cacheKey of cacheKeysForTag) {
|
|
223
|
+
const deleted = await this.tryDeleteCacheEntry(cacheKey);
|
|
224
|
+
if (deleted) {
|
|
225
|
+
deletedKeys.push(cacheKey);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (deletedKeys.length > 0) {
|
|
230
|
+
await this.updateTagsMappingBulkDelete(deletedKeys, tagsMapping);
|
|
231
|
+
this.log.debug(`Updated tags mapping after deleting ${deletedKeys.length} entries`);
|
|
232
|
+
}
|
|
233
|
+
this.log.info(`Revalidated ${deletedKeys.length} entries for tags: ${tagArray.join(', ')}`);
|
|
234
|
+
// Hook for subclasses to perform additional cleanup (e.g., edge cache clearing)
|
|
235
|
+
await this.onRevalidateComplete(tagArray, deletedKeys);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Hook called after revalidation is complete.
|
|
239
|
+
* Subclasses can override to perform additional cleanup.
|
|
240
|
+
*/
|
|
241
|
+
async onRevalidateComplete(_tags, _deletedKeys) {
|
|
242
|
+
// Default implementation does nothing
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Hook called when a route cache entry is set (ISR page update).
|
|
246
|
+
* Subclasses can override to perform edge cache invalidation.
|
|
247
|
+
*/
|
|
248
|
+
onRouteCacheSet(_cacheKey) {
|
|
249
|
+
// Default implementation does nothing
|
|
250
|
+
}
|
|
251
|
+
async tryDeleteCacheEntry(cacheKey) {
|
|
252
|
+
// Try fetch cache first
|
|
253
|
+
try {
|
|
254
|
+
await this.deleteCacheEntry(cacheKey, 'fetch');
|
|
255
|
+
this.log.debug(`Deleted fetch cache entry: ${cacheKey}`);
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
// Entry might not exist in fetch cache
|
|
260
|
+
}
|
|
261
|
+
// Try route cache
|
|
262
|
+
try {
|
|
263
|
+
await this.deleteCacheEntry(cacheKey, 'route');
|
|
264
|
+
this.log.debug(`Deleted route cache entry: ${cacheKey}`);
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
this.log.warn(`Cache entry not found in either cache: ${cacheKey}`);
|
|
269
|
+
}
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
resetRequestCache() {
|
|
273
|
+
this.log.debug('RESET REQUEST CACHE: No-op for this cache handler');
|
|
274
|
+
// For persistent cache handlers, this is typically a no-op since we're not maintaining
|
|
275
|
+
// per-request caches. The storage backend is the source of truth.
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/handlers/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { CacheStats, CacheHandlerValue, FileSystemCacheContext } from '../types.js';
|
|
2
|
+
import { BaseCacheHandler, type BuildMeta } from './base.js';
|
|
3
|
+
/**
|
|
4
|
+
* File-based cache handler for local development.
|
|
5
|
+
* Stores cache entries in the .next/cache directory.
|
|
6
|
+
*/
|
|
7
|
+
export declare class FileCacheHandler extends BaseCacheHandler {
|
|
8
|
+
private readonly baseDir;
|
|
9
|
+
private readonly fetchCacheDir;
|
|
10
|
+
private readonly routeCacheDir;
|
|
11
|
+
private readonly buildMetaFile;
|
|
12
|
+
private readonly tagsDir;
|
|
13
|
+
private readonly tagsMapFile;
|
|
14
|
+
private readonly tagsBuffer;
|
|
15
|
+
constructor(context: FileSystemCacheContext);
|
|
16
|
+
private ensureCacheDir;
|
|
17
|
+
protected initializeTagsMapping(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Read tags mapping, flushing any pending updates first to ensure accuracy.
|
|
20
|
+
*/
|
|
21
|
+
protected readTagsMapping(): Promise<Record<string, string[]>>;
|
|
22
|
+
/**
|
|
23
|
+
* Direct read from file system without flushing buffer.
|
|
24
|
+
* Used internally by the buffer.
|
|
25
|
+
*/
|
|
26
|
+
private readTagsMappingDirect;
|
|
27
|
+
/**
|
|
28
|
+
* Write tags mapping directly to file system.
|
|
29
|
+
* Used by the buffer for batched writes.
|
|
30
|
+
*/
|
|
31
|
+
protected writeTagsMapping(tagsMapping: Record<string, string[]>): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Direct write to file system (sync).
|
|
34
|
+
* Used internally by the buffer.
|
|
35
|
+
*/
|
|
36
|
+
private writeTagsMappingDirect;
|
|
37
|
+
/**
|
|
38
|
+
* Override to use buffered updates instead of immediate writes.
|
|
39
|
+
*/
|
|
40
|
+
protected updateTagsMapping(cacheKey: string, tags: string[], isDelete?: boolean): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Override to use buffered deletes instead of immediate writes.
|
|
43
|
+
*/
|
|
44
|
+
protected updateTagsMappingBulkDelete(cacheKeysToDelete: string[], _tagsMapping: Record<string, string[]>): Promise<void>;
|
|
45
|
+
private getCacheFilePath;
|
|
46
|
+
protected readCacheEntry(cacheKey: string, cacheType: 'fetch' | 'route'): Promise<CacheHandlerValue | null>;
|
|
47
|
+
protected writeCacheEntry(cacheKey: string, cacheValue: CacheHandlerValue, cacheType: 'fetch' | 'route'): Promise<void>;
|
|
48
|
+
protected deleteCacheEntry(cacheKey: string, cacheType: 'fetch' | 'route'): Promise<void>;
|
|
49
|
+
protected readBuildMeta(): Promise<BuildMeta>;
|
|
50
|
+
protected writeBuildMeta(meta: BuildMeta): Promise<void>;
|
|
51
|
+
protected invalidateRouteCache(): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get cache statistics for the file-based cache.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getSharedCacheStats(): Promise<CacheStats>;
|
|
57
|
+
/**
|
|
58
|
+
* Clear all cache entries for the file-based cache.
|
|
59
|
+
*/
|
|
60
|
+
export declare function clearSharedCache(): Promise<number>;
|
|
61
|
+
export default FileCacheHandler;
|
|
62
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/handlers/file.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,UAAU,EAEV,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAW7D;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,gBAAgB;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;gBAE5B,OAAO,EAAE,sBAAsB;IA2B3C,OAAO,CAAC,cAAc;cAgBN,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAUtD;;OAEG;cACa,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAMpE;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAa7B;;;OAGG;cACa,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAItF;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAS9B;;OAEG;cACsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7G;;OAEG;cACsB,2BAA2B,CAClD,iBAAiB,EAAE,MAAM,EAAE,EAC3B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC;IAUhB,OAAO,CAAC,gBAAgB;cAMR,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;cAWjG,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,iBAAiB,EAC7B,SAAS,EAAE,OAAO,GAAG,OAAO,GAC3B,OAAO,CAAC,IAAI,CAAC;cAWA,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;cAgB/E,aAAa,IAAI,OAAO,CAAC,SAAS,CAAC;cAKnC,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;cAM9C,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;CAQtD;AAMD;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,UAAU,CAAC,CAsB/D;AAmDD;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CA2BxD;AA+DD,eAAe,gBAAgB,CAAC"}
|