@danielsimonjr/memoryjs 1.0.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/LICENSE +22 -0
- package/README.md +266 -0
- package/dist/core/EntityManager.d.ts +268 -0
- package/dist/core/EntityManager.d.ts.map +1 -0
- package/dist/core/EntityManager.js +512 -0
- package/dist/core/EntityManager.js.map +1 -0
- package/dist/core/GraphEventEmitter.d.ts +202 -0
- package/dist/core/GraphEventEmitter.d.ts.map +1 -0
- package/dist/core/GraphEventEmitter.js +347 -0
- package/dist/core/GraphEventEmitter.js.map +1 -0
- package/dist/core/GraphStorage.d.ts +395 -0
- package/dist/core/GraphStorage.d.ts.map +1 -0
- package/dist/core/GraphStorage.js +786 -0
- package/dist/core/GraphStorage.js.map +1 -0
- package/dist/core/GraphTraversal.d.ts +141 -0
- package/dist/core/GraphTraversal.d.ts.map +1 -0
- package/dist/core/GraphTraversal.js +574 -0
- package/dist/core/GraphTraversal.js.map +1 -0
- package/dist/core/HierarchyManager.d.ts +111 -0
- package/dist/core/HierarchyManager.d.ts.map +1 -0
- package/dist/core/HierarchyManager.js +225 -0
- package/dist/core/HierarchyManager.js.map +1 -0
- package/dist/core/ManagerContext.d.ts +76 -0
- package/dist/core/ManagerContext.d.ts.map +1 -0
- package/dist/core/ManagerContext.js +129 -0
- package/dist/core/ManagerContext.js.map +1 -0
- package/dist/core/ObservationManager.d.ts +85 -0
- package/dist/core/ObservationManager.d.ts.map +1 -0
- package/dist/core/ObservationManager.js +124 -0
- package/dist/core/ObservationManager.js.map +1 -0
- package/dist/core/RelationManager.d.ts +131 -0
- package/dist/core/RelationManager.d.ts.map +1 -0
- package/dist/core/RelationManager.js +212 -0
- package/dist/core/RelationManager.js.map +1 -0
- package/dist/core/SQLiteStorage.d.ts +354 -0
- package/dist/core/SQLiteStorage.d.ts.map +1 -0
- package/dist/core/SQLiteStorage.js +919 -0
- package/dist/core/SQLiteStorage.js.map +1 -0
- package/dist/core/StorageFactory.d.ts +45 -0
- package/dist/core/StorageFactory.d.ts.map +1 -0
- package/dist/core/StorageFactory.js +65 -0
- package/dist/core/StorageFactory.js.map +1 -0
- package/dist/core/TransactionManager.d.ts +464 -0
- package/dist/core/TransactionManager.d.ts.map +1 -0
- package/dist/core/TransactionManager.js +869 -0
- package/dist/core/TransactionManager.js.map +1 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +20 -0
- package/dist/core/index.js.map +1 -0
- package/dist/features/AnalyticsManager.d.ts +44 -0
- package/dist/features/AnalyticsManager.d.ts.map +1 -0
- package/dist/features/AnalyticsManager.js +224 -0
- package/dist/features/AnalyticsManager.js.map +1 -0
- package/dist/features/ArchiveManager.d.ts +133 -0
- package/dist/features/ArchiveManager.d.ts.map +1 -0
- package/dist/features/ArchiveManager.js +282 -0
- package/dist/features/ArchiveManager.js.map +1 -0
- package/dist/features/CompressionManager.d.ts +119 -0
- package/dist/features/CompressionManager.d.ts.map +1 -0
- package/dist/features/CompressionManager.js +470 -0
- package/dist/features/CompressionManager.js.map +1 -0
- package/dist/features/IOManager.d.ts +225 -0
- package/dist/features/IOManager.d.ts.map +1 -0
- package/dist/features/IOManager.js +1093 -0
- package/dist/features/IOManager.js.map +1 -0
- package/dist/features/KeywordExtractor.d.ts +61 -0
- package/dist/features/KeywordExtractor.d.ts.map +1 -0
- package/dist/features/KeywordExtractor.js +127 -0
- package/dist/features/KeywordExtractor.js.map +1 -0
- package/dist/features/ObservationNormalizer.d.ts +90 -0
- package/dist/features/ObservationNormalizer.d.ts.map +1 -0
- package/dist/features/ObservationNormalizer.js +194 -0
- package/dist/features/ObservationNormalizer.js.map +1 -0
- package/dist/features/StreamingExporter.d.ts +128 -0
- package/dist/features/StreamingExporter.d.ts.map +1 -0
- package/dist/features/StreamingExporter.js +212 -0
- package/dist/features/StreamingExporter.js.map +1 -0
- package/dist/features/TagManager.d.ts +147 -0
- package/dist/features/TagManager.d.ts.map +1 -0
- package/dist/features/TagManager.js +211 -0
- package/dist/features/TagManager.js.map +1 -0
- package/dist/features/index.d.ts +14 -0
- package/dist/features/index.d.ts.map +1 -0
- package/dist/features/index.js +15 -0
- package/dist/features/index.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/search/BM25Search.d.ts +148 -0
- package/dist/search/BM25Search.d.ts.map +1 -0
- package/dist/search/BM25Search.js +340 -0
- package/dist/search/BM25Search.js.map +1 -0
- package/dist/search/BasicSearch.d.ts +51 -0
- package/dist/search/BasicSearch.d.ts.map +1 -0
- package/dist/search/BasicSearch.js +138 -0
- package/dist/search/BasicSearch.js.map +1 -0
- package/dist/search/BooleanSearch.d.ts +98 -0
- package/dist/search/BooleanSearch.d.ts.map +1 -0
- package/dist/search/BooleanSearch.js +431 -0
- package/dist/search/BooleanSearch.js.map +1 -0
- package/dist/search/EarlyTerminationManager.d.ts +140 -0
- package/dist/search/EarlyTerminationManager.d.ts.map +1 -0
- package/dist/search/EarlyTerminationManager.js +280 -0
- package/dist/search/EarlyTerminationManager.js.map +1 -0
- package/dist/search/EmbeddingCache.d.ts +175 -0
- package/dist/search/EmbeddingCache.d.ts.map +1 -0
- package/dist/search/EmbeddingCache.js +247 -0
- package/dist/search/EmbeddingCache.js.map +1 -0
- package/dist/search/EmbeddingService.d.ts +277 -0
- package/dist/search/EmbeddingService.d.ts.map +1 -0
- package/dist/search/EmbeddingService.js +531 -0
- package/dist/search/EmbeddingService.js.map +1 -0
- package/dist/search/FuzzySearch.d.ts +118 -0
- package/dist/search/FuzzySearch.d.ts.map +1 -0
- package/dist/search/FuzzySearch.js +313 -0
- package/dist/search/FuzzySearch.js.map +1 -0
- package/dist/search/HybridScorer.d.ts +181 -0
- package/dist/search/HybridScorer.d.ts.map +1 -0
- package/dist/search/HybridScorer.js +258 -0
- package/dist/search/HybridScorer.js.map +1 -0
- package/dist/search/HybridSearchManager.d.ts +80 -0
- package/dist/search/HybridSearchManager.d.ts.map +1 -0
- package/dist/search/HybridSearchManager.js +188 -0
- package/dist/search/HybridSearchManager.js.map +1 -0
- package/dist/search/IncrementalIndexer.d.ts +201 -0
- package/dist/search/IncrementalIndexer.d.ts.map +1 -0
- package/dist/search/IncrementalIndexer.js +343 -0
- package/dist/search/IncrementalIndexer.js.map +1 -0
- package/dist/search/OptimizedInvertedIndex.d.ts +163 -0
- package/dist/search/OptimizedInvertedIndex.d.ts.map +1 -0
- package/dist/search/OptimizedInvertedIndex.js +359 -0
- package/dist/search/OptimizedInvertedIndex.js.map +1 -0
- package/dist/search/ParallelSearchExecutor.d.ts +172 -0
- package/dist/search/ParallelSearchExecutor.d.ts.map +1 -0
- package/dist/search/ParallelSearchExecutor.js +310 -0
- package/dist/search/ParallelSearchExecutor.js.map +1 -0
- package/dist/search/QuantizedVectorStore.d.ts +171 -0
- package/dist/search/QuantizedVectorStore.d.ts.map +1 -0
- package/dist/search/QuantizedVectorStore.js +308 -0
- package/dist/search/QuantizedVectorStore.js.map +1 -0
- package/dist/search/QueryAnalyzer.d.ts +76 -0
- package/dist/search/QueryAnalyzer.d.ts.map +1 -0
- package/dist/search/QueryAnalyzer.js +228 -0
- package/dist/search/QueryAnalyzer.js.map +1 -0
- package/dist/search/QueryCostEstimator.d.ts +244 -0
- package/dist/search/QueryCostEstimator.d.ts.map +1 -0
- package/dist/search/QueryCostEstimator.js +653 -0
- package/dist/search/QueryCostEstimator.js.map +1 -0
- package/dist/search/QueryPlanCache.d.ts +220 -0
- package/dist/search/QueryPlanCache.d.ts.map +1 -0
- package/dist/search/QueryPlanCache.js +380 -0
- package/dist/search/QueryPlanCache.js.map +1 -0
- package/dist/search/QueryPlanner.d.ts +58 -0
- package/dist/search/QueryPlanner.d.ts.map +1 -0
- package/dist/search/QueryPlanner.js +138 -0
- package/dist/search/QueryPlanner.js.map +1 -0
- package/dist/search/RankedSearch.d.ts +71 -0
- package/dist/search/RankedSearch.d.ts.map +1 -0
- package/dist/search/RankedSearch.js +239 -0
- package/dist/search/RankedSearch.js.map +1 -0
- package/dist/search/ReflectionManager.d.ts +120 -0
- package/dist/search/ReflectionManager.d.ts.map +1 -0
- package/dist/search/ReflectionManager.js +232 -0
- package/dist/search/ReflectionManager.js.map +1 -0
- package/dist/search/SavedSearchManager.d.ts +79 -0
- package/dist/search/SavedSearchManager.d.ts.map +1 -0
- package/dist/search/SavedSearchManager.js +147 -0
- package/dist/search/SavedSearchManager.js.map +1 -0
- package/dist/search/SearchFilterChain.d.ts +120 -0
- package/dist/search/SearchFilterChain.d.ts.map +1 -0
- package/dist/search/SearchFilterChain.js +186 -0
- package/dist/search/SearchFilterChain.js.map +1 -0
- package/dist/search/SearchManager.d.ts +326 -0
- package/dist/search/SearchManager.d.ts.map +1 -0
- package/dist/search/SearchManager.js +454 -0
- package/dist/search/SearchManager.js.map +1 -0
- package/dist/search/SearchSuggestions.d.ts +27 -0
- package/dist/search/SearchSuggestions.d.ts.map +1 -0
- package/dist/search/SearchSuggestions.js +58 -0
- package/dist/search/SearchSuggestions.js.map +1 -0
- package/dist/search/SemanticSearch.d.ts +149 -0
- package/dist/search/SemanticSearch.d.ts.map +1 -0
- package/dist/search/SemanticSearch.js +324 -0
- package/dist/search/SemanticSearch.js.map +1 -0
- package/dist/search/SymbolicSearch.d.ts +61 -0
- package/dist/search/SymbolicSearch.d.ts.map +1 -0
- package/dist/search/SymbolicSearch.js +164 -0
- package/dist/search/SymbolicSearch.js.map +1 -0
- package/dist/search/TFIDFEventSync.d.ts +85 -0
- package/dist/search/TFIDFEventSync.d.ts.map +1 -0
- package/dist/search/TFIDFEventSync.js +134 -0
- package/dist/search/TFIDFEventSync.js.map +1 -0
- package/dist/search/TFIDFIndexManager.d.ts +151 -0
- package/dist/search/TFIDFIndexManager.d.ts.map +1 -0
- package/dist/search/TFIDFIndexManager.js +433 -0
- package/dist/search/TFIDFIndexManager.js.map +1 -0
- package/dist/search/VectorStore.d.ts +235 -0
- package/dist/search/VectorStore.d.ts.map +1 -0
- package/dist/search/VectorStore.js +312 -0
- package/dist/search/VectorStore.js.map +1 -0
- package/dist/search/index.d.ts +35 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +53 -0
- package/dist/search/index.js.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +13 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/types.d.ts +1811 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +10 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils/BatchProcessor.d.ts +271 -0
- package/dist/utils/BatchProcessor.d.ts.map +1 -0
- package/dist/utils/BatchProcessor.js +377 -0
- package/dist/utils/BatchProcessor.js.map +1 -0
- package/dist/utils/MemoryMonitor.d.ts +176 -0
- package/dist/utils/MemoryMonitor.d.ts.map +1 -0
- package/dist/utils/MemoryMonitor.js +306 -0
- package/dist/utils/MemoryMonitor.js.map +1 -0
- package/dist/utils/WorkerPoolManager.d.ts +233 -0
- package/dist/utils/WorkerPoolManager.d.ts.map +1 -0
- package/dist/utils/WorkerPoolManager.js +421 -0
- package/dist/utils/WorkerPoolManager.js.map +1 -0
- package/dist/utils/compressedCache.d.ts +221 -0
- package/dist/utils/compressedCache.d.ts.map +1 -0
- package/dist/utils/compressedCache.js +349 -0
- package/dist/utils/compressedCache.js.map +1 -0
- package/dist/utils/compressionUtil.d.ts +214 -0
- package/dist/utils/compressionUtil.d.ts.map +1 -0
- package/dist/utils/compressionUtil.js +248 -0
- package/dist/utils/compressionUtil.js.map +1 -0
- package/dist/utils/constants.d.ts +245 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +253 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/entityUtils.d.ts +379 -0
- package/dist/utils/entityUtils.d.ts.map +1 -0
- package/dist/utils/entityUtils.js +649 -0
- package/dist/utils/entityUtils.js.map +1 -0
- package/dist/utils/errors.d.ts +95 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +146 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/formatters.d.ts +145 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/formatters.js +133 -0
- package/dist/utils/formatters.js.map +1 -0
- package/dist/utils/index.d.ts +26 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +88 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/indexes.d.ts +270 -0
- package/dist/utils/indexes.d.ts.map +1 -0
- package/dist/utils/indexes.js +527 -0
- package/dist/utils/indexes.js.map +1 -0
- package/dist/utils/logger.d.ts +31 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +41 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/operationUtils.d.ts +124 -0
- package/dist/utils/operationUtils.d.ts.map +1 -0
- package/dist/utils/operationUtils.js +176 -0
- package/dist/utils/operationUtils.js.map +1 -0
- package/dist/utils/parallelUtils.d.ts +76 -0
- package/dist/utils/parallelUtils.d.ts.map +1 -0
- package/dist/utils/parallelUtils.js +192 -0
- package/dist/utils/parallelUtils.js.map +1 -0
- package/dist/utils/schemas.d.ts +556 -0
- package/dist/utils/schemas.d.ts.map +1 -0
- package/dist/utils/schemas.js +485 -0
- package/dist/utils/schemas.js.map +1 -0
- package/dist/utils/searchAlgorithms.d.ts +99 -0
- package/dist/utils/searchAlgorithms.d.ts.map +1 -0
- package/dist/utils/searchAlgorithms.js +168 -0
- package/dist/utils/searchAlgorithms.js.map +1 -0
- package/dist/utils/searchCache.d.ts +108 -0
- package/dist/utils/searchCache.d.ts.map +1 -0
- package/dist/utils/searchCache.js +210 -0
- package/dist/utils/searchCache.js.map +1 -0
- package/dist/utils/taskScheduler.d.ts +294 -0
- package/dist/utils/taskScheduler.d.ts.map +1 -0
- package/dist/utils/taskScheduler.js +487 -0
- package/dist/utils/taskScheduler.js.map +1 -0
- package/dist/workers/index.d.ts +12 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/index.js +10 -0
- package/dist/workers/index.js.map +1 -0
- package/dist/workers/levenshteinWorker.d.ts +60 -0
- package/dist/workers/levenshteinWorker.d.ts.map +1 -0
- package/dist/workers/levenshteinWorker.js +99 -0
- package/dist/workers/levenshteinWorker.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compressed Cache Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides an LRU cache with automatic compression of old entries.
|
|
5
|
+
* Reduces memory footprint for large knowledge graphs (50k+ entities).
|
|
6
|
+
*
|
|
7
|
+
* Uses synchronous brotli compression/decompression for cache operations
|
|
8
|
+
* to avoid async complexity in hot paths.
|
|
9
|
+
*
|
|
10
|
+
* Phase 3 Sprint 5: Archive & Cache Compression
|
|
11
|
+
*
|
|
12
|
+
* @module utils/compressedCache
|
|
13
|
+
*/
|
|
14
|
+
import { brotliCompressSync, brotliDecompressSync, constants } from 'zlib';
|
|
15
|
+
import { COMPRESSION_CONFIG } from './constants.js';
|
|
16
|
+
/**
|
|
17
|
+
* LRU cache with automatic compression of old entries.
|
|
18
|
+
*
|
|
19
|
+
* Reduces memory footprint by compressing infrequently accessed entries
|
|
20
|
+
* using brotli compression. Hot (recently accessed) entries stay
|
|
21
|
+
* uncompressed for fast access.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const cache = new CompressedCache({
|
|
26
|
+
* maxUncompressed: 500,
|
|
27
|
+
* compressionThresholdMs: 60000 // 1 minute
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Store entity
|
|
31
|
+
* cache.set('Alice', { name: 'Alice', entityType: 'person', observations: [] });
|
|
32
|
+
*
|
|
33
|
+
* // Retrieve entity (decompresses if needed)
|
|
34
|
+
* const entity = cache.get('Alice');
|
|
35
|
+
*
|
|
36
|
+
* // Check stats
|
|
37
|
+
* const stats = cache.getStats();
|
|
38
|
+
* console.log(`Memory saved: ${stats.memorySaved} bytes`);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export class CompressedCache {
|
|
42
|
+
_entryMap = new Map();
|
|
43
|
+
maxUncompressed;
|
|
44
|
+
compressionThresholdMs;
|
|
45
|
+
autoCompress;
|
|
46
|
+
// Phase 12 Sprint 6: Adaptive compression options
|
|
47
|
+
minCompressionSize;
|
|
48
|
+
minCompressionRatio;
|
|
49
|
+
// Statistics
|
|
50
|
+
hits = 0;
|
|
51
|
+
misses = 0;
|
|
52
|
+
compressions = 0;
|
|
53
|
+
decompressions = 0;
|
|
54
|
+
// Phase 12 Sprint 6: Adaptive compression stats
|
|
55
|
+
skippedSmallEntries = 0;
|
|
56
|
+
skippedPoorRatio = 0;
|
|
57
|
+
compressionRatios = [];
|
|
58
|
+
constructor(options = {}) {
|
|
59
|
+
this.maxUncompressed = options.maxUncompressed ?? 1000;
|
|
60
|
+
this.compressionThresholdMs = options.compressionThresholdMs ?? 5 * 60 * 1000;
|
|
61
|
+
this.autoCompress = options.autoCompress ?? true;
|
|
62
|
+
// Phase 12 Sprint 6: Adaptive compression defaults
|
|
63
|
+
this.minCompressionSize = options.minCompressionSize ?? 256;
|
|
64
|
+
this.minCompressionRatio = options.minCompressionRatio ?? 0.7;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get an entity from the cache.
|
|
68
|
+
*
|
|
69
|
+
* If the entity is compressed, it will be decompressed on access.
|
|
70
|
+
* The entry is marked as recently accessed to prevent re-compression.
|
|
71
|
+
*
|
|
72
|
+
* @param name - Entity name to retrieve
|
|
73
|
+
* @returns The entity if found, undefined otherwise
|
|
74
|
+
*/
|
|
75
|
+
get(name) {
|
|
76
|
+
const entry = this._entryMap.get(name);
|
|
77
|
+
if (!entry) {
|
|
78
|
+
this.misses++;
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
this.hits++;
|
|
82
|
+
entry.lastAccessed = Date.now();
|
|
83
|
+
if (entry.compressed && entry.compressedData) {
|
|
84
|
+
// Decompress on access
|
|
85
|
+
try {
|
|
86
|
+
const decompressed = brotliDecompressSync(entry.compressedData);
|
|
87
|
+
entry.entity = JSON.parse(decompressed.toString('utf-8'));
|
|
88
|
+
entry.compressed = false;
|
|
89
|
+
entry.compressedData = undefined;
|
|
90
|
+
this.decompressions++;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// Decompression failed - remove corrupt entry
|
|
94
|
+
this._entryMap.delete(name);
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return entry.entity ?? undefined;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Store an entity in the cache.
|
|
102
|
+
*
|
|
103
|
+
* Entries are stored uncompressed initially. Old entries may be
|
|
104
|
+
* compressed automatically based on cache settings.
|
|
105
|
+
*
|
|
106
|
+
* @param name - Entity name (key)
|
|
107
|
+
* @param entity - Entity to store
|
|
108
|
+
*/
|
|
109
|
+
set(name, entity) {
|
|
110
|
+
const jsonStr = JSON.stringify(entity);
|
|
111
|
+
const originalSize = Buffer.byteLength(jsonStr, 'utf-8');
|
|
112
|
+
this._entryMap.set(name, {
|
|
113
|
+
entity,
|
|
114
|
+
compressed: false,
|
|
115
|
+
originalSize,
|
|
116
|
+
lastAccessed: Date.now(),
|
|
117
|
+
});
|
|
118
|
+
if (this.autoCompress) {
|
|
119
|
+
this.maybeCompressOldEntries();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if an entity exists in the cache.
|
|
124
|
+
*
|
|
125
|
+
* @param name - Entity name to check
|
|
126
|
+
* @returns True if entity exists in cache
|
|
127
|
+
*/
|
|
128
|
+
has(name) {
|
|
129
|
+
return this._entryMap.has(name);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Delete an entity from the cache.
|
|
133
|
+
*
|
|
134
|
+
* @param name - Entity name to delete
|
|
135
|
+
* @returns True if entity was deleted, false if not found
|
|
136
|
+
*/
|
|
137
|
+
delete(name) {
|
|
138
|
+
return this._entryMap.delete(name);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Clear all entries from the cache.
|
|
142
|
+
*/
|
|
143
|
+
clear() {
|
|
144
|
+
this._entryMap.clear();
|
|
145
|
+
// Don't reset statistics - they track lifetime totals
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Get the number of entries in the cache.
|
|
149
|
+
*/
|
|
150
|
+
get size() {
|
|
151
|
+
return this._entryMap.size;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get all entity names in the cache.
|
|
155
|
+
*/
|
|
156
|
+
keys() {
|
|
157
|
+
return this._entryMap.keys();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get comprehensive cache statistics.
|
|
161
|
+
*
|
|
162
|
+
* @returns Statistics about cache state and performance
|
|
163
|
+
*/
|
|
164
|
+
getStats() {
|
|
165
|
+
let compressed = 0;
|
|
166
|
+
let uncompressed = 0;
|
|
167
|
+
let memorySaved = 0;
|
|
168
|
+
let totalOriginalSize = 0;
|
|
169
|
+
let totalCompressedSize = 0;
|
|
170
|
+
let estimatedMemoryBytes = 0;
|
|
171
|
+
for (const entry of this._entryMap.values()) {
|
|
172
|
+
totalOriginalSize += entry.originalSize;
|
|
173
|
+
if (entry.compressed && entry.compressedData) {
|
|
174
|
+
compressed++;
|
|
175
|
+
totalCompressedSize += entry.compressedData.length;
|
|
176
|
+
estimatedMemoryBytes += entry.compressedData.length;
|
|
177
|
+
// Memory saved = original size - compressed size
|
|
178
|
+
memorySaved += entry.originalSize - entry.compressedData.length;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
uncompressed++;
|
|
182
|
+
estimatedMemoryBytes += entry.originalSize;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Calculate average compression ratio
|
|
186
|
+
const avgCompressionRatio = this.compressionRatios.length > 0
|
|
187
|
+
? this.compressionRatios.reduce((a, b) => a + b, 0) / this.compressionRatios.length
|
|
188
|
+
: 0;
|
|
189
|
+
return {
|
|
190
|
+
total: this._entryMap.size,
|
|
191
|
+
compressed,
|
|
192
|
+
uncompressed,
|
|
193
|
+
memorySaved: Math.max(0, memorySaved),
|
|
194
|
+
totalOriginalSize,
|
|
195
|
+
totalCompressedSize,
|
|
196
|
+
hits: this.hits,
|
|
197
|
+
misses: this.misses,
|
|
198
|
+
compressions: this.compressions,
|
|
199
|
+
decompressions: this.decompressions,
|
|
200
|
+
// Phase 12 Sprint 6: Adaptive compression stats
|
|
201
|
+
skippedSmallEntries: this.skippedSmallEntries,
|
|
202
|
+
skippedPoorRatio: this.skippedPoorRatio,
|
|
203
|
+
avgCompressionRatio,
|
|
204
|
+
estimatedMemoryBytes,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Force compression of entries older than the threshold.
|
|
209
|
+
*
|
|
210
|
+
* Called automatically after set() when autoCompress is enabled.
|
|
211
|
+
* Can be called manually to trigger compression on demand.
|
|
212
|
+
*
|
|
213
|
+
* @returns Number of entries compressed
|
|
214
|
+
*/
|
|
215
|
+
compressOldEntries() {
|
|
216
|
+
return this.maybeCompressOldEntries(true);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Compress old entries if we're over the uncompressed limit.
|
|
220
|
+
*
|
|
221
|
+
* @param force - If true, compress regardless of limit
|
|
222
|
+
* @returns Number of entries compressed
|
|
223
|
+
*/
|
|
224
|
+
maybeCompressOldEntries(force = false) {
|
|
225
|
+
// Count uncompressed entries
|
|
226
|
+
let uncompressedCount = 0;
|
|
227
|
+
for (const entry of this._entryMap.values()) {
|
|
228
|
+
if (!entry.compressed) {
|
|
229
|
+
uncompressedCount++;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// Only compress if over limit (unless forced)
|
|
233
|
+
if (!force && uncompressedCount <= this.maxUncompressed) {
|
|
234
|
+
return 0;
|
|
235
|
+
}
|
|
236
|
+
const now = Date.now();
|
|
237
|
+
let compressedCount = 0;
|
|
238
|
+
// Sort uncompressed entries by last accessed time (oldest first)
|
|
239
|
+
const sortedEntries = [...this._entryMap.entries()]
|
|
240
|
+
.filter(([, e]) => !e.compressed && e.entity !== null)
|
|
241
|
+
.sort((a, b) => a[1].lastAccessed - b[1].lastAccessed);
|
|
242
|
+
// Compress oldest entries until we're under the limit
|
|
243
|
+
for (const [, entry] of sortedEntries) {
|
|
244
|
+
// Stop if we've compressed enough
|
|
245
|
+
if (!force && (uncompressedCount - compressedCount) <= this.maxUncompressed) {
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
// Only compress if entry is old enough
|
|
249
|
+
if (now - entry.lastAccessed < this.compressionThresholdMs) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
// Compress the entry
|
|
253
|
+
if (entry.entity) {
|
|
254
|
+
// Phase 12 Sprint 6: Skip small entries (adaptive compression)
|
|
255
|
+
if (entry.originalSize < this.minCompressionSize) {
|
|
256
|
+
this.skippedSmallEntries++;
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
const jsonStr = JSON.stringify(entry.entity);
|
|
261
|
+
const compressed = brotliCompressSync(Buffer.from(jsonStr, 'utf-8'), {
|
|
262
|
+
params: {
|
|
263
|
+
[constants.BROTLI_PARAM_QUALITY]: COMPRESSION_CONFIG.BROTLI_QUALITY_CACHE,
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
// Phase 12 Sprint 6: Check compression ratio
|
|
267
|
+
const ratio = compressed.length / entry.originalSize;
|
|
268
|
+
if (ratio > this.minCompressionRatio) {
|
|
269
|
+
// Compression didn't achieve enough reduction
|
|
270
|
+
this.skippedPoorRatio++;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
// Track compression ratio
|
|
274
|
+
this.compressionRatios.push(ratio);
|
|
275
|
+
entry.compressedData = compressed;
|
|
276
|
+
entry.compressed = true;
|
|
277
|
+
entry.entity = null; // Free memory
|
|
278
|
+
this.compressions++;
|
|
279
|
+
compressedCount++;
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
// Compression failed - leave entry uncompressed
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return compressedCount;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Decompress all entries in the cache.
|
|
291
|
+
*
|
|
292
|
+
* Useful when preparing for bulk operations or export.
|
|
293
|
+
*
|
|
294
|
+
* @returns Number of entries decompressed
|
|
295
|
+
*/
|
|
296
|
+
decompressAll() {
|
|
297
|
+
let decompressedCount = 0;
|
|
298
|
+
for (const [name, entry] of this._entryMap) {
|
|
299
|
+
if (entry.compressed && entry.compressedData) {
|
|
300
|
+
try {
|
|
301
|
+
const decompressed = brotliDecompressSync(entry.compressedData);
|
|
302
|
+
entry.entity = JSON.parse(decompressed.toString('utf-8'));
|
|
303
|
+
entry.compressed = false;
|
|
304
|
+
entry.compressedData = undefined;
|
|
305
|
+
this.decompressions++;
|
|
306
|
+
decompressedCount++;
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
// Decompression failed - remove corrupt entry
|
|
310
|
+
this._entryMap.delete(name);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return decompressedCount;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Get all entities from the cache (decompressing as needed).
|
|
318
|
+
*
|
|
319
|
+
* @returns Array of all entities in the cache
|
|
320
|
+
*/
|
|
321
|
+
getAllEntities() {
|
|
322
|
+
const entities = [];
|
|
323
|
+
for (const [name] of this._entryMap) {
|
|
324
|
+
const entity = this.get(name);
|
|
325
|
+
if (entity) {
|
|
326
|
+
entities.push(entity);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return entities;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Iterate over all entries with their compression status.
|
|
333
|
+
*
|
|
334
|
+
* Does not decompress entries - useful for inspection.
|
|
335
|
+
*
|
|
336
|
+
* @yields Entry information without decompressing
|
|
337
|
+
*/
|
|
338
|
+
*entries() {
|
|
339
|
+
for (const [name, entry] of this._entryMap) {
|
|
340
|
+
yield {
|
|
341
|
+
name,
|
|
342
|
+
compressed: entry.compressed,
|
|
343
|
+
originalSize: entry.originalSize,
|
|
344
|
+
lastAccessed: entry.lastAccessed,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=compressedCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compressedCache.js","sourceRoot":"","sources":["../../src/utils/compressedCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compression Utility Module
|
|
3
|
+
*
|
|
4
|
+
* Provides brotli compression and decompression utilities using Node.js
|
|
5
|
+
* built-in zlib module. No external dependencies required.
|
|
6
|
+
*
|
|
7
|
+
* Brotli offers 15-20% better compression than gzip, with 60-75%
|
|
8
|
+
* compression typical for JSON data.
|
|
9
|
+
*
|
|
10
|
+
* @module utils/compressionUtil
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Options for compression operations.
|
|
14
|
+
*/
|
|
15
|
+
export interface CompressionOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Brotli quality level (0-11).
|
|
18
|
+
* Higher values = better compression but slower.
|
|
19
|
+
* @default 6
|
|
20
|
+
*/
|
|
21
|
+
quality?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Window size (10-24) for the LZ77 algorithm.
|
|
24
|
+
* Larger windows = better compression for large files.
|
|
25
|
+
* @default 22
|
|
26
|
+
*/
|
|
27
|
+
lgwin?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Compression mode hint.
|
|
30
|
+
* - 'text': Optimized for UTF-8 text
|
|
31
|
+
* - 'generic': General-purpose compression
|
|
32
|
+
* @default 'generic'
|
|
33
|
+
*/
|
|
34
|
+
mode?: 'text' | 'generic';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Result of a compression operation.
|
|
38
|
+
*/
|
|
39
|
+
export interface CompressionResult {
|
|
40
|
+
/** The compressed data as a Buffer */
|
|
41
|
+
compressed: Buffer;
|
|
42
|
+
/** Original size in bytes */
|
|
43
|
+
originalSize: number;
|
|
44
|
+
/** Compressed size in bytes */
|
|
45
|
+
compressedSize: number;
|
|
46
|
+
/** Compression ratio (compressedSize / originalSize). Lower is better. */
|
|
47
|
+
ratio: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Metadata about a compressed file for storage alongside the compressed data.
|
|
51
|
+
*/
|
|
52
|
+
export interface CompressionMetadata {
|
|
53
|
+
/** Whether the data is compressed */
|
|
54
|
+
compressed: boolean;
|
|
55
|
+
/** Compression format used */
|
|
56
|
+
compressionFormat: 'brotli' | 'none';
|
|
57
|
+
/** Original size before compression in bytes */
|
|
58
|
+
originalSize: number;
|
|
59
|
+
/** Size after compression in bytes */
|
|
60
|
+
compressedSize: number;
|
|
61
|
+
/** Optional checksum of original data for integrity verification */
|
|
62
|
+
originalChecksum?: string;
|
|
63
|
+
/** ISO 8601 timestamp when compression was performed */
|
|
64
|
+
createdAt: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Check if a file path indicates brotli compression based on extension.
|
|
68
|
+
*
|
|
69
|
+
* Note: Brotli doesn't have reliable magic bytes for detection.
|
|
70
|
+
* Using file extension (.br) is the recommended detection method.
|
|
71
|
+
*
|
|
72
|
+
* @param filePath - The file path to check
|
|
73
|
+
* @returns True if the path ends with .br extension
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* hasBrotliExtension('backup.jsonl.br') // true
|
|
78
|
+
* hasBrotliExtension('backup.jsonl') // false
|
|
79
|
+
* hasBrotliExtension('data.json') // false
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export declare function hasBrotliExtension(filePath: string): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Compress data using brotli algorithm.
|
|
85
|
+
*
|
|
86
|
+
* @param data - The data to compress (string or Buffer)
|
|
87
|
+
* @param options - Compression options
|
|
88
|
+
* @returns Compression result with compressed data and statistics
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const jsonData = JSON.stringify({ entities: [...] });
|
|
93
|
+
* const result = await compress(jsonData, { quality: 11 });
|
|
94
|
+
* console.log(`Compressed from ${result.originalSize} to ${result.compressedSize} bytes`);
|
|
95
|
+
* console.log(`Compression ratio: ${(result.ratio * 100).toFixed(1)}%`);
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export declare function compress(data: Buffer | string, options?: CompressionOptions): Promise<CompressionResult>;
|
|
99
|
+
/**
|
|
100
|
+
* Decompress brotli-compressed data.
|
|
101
|
+
*
|
|
102
|
+
* @param data - The compressed data as a Buffer
|
|
103
|
+
* @returns The decompressed data as a Buffer
|
|
104
|
+
* @throws Error if decompression fails (corrupt or invalid data)
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const compressed = await fs.readFile('backup.jsonl.br');
|
|
109
|
+
* const decompressed = await decompress(compressed);
|
|
110
|
+
* const jsonData = decompressed.toString('utf-8');
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export declare function decompress(data: Buffer): Promise<Buffer>;
|
|
114
|
+
/**
|
|
115
|
+
* Calculate compression ratio.
|
|
116
|
+
*
|
|
117
|
+
* @param originalSize - Original size in bytes
|
|
118
|
+
* @param compressedSize - Compressed size in bytes
|
|
119
|
+
* @returns Ratio as a decimal (e.g., 0.25 = 75% compression)
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const ratio = getCompressionRatio(1000, 250);
|
|
124
|
+
* console.log(`Compression ratio: ${(1 - ratio) * 100}%`); // "Compression ratio: 75%"
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export declare function getCompressionRatio(originalSize: number, compressedSize: number): number;
|
|
128
|
+
/**
|
|
129
|
+
* Compress a file and write the result to disk.
|
|
130
|
+
*
|
|
131
|
+
* @param inputPath - Path to the input file
|
|
132
|
+
* @param outputPath - Path for the compressed output file
|
|
133
|
+
* @param options - Compression options
|
|
134
|
+
* @returns Compression result with statistics
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const result = await compressFile(
|
|
139
|
+
* 'memory.jsonl',
|
|
140
|
+
* 'memory.jsonl.br',
|
|
141
|
+
* { quality: 11 }
|
|
142
|
+
* );
|
|
143
|
+
* console.log(`Saved ${result.originalSize - result.compressedSize} bytes`);
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export declare function compressFile(inputPath: string, outputPath: string, options?: CompressionOptions): Promise<CompressionResult>;
|
|
147
|
+
/**
|
|
148
|
+
* Decompress a file and write the result to disk.
|
|
149
|
+
*
|
|
150
|
+
* @param inputPath - Path to the compressed input file
|
|
151
|
+
* @param outputPath - Path for the decompressed output file
|
|
152
|
+
* @throws Error if file not found or decompression fails
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```typescript
|
|
156
|
+
* await decompressFile('backup.jsonl.br', 'restored.jsonl');
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
export declare function decompressFile(inputPath: string, outputPath: string): Promise<void>;
|
|
160
|
+
/**
|
|
161
|
+
* Create metadata object for a compression result.
|
|
162
|
+
* This metadata should be stored alongside compressed files for
|
|
163
|
+
* integrity verification and restoration.
|
|
164
|
+
*
|
|
165
|
+
* @param result - The compression result
|
|
166
|
+
* @param checksum - Optional checksum of the original data
|
|
167
|
+
* @returns Compression metadata object
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const result = await compress(data);
|
|
172
|
+
* const metadata = createMetadata(result);
|
|
173
|
+
* await fs.writeFile('backup.meta.json', JSON.stringify(metadata, null, 2));
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export declare function createMetadata(result: CompressionResult, checksum?: string): CompressionMetadata;
|
|
177
|
+
/**
|
|
178
|
+
* Create metadata for uncompressed data.
|
|
179
|
+
* Useful for consistent metadata format when compression is disabled.
|
|
180
|
+
*
|
|
181
|
+
* @param size - Size of the data in bytes
|
|
182
|
+
* @returns Compression metadata indicating no compression
|
|
183
|
+
*/
|
|
184
|
+
export declare function createUncompressedMetadata(size: number): CompressionMetadata;
|
|
185
|
+
/**
|
|
186
|
+
* Compress a string and return base64-encoded result.
|
|
187
|
+
* Useful for embedding compressed data in JSON responses.
|
|
188
|
+
*
|
|
189
|
+
* @param data - String data to compress
|
|
190
|
+
* @param options - Compression options
|
|
191
|
+
* @returns Base64-encoded compressed data
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```typescript
|
|
195
|
+
* const encoded = await compressToBase64(jsonString);
|
|
196
|
+
* // Send in response: { compressed: true, data: encoded }
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export declare function compressToBase64(data: string, options?: CompressionOptions): Promise<string>;
|
|
200
|
+
/**
|
|
201
|
+
* Decompress base64-encoded compressed data.
|
|
202
|
+
* Counterpart to compressToBase64.
|
|
203
|
+
*
|
|
204
|
+
* @param base64Data - Base64-encoded compressed data
|
|
205
|
+
* @returns Decompressed string
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```typescript
|
|
209
|
+
* const original = await decompressFromBase64(response.data);
|
|
210
|
+
* const parsed = JSON.parse(original);
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
export declare function decompressFromBase64(base64Data: string): Promise<string>;
|
|
214
|
+
//# sourceMappingURL=compressionUtil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compressionUtil.d.ts","sourceRoot":"","sources":["../../src/utils/compressionUtil.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,UAAU,EAAE,OAAO,CAAC;IACpB,8BAA8B;IAC9B,iBAAiB,EAAE,QAAQ,GAAG,MAAM,CAAC;IACrC,gDAAgD;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAoC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAe9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,GACrB,MAAM,CAGR;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAK5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,iBAAiB,EACzB,QAAQ,CAAC,EAAE,MAAM,GAChB,mBAAmB,CASrB;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAQ5E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI9E"}
|