doc-freshness-checker 2.0.21 → 2.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/cache/cacheManager.d.ts +20 -2
- package/dist/cache/cacheManager.js +137 -39
- package/dist/cache/cacheManager.js.map +1 -1
- package/dist/cache/cacheManager.test.js +132 -4
- package/dist/cache/cacheManager.test.js.map +1 -1
- package/dist/runner.js +21 -22
- package/dist/runner.js.map +1 -1
- package/dist/runner.test.js +101 -14
- package/dist/runner.test.js.map +1 -1
- package/dist/semantic/vectorSearch.d.ts +3 -3
- package/dist/semantic/vectorSearch.js +27 -29
- package/dist/semantic/vectorSearch.js.map +1 -1
- package/dist/semantic/vectorSearch.test.js +51 -2
- package/dist/semantic/vectorSearch.test.js.map +1 -1
- package/dist/utils/incremental.d.ts +3 -1
- package/dist/utils/incremental.js +32 -8
- package/dist/utils/incremental.js.map +1 -1
- package/dist/utils/incremental.test.js +17 -0
- package/dist/utils/incremental.test.js.map +1 -1
- package/dist/validators/versionValidator.js +16 -4
- package/dist/validators/versionValidator.js.map +1 -1
- package/dist/validators/versionValidator.test.js +55 -5
- package/dist/validators/versionValidator.test.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ Validate documentation against your codebase to catch stale references before th
|
|
|
38
38
|
- **Documentation formats:** Markdown (`.md`, `.markdown`), reStructuredText (`.rst`), AsciiDoc (`.adoc`, `.asciidoc`), plaintext (`.txt`).
|
|
39
39
|
- **Source indexing for symbol validation:** JavaScript, TypeScript, Python, Go, Rust, Java.
|
|
40
40
|
- **Code snippet validation:** verifies import paths resolve, imported symbols are exported, function call signatures still match example placeholders, and config object keys match type/interface definitions.
|
|
41
|
-
- **Manifest
|
|
41
|
+
- **Manifest hints for version/dependency checks:** basic format-specific identifiers and versions from listed `package.json`, `requirements.txt`, `pyproject.toml`, `go.mod`, `Cargo.toml`, and `pom.xml` files.
|
|
42
42
|
- In the general manifest candidate set, concrete versions take precedence over unpinned entries. Python package names retain their Python-specific source precedence. Among equally concrete candidates, the later configured manifest wins.
|
|
43
43
|
- Cargo parses simple and inline-table entries in `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`, and `[workspace.dependencies]`. Workspace references resolve from matching workspace definitions across explicitly listed `Cargo.toml` files. Dependency subtables, dotted keys, and target-specific sections are not parsed.
|
|
44
44
|
- **Reporters:** `console`, `json`, `markdown`, `enhanced`.
|
|
@@ -173,11 +173,13 @@ doc-freshness --score --incremental
|
|
|
173
173
|
| --------------------- | ------------------------------------------------------------------------------------------------ |
|
|
174
174
|
| `file-path` | Referenced files/directories exist |
|
|
175
175
|
| `external-url` | External URLs are reachable (with caching and skip rules) |
|
|
176
|
-
| `version` | Mentioned versions compared to
|
|
176
|
+
| `version` | Mentioned versions compared to extracted manifest version hints |
|
|
177
177
|
| `directory-structure` | Tree snippets align with actual structure |
|
|
178
178
|
| `code-pattern` | Mentioned symbols exist in indexed source |
|
|
179
179
|
| `code-snippet` | Import paths resolve, exported symbols exist, function signatures still match, config keys valid |
|
|
180
|
-
| `dependency` | Mentioned packages exist
|
|
180
|
+
| `dependency` | Mentioned packages exist among extracted manifest identifiers |
|
|
181
|
+
|
|
182
|
+
Extraction uses basic format-specific heuristics; it does not execute package managers or build backends, inspect generated metadata, discover workspace members, or implement full ecosystem grammars.
|
|
181
183
|
|
|
182
184
|
### URL Validation Behavior
|
|
183
185
|
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
import { CodeDocGraph } from '../graph/codeDocGraph.js';
|
|
2
2
|
import type { CacheStats2, DocFreshnessConfig, UrlCacheEntry } from '../types.js';
|
|
3
|
+
export type CachePolicy = Readonly<{
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
dir: string;
|
|
6
|
+
}>;
|
|
3
7
|
/**
|
|
4
|
-
*
|
|
8
|
+
* Resolves result-cache policy and manages persisted cache data
|
|
5
9
|
*/
|
|
6
10
|
export declare class CacheManager {
|
|
7
11
|
private config;
|
|
8
|
-
private
|
|
12
|
+
private rootDir;
|
|
13
|
+
private rawDir;
|
|
14
|
+
readonly policy: CachePolicy;
|
|
9
15
|
private cacheFile;
|
|
10
16
|
private urlCacheFile;
|
|
17
|
+
private embeddingCacheFile;
|
|
18
|
+
private incrementalStateFile;
|
|
11
19
|
constructor(config: DocFreshnessConfig);
|
|
20
|
+
private validateCacheDir;
|
|
12
21
|
private ensureCacheDir;
|
|
22
|
+
private validateCacheFile;
|
|
23
|
+
private readCacheFile;
|
|
24
|
+
private writeCacheFile;
|
|
25
|
+
private statCacheFile;
|
|
13
26
|
/**
|
|
14
27
|
* Save the code-to-doc graph
|
|
15
28
|
*/
|
|
@@ -31,6 +44,11 @@ export declare class CacheManager {
|
|
|
31
44
|
* Load URL validation cache
|
|
32
45
|
*/
|
|
33
46
|
loadUrlCache(): Promise<Record<string, UrlCacheEntry>>;
|
|
47
|
+
readEmbeddingCache(): Promise<string | null>;
|
|
48
|
+
writeEmbeddingCache(content: string): Promise<void>;
|
|
49
|
+
clearEmbeddingCache(): Promise<void>;
|
|
50
|
+
readIncrementalState(): Promise<string | null>;
|
|
51
|
+
writeIncrementalState(content: string): Promise<void>;
|
|
34
52
|
/**
|
|
35
53
|
* Clear all caches
|
|
36
54
|
*/
|
|
@@ -4,44 +4,130 @@ import crypto from 'crypto';
|
|
|
4
4
|
import { CodeDocGraph } from '../graph/codeDocGraph.js';
|
|
5
5
|
import { isWithinRoot, resolveProjectRoot } from '../utils/pathSecurity.js';
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Resolves result-cache policy and manages persisted cache data
|
|
8
8
|
*/
|
|
9
9
|
export class CacheManager {
|
|
10
10
|
config;
|
|
11
|
-
|
|
11
|
+
rootDir;
|
|
12
|
+
rawDir;
|
|
13
|
+
policy;
|
|
12
14
|
cacheFile;
|
|
13
15
|
urlCacheFile;
|
|
16
|
+
embeddingCacheFile;
|
|
17
|
+
incrementalStateFile;
|
|
14
18
|
constructor(config) {
|
|
15
19
|
this.config = config;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
this.rawDir = config.cache?.dir || config.graph?.cacheDir || '.doc-freshness-cache';
|
|
21
|
+
this.rootDir = resolveProjectRoot(config.rootDir);
|
|
22
|
+
const resolved = path.resolve(this.rootDir, this.rawDir);
|
|
23
|
+
this.policy = Object.freeze({ enabled: config.cache?.enabled !== false, dir: resolved });
|
|
24
|
+
this.cacheFile = path.join(this.policy.dir, 'graph-cache.json');
|
|
25
|
+
this.urlCacheFile = path.join(this.policy.dir, 'url-cache.json');
|
|
26
|
+
this.embeddingCacheFile = path.join(this.policy.dir, 'embedding-cache.json');
|
|
27
|
+
this.incrementalStateFile = path.join(this.policy.dir, 'file-hashes.json');
|
|
28
|
+
if (this.policy.enabled) {
|
|
29
|
+
this.validateCacheDir();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
validateCacheDir() {
|
|
33
|
+
if (this.policy.dir === this.rootDir || !isWithinRoot(this.policy.dir, this.rootDir)) {
|
|
34
|
+
throw new Error(`Cache directory "${this.rawDir}" must resolve to a strict descendant of project root`);
|
|
35
|
+
}
|
|
36
|
+
const realRoot = fs.realpathSync(this.rootDir);
|
|
37
|
+
let ancestor = this.policy.dir;
|
|
38
|
+
while (!fs.existsSync(ancestor)) {
|
|
39
|
+
const parent = path.dirname(ancestor);
|
|
40
|
+
if (parent === ancestor) {
|
|
41
|
+
throw new Error(`Cache directory "${this.rawDir}" has no existing ancestor`);
|
|
42
|
+
}
|
|
43
|
+
ancestor = parent;
|
|
44
|
+
}
|
|
45
|
+
const realAncestor = fs.realpathSync(ancestor);
|
|
46
|
+
const realCacheDir = path.resolve(realAncestor, path.relative(ancestor, this.policy.dir));
|
|
47
|
+
if (realCacheDir === realRoot || !isWithinRoot(realCacheDir, realRoot)) {
|
|
48
|
+
throw new Error(`Cache directory "${this.rawDir}" must resolve to a strict descendant of project root`);
|
|
22
49
|
}
|
|
23
|
-
this.cacheDir = resolved;
|
|
24
|
-
this.cacheFile = path.join(this.cacheDir, 'graph-cache.json');
|
|
25
|
-
this.urlCacheFile = path.join(this.cacheDir, 'url-cache.json');
|
|
26
50
|
}
|
|
27
51
|
async ensureCacheDir() {
|
|
28
|
-
|
|
52
|
+
this.validateCacheDir();
|
|
53
|
+
await fs.promises.mkdir(this.policy.dir, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
validateCacheFile(filePath) {
|
|
56
|
+
this.validateCacheDir();
|
|
57
|
+
let fileStats;
|
|
58
|
+
try {
|
|
59
|
+
fileStats = fs.lstatSync(filePath);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error.code === 'ENOENT') {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
if (fileStats.isSymbolicLink()) {
|
|
68
|
+
throw new Error(`Cache file "${path.basename(filePath)}" must not be a symbolic link`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async readCacheFile(filePath) {
|
|
72
|
+
if (!this.policy.enabled) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
this.validateCacheFile(filePath);
|
|
76
|
+
try {
|
|
77
|
+
return await fs.promises.readFile(filePath, 'utf-8');
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async writeCacheFile(filePath, content) {
|
|
84
|
+
if (!this.policy.enabled) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
await this.ensureCacheDir();
|
|
88
|
+
this.validateCacheFile(filePath);
|
|
89
|
+
const tempFile = path.join(this.policy.dir, `.${path.basename(filePath)}.${crypto.randomUUID()}.tmp`);
|
|
90
|
+
try {
|
|
91
|
+
await fs.promises.writeFile(tempFile, content, { encoding: 'utf-8', flag: 'wx' });
|
|
92
|
+
this.validateCacheFile(filePath);
|
|
93
|
+
await fs.promises.rename(tempFile, filePath);
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
await fs.promises.rm(tempFile, { force: true }).catch(() => { });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async statCacheFile(filePath) {
|
|
100
|
+
if (!this.policy.enabled) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
this.validateCacheFile(filePath);
|
|
104
|
+
try {
|
|
105
|
+
return await fs.promises.stat(filePath);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
29
110
|
}
|
|
30
111
|
/**
|
|
31
112
|
* Save the code-to-doc graph
|
|
32
113
|
*/
|
|
33
114
|
async saveGraph(graph) {
|
|
34
|
-
|
|
115
|
+
if (!this.policy.enabled) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
35
118
|
const data = graph.serialize();
|
|
36
119
|
data.configHash = this.getConfigHash();
|
|
37
|
-
await
|
|
120
|
+
await this.writeCacheFile(this.cacheFile, JSON.stringify(data, null, 2));
|
|
38
121
|
}
|
|
39
122
|
/**
|
|
40
123
|
* Load the cached graph
|
|
41
124
|
*/
|
|
42
125
|
async loadGraph() {
|
|
126
|
+
const content = await this.readCacheFile(this.cacheFile);
|
|
127
|
+
if (content === null) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
43
130
|
try {
|
|
44
|
-
const content = await fs.promises.readFile(this.cacheFile, 'utf-8');
|
|
45
131
|
const data = JSON.parse(content);
|
|
46
132
|
return CodeDocGraph.deserialize(data);
|
|
47
133
|
}
|
|
@@ -53,7 +139,7 @@ export class CacheManager {
|
|
|
53
139
|
* Check if cache is valid based on config hash and git state
|
|
54
140
|
*/
|
|
55
141
|
isCacheValid(graph, currentCommit) {
|
|
56
|
-
if (!graph) {
|
|
142
|
+
if (!this.policy.enabled || !graph) {
|
|
57
143
|
return false;
|
|
58
144
|
}
|
|
59
145
|
if (!graph.buildTimestamp) {
|
|
@@ -82,31 +168,48 @@ export class CacheManager {
|
|
|
82
168
|
* Save URL validation cache
|
|
83
169
|
*/
|
|
84
170
|
async saveUrlCache(urlResults) {
|
|
85
|
-
await this.
|
|
86
|
-
await fs.promises.writeFile(this.urlCacheFile, JSON.stringify(urlResults, null, 2));
|
|
171
|
+
await this.writeCacheFile(this.urlCacheFile, JSON.stringify(urlResults, null, 2));
|
|
87
172
|
}
|
|
88
173
|
/**
|
|
89
174
|
* Load URL validation cache
|
|
90
175
|
*/
|
|
91
176
|
async loadUrlCache() {
|
|
177
|
+
const content = await this.readCacheFile(this.urlCacheFile);
|
|
178
|
+
if (content === null) {
|
|
179
|
+
return {};
|
|
180
|
+
}
|
|
92
181
|
try {
|
|
93
|
-
const content = await fs.promises.readFile(this.urlCacheFile, 'utf-8');
|
|
94
182
|
return JSON.parse(content);
|
|
95
183
|
}
|
|
96
184
|
catch {
|
|
97
185
|
return {};
|
|
98
186
|
}
|
|
99
187
|
}
|
|
188
|
+
async readEmbeddingCache() {
|
|
189
|
+
return this.readCacheFile(this.embeddingCacheFile);
|
|
190
|
+
}
|
|
191
|
+
async writeEmbeddingCache(content) {
|
|
192
|
+
await this.writeCacheFile(this.embeddingCacheFile, content);
|
|
193
|
+
}
|
|
194
|
+
async clearEmbeddingCache() {
|
|
195
|
+
if (!this.policy.enabled) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
this.validateCacheFile(this.embeddingCacheFile);
|
|
199
|
+
await fs.promises.rm(this.embeddingCacheFile, { force: true });
|
|
200
|
+
}
|
|
201
|
+
async readIncrementalState() {
|
|
202
|
+
return this.readCacheFile(this.incrementalStateFile);
|
|
203
|
+
}
|
|
204
|
+
async writeIncrementalState(content) {
|
|
205
|
+
await this.writeCacheFile(this.incrementalStateFile, content);
|
|
206
|
+
}
|
|
100
207
|
/**
|
|
101
208
|
* Clear all caches
|
|
102
209
|
*/
|
|
103
210
|
async clearCache() {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
catch {
|
|
108
|
-
// Directory doesn't exist
|
|
109
|
-
}
|
|
211
|
+
this.validateCacheDir();
|
|
212
|
+
await fs.promises.rm(this.policy.dir, { recursive: true, force: true });
|
|
110
213
|
}
|
|
111
214
|
/**
|
|
112
215
|
* Get cache statistics
|
|
@@ -118,21 +221,16 @@ export class CacheManager {
|
|
|
118
221
|
urlCacheSize: 0,
|
|
119
222
|
lastUpdated: null,
|
|
120
223
|
};
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
stats.exists = true;
|
|
124
|
-
stats.graphSize = graphStat.size;
|
|
125
|
-
stats.lastUpdated = graphStat.mtime;
|
|
126
|
-
}
|
|
127
|
-
catch {
|
|
128
|
-
// File doesn't exist
|
|
224
|
+
if (!this.policy.enabled) {
|
|
225
|
+
return stats;
|
|
129
226
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
227
|
+
const [graphStat, urlStat, embeddingStat, incrementalStat] = await Promise.all([this.cacheFile, this.urlCacheFile, this.embeddingCacheFile, this.incrementalStateFile].map((file) => this.statCacheFile(file)));
|
|
228
|
+
const existingStats = [graphStat, urlStat, embeddingStat, incrementalStat].filter((stat) => stat !== null);
|
|
229
|
+
if (existingStats.length > 0) {
|
|
230
|
+
stats.exists = true;
|
|
231
|
+
stats.graphSize = graphStat?.size ?? 0;
|
|
232
|
+
stats.urlCacheSize = urlStat?.size ?? 0;
|
|
233
|
+
stats.lastUpdated = new Date(Math.max(...existingStats.map((stat) => stat.mtimeMs)));
|
|
136
234
|
}
|
|
137
235
|
return stats;
|
|
138
236
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cacheManager.js","sourceRoot":"","sources":["../../src/cache/cacheManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"cacheManager.js","sourceRoot":"","sources":["../../src/cache/cacheManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
+
import os from 'os';
|
|
2
3
|
import path from 'path';
|
|
3
4
|
import { CacheManager } from './cacheManager.js';
|
|
4
5
|
import { CodeDocGraph } from '../graph/codeDocGraph.js';
|
|
@@ -11,12 +12,90 @@ describe('CacheManager', () => {
|
|
|
11
12
|
afterAll(async () => {
|
|
12
13
|
await fs.promises.rm(cacheDir, { recursive: true, force: true }).catch(() => { });
|
|
13
14
|
});
|
|
14
|
-
it('
|
|
15
|
+
it('rejects cache directories outside the project root', async () => {
|
|
15
16
|
const badConfig = {
|
|
16
17
|
rootDir: '/project',
|
|
17
18
|
cache: { dir: '../../etc/evil' },
|
|
18
19
|
};
|
|
19
|
-
expect(() => new CacheManager(badConfig)).toThrow('
|
|
20
|
+
expect(() => new CacheManager(badConfig)).toThrow('strict descendant of project root');
|
|
21
|
+
const disabledManager = new CacheManager({ ...badConfig, cache: { ...badConfig.cache, enabled: false } });
|
|
22
|
+
await expect(disabledManager.clearCache()).rejects.toThrow('strict descendant of project root');
|
|
23
|
+
});
|
|
24
|
+
it('rejects the project root itself without deleting it', async () => {
|
|
25
|
+
const rootDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doc-freshness-cache-root-'));
|
|
26
|
+
const sentinel = path.join(rootDir, 'sentinel');
|
|
27
|
+
await fs.promises.writeFile(sentinel, 'keep');
|
|
28
|
+
expect(() => new CacheManager({ rootDir, cache: { enabled: true, dir: '.' } })).toThrow('strict descendant of project root');
|
|
29
|
+
expect(() => new CacheManager({ rootDir, cache: { enabled: true, dir: rootDir } })).toThrow('strict descendant of project root');
|
|
30
|
+
const disabledManager = new CacheManager({ rootDir, cache: { enabled: false, dir: rootDir } });
|
|
31
|
+
await expect(disabledManager.clearCache()).rejects.toThrow('strict descendant of project root');
|
|
32
|
+
expect(await fs.promises.readFile(sentinel, 'utf-8')).toBe('keep');
|
|
33
|
+
await fs.promises.rm(rootDir, { recursive: true, force: true });
|
|
34
|
+
});
|
|
35
|
+
it('rejects cache symlinks that escape the project root', async () => {
|
|
36
|
+
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doc-freshness-cache-link-'));
|
|
37
|
+
const rootDir = path.join(tempDir, 'root');
|
|
38
|
+
const outsideDir = path.join(tempDir, 'outside');
|
|
39
|
+
const cacheLink = path.join(rootDir, 'cache');
|
|
40
|
+
const sentinel = path.join(outsideDir, 'sentinel');
|
|
41
|
+
await fs.promises.mkdir(rootDir);
|
|
42
|
+
await fs.promises.mkdir(outsideDir);
|
|
43
|
+
await fs.promises.writeFile(sentinel, 'keep');
|
|
44
|
+
await fs.promises.symlink(outsideDir, cacheLink);
|
|
45
|
+
expect(() => new CacheManager({ rootDir, cache: { enabled: true, dir: 'cache/nested' } })).toThrow('strict descendant of project root');
|
|
46
|
+
const disabledManager = new CacheManager({ rootDir, cache: { enabled: false, dir: 'cache/nested' } });
|
|
47
|
+
await disabledManager.saveUrlCache({ test: { result: { valid: true }, timestamp: Date.now() } });
|
|
48
|
+
await expect(disabledManager.clearCache()).rejects.toThrow('strict descendant of project root');
|
|
49
|
+
expect(await fs.promises.readdir(outsideDir)).toEqual(['sentinel']);
|
|
50
|
+
expect(await fs.promises.readFile(sentinel, 'utf-8')).toBe('keep');
|
|
51
|
+
await fs.promises.rm(tempDir, { recursive: true, force: true });
|
|
52
|
+
});
|
|
53
|
+
it('revalidates containment after a safe cache ancestor is replaced by a symlink', async () => {
|
|
54
|
+
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doc-freshness-cache-swap-'));
|
|
55
|
+
const rootDir = path.join(tempDir, 'root');
|
|
56
|
+
const outsideDir = path.join(tempDir, 'outside');
|
|
57
|
+
const cacheAncestor = path.join(rootDir, 'results');
|
|
58
|
+
await fs.promises.mkdir(path.join(cacheAncestor, 'cache'), { recursive: true });
|
|
59
|
+
await fs.promises.mkdir(outsideDir);
|
|
60
|
+
await fs.promises.writeFile(path.join(outsideDir, 'sentinel'), 'keep');
|
|
61
|
+
const manager = new CacheManager({ rootDir, cache: { enabled: true, dir: 'results/cache' } });
|
|
62
|
+
await fs.promises.rm(cacheAncestor, { recursive: true, force: true });
|
|
63
|
+
await fs.promises.symlink(outsideDir, cacheAncestor);
|
|
64
|
+
await expect(manager.saveUrlCache({ test: { result: { valid: true }, timestamp: Date.now() } })).rejects.toThrow('strict descendant of project root');
|
|
65
|
+
await expect(manager.writeEmbeddingCache('{}')).rejects.toThrow('strict descendant of project root');
|
|
66
|
+
expect(await fs.promises.readdir(outsideDir)).toEqual(['sentinel']);
|
|
67
|
+
await fs.promises.rm(tempDir, { recursive: true, force: true });
|
|
68
|
+
});
|
|
69
|
+
it('rejects symbolic links at final cache file paths', async () => {
|
|
70
|
+
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doc-freshness-cache-file-link-'));
|
|
71
|
+
const rootDir = path.join(tempDir, 'root');
|
|
72
|
+
const cachePath = path.join(rootDir, 'cache');
|
|
73
|
+
const sentinel = path.join(tempDir, 'sentinel');
|
|
74
|
+
await fs.promises.mkdir(cachePath, { recursive: true });
|
|
75
|
+
await fs.promises.writeFile(sentinel, 'keep');
|
|
76
|
+
await fs.promises.symlink(sentinel, path.join(cachePath, 'url-cache.json'));
|
|
77
|
+
const manager = new CacheManager({ rootDir, cache: { enabled: true, dir: 'cache' } });
|
|
78
|
+
await expect(manager.loadUrlCache()).rejects.toThrow('must not be a symbolic link');
|
|
79
|
+
await expect(manager.saveUrlCache({ test: { result: { valid: true }, timestamp: Date.now() } })).rejects.toThrow('must not be a symbolic link');
|
|
80
|
+
expect(await fs.promises.readFile(sentinel, 'utf-8')).toBe('keep');
|
|
81
|
+
await fs.promises.rm(tempDir, { recursive: true, force: true });
|
|
82
|
+
});
|
|
83
|
+
it('atomically replaces a hard-linked cache file without changing its other link', async () => {
|
|
84
|
+
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doc-freshness-cache-hard-link-'));
|
|
85
|
+
const rootDir = path.join(tempDir, 'root');
|
|
86
|
+
const cachePath = path.join(rootDir, 'cache');
|
|
87
|
+
const cacheFile = path.join(cachePath, 'url-cache.json');
|
|
88
|
+
const sentinel = path.join(tempDir, 'sentinel');
|
|
89
|
+
const urlData = { 'https://example.com': { result: { valid: true }, timestamp: Date.now() } };
|
|
90
|
+
await fs.promises.mkdir(cachePath, { recursive: true });
|
|
91
|
+
await fs.promises.writeFile(sentinel, 'keep');
|
|
92
|
+
await fs.promises.link(sentinel, cacheFile);
|
|
93
|
+
const manager = new CacheManager({ rootDir, cache: { enabled: true, dir: 'cache' } });
|
|
94
|
+
await manager.saveUrlCache(urlData);
|
|
95
|
+
expect(await fs.promises.readFile(sentinel, 'utf-8')).toBe('keep');
|
|
96
|
+
expect(await manager.loadUrlCache()).toEqual(urlData);
|
|
97
|
+
expect(await fs.promises.readdir(cachePath)).toEqual(['url-cache.json']);
|
|
98
|
+
await fs.promises.rm(tempDir, { recursive: true, force: true });
|
|
20
99
|
});
|
|
21
100
|
describe('graph operations', () => {
|
|
22
101
|
it('saves and loads a graph', async () => {
|
|
@@ -51,6 +130,36 @@ describe('CacheManager', () => {
|
|
|
51
130
|
const manager = new CacheManager(freshConfig);
|
|
52
131
|
expect(await manager.loadUrlCache()).toEqual({});
|
|
53
132
|
});
|
|
133
|
+
it('does not load or save URL results when caching is disabled', async () => {
|
|
134
|
+
const disabledDir = path.join(cacheDir, 'disabled');
|
|
135
|
+
const cacheFile = path.join(disabledDir, 'url-cache.json');
|
|
136
|
+
await fs.promises.mkdir(disabledDir, { recursive: true });
|
|
137
|
+
await fs.promises.writeFile(cacheFile, '{"sentinel":true}');
|
|
138
|
+
const manager = new CacheManager({
|
|
139
|
+
rootDir: process.cwd(),
|
|
140
|
+
cache: { enabled: false, dir: path.relative(process.cwd(), disabledDir) },
|
|
141
|
+
});
|
|
142
|
+
expect(await manager.loadUrlCache()).toEqual({});
|
|
143
|
+
await manager.saveUrlCache({ test: { result: { valid: true }, timestamp: Date.now() } });
|
|
144
|
+
expect(await fs.promises.readFile(cacheFile, 'utf-8')).toBe('{"sentinel":true}');
|
|
145
|
+
});
|
|
146
|
+
it('treats ordinary read failures as cache misses', async () => {
|
|
147
|
+
const manager = new CacheManager(config);
|
|
148
|
+
const readSpy = vi.spyOn(fs.promises, 'readFile').mockRejectedValue(Object.assign(new Error('denied'), { code: 'EACCES' }));
|
|
149
|
+
expect(await manager.loadUrlCache()).toEqual({});
|
|
150
|
+
expect(await manager.loadGraph()).toBeNull();
|
|
151
|
+
expect(await manager.readEmbeddingCache()).toBeNull();
|
|
152
|
+
readSpy.mockRestore();
|
|
153
|
+
});
|
|
154
|
+
it('propagates final-file safety check failures other than absence', async () => {
|
|
155
|
+
const manager = new CacheManager(config);
|
|
156
|
+
const error = Object.assign(new Error('denied'), { code: 'EACCES' });
|
|
157
|
+
const lstatSpy = vi.spyOn(fs, 'lstatSync').mockImplementationOnce(() => {
|
|
158
|
+
throw error;
|
|
159
|
+
});
|
|
160
|
+
await expect(manager.loadUrlCache()).rejects.toBe(error);
|
|
161
|
+
lstatSpy.mockRestore();
|
|
162
|
+
});
|
|
54
163
|
});
|
|
55
164
|
describe('isCacheValid', () => {
|
|
56
165
|
it('returns false for null graph', () => {
|
|
@@ -97,6 +206,14 @@ describe('CacheManager', () => {
|
|
|
97
206
|
const manager = new CacheManager(freshConfig);
|
|
98
207
|
await expect(manager.clearCache()).resolves.not.toThrow();
|
|
99
208
|
});
|
|
209
|
+
it('propagates removal failures', async () => {
|
|
210
|
+
const manager = new CacheManager(config);
|
|
211
|
+
const error = Object.assign(new Error('permission denied'), { code: 'EACCES' });
|
|
212
|
+
const rmSpy = vi.spyOn(fs.promises, 'rm').mockRejectedValueOnce(error);
|
|
213
|
+
await expect(manager.clearCache()).rejects.toBe(error);
|
|
214
|
+
expect(rmSpy).toHaveBeenCalledWith(cacheDir, { recursive: true, force: true });
|
|
215
|
+
rmSpy.mockRestore();
|
|
216
|
+
});
|
|
100
217
|
});
|
|
101
218
|
describe('isCacheValid - configHash', () => {
|
|
102
219
|
it('returns false when configHash differs', () => {
|
|
@@ -131,11 +248,22 @@ describe('CacheManager', () => {
|
|
|
131
248
|
expect(stats.exists).toBe(false);
|
|
132
249
|
expect(stats.lastUpdated).toBeNull();
|
|
133
250
|
});
|
|
134
|
-
it('
|
|
135
|
-
const manager = new CacheManager(
|
|
251
|
+
it('reports a populated result cache without a graph cache', async () => {
|
|
252
|
+
const manager = new CacheManager({
|
|
253
|
+
rootDir: process.cwd(),
|
|
254
|
+
cache: { dir: '.doc-freshness-cache/test-cache/url-only-stats' },
|
|
255
|
+
});
|
|
136
256
|
await manager.saveUrlCache({ 'https://x.com': { result: { valid: true }, timestamp: Date.now() } });
|
|
137
257
|
const stats = await manager.getCacheStats();
|
|
258
|
+
expect(stats.exists).toBe(true);
|
|
138
259
|
expect(stats.urlCacheSize).toBeGreaterThan(0);
|
|
260
|
+
expect(stats.lastUpdated).toBeInstanceOf(Date);
|
|
261
|
+
});
|
|
262
|
+
it('treats ordinary stat failures as missing cache files', async () => {
|
|
263
|
+
const manager = new CacheManager(config);
|
|
264
|
+
const statSpy = vi.spyOn(fs.promises, 'stat').mockRejectedValue(Object.assign(new Error('denied'), { code: 'EACCES' }));
|
|
265
|
+
expect(await manager.getCacheStats()).toEqual({ exists: false, graphSize: 0, urlCacheSize: 0, lastUpdated: null });
|
|
266
|
+
statSpy.mockRestore();
|
|
139
267
|
});
|
|
140
268
|
});
|
|
141
269
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cacheManager.test.js","sourceRoot":"","sources":["../../src/cache/cacheManager.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cacheManager.test.js","sourceRoot":"","sources":["../../src/cache/cacheManager.test.ts"],"names":[],"mappings":"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"}
|