@git.zone/tsdoc 1.11.0 → 1.11.2

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 (62) hide show
  1. package/dist_ts/aidocs_classes/commit.js +27 -34
  2. package/dist_ts/aidocs_classes/description.js +68 -29
  3. package/dist_ts/aidocs_classes/projectcontext.d.ts +5 -5
  4. package/dist_ts/aidocs_classes/projectcontext.js +8 -16
  5. package/dist_ts/aidocs_classes/readme.js +156 -88
  6. package/dist_ts/classes.aidoc.d.ts +10 -6
  7. package/dist_ts/classes.aidoc.js +17 -11
  8. package/dist_ts/classes.diffprocessor.js +284 -0
  9. package/dist_ts/cli.js +21 -92
  10. package/dist_ts/plugins.d.ts +1 -2
  11. package/dist_ts/plugins.js +2 -3
  12. package/package.json +11 -13
  13. package/ts/aidocs_classes/commit.ts +26 -41
  14. package/ts/aidocs_classes/description.ts +72 -34
  15. package/ts/aidocs_classes/projectcontext.ts +7 -14
  16. package/ts/aidocs_classes/readme.ts +168 -93
  17. package/ts/classes.aidoc.ts +18 -11
  18. package/ts/cli.ts +20 -100
  19. package/ts/plugins.ts +1 -2
  20. package/dist_ts/context/config-manager.d.ts +0 -83
  21. package/dist_ts/context/config-manager.js +0 -318
  22. package/dist_ts/context/context-analyzer.d.ts +0 -73
  23. package/dist_ts/context/context-analyzer.js +0 -311
  24. package/dist_ts/context/context-cache.d.ts +0 -73
  25. package/dist_ts/context/context-cache.js +0 -239
  26. package/dist_ts/context/context-trimmer.d.ts +0 -60
  27. package/dist_ts/context/context-trimmer.js +0 -258
  28. package/dist_ts/context/diff-processor.js +0 -284
  29. package/dist_ts/context/enhanced-context.d.ts +0 -73
  30. package/dist_ts/context/enhanced-context.js +0 -275
  31. package/dist_ts/context/index.d.ts +0 -11
  32. package/dist_ts/context/index.js +0 -12
  33. package/dist_ts/context/iterative-context-builder.d.ts +0 -62
  34. package/dist_ts/context/iterative-context-builder.js +0 -395
  35. package/dist_ts/context/lazy-file-loader.d.ts +0 -60
  36. package/dist_ts/context/lazy-file-loader.js +0 -182
  37. package/dist_ts/context/task-context-factory.d.ts +0 -48
  38. package/dist_ts/context/task-context-factory.js +0 -86
  39. package/dist_ts/context/types.d.ts +0 -301
  40. package/dist_ts/context/types.js +0 -2
  41. package/dist_ts/tsdoc.classes.typedoc.d.ts +0 -10
  42. package/dist_ts/tsdoc.classes.typedoc.js +0 -48
  43. package/dist_ts/tsdoc.cli.d.ts +0 -1
  44. package/dist_ts/tsdoc.cli.js +0 -32
  45. package/dist_ts/tsdoc.logging.d.ts +0 -2
  46. package/dist_ts/tsdoc.logging.js +0 -14
  47. package/dist_ts/tsdoc.paths.d.ts +0 -8
  48. package/dist_ts/tsdoc.paths.js +0 -12
  49. package/dist_ts/tsdoc.plugins.d.ts +0 -11
  50. package/dist_ts/tsdoc.plugins.js +0 -15
  51. package/ts/context/config-manager.ts +0 -369
  52. package/ts/context/context-analyzer.ts +0 -391
  53. package/ts/context/context-cache.ts +0 -286
  54. package/ts/context/context-trimmer.ts +0 -310
  55. package/ts/context/enhanced-context.ts +0 -332
  56. package/ts/context/index.ts +0 -70
  57. package/ts/context/iterative-context-builder.ts +0 -512
  58. package/ts/context/lazy-file-loader.ts +0 -207
  59. package/ts/context/task-context-factory.ts +0 -120
  60. package/ts/context/types.ts +0 -324
  61. /package/dist_ts/{context/diff-processor.d.ts → classes.diffprocessor.d.ts} +0 -0
  62. /package/ts/{context/diff-processor.ts → classes.diffprocessor.ts} +0 -0
@@ -1,311 +0,0 @@
1
- import * as plugins from '../plugins.js';
2
- /**
3
- * ContextAnalyzer provides intelligent file selection and prioritization
4
- * based on dependency analysis, task relevance, and configurable weights
5
- */
6
- export class ContextAnalyzer {
7
- /**
8
- * Creates a new ContextAnalyzer
9
- * @param projectRoot - Root directory of the project
10
- * @param weights - Prioritization weights
11
- * @param tiers - Tier configuration
12
- */
13
- constructor(projectRoot, weights = {}, tiers = {}) {
14
- this.projectRoot = projectRoot;
15
- // Default weights
16
- this.weights = {
17
- dependencyWeight: weights.dependencyWeight ?? 0.3,
18
- relevanceWeight: weights.relevanceWeight ?? 0.4,
19
- efficiencyWeight: weights.efficiencyWeight ?? 0.2,
20
- recencyWeight: weights.recencyWeight ?? 0.1,
21
- };
22
- // Default tiers
23
- this.tiers = {
24
- essential: tiers.essential ?? { minScore: 0.8, trimLevel: 'none' },
25
- important: tiers.important ?? { minScore: 0.5, trimLevel: 'light' },
26
- optional: tiers.optional ?? { minScore: 0.2, trimLevel: 'aggressive' },
27
- };
28
- }
29
- /**
30
- * Analyzes files for a specific task type
31
- * @param metadata - Array of file metadata to analyze
32
- * @param taskType - Type of task being performed
33
- * @param changedFiles - Optional list of recently changed files (for commits)
34
- * @returns Analysis result with scored files
35
- */
36
- async analyze(metadata, taskType, changedFiles = []) {
37
- const startTime = Date.now();
38
- // Build dependency graph
39
- const dependencyGraph = await this.buildDependencyGraph(metadata);
40
- // Calculate centrality scores
41
- this.calculateCentrality(dependencyGraph);
42
- // Analyze each file
43
- const files = [];
44
- for (const meta of metadata) {
45
- const analysis = await this.analyzeFile(meta, taskType, dependencyGraph, changedFiles);
46
- files.push(analysis);
47
- }
48
- // Sort by importance score (highest first)
49
- files.sort((a, b) => b.importanceScore - a.importanceScore);
50
- const analysisDuration = Date.now() - startTime;
51
- return {
52
- taskType,
53
- files,
54
- dependencyGraph,
55
- totalFiles: metadata.length,
56
- analysisDuration,
57
- };
58
- }
59
- /**
60
- * Builds a dependency graph from file metadata
61
- * @param metadata - Array of file metadata
62
- * @returns Dependency graph as a map
63
- */
64
- async buildDependencyGraph(metadata) {
65
- const graph = new Map();
66
- // Initialize graph entries
67
- for (const meta of metadata) {
68
- graph.set(meta.path, {
69
- path: meta.path,
70
- imports: [],
71
- importedBy: [],
72
- centrality: 0,
73
- });
74
- }
75
- // Parse imports from each file
76
- for (const meta of metadata) {
77
- try {
78
- const contents = await plugins.fsInstance.file(meta.path).encoding('utf8').read();
79
- const imports = this.extractImports(contents, meta.path);
80
- const deps = graph.get(meta.path);
81
- deps.imports = imports;
82
- // Update importedBy for imported files
83
- for (const importPath of imports) {
84
- const importedDeps = graph.get(importPath);
85
- if (importedDeps) {
86
- importedDeps.importedBy.push(meta.path);
87
- }
88
- }
89
- }
90
- catch (error) {
91
- console.warn(`Failed to parse imports from ${meta.path}:`, error.message);
92
- }
93
- }
94
- return graph;
95
- }
96
- /**
97
- * Extracts import statements from file contents
98
- * @param contents - File contents
99
- * @param filePath - Path of the file being analyzed
100
- * @returns Array of absolute paths to imported files
101
- */
102
- extractImports(contents, filePath) {
103
- const imports = [];
104
- const fileDir = plugins.path.dirname(filePath);
105
- // Match various import patterns
106
- const importRegex = /(?:import|export).*?from\s+['"](.+?)['"]/g;
107
- let match;
108
- while ((match = importRegex.exec(contents)) !== null) {
109
- const importPath = match[1];
110
- // Skip external modules
111
- if (!importPath.startsWith('.')) {
112
- continue;
113
- }
114
- // Resolve relative import to absolute path
115
- let resolvedPath = plugins.path.resolve(fileDir, importPath);
116
- // Handle various file extensions
117
- const extensions = ['.ts', '.js', '.tsx', '.jsx', '/index.ts', '/index.js'];
118
- let found = false;
119
- for (const ext of extensions) {
120
- const testPath = resolvedPath.endsWith(ext) ? resolvedPath : resolvedPath + ext;
121
- try {
122
- // Use synchronous file check to avoid async in this context
123
- const fs = require('fs');
124
- const exists = fs.existsSync(testPath);
125
- if (exists) {
126
- imports.push(testPath);
127
- found = true;
128
- break;
129
- }
130
- }
131
- catch (error) {
132
- // Continue trying other extensions
133
- }
134
- }
135
- if (!found && !resolvedPath.includes('.')) {
136
- // Try with .ts extension as default
137
- imports.push(resolvedPath + '.ts');
138
- }
139
- }
140
- return imports;
141
- }
142
- /**
143
- * Calculates centrality scores for all nodes in the dependency graph
144
- * Uses a simplified PageRank-like algorithm
145
- * @param graph - Dependency graph
146
- */
147
- calculateCentrality(graph) {
148
- const damping = 0.85;
149
- const iterations = 10;
150
- const nodeCount = graph.size;
151
- // Initialize scores
152
- const scores = new Map();
153
- for (const path of graph.keys()) {
154
- scores.set(path, 1.0 / nodeCount);
155
- }
156
- // Iterative calculation
157
- for (let i = 0; i < iterations; i++) {
158
- const newScores = new Map();
159
- for (const [path, deps] of graph.entries()) {
160
- let score = (1 - damping) / nodeCount;
161
- // Add contributions from nodes that import this file
162
- for (const importerPath of deps.importedBy) {
163
- const importerDeps = graph.get(importerPath);
164
- if (importerDeps) {
165
- const importerScore = scores.get(importerPath) ?? 0;
166
- const outgoingCount = importerDeps.imports.length || 1;
167
- score += damping * (importerScore / outgoingCount);
168
- }
169
- }
170
- newScores.set(path, score);
171
- }
172
- // Update scores
173
- for (const [path, score] of newScores) {
174
- scores.set(path, score);
175
- }
176
- }
177
- // Normalize scores to 0-1 range
178
- const maxScore = Math.max(...scores.values());
179
- if (maxScore > 0) {
180
- for (const deps of graph.values()) {
181
- const score = scores.get(deps.path) ?? 0;
182
- deps.centrality = score / maxScore;
183
- }
184
- }
185
- }
186
- /**
187
- * Analyzes a single file
188
- * @param meta - File metadata
189
- * @param taskType - Task being performed
190
- * @param graph - Dependency graph
191
- * @param changedFiles - Recently changed files
192
- * @returns File analysis
193
- */
194
- async analyzeFile(meta, taskType, graph, changedFiles) {
195
- const deps = graph.get(meta.path);
196
- const centralityScore = deps?.centrality ?? 0;
197
- // Calculate task-specific relevance
198
- const relevanceScore = this.calculateRelevance(meta, taskType);
199
- // Calculate efficiency (information per token)
200
- const efficiencyScore = this.calculateEfficiency(meta);
201
- // Calculate recency (for commit tasks)
202
- const recencyScore = this.calculateRecency(meta, changedFiles);
203
- // Calculate combined importance score
204
- const importanceScore = relevanceScore * this.weights.relevanceWeight +
205
- centralityScore * this.weights.dependencyWeight +
206
- efficiencyScore * this.weights.efficiencyWeight +
207
- recencyScore * this.weights.recencyWeight;
208
- // Assign tier
209
- const tier = this.assignTier(importanceScore);
210
- return {
211
- path: meta.path,
212
- relevanceScore,
213
- centralityScore,
214
- efficiencyScore,
215
- recencyScore,
216
- importanceScore,
217
- tier,
218
- reason: this.generateReason(meta, taskType, importanceScore, tier),
219
- };
220
- }
221
- /**
222
- * Calculates task-specific relevance score
223
- */
224
- calculateRelevance(meta, taskType) {
225
- const relativePath = meta.relativePath.toLowerCase();
226
- let score = 0.5; // Base score
227
- // README generation - prioritize public APIs and main exports
228
- if (taskType === 'readme') {
229
- if (relativePath.includes('index.ts'))
230
- score += 0.3;
231
- if (relativePath.match(/^ts\/[^\/]+\.ts$/))
232
- score += 0.2; // Root level exports
233
- if (relativePath.includes('test/'))
234
- score -= 0.3;
235
- if (relativePath.includes('classes/'))
236
- score += 0.1;
237
- if (relativePath.includes('interfaces/'))
238
- score += 0.1;
239
- }
240
- // Commit messages - prioritize changed files and their dependencies
241
- if (taskType === 'commit') {
242
- if (relativePath.includes('test/'))
243
- score -= 0.2;
244
- // Recency will handle changed files
245
- }
246
- // Description generation - prioritize main exports and core interfaces
247
- if (taskType === 'description') {
248
- if (relativePath.includes('index.ts'))
249
- score += 0.4;
250
- if (relativePath.match(/^ts\/[^\/]+\.ts$/))
251
- score += 0.3;
252
- if (relativePath.includes('test/'))
253
- score -= 0.4;
254
- if (relativePath.includes('interfaces/'))
255
- score += 0.2;
256
- }
257
- return Math.max(0, Math.min(1, score));
258
- }
259
- /**
260
- * Calculates efficiency score (information density)
261
- */
262
- calculateEfficiency(meta) {
263
- // Prefer files that are not too large (good signal-to-noise ratio)
264
- const optimalSize = 5000; // ~1250 tokens
265
- const distance = Math.abs(meta.estimatedTokens - optimalSize);
266
- const normalized = Math.max(0, 1 - distance / optimalSize);
267
- return normalized;
268
- }
269
- /**
270
- * Calculates recency score for changed files
271
- */
272
- calculateRecency(meta, changedFiles) {
273
- if (changedFiles.length === 0) {
274
- return 0;
275
- }
276
- // Check if this file was changed
277
- const isChanged = changedFiles.some((changed) => changed === meta.path);
278
- return isChanged ? 1.0 : 0.0;
279
- }
280
- /**
281
- * Assigns a tier based on importance score
282
- */
283
- assignTier(score) {
284
- if (score >= this.tiers.essential.minScore)
285
- return 'essential';
286
- if (score >= this.tiers.important.minScore)
287
- return 'important';
288
- if (score >= this.tiers.optional.minScore)
289
- return 'optional';
290
- return 'excluded';
291
- }
292
- /**
293
- * Generates a human-readable reason for the score
294
- */
295
- generateReason(meta, taskType, score, tier) {
296
- const reasons = [];
297
- if (meta.relativePath.includes('index.ts')) {
298
- reasons.push('main export file');
299
- }
300
- if (meta.relativePath.includes('test/')) {
301
- reasons.push('test file (lower priority)');
302
- }
303
- if (taskType === 'readme' && meta.relativePath.match(/^ts\/[^\/]+\.ts$/)) {
304
- reasons.push('root-level module');
305
- }
306
- reasons.push(`score: ${score.toFixed(2)}`);
307
- reasons.push(`tier: ${tier}`);
308
- return reasons.join(', ');
309
- }
310
- }
311
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1hbmFseXplci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NvbnRleHQvY29udGV4dC1hbmFseXplci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQVd6Qzs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQUsxQjs7Ozs7T0FLRztJQUNILFlBQ0UsV0FBbUIsRUFDbkIsVUFBMkMsRUFBRSxFQUM3QyxRQUE4QixFQUFFO1FBRWhDLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBRS9CLGtCQUFrQjtRQUNsQixJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2IsZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLGdCQUFnQixJQUFJLEdBQUc7WUFDakQsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlLElBQUksR0FBRztZQUMvQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsZ0JBQWdCLElBQUksR0FBRztZQUNqRCxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWEsSUFBSSxHQUFHO1NBQzVDLENBQUM7UUFFRixnQkFBZ0I7UUFDaEIsSUFBSSxDQUFDLEtBQUssR0FBRztZQUNYLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUyxJQUFJLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFO1lBQ2xFLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUyxJQUFJLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFO1lBQ25FLFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUSxJQUFJLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFO1NBQ3ZFLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksS0FBSyxDQUFDLE9BQU8sQ0FDbEIsUUFBeUIsRUFDekIsUUFBa0IsRUFDbEIsZUFBeUIsRUFBRTtR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
@@ -1,73 +0,0 @@
1
- import type { ICacheEntry, ICacheConfig } from './types.js';
2
- /**
3
- * ContextCache provides persistent caching of file contents and token counts
4
- * with automatic invalidation on file changes
5
- */
6
- export declare class ContextCache {
7
- private cacheDir;
8
- private cache;
9
- private config;
10
- private cacheIndexPath;
11
- /**
12
- * Creates a new ContextCache
13
- * @param projectRoot - Root directory of the project
14
- * @param config - Cache configuration
15
- */
16
- constructor(projectRoot: string, config?: Partial<ICacheConfig>);
17
- /**
18
- * Initializes the cache by loading from disk
19
- */
20
- init(): Promise<void>;
21
- /**
22
- * Gets a cached entry if it's still valid
23
- * @param filePath - Absolute path to the file
24
- * @returns Cache entry if valid, null otherwise
25
- */
26
- get(filePath: string): Promise<ICacheEntry | null>;
27
- /**
28
- * Stores a cache entry
29
- * @param entry - Cache entry to store
30
- */
31
- set(entry: ICacheEntry): Promise<void>;
32
- /**
33
- * Stores multiple cache entries
34
- * @param entries - Array of cache entries
35
- */
36
- setMany(entries: ICacheEntry[]): Promise<void>;
37
- /**
38
- * Checks if a file is cached and valid
39
- * @param filePath - Absolute path to the file
40
- * @returns True if cached and valid
41
- */
42
- has(filePath: string): Promise<boolean>;
43
- /**
44
- * Gets cache statistics
45
- */
46
- getStats(): {
47
- entries: number;
48
- totalSize: number;
49
- oldestEntry: number | null;
50
- newestEntry: number | null;
51
- };
52
- /**
53
- * Clears all cache entries
54
- */
55
- clear(): Promise<void>;
56
- /**
57
- * Clears specific cache entries
58
- * @param filePaths - Array of file paths to clear
59
- */
60
- clearPaths(filePaths: string[]): Promise<void>;
61
- /**
62
- * Cleans up expired and invalid cache entries
63
- */
64
- private cleanup;
65
- /**
66
- * Enforces maximum cache size by evicting oldest entries
67
- */
68
- private enforceMaxSize;
69
- /**
70
- * Persists cache index to disk
71
- */
72
- private persist;
73
- }
@@ -1,239 +0,0 @@
1
- import * as plugins from '../plugins.js';
2
- import * as fs from 'fs';
3
- import { logger } from '../logging.js';
4
- /**
5
- * ContextCache provides persistent caching of file contents and token counts
6
- * with automatic invalidation on file changes
7
- */
8
- export class ContextCache {
9
- /**
10
- * Creates a new ContextCache
11
- * @param projectRoot - Root directory of the project
12
- * @param config - Cache configuration
13
- */
14
- constructor(projectRoot, config = {}) {
15
- this.cache = new Map();
16
- this.config = {
17
- enabled: config.enabled ?? true,
18
- ttl: config.ttl ?? 3600, // 1 hour default
19
- maxSize: config.maxSize ?? 100, // 100MB default
20
- directory: config.directory ?? plugins.path.join(projectRoot, '.nogit', 'context-cache'),
21
- };
22
- this.cacheDir = this.config.directory;
23
- this.cacheIndexPath = plugins.path.join(this.cacheDir, 'index.json');
24
- }
25
- /**
26
- * Initializes the cache by loading from disk
27
- */
28
- async init() {
29
- if (!this.config.enabled) {
30
- return;
31
- }
32
- // Ensure cache directory exists
33
- await plugins.fsInstance.directory(this.cacheDir).recursive().create();
34
- // Load cache index if it exists
35
- try {
36
- const indexExists = await plugins.fsInstance.file(this.cacheIndexPath).exists();
37
- if (indexExists) {
38
- const indexContent = await plugins.fsInstance.file(this.cacheIndexPath).encoding('utf8').read();
39
- const indexData = JSON.parse(indexContent);
40
- if (Array.isArray(indexData)) {
41
- for (const entry of indexData) {
42
- this.cache.set(entry.path, entry);
43
- }
44
- }
45
- }
46
- }
47
- catch (error) {
48
- console.warn('Failed to load cache index:', error.message);
49
- // Start with empty cache if loading fails
50
- }
51
- // Clean up expired and invalid entries
52
- await this.cleanup();
53
- }
54
- /**
55
- * Gets a cached entry if it's still valid
56
- * @param filePath - Absolute path to the file
57
- * @returns Cache entry if valid, null otherwise
58
- */
59
- async get(filePath) {
60
- if (!this.config.enabled) {
61
- return null;
62
- }
63
- const entry = this.cache.get(filePath);
64
- if (!entry) {
65
- return null;
66
- }
67
- // Check if entry is expired
68
- const now = Date.now();
69
- if (now - entry.cachedAt > this.config.ttl * 1000) {
70
- this.cache.delete(filePath);
71
- return null;
72
- }
73
- // Check if file has been modified
74
- try {
75
- const stats = await fs.promises.stat(filePath);
76
- const currentMtime = Math.floor(stats.mtimeMs);
77
- if (currentMtime !== entry.mtime) {
78
- // File has changed, invalidate cache
79
- this.cache.delete(filePath);
80
- return null;
81
- }
82
- return entry;
83
- }
84
- catch (error) {
85
- // File doesn't exist anymore
86
- this.cache.delete(filePath);
87
- return null;
88
- }
89
- }
90
- /**
91
- * Stores a cache entry
92
- * @param entry - Cache entry to store
93
- */
94
- async set(entry) {
95
- if (!this.config.enabled) {
96
- return;
97
- }
98
- this.cache.set(entry.path, entry);
99
- // Check cache size and evict old entries if needed
100
- await this.enforceMaxSize();
101
- // Persist to disk (async, don't await)
102
- this.persist().catch((error) => {
103
- console.warn('Failed to persist cache:', error.message);
104
- });
105
- }
106
- /**
107
- * Stores multiple cache entries
108
- * @param entries - Array of cache entries
109
- */
110
- async setMany(entries) {
111
- if (!this.config.enabled) {
112
- return;
113
- }
114
- for (const entry of entries) {
115
- this.cache.set(entry.path, entry);
116
- }
117
- await this.enforceMaxSize();
118
- await this.persist();
119
- }
120
- /**
121
- * Checks if a file is cached and valid
122
- * @param filePath - Absolute path to the file
123
- * @returns True if cached and valid
124
- */
125
- async has(filePath) {
126
- const entry = await this.get(filePath);
127
- return entry !== null;
128
- }
129
- /**
130
- * Gets cache statistics
131
- */
132
- getStats() {
133
- let totalSize = 0;
134
- let oldestEntry = null;
135
- let newestEntry = null;
136
- for (const entry of this.cache.values()) {
137
- totalSize += entry.contents.length;
138
- if (oldestEntry === null || entry.cachedAt < oldestEntry) {
139
- oldestEntry = entry.cachedAt;
140
- }
141
- if (newestEntry === null || entry.cachedAt > newestEntry) {
142
- newestEntry = entry.cachedAt;
143
- }
144
- }
145
- return {
146
- entries: this.cache.size,
147
- totalSize,
148
- oldestEntry,
149
- newestEntry,
150
- };
151
- }
152
- /**
153
- * Clears all cache entries
154
- */
155
- async clear() {
156
- this.cache.clear();
157
- await this.persist();
158
- }
159
- /**
160
- * Clears specific cache entries
161
- * @param filePaths - Array of file paths to clear
162
- */
163
- async clearPaths(filePaths) {
164
- for (const path of filePaths) {
165
- this.cache.delete(path);
166
- }
167
- await this.persist();
168
- }
169
- /**
170
- * Cleans up expired and invalid cache entries
171
- */
172
- async cleanup() {
173
- const now = Date.now();
174
- const toDelete = [];
175
- for (const [path, entry] of this.cache.entries()) {
176
- // Check expiration
177
- if (now - entry.cachedAt > this.config.ttl * 1000) {
178
- toDelete.push(path);
179
- continue;
180
- }
181
- // Check if file still exists and hasn't changed
182
- try {
183
- const stats = await fs.promises.stat(path);
184
- const currentMtime = Math.floor(stats.mtimeMs);
185
- if (currentMtime !== entry.mtime) {
186
- toDelete.push(path);
187
- }
188
- }
189
- catch (error) {
190
- // File doesn't exist
191
- toDelete.push(path);
192
- }
193
- }
194
- for (const path of toDelete) {
195
- this.cache.delete(path);
196
- }
197
- if (toDelete.length > 0) {
198
- await this.persist();
199
- }
200
- }
201
- /**
202
- * Enforces maximum cache size by evicting oldest entries
203
- */
204
- async enforceMaxSize() {
205
- const stats = this.getStats();
206
- const maxSizeBytes = this.config.maxSize * 1024 * 1024; // Convert MB to bytes
207
- if (stats.totalSize <= maxSizeBytes) {
208
- return;
209
- }
210
- // Sort entries by age (oldest first)
211
- const entries = Array.from(this.cache.entries()).sort((a, b) => a[1].cachedAt - b[1].cachedAt);
212
- // Remove oldest entries until we're under the limit
213
- let currentSize = stats.totalSize;
214
- for (const [path, entry] of entries) {
215
- if (currentSize <= maxSizeBytes) {
216
- break;
217
- }
218
- currentSize -= entry.contents.length;
219
- this.cache.delete(path);
220
- }
221
- }
222
- /**
223
- * Persists cache index to disk
224
- */
225
- async persist() {
226
- if (!this.config.enabled) {
227
- return;
228
- }
229
- try {
230
- const entries = Array.from(this.cache.values());
231
- const content = JSON.stringify(entries, null, 2);
232
- await plugins.fsInstance.file(this.cacheIndexPath).encoding('utf8').write(content);
233
- }
234
- catch (error) {
235
- console.warn('Failed to persist cache index:', error.message);
236
- }
237
- }
238
- }
239
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1jYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NvbnRleHQvY29udGV4dC1jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUV6QixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXZDOzs7R0FHRztBQUNILE1BQU0sT0FBTyxZQUFZO0lBTXZCOzs7O09BSUc7SUFDSCxZQUFZLFdBQW1CLEVBQUUsU0FBZ0MsRUFBRTtRQVQzRCxVQUFLLEdBQTZCLElBQUksR0FBRyxFQUFFLENBQUM7UUFVbEQsSUFBSSxDQUFDLE1BQU0sR0FBRztZQUNaLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxJQUFJLElBQUk7WUFDL0IsR0FBRyxFQUFFLE1BQU0sQ0FBQyxHQUFHLElBQUksSUFBSSxFQUFFLGlCQUFpQjtZQUMxQyxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sSUFBSSxHQUFHLEVBQUUsZ0JBQWdCO1lBQ2hELFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxRQUFRLEVBQUUsZUFBZSxDQUFDO1NBQ3pGLENBQUM7UUFFRixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDO1FBQ3RDLElBQUksQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxZQUFZLENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsSUFBSTtRQUNmLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3pCLE9BQU87UUFDVCxDQUFDO1FBRUQsZ0NB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