driftdetect-core 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/dist/analyzers/ast-analyzer.d.ts +251 -0
- package/dist/analyzers/ast-analyzer.d.ts.map +1 -0
- package/dist/analyzers/ast-analyzer.js +548 -0
- package/dist/analyzers/ast-analyzer.js.map +1 -0
- package/dist/analyzers/flow-analyzer.d.ts +241 -0
- package/dist/analyzers/flow-analyzer.d.ts.map +1 -0
- package/dist/analyzers/flow-analyzer.js +1219 -0
- package/dist/analyzers/flow-analyzer.js.map +1 -0
- package/dist/analyzers/index.d.ts +18 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +19 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/semantic-analyzer.d.ts +252 -0
- package/dist/analyzers/semantic-analyzer.d.ts.map +1 -0
- package/dist/analyzers/semantic-analyzer.js +1182 -0
- package/dist/analyzers/semantic-analyzer.js.map +1 -0
- package/dist/analyzers/type-analyzer.d.ts +289 -0
- package/dist/analyzers/type-analyzer.d.ts.map +1 -0
- package/dist/analyzers/type-analyzer.js +1269 -0
- package/dist/analyzers/type-analyzer.js.map +1 -0
- package/dist/analyzers/types.d.ts +537 -0
- package/dist/analyzers/types.d.ts.map +1 -0
- package/dist/analyzers/types.js +11 -0
- package/dist/analyzers/types.js.map +1 -0
- package/dist/config/config-loader.d.ts +166 -0
- package/dist/config/config-loader.d.ts.map +1 -0
- package/dist/config/config-loader.js +429 -0
- package/dist/config/config-loader.js.map +1 -0
- package/dist/config/config-validator.d.ts +204 -0
- package/dist/config/config-validator.d.ts.map +1 -0
- package/dist/config/config-validator.js +632 -0
- package/dist/config/config-validator.js.map +1 -0
- package/dist/config/defaults.d.ts +8 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +26 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +10 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +10 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +47 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +7 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest/exporter.d.ts +21 -0
- package/dist/manifest/exporter.d.ts.map +1 -0
- package/dist/manifest/exporter.js +339 -0
- package/dist/manifest/exporter.js.map +1 -0
- package/dist/manifest/index.d.ts +14 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +15 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/manifest/manifest-store.d.ts +111 -0
- package/dist/manifest/manifest-store.d.ts.map +1 -0
- package/dist/manifest/manifest-store.js +418 -0
- package/dist/manifest/manifest-store.js.map +1 -0
- package/dist/manifest/types.d.ts +238 -0
- package/dist/manifest/types.d.ts.map +1 -0
- package/dist/manifest/types.js +11 -0
- package/dist/manifest/types.js.map +1 -0
- package/dist/matcher/confidence-scorer.d.ts +188 -0
- package/dist/matcher/confidence-scorer.d.ts.map +1 -0
- package/dist/matcher/confidence-scorer.js +302 -0
- package/dist/matcher/confidence-scorer.js.map +1 -0
- package/dist/matcher/index.d.ts +24 -0
- package/dist/matcher/index.d.ts.map +1 -0
- package/dist/matcher/index.js +26 -0
- package/dist/matcher/index.js.map +1 -0
- package/dist/matcher/outlier-detector.d.ts +252 -0
- package/dist/matcher/outlier-detector.d.ts.map +1 -0
- package/dist/matcher/outlier-detector.js +544 -0
- package/dist/matcher/outlier-detector.js.map +1 -0
- package/dist/matcher/pattern-matcher.d.ts +169 -0
- package/dist/matcher/pattern-matcher.d.ts.map +1 -0
- package/dist/matcher/pattern-matcher.js +692 -0
- package/dist/matcher/pattern-matcher.js.map +1 -0
- package/dist/matcher/types.d.ts +476 -0
- package/dist/matcher/types.d.ts.map +1 -0
- package/dist/matcher/types.js +36 -0
- package/dist/matcher/types.js.map +1 -0
- package/dist/parsers/base-parser.d.ts +282 -0
- package/dist/parsers/base-parser.d.ts.map +1 -0
- package/dist/parsers/base-parser.js +421 -0
- package/dist/parsers/base-parser.js.map +1 -0
- package/dist/parsers/css-parser.d.ts +225 -0
- package/dist/parsers/css-parser.d.ts.map +1 -0
- package/dist/parsers/css-parser.js +477 -0
- package/dist/parsers/css-parser.js.map +1 -0
- package/dist/parsers/index.d.ts +15 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +15 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/json-parser.d.ts +219 -0
- package/dist/parsers/json-parser.d.ts.map +1 -0
- package/dist/parsers/json-parser.js +602 -0
- package/dist/parsers/json-parser.js.map +1 -0
- package/dist/parsers/markdown-parser.d.ts +276 -0
- package/dist/parsers/markdown-parser.d.ts.map +1 -0
- package/dist/parsers/markdown-parser.js +731 -0
- package/dist/parsers/markdown-parser.js.map +1 -0
- package/dist/parsers/parser-manager.d.ts +294 -0
- package/dist/parsers/parser-manager.d.ts.map +1 -0
- package/dist/parsers/parser-manager.js +738 -0
- package/dist/parsers/parser-manager.js.map +1 -0
- package/dist/parsers/python-parser.d.ts +204 -0
- package/dist/parsers/python-parser.d.ts.map +1 -0
- package/dist/parsers/python-parser.js +517 -0
- package/dist/parsers/python-parser.js.map +1 -0
- package/dist/parsers/types.d.ts +43 -0
- package/dist/parsers/types.d.ts.map +1 -0
- package/dist/parsers/types.js +7 -0
- package/dist/parsers/types.js.map +1 -0
- package/dist/parsers/typescript-parser.d.ts +264 -0
- package/dist/parsers/typescript-parser.d.ts.map +1 -0
- package/dist/parsers/typescript-parser.js +658 -0
- package/dist/parsers/typescript-parser.js.map +1 -0
- package/dist/rules/evaluator.d.ts +305 -0
- package/dist/rules/evaluator.d.ts.map +1 -0
- package/dist/rules/evaluator.js +579 -0
- package/dist/rules/evaluator.js.map +1 -0
- package/dist/rules/index.d.ts +13 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +13 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/quick-fix-generator.d.ts +334 -0
- package/dist/rules/quick-fix-generator.d.ts.map +1 -0
- package/dist/rules/quick-fix-generator.js +1075 -0
- package/dist/rules/quick-fix-generator.js.map +1 -0
- package/dist/rules/rule-engine.d.ts +241 -0
- package/dist/rules/rule-engine.d.ts.map +1 -0
- package/dist/rules/rule-engine.js +585 -0
- package/dist/rules/rule-engine.js.map +1 -0
- package/dist/rules/severity-manager.d.ts +394 -0
- package/dist/rules/severity-manager.d.ts.map +1 -0
- package/dist/rules/severity-manager.js +619 -0
- package/dist/rules/severity-manager.js.map +1 -0
- package/dist/rules/types.d.ts +370 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +133 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/rules/variant-manager.d.ts +388 -0
- package/dist/rules/variant-manager.d.ts.map +1 -0
- package/dist/rules/variant-manager.js +777 -0
- package/dist/rules/variant-manager.js.map +1 -0
- package/dist/scanner/change-detector.d.ts +164 -0
- package/dist/scanner/change-detector.d.ts.map +1 -0
- package/dist/scanner/change-detector.js +263 -0
- package/dist/scanner/change-detector.js.map +1 -0
- package/dist/scanner/dependency-graph.d.ts +270 -0
- package/dist/scanner/dependency-graph.d.ts.map +1 -0
- package/dist/scanner/dependency-graph.js +436 -0
- package/dist/scanner/dependency-graph.js.map +1 -0
- package/dist/scanner/file-walker.d.ts +127 -0
- package/dist/scanner/file-walker.d.ts.map +1 -0
- package/dist/scanner/file-walker.js +526 -0
- package/dist/scanner/file-walker.js.map +1 -0
- package/dist/scanner/index.d.ts +12 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +12 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/types.d.ts +218 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +10 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/scanner/worker-pool.d.ts +317 -0
- package/dist/scanner/worker-pool.d.ts.map +1 -0
- package/dist/scanner/worker-pool.js +571 -0
- package/dist/scanner/worker-pool.js.map +1 -0
- package/dist/store/cache-manager.d.ts +179 -0
- package/dist/store/cache-manager.d.ts.map +1 -0
- package/dist/store/cache-manager.js +391 -0
- package/dist/store/cache-manager.js.map +1 -0
- package/dist/store/history-store.d.ts +314 -0
- package/dist/store/history-store.d.ts.map +1 -0
- package/dist/store/history-store.js +707 -0
- package/dist/store/history-store.js.map +1 -0
- package/dist/store/index.d.ts +20 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +26 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/lock-file-manager.d.ts +202 -0
- package/dist/store/lock-file-manager.d.ts.map +1 -0
- package/dist/store/lock-file-manager.js +475 -0
- package/dist/store/lock-file-manager.js.map +1 -0
- package/dist/store/pattern-store.d.ts +289 -0
- package/dist/store/pattern-store.d.ts.map +1 -0
- package/dist/store/pattern-store.js +936 -0
- package/dist/store/pattern-store.js.map +1 -0
- package/dist/store/schema-validator.d.ts +159 -0
- package/dist/store/schema-validator.d.ts.map +1 -0
- package/dist/store/schema-validator.js +1096 -0
- package/dist/store/schema-validator.js.map +1 -0
- package/dist/store/types.d.ts +585 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +82 -0
- package/dist/store/types.js.map +1 -0
- package/dist/types/analysis.d.ts +19 -0
- package/dist/types/analysis.d.ts.map +1 -0
- package/dist/types/analysis.js +5 -0
- package/dist/types/analysis.js.map +1 -0
- package/dist/types/common.d.ts +7 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +5 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/patterns.d.ts +40 -0
- package/dist/types/patterns.d.ts.map +1 -0
- package/dist/types/patterns.js +7 -0
- package/dist/types/patterns.js.map +1 -0
- package/dist/types/violations.d.ts +7 -0
- package/dist/types/violations.d.ts.map +1 -0
- package/dist/types/violations.js +7 -0
- package/dist/types/violations.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache Manager - Analysis result caching
|
|
3
|
+
*
|
|
4
|
+
* LRU cache for analysis results with file hash-based keys.
|
|
5
|
+
* Handles cache invalidation on file changes.
|
|
6
|
+
*
|
|
7
|
+
* @requirements 2.5 - THE Scanner SHALL cache analysis results using file content hashes
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Configuration options for the CacheManager
|
|
11
|
+
*/
|
|
12
|
+
export interface CacheManagerOptions {
|
|
13
|
+
/** Maximum number of entries in the cache (default: 1000) */
|
|
14
|
+
maxSize: number;
|
|
15
|
+
/** Time-to-live in milliseconds (default: 1 hour, 0 = no expiry) */
|
|
16
|
+
ttl: number;
|
|
17
|
+
/** Path to persist cache to disk (optional) */
|
|
18
|
+
persistPath?: string;
|
|
19
|
+
/** Whether to enable statistics tracking (default: true) */
|
|
20
|
+
enableStats: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A single cache entry with metadata
|
|
24
|
+
*/
|
|
25
|
+
export interface CacheEntry<T> {
|
|
26
|
+
/** The cached value */
|
|
27
|
+
value: T;
|
|
28
|
+
/** File content hash used as key */
|
|
29
|
+
hash: string;
|
|
30
|
+
/** Timestamp when entry was created */
|
|
31
|
+
timestamp: number;
|
|
32
|
+
/** Number of times this entry has been accessed */
|
|
33
|
+
hits: number;
|
|
34
|
+
/** Size estimate in bytes (for memory tracking) */
|
|
35
|
+
size: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Cache statistics for monitoring
|
|
39
|
+
*/
|
|
40
|
+
export interface CacheStats {
|
|
41
|
+
/** Total number of cache hits */
|
|
42
|
+
hits: number;
|
|
43
|
+
/** Total number of cache misses */
|
|
44
|
+
misses: number;
|
|
45
|
+
/** Total number of evictions due to size limit */
|
|
46
|
+
evictions: number;
|
|
47
|
+
/** Total number of expirations due to TTL */
|
|
48
|
+
expirations: number;
|
|
49
|
+
/** Current number of entries in cache */
|
|
50
|
+
size: number;
|
|
51
|
+
/** Maximum size of cache */
|
|
52
|
+
maxSize: number;
|
|
53
|
+
/** Cache hit ratio (hits / (hits + misses)) */
|
|
54
|
+
hitRatio: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* LRU Cache Manager for analysis results
|
|
58
|
+
*
|
|
59
|
+
* Implements a Least Recently Used (LRU) eviction strategy with:
|
|
60
|
+
* - File hash-based cache keys
|
|
61
|
+
* - Configurable maximum size
|
|
62
|
+
* - Optional TTL-based expiration
|
|
63
|
+
* - Statistics tracking (hits, misses, evictions)
|
|
64
|
+
* - Optional persistence to disk
|
|
65
|
+
*/
|
|
66
|
+
export declare class CacheManager<T = unknown> {
|
|
67
|
+
private readonly options;
|
|
68
|
+
private readonly cache;
|
|
69
|
+
private head;
|
|
70
|
+
private tail;
|
|
71
|
+
private stats;
|
|
72
|
+
constructor(options?: Partial<CacheManagerOptions>);
|
|
73
|
+
/**
|
|
74
|
+
* Get a value from the cache by its hash key
|
|
75
|
+
*
|
|
76
|
+
* @param hash - The file content hash to look up
|
|
77
|
+
* @returns The cached value or undefined if not found/expired
|
|
78
|
+
*/
|
|
79
|
+
get(hash: string): T | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Store a value in the cache with the given hash key
|
|
82
|
+
*
|
|
83
|
+
* @param hash - The file content hash to use as key
|
|
84
|
+
* @param value - The value to cache
|
|
85
|
+
* @param size - Optional size estimate in bytes
|
|
86
|
+
*/
|
|
87
|
+
set(hash: string, value: T, size?: number): void;
|
|
88
|
+
/**
|
|
89
|
+
* Check if a hash key exists in the cache (without updating LRU order)
|
|
90
|
+
*
|
|
91
|
+
* @param hash - The file content hash to check
|
|
92
|
+
* @returns True if the key exists and is not expired
|
|
93
|
+
*/
|
|
94
|
+
has(hash: string): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Delete an entry from the cache
|
|
97
|
+
*
|
|
98
|
+
* @param hash - The file content hash to delete
|
|
99
|
+
* @returns True if the entry was deleted, false if not found
|
|
100
|
+
*/
|
|
101
|
+
delete(hash: string): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Clear all entries from the cache
|
|
104
|
+
*/
|
|
105
|
+
clear(): void;
|
|
106
|
+
/**
|
|
107
|
+
* Get the current cache statistics
|
|
108
|
+
*
|
|
109
|
+
* @returns Current cache statistics
|
|
110
|
+
*/
|
|
111
|
+
getStats(): CacheStats;
|
|
112
|
+
/**
|
|
113
|
+
* Reset cache statistics
|
|
114
|
+
*/
|
|
115
|
+
resetStats(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Get all cache entries (for debugging/persistence)
|
|
118
|
+
*
|
|
119
|
+
* @returns Array of all cache entries
|
|
120
|
+
*/
|
|
121
|
+
entries(): Array<{
|
|
122
|
+
key: string;
|
|
123
|
+
entry: CacheEntry<T>;
|
|
124
|
+
}>;
|
|
125
|
+
/**
|
|
126
|
+
* Get the current size of the cache
|
|
127
|
+
*
|
|
128
|
+
* @returns Number of entries in the cache
|
|
129
|
+
*/
|
|
130
|
+
get size(): number;
|
|
131
|
+
/**
|
|
132
|
+
* Compute a SHA-256 hash of file content
|
|
133
|
+
*
|
|
134
|
+
* @param content - The file content to hash
|
|
135
|
+
* @returns The hex-encoded SHA-256 hash
|
|
136
|
+
*/
|
|
137
|
+
static computeHash(content: string | Buffer): string;
|
|
138
|
+
/**
|
|
139
|
+
* Compute a SHA-256 hash of a file on disk
|
|
140
|
+
*
|
|
141
|
+
* @param filePath - Path to the file
|
|
142
|
+
* @returns The hex-encoded SHA-256 hash
|
|
143
|
+
*/
|
|
144
|
+
static computeFileHash(filePath: string): Promise<string>;
|
|
145
|
+
/**
|
|
146
|
+
* Persist the cache to disk
|
|
147
|
+
*
|
|
148
|
+
* @param filePath - Path to save the cache (uses options.persistPath if not provided)
|
|
149
|
+
*/
|
|
150
|
+
persist(filePath?: string): Promise<void>;
|
|
151
|
+
/**
|
|
152
|
+
* Load the cache from disk
|
|
153
|
+
*
|
|
154
|
+
* @param filePath - Path to load the cache from (uses options.persistPath if not provided)
|
|
155
|
+
*/
|
|
156
|
+
load(filePath?: string): Promise<void>;
|
|
157
|
+
/**
|
|
158
|
+
* Invalidate cache entries for a specific file and its dependents
|
|
159
|
+
*
|
|
160
|
+
* @param hash - The hash of the file that changed
|
|
161
|
+
* @param dependentHashes - Hashes of files that depend on the changed file
|
|
162
|
+
* @returns Number of entries invalidated
|
|
163
|
+
*/
|
|
164
|
+
invalidate(hash: string, dependentHashes?: string[]): number;
|
|
165
|
+
/**
|
|
166
|
+
* Prune expired entries from the cache
|
|
167
|
+
*
|
|
168
|
+
* @returns Number of entries pruned
|
|
169
|
+
*/
|
|
170
|
+
prune(): number;
|
|
171
|
+
private isExpired;
|
|
172
|
+
private isExpiredAt;
|
|
173
|
+
private addToFront;
|
|
174
|
+
private removeFromList;
|
|
175
|
+
private moveToFront;
|
|
176
|
+
private evictLRU;
|
|
177
|
+
private updateHitRatio;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=cache-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-manager.d.ts","sourceRoot":"","sources":["../../src/store/cache-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache Manager - Analysis result caching
|
|
3
|
+
*
|
|
4
|
+
* LRU cache for analysis results with file hash-based keys.
|
|
5
|
+
* Handles cache invalidation on file changes.
|
|
6
|
+
*
|
|
7
|
+
* @requirements 2.5 - THE Scanner SHALL cache analysis results using file content hashes
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'node:fs/promises';
|
|
10
|
+
import * as path from 'node:path';
|
|
11
|
+
import * as crypto from 'node:crypto';
|
|
12
|
+
const DEFAULT_OPTIONS = {
|
|
13
|
+
maxSize: 1000,
|
|
14
|
+
ttl: 3600000, // 1 hour
|
|
15
|
+
enableStats: true,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* LRU Cache Manager for analysis results
|
|
19
|
+
*
|
|
20
|
+
* Implements a Least Recently Used (LRU) eviction strategy with:
|
|
21
|
+
* - File hash-based cache keys
|
|
22
|
+
* - Configurable maximum size
|
|
23
|
+
* - Optional TTL-based expiration
|
|
24
|
+
* - Statistics tracking (hits, misses, evictions)
|
|
25
|
+
* - Optional persistence to disk
|
|
26
|
+
*/
|
|
27
|
+
export class CacheManager {
|
|
28
|
+
options;
|
|
29
|
+
cache;
|
|
30
|
+
head = null;
|
|
31
|
+
tail = null;
|
|
32
|
+
stats;
|
|
33
|
+
constructor(options = {}) {
|
|
34
|
+
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
35
|
+
this.cache = new Map();
|
|
36
|
+
this.stats = {
|
|
37
|
+
hits: 0,
|
|
38
|
+
misses: 0,
|
|
39
|
+
evictions: 0,
|
|
40
|
+
expirations: 0,
|
|
41
|
+
size: 0,
|
|
42
|
+
maxSize: this.options.maxSize,
|
|
43
|
+
hitRatio: 0,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get a value from the cache by its hash key
|
|
48
|
+
*
|
|
49
|
+
* @param hash - The file content hash to look up
|
|
50
|
+
* @returns The cached value or undefined if not found/expired
|
|
51
|
+
*/
|
|
52
|
+
get(hash) {
|
|
53
|
+
const node = this.cache.get(hash);
|
|
54
|
+
if (!node) {
|
|
55
|
+
if (this.options.enableStats) {
|
|
56
|
+
this.stats.misses++;
|
|
57
|
+
this.updateHitRatio();
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
// Check TTL expiration
|
|
62
|
+
if (this.isExpired(node.entry)) {
|
|
63
|
+
this.delete(hash);
|
|
64
|
+
if (this.options.enableStats) {
|
|
65
|
+
this.stats.misses++;
|
|
66
|
+
this.stats.expirations++;
|
|
67
|
+
this.updateHitRatio();
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
// Move to front (most recently used)
|
|
72
|
+
this.moveToFront(node);
|
|
73
|
+
// Update stats
|
|
74
|
+
if (this.options.enableStats) {
|
|
75
|
+
node.entry.hits++;
|
|
76
|
+
this.stats.hits++;
|
|
77
|
+
this.updateHitRatio();
|
|
78
|
+
}
|
|
79
|
+
return node.entry.value;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Store a value in the cache with the given hash key
|
|
83
|
+
*
|
|
84
|
+
* @param hash - The file content hash to use as key
|
|
85
|
+
* @param value - The value to cache
|
|
86
|
+
* @param size - Optional size estimate in bytes
|
|
87
|
+
*/
|
|
88
|
+
set(hash, value, size = 0) {
|
|
89
|
+
// Check if key already exists
|
|
90
|
+
const existingNode = this.cache.get(hash);
|
|
91
|
+
if (existingNode) {
|
|
92
|
+
// Update existing entry
|
|
93
|
+
existingNode.entry.value = value;
|
|
94
|
+
existingNode.entry.timestamp = Date.now();
|
|
95
|
+
existingNode.entry.size = size;
|
|
96
|
+
this.moveToFront(existingNode);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// Evict if at capacity
|
|
100
|
+
while (this.cache.size >= this.options.maxSize) {
|
|
101
|
+
this.evictLRU();
|
|
102
|
+
}
|
|
103
|
+
// Create new entry
|
|
104
|
+
const entry = {
|
|
105
|
+
value,
|
|
106
|
+
hash,
|
|
107
|
+
timestamp: Date.now(),
|
|
108
|
+
hits: 0,
|
|
109
|
+
size,
|
|
110
|
+
};
|
|
111
|
+
const node = {
|
|
112
|
+
key: hash,
|
|
113
|
+
entry,
|
|
114
|
+
prev: null,
|
|
115
|
+
next: null,
|
|
116
|
+
};
|
|
117
|
+
// Add to cache and front of list
|
|
118
|
+
this.cache.set(hash, node);
|
|
119
|
+
this.addToFront(node);
|
|
120
|
+
this.stats.size = this.cache.size;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if a hash key exists in the cache (without updating LRU order)
|
|
124
|
+
*
|
|
125
|
+
* @param hash - The file content hash to check
|
|
126
|
+
* @returns True if the key exists and is not expired
|
|
127
|
+
*/
|
|
128
|
+
has(hash) {
|
|
129
|
+
const node = this.cache.get(hash);
|
|
130
|
+
if (!node) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
// Check TTL expiration
|
|
134
|
+
if (this.isExpired(node.entry)) {
|
|
135
|
+
this.delete(hash);
|
|
136
|
+
if (this.options.enableStats) {
|
|
137
|
+
this.stats.expirations++;
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Delete an entry from the cache
|
|
145
|
+
*
|
|
146
|
+
* @param hash - The file content hash to delete
|
|
147
|
+
* @returns True if the entry was deleted, false if not found
|
|
148
|
+
*/
|
|
149
|
+
delete(hash) {
|
|
150
|
+
const node = this.cache.get(hash);
|
|
151
|
+
if (!node) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
this.removeFromList(node);
|
|
155
|
+
this.cache.delete(hash);
|
|
156
|
+
this.stats.size = this.cache.size;
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Clear all entries from the cache
|
|
161
|
+
*/
|
|
162
|
+
clear() {
|
|
163
|
+
this.cache.clear();
|
|
164
|
+
this.head = null;
|
|
165
|
+
this.tail = null;
|
|
166
|
+
this.stats.size = 0;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get the current cache statistics
|
|
170
|
+
*
|
|
171
|
+
* @returns Current cache statistics
|
|
172
|
+
*/
|
|
173
|
+
getStats() {
|
|
174
|
+
return { ...this.stats };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Reset cache statistics
|
|
178
|
+
*/
|
|
179
|
+
resetStats() {
|
|
180
|
+
this.stats = {
|
|
181
|
+
hits: 0,
|
|
182
|
+
misses: 0,
|
|
183
|
+
evictions: 0,
|
|
184
|
+
expirations: 0,
|
|
185
|
+
size: this.cache.size,
|
|
186
|
+
maxSize: this.options.maxSize,
|
|
187
|
+
hitRatio: 0,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get all cache entries (for debugging/persistence)
|
|
192
|
+
*
|
|
193
|
+
* @returns Array of all cache entries
|
|
194
|
+
*/
|
|
195
|
+
entries() {
|
|
196
|
+
const result = [];
|
|
197
|
+
for (const [key, node] of this.cache) {
|
|
198
|
+
if (!this.isExpired(node.entry)) {
|
|
199
|
+
result.push({ key, entry: node.entry });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get the current size of the cache
|
|
206
|
+
*
|
|
207
|
+
* @returns Number of entries in the cache
|
|
208
|
+
*/
|
|
209
|
+
get size() {
|
|
210
|
+
return this.cache.size;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Compute a SHA-256 hash of file content
|
|
214
|
+
*
|
|
215
|
+
* @param content - The file content to hash
|
|
216
|
+
* @returns The hex-encoded SHA-256 hash
|
|
217
|
+
*/
|
|
218
|
+
static computeHash(content) {
|
|
219
|
+
return crypto.createHash('sha256').update(content).digest('hex');
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Compute a SHA-256 hash of a file on disk
|
|
223
|
+
*
|
|
224
|
+
* @param filePath - Path to the file
|
|
225
|
+
* @returns The hex-encoded SHA-256 hash
|
|
226
|
+
*/
|
|
227
|
+
static async computeFileHash(filePath) {
|
|
228
|
+
const content = await fs.readFile(filePath);
|
|
229
|
+
return CacheManager.computeHash(content);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Persist the cache to disk
|
|
233
|
+
*
|
|
234
|
+
* @param filePath - Path to save the cache (uses options.persistPath if not provided)
|
|
235
|
+
*/
|
|
236
|
+
async persist(filePath) {
|
|
237
|
+
const targetPath = filePath ?? this.options.persistPath;
|
|
238
|
+
if (!targetPath) {
|
|
239
|
+
throw new Error('No persist path specified');
|
|
240
|
+
}
|
|
241
|
+
const persistedCache = {
|
|
242
|
+
version: '1.0.0',
|
|
243
|
+
createdAt: new Date().toISOString(),
|
|
244
|
+
entries: this.entries(),
|
|
245
|
+
};
|
|
246
|
+
// Ensure directory exists
|
|
247
|
+
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
248
|
+
await fs.writeFile(targetPath, JSON.stringify(persistedCache, null, 2));
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Load the cache from disk
|
|
252
|
+
*
|
|
253
|
+
* @param filePath - Path to load the cache from (uses options.persistPath if not provided)
|
|
254
|
+
*/
|
|
255
|
+
async load(filePath) {
|
|
256
|
+
const targetPath = filePath ?? this.options.persistPath;
|
|
257
|
+
if (!targetPath) {
|
|
258
|
+
throw new Error('No persist path specified');
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
const content = await fs.readFile(targetPath, 'utf-8');
|
|
262
|
+
const persistedCache = JSON.parse(content);
|
|
263
|
+
if (!persistedCache.version) {
|
|
264
|
+
throw new Error('Invalid cache file: missing version');
|
|
265
|
+
}
|
|
266
|
+
if (persistedCache.version !== '1.0.0') {
|
|
267
|
+
throw new Error(`Unsupported cache version: ${persistedCache.version}`);
|
|
268
|
+
}
|
|
269
|
+
// Clear current cache and load entries
|
|
270
|
+
this.clear();
|
|
271
|
+
for (const { key, entry } of persistedCache.entries) {
|
|
272
|
+
// Skip expired entries
|
|
273
|
+
if (!this.isExpired(entry)) {
|
|
274
|
+
this.set(key, entry.value, entry.size);
|
|
275
|
+
// Restore original timestamp and hits
|
|
276
|
+
const node = this.cache.get(key);
|
|
277
|
+
if (node) {
|
|
278
|
+
node.entry.timestamp = entry.timestamp;
|
|
279
|
+
node.entry.hits = entry.hits;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
if (error.code === 'ENOENT') {
|
|
286
|
+
// File doesn't exist, start with empty cache
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Invalidate cache entries for a specific file and its dependents
|
|
294
|
+
*
|
|
295
|
+
* @param hash - The hash of the file that changed
|
|
296
|
+
* @param dependentHashes - Hashes of files that depend on the changed file
|
|
297
|
+
* @returns Number of entries invalidated
|
|
298
|
+
*/
|
|
299
|
+
invalidate(hash, dependentHashes = []) {
|
|
300
|
+
let count = 0;
|
|
301
|
+
if (this.delete(hash)) {
|
|
302
|
+
count++;
|
|
303
|
+
}
|
|
304
|
+
for (const depHash of dependentHashes) {
|
|
305
|
+
if (this.delete(depHash)) {
|
|
306
|
+
count++;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return count;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Prune expired entries from the cache
|
|
313
|
+
*
|
|
314
|
+
* @returns Number of entries pruned
|
|
315
|
+
*/
|
|
316
|
+
prune() {
|
|
317
|
+
let count = 0;
|
|
318
|
+
const now = Date.now();
|
|
319
|
+
for (const [key, node] of this.cache) {
|
|
320
|
+
if (this.isExpiredAt(node.entry, now)) {
|
|
321
|
+
this.delete(key);
|
|
322
|
+
count++;
|
|
323
|
+
if (this.options.enableStats) {
|
|
324
|
+
this.stats.expirations++;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return count;
|
|
329
|
+
}
|
|
330
|
+
// Private helper methods
|
|
331
|
+
isExpired(entry) {
|
|
332
|
+
return this.isExpiredAt(entry, Date.now());
|
|
333
|
+
}
|
|
334
|
+
isExpiredAt(entry, now) {
|
|
335
|
+
if (this.options.ttl === 0) {
|
|
336
|
+
return false; // No expiration
|
|
337
|
+
}
|
|
338
|
+
return now - entry.timestamp > this.options.ttl;
|
|
339
|
+
}
|
|
340
|
+
addToFront(node) {
|
|
341
|
+
node.prev = null;
|
|
342
|
+
node.next = this.head;
|
|
343
|
+
if (this.head) {
|
|
344
|
+
this.head.prev = node;
|
|
345
|
+
}
|
|
346
|
+
this.head = node;
|
|
347
|
+
if (!this.tail) {
|
|
348
|
+
this.tail = node;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
removeFromList(node) {
|
|
352
|
+
if (node.prev) {
|
|
353
|
+
node.prev.next = node.next;
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
this.head = node.next;
|
|
357
|
+
}
|
|
358
|
+
if (node.next) {
|
|
359
|
+
node.next.prev = node.prev;
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
this.tail = node.prev;
|
|
363
|
+
}
|
|
364
|
+
node.prev = null;
|
|
365
|
+
node.next = null;
|
|
366
|
+
}
|
|
367
|
+
moveToFront(node) {
|
|
368
|
+
if (node === this.head) {
|
|
369
|
+
return; // Already at front
|
|
370
|
+
}
|
|
371
|
+
this.removeFromList(node);
|
|
372
|
+
this.addToFront(node);
|
|
373
|
+
}
|
|
374
|
+
evictLRU() {
|
|
375
|
+
if (!this.tail) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const key = this.tail.key;
|
|
379
|
+
this.removeFromList(this.tail);
|
|
380
|
+
this.cache.delete(key);
|
|
381
|
+
if (this.options.enableStats) {
|
|
382
|
+
this.stats.evictions++;
|
|
383
|
+
}
|
|
384
|
+
this.stats.size = this.cache.size;
|
|
385
|
+
}
|
|
386
|
+
updateHitRatio() {
|
|
387
|
+
const total = this.stats.hits + this.stats.misses;
|
|
388
|
+
this.stats.hitRatio = total > 0 ? this.stats.hits / total : 0;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
//# sourceMappingURL=cache-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-manager.js","sourceRoot":"","sources":["../../src/store/cache-manager.ts"],"names":[],"mappings":"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"}
|