doc-freshness-checker 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.
Files changed (246) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +305 -0
  3. package/dist/cache/cacheManager.d.ts +42 -0
  4. package/dist/cache/cacheManager.js +138 -0
  5. package/dist/cache/cacheManager.js.map +1 -0
  6. package/dist/cache/cacheManager.test.d.ts +1 -0
  7. package/dist/cache/cacheManager.test.js +142 -0
  8. package/dist/cache/cacheManager.test.js.map +1 -0
  9. package/dist/cli.d.ts +32 -0
  10. package/dist/cli.js +137 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/cli.test.d.ts +1 -0
  13. package/dist/cli.test.js +184 -0
  14. package/dist/cli.test.js.map +1 -0
  15. package/dist/config/defaults.d.ts +5 -0
  16. package/dist/config/defaults.js +135 -0
  17. package/dist/config/defaults.js.map +1 -0
  18. package/dist/config/defineConfig.d.ts +28 -0
  19. package/dist/config/defineConfig.js +30 -0
  20. package/dist/config/defineConfig.js.map +1 -0
  21. package/dist/config/defineConfig.test.d.ts +1 -0
  22. package/dist/config/defineConfig.test.js +10 -0
  23. package/dist/config/defineConfig.test.js.map +1 -0
  24. package/dist/config/loader.d.ts +7 -0
  25. package/dist/config/loader.js +250 -0
  26. package/dist/config/loader.js.map +1 -0
  27. package/dist/config/loader.test.d.ts +1 -0
  28. package/dist/config/loader.test.js +276 -0
  29. package/dist/config/loader.test.js.map +1 -0
  30. package/dist/git/changeTracker.d.ts +44 -0
  31. package/dist/git/changeTracker.js +149 -0
  32. package/dist/git/changeTracker.js.map +1 -0
  33. package/dist/git/changeTracker.test.d.ts +1 -0
  34. package/dist/git/changeTracker.test.js +184 -0
  35. package/dist/git/changeTracker.test.js.map +1 -0
  36. package/dist/graph/codeDocGraph.d.ts +43 -0
  37. package/dist/graph/codeDocGraph.js +103 -0
  38. package/dist/graph/codeDocGraph.js.map +1 -0
  39. package/dist/graph/codeDocGraph.test.d.ts +1 -0
  40. package/dist/graph/codeDocGraph.test.js +78 -0
  41. package/dist/graph/codeDocGraph.test.js.map +1 -0
  42. package/dist/graph/graphBuilder.d.ts +17 -0
  43. package/dist/graph/graphBuilder.js +76 -0
  44. package/dist/graph/graphBuilder.js.map +1 -0
  45. package/dist/graph/graphBuilder.test.d.ts +1 -0
  46. package/dist/graph/graphBuilder.test.js +87 -0
  47. package/dist/graph/graphBuilder.test.js.map +1 -0
  48. package/dist/index.d.ts +37 -0
  49. package/dist/index.js +37 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/parsers/documentParser.d.ts +22 -0
  52. package/dist/parsers/documentParser.js +76 -0
  53. package/dist/parsers/documentParser.js.map +1 -0
  54. package/dist/parsers/documentParser.test.d.ts +1 -0
  55. package/dist/parsers/documentParser.test.js +116 -0
  56. package/dist/parsers/documentParser.test.js.map +1 -0
  57. package/dist/parsers/extractors/baseExtractor.d.ts +19 -0
  58. package/dist/parsers/extractors/baseExtractor.js +33 -0
  59. package/dist/parsers/extractors/baseExtractor.js.map +1 -0
  60. package/dist/parsers/extractors/baseExtractor.test.d.ts +1 -0
  61. package/dist/parsers/extractors/baseExtractor.test.js +43 -0
  62. package/dist/parsers/extractors/baseExtractor.test.js.map +1 -0
  63. package/dist/parsers/extractors/codePatternExtractor.d.ts +13 -0
  64. package/dist/parsers/extractors/codePatternExtractor.js +108 -0
  65. package/dist/parsers/extractors/codePatternExtractor.js.map +1 -0
  66. package/dist/parsers/extractors/codePatternExtractor.test.d.ts +1 -0
  67. package/dist/parsers/extractors/codePatternExtractor.test.js +49 -0
  68. package/dist/parsers/extractors/codePatternExtractor.test.js.map +1 -0
  69. package/dist/parsers/extractors/dependencyExtractor.d.ts +12 -0
  70. package/dist/parsers/extractors/dependencyExtractor.js +92 -0
  71. package/dist/parsers/extractors/dependencyExtractor.js.map +1 -0
  72. package/dist/parsers/extractors/dependencyExtractor.test.d.ts +1 -0
  73. package/dist/parsers/extractors/dependencyExtractor.test.js +48 -0
  74. package/dist/parsers/extractors/dependencyExtractor.test.js.map +1 -0
  75. package/dist/parsers/extractors/directoryStructureExtractor.d.ts +34 -0
  76. package/dist/parsers/extractors/directoryStructureExtractor.js +168 -0
  77. package/dist/parsers/extractors/directoryStructureExtractor.js.map +1 -0
  78. package/dist/parsers/extractors/directoryStructureExtractor.test.d.ts +1 -0
  79. package/dist/parsers/extractors/directoryStructureExtractor.test.js +121 -0
  80. package/dist/parsers/extractors/directoryStructureExtractor.test.js.map +1 -0
  81. package/dist/parsers/extractors/externalUrlExtractor.d.ts +14 -0
  82. package/dist/parsers/extractors/externalUrlExtractor.js +53 -0
  83. package/dist/parsers/extractors/externalUrlExtractor.js.map +1 -0
  84. package/dist/parsers/extractors/externalUrlExtractor.test.d.ts +1 -0
  85. package/dist/parsers/extractors/externalUrlExtractor.test.js +85 -0
  86. package/dist/parsers/extractors/externalUrlExtractor.test.js.map +1 -0
  87. package/dist/parsers/extractors/filePathExtractor.d.ts +18 -0
  88. package/dist/parsers/extractors/filePathExtractor.js +72 -0
  89. package/dist/parsers/extractors/filePathExtractor.js.map +1 -0
  90. package/dist/parsers/extractors/filePathExtractor.test.d.ts +1 -0
  91. package/dist/parsers/extractors/filePathExtractor.test.js +73 -0
  92. package/dist/parsers/extractors/filePathExtractor.test.js.map +1 -0
  93. package/dist/parsers/extractors/versionExtractor.d.ts +11 -0
  94. package/dist/parsers/extractors/versionExtractor.js +74 -0
  95. package/dist/parsers/extractors/versionExtractor.js.map +1 -0
  96. package/dist/parsers/extractors/versionExtractor.test.d.ts +1 -0
  97. package/dist/parsers/extractors/versionExtractor.test.js +55 -0
  98. package/dist/parsers/extractors/versionExtractor.test.js.map +1 -0
  99. package/dist/plugins/plugin.d.ts +32 -0
  100. package/dist/plugins/plugin.js +40 -0
  101. package/dist/plugins/plugin.js.map +1 -0
  102. package/dist/plugins/plugin.test.d.ts +1 -0
  103. package/dist/plugins/plugin.test.js +23 -0
  104. package/dist/plugins/plugin.test.js.map +1 -0
  105. package/dist/reporters/consoleReporter.d.ts +15 -0
  106. package/dist/reporters/consoleReporter.js +73 -0
  107. package/dist/reporters/consoleReporter.js.map +1 -0
  108. package/dist/reporters/consoleReporter.test.d.ts +1 -0
  109. package/dist/reporters/consoleReporter.test.js +155 -0
  110. package/dist/reporters/consoleReporter.test.js.map +1 -0
  111. package/dist/reporters/enhancedReporter.d.ts +12 -0
  112. package/dist/reporters/enhancedReporter.js +81 -0
  113. package/dist/reporters/enhancedReporter.js.map +1 -0
  114. package/dist/reporters/enhancedReporter.test.d.ts +1 -0
  115. package/dist/reporters/enhancedReporter.test.js +152 -0
  116. package/dist/reporters/enhancedReporter.test.js.map +1 -0
  117. package/dist/reporters/jsonReporter.d.ts +11 -0
  118. package/dist/reporters/jsonReporter.js +20 -0
  119. package/dist/reporters/jsonReporter.js.map +1 -0
  120. package/dist/reporters/jsonReporter.test.d.ts +1 -0
  121. package/dist/reporters/jsonReporter.test.js +31 -0
  122. package/dist/reporters/jsonReporter.test.js.map +1 -0
  123. package/dist/reporters/markdownReporter.d.ts +11 -0
  124. package/dist/reporters/markdownReporter.js +55 -0
  125. package/dist/reporters/markdownReporter.js.map +1 -0
  126. package/dist/reporters/markdownReporter.test.d.ts +1 -0
  127. package/dist/reporters/markdownReporter.test.js +136 -0
  128. package/dist/reporters/markdownReporter.test.js.map +1 -0
  129. package/dist/runner.d.ts +9 -0
  130. package/dist/runner.js +265 -0
  131. package/dist/runner.js.map +1 -0
  132. package/dist/runner.test.d.ts +1 -0
  133. package/dist/runner.test.js +353 -0
  134. package/dist/runner.test.js.map +1 -0
  135. package/dist/scoring/freshnessScorer.d.ts +40 -0
  136. package/dist/scoring/freshnessScorer.js +170 -0
  137. package/dist/scoring/freshnessScorer.js.map +1 -0
  138. package/dist/scoring/freshnessScorer.test.d.ts +1 -0
  139. package/dist/scoring/freshnessScorer.test.js +397 -0
  140. package/dist/scoring/freshnessScorer.test.js.map +1 -0
  141. package/dist/semantic/vectorSearch.d.ts +84 -0
  142. package/dist/semantic/vectorSearch.js +484 -0
  143. package/dist/semantic/vectorSearch.js.map +1 -0
  144. package/dist/semantic/vectorSearch.test.d.ts +1 -0
  145. package/dist/semantic/vectorSearch.test.js +660 -0
  146. package/dist/semantic/vectorSearch.test.js.map +1 -0
  147. package/dist/setupTests.d.ts +4 -0
  148. package/dist/setupTests.js +11 -0
  149. package/dist/setupTests.js.map +1 -0
  150. package/dist/test-utils/console.d.ts +2 -0
  151. package/dist/test-utils/console.js +3 -0
  152. package/dist/test-utils/console.js.map +1 -0
  153. package/dist/test-utils/factories.d.ts +3 -0
  154. package/dist/test-utils/factories.js +25 -0
  155. package/dist/test-utils/factories.js.map +1 -0
  156. package/dist/test-utils/tempFiles.d.ts +1 -0
  157. package/dist/test-utils/tempFiles.js +12 -0
  158. package/dist/test-utils/tempFiles.js.map +1 -0
  159. package/dist/types.d.ts +304 -0
  160. package/dist/types.js +5 -0
  161. package/dist/types.js.map +1 -0
  162. package/dist/utils/boundedMap.d.ts +8 -0
  163. package/dist/utils/boundedMap.js +22 -0
  164. package/dist/utils/boundedMap.js.map +1 -0
  165. package/dist/utils/boundedMap.test.d.ts +1 -0
  166. package/dist/utils/boundedMap.test.js +57 -0
  167. package/dist/utils/boundedMap.test.js.map +1 -0
  168. package/dist/utils/illustrativePatterns.d.ts +28 -0
  169. package/dist/utils/illustrativePatterns.js +80 -0
  170. package/dist/utils/illustrativePatterns.js.map +1 -0
  171. package/dist/utils/illustrativePatterns.test.d.ts +1 -0
  172. package/dist/utils/illustrativePatterns.test.js +48 -0
  173. package/dist/utils/illustrativePatterns.test.js.map +1 -0
  174. package/dist/utils/incremental.d.ts +36 -0
  175. package/dist/utils/incremental.js +87 -0
  176. package/dist/utils/incremental.js.map +1 -0
  177. package/dist/utils/incremental.test.d.ts +1 -0
  178. package/dist/utils/incremental.test.js +84 -0
  179. package/dist/utils/incremental.test.js.map +1 -0
  180. package/dist/utils/parallel.d.ts +14 -0
  181. package/dist/utils/parallel.js +43 -0
  182. package/dist/utils/parallel.js.map +1 -0
  183. package/dist/utils/parallel.test.d.ts +1 -0
  184. package/dist/utils/parallel.test.js +48 -0
  185. package/dist/utils/parallel.test.js.map +1 -0
  186. package/dist/utils/pathSecurity.d.ts +12 -0
  187. package/dist/utils/pathSecurity.js +22 -0
  188. package/dist/utils/pathSecurity.js.map +1 -0
  189. package/dist/utils/pathSecurity.test.d.ts +1 -0
  190. package/dist/utils/pathSecurity.test.js +34 -0
  191. package/dist/utils/pathSecurity.test.js.map +1 -0
  192. package/dist/utils/similarity.d.ts +12 -0
  193. package/dist/utils/similarity.js +64 -0
  194. package/dist/utils/similarity.js.map +1 -0
  195. package/dist/utils/similarity.test.d.ts +1 -0
  196. package/dist/utils/similarity.test.js +49 -0
  197. package/dist/utils/similarity.test.js.map +1 -0
  198. package/dist/utils/validation.d.ts +13 -0
  199. package/dist/utils/validation.js +24 -0
  200. package/dist/utils/validation.js.map +1 -0
  201. package/dist/utils/validation.test.d.ts +1 -0
  202. package/dist/utils/validation.test.js +28 -0
  203. package/dist/utils/validation.test.js.map +1 -0
  204. package/dist/validators/codePatternValidator.d.ts +28 -0
  205. package/dist/validators/codePatternValidator.js +200 -0
  206. package/dist/validators/codePatternValidator.js.map +1 -0
  207. package/dist/validators/codePatternValidator.test.d.ts +1 -0
  208. package/dist/validators/codePatternValidator.test.js +86 -0
  209. package/dist/validators/codePatternValidator.test.js.map +1 -0
  210. package/dist/validators/dependencyValidator.d.ts +12 -0
  211. package/dist/validators/dependencyValidator.js +102 -0
  212. package/dist/validators/dependencyValidator.js.map +1 -0
  213. package/dist/validators/dependencyValidator.test.d.ts +1 -0
  214. package/dist/validators/dependencyValidator.test.js +179 -0
  215. package/dist/validators/dependencyValidator.test.js.map +1 -0
  216. package/dist/validators/directoryValidator.d.ts +30 -0
  217. package/dist/validators/directoryValidator.js +192 -0
  218. package/dist/validators/directoryValidator.js.map +1 -0
  219. package/dist/validators/directoryValidator.test.d.ts +1 -0
  220. package/dist/validators/directoryValidator.test.js +193 -0
  221. package/dist/validators/directoryValidator.test.js.map +1 -0
  222. package/dist/validators/fileValidator.d.ts +16 -0
  223. package/dist/validators/fileValidator.js +114 -0
  224. package/dist/validators/fileValidator.js.map +1 -0
  225. package/dist/validators/fileValidator.test.d.ts +1 -0
  226. package/dist/validators/fileValidator.test.js +108 -0
  227. package/dist/validators/fileValidator.test.js.map +1 -0
  228. package/dist/validators/urlValidator.d.ts +25 -0
  229. package/dist/validators/urlValidator.js +320 -0
  230. package/dist/validators/urlValidator.js.map +1 -0
  231. package/dist/validators/urlValidator.test.d.ts +1 -0
  232. package/dist/validators/urlValidator.test.js +252 -0
  233. package/dist/validators/urlValidator.test.js.map +1 -0
  234. package/dist/validators/validationEngine.d.ts +23 -0
  235. package/dist/validators/validationEngine.js +117 -0
  236. package/dist/validators/validationEngine.js.map +1 -0
  237. package/dist/validators/validationEngine.test.d.ts +1 -0
  238. package/dist/validators/validationEngine.test.js +82 -0
  239. package/dist/validators/validationEngine.test.js.map +1 -0
  240. package/dist/validators/versionValidator.d.ts +18 -0
  241. package/dist/validators/versionValidator.js +211 -0
  242. package/dist/validators/versionValidator.js.map +1 -0
  243. package/dist/validators/versionValidator.test.d.ts +1 -0
  244. package/dist/validators/versionValidator.test.js +308 -0
  245. package/dist/validators/versionValidator.test.js.map +1 -0
  246. package/package.json +98 -0
@@ -0,0 +1,193 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { DirectoryValidator } from './directoryValidator.js';
4
+ import { makeDoc as makeBaseDoc, makeRef as makeBaseRef } from '../test-utils/factories.js';
5
+ function makeRef(value, overrides = {}) {
6
+ return makeBaseRef('directory-structure', value, overrides);
7
+ }
8
+ const doc = makeBaseDoc({
9
+ path: 'docs/README.md',
10
+ absolutePath: `${process.cwd()}/docs/README.md`,
11
+ });
12
+ describe('DirectoryValidator', () => {
13
+ const config = {
14
+ rootDir: process.cwd(),
15
+ rules: { 'directory-structure': { enabled: true, severity: 'warning', skipIllustrative: true } },
16
+ };
17
+ it('validates existing directories as valid (from project root)', async () => {
18
+ const validator = new DirectoryValidator();
19
+ const results = await validator.validateBatch([makeRef('src')], doc, config);
20
+ expect(results[0].valid).toBe(true);
21
+ expect(results[0].foundAt).toBe('src');
22
+ });
23
+ it('validates paths relative to document location', async () => {
24
+ const validator = new DirectoryValidator();
25
+ const results = await validator.validateBatch([makeRef('../src')], doc, config);
26
+ expect(results[0].valid).toBe(true);
27
+ });
28
+ it('marks missing paths as invalid', async () => {
29
+ const validator = new DirectoryValidator();
30
+ const results = await validator.validateBatch([makeRef('nonexistent-dir-xyz')], doc, config);
31
+ expect(results[0].valid).toBe(false);
32
+ expect(results[0].severity).toBe('warning');
33
+ expect(results[0].message).toContain('not found');
34
+ });
35
+ it('skips illustrative paths when configured', async () => {
36
+ const validator = new DirectoryValidator();
37
+ const results = await validator.validateBatch([makeRef('YourProject')], doc, config);
38
+ expect(results[0].skipped).toBe(true);
39
+ });
40
+ it('validates illustrative paths when skipIllustrative is false', async () => {
41
+ const validator = new DirectoryValidator();
42
+ const noSkipConfig = {
43
+ ...config,
44
+ rules: { 'directory-structure': { enabled: true, severity: 'warning', skipIllustrative: false } },
45
+ };
46
+ const results = await validator.validateBatch([makeRef('YourProject')], doc, noSkipConfig);
47
+ expect(results[0].valid).toBe(false);
48
+ expect(results[0].message).toContain('illustrative');
49
+ });
50
+ it('handles extractor-marked illustrative paths', async () => {
51
+ const validator = new DirectoryValidator();
52
+ const results = await validator.validateBatch([makeRef('example-dir', { isIllustrative: true })], doc, config);
53
+ expect(results[0].skipped).toBe(true);
54
+ });
55
+ it('caches results for repeated path lookups', async () => {
56
+ const validator = new DirectoryValidator();
57
+ await validator.validateBatch([makeRef('src')], doc, config);
58
+ const results = await validator.validateBatch([makeRef('src')], doc, config);
59
+ expect(results[0].valid).toBe(true);
60
+ });
61
+ it('caches invalid results too', async () => {
62
+ const validator = new DirectoryValidator();
63
+ await validator.validateBatch([makeRef('xyz-missing')], doc, config);
64
+ const results = await validator.validateBatch([makeRef('xyz-missing')], doc, config);
65
+ expect(results[0].valid).toBe(false);
66
+ });
67
+ it('provides suggestions for similar paths (e.g., case mismatch)', async () => {
68
+ const validator = new DirectoryValidator();
69
+ const results = await validator.validateBatch([makeRef('SRC')], doc, config);
70
+ if (!results[0].valid && results[0].suggestion) {
71
+ expect(results[0].suggestion).toContain('src');
72
+ }
73
+ });
74
+ it('provides suggestions for similar names (similarity ratio)', async () => {
75
+ const validator = new DirectoryValidator();
76
+ const results = await validator.validateBatch([makeRef('scr')], doc, config);
77
+ if (results[0].suggestion) {
78
+ expect(results[0].suggestion).toBeTruthy();
79
+ }
80
+ });
81
+ it('rejects paths that escape project root', async () => {
82
+ const validator = new DirectoryValidator();
83
+ const results = await validator.validateBatch([makeRef('../../../../etc/passwd')], doc, config);
84
+ expect(results[0].valid).toBe(false);
85
+ expect(results[0].message).toContain('escapes project root');
86
+ });
87
+ it('uses custom illustrative patterns from config', async () => {
88
+ const validator = new DirectoryValidator();
89
+ const customConfig = {
90
+ rootDir: process.cwd(),
91
+ rules: { 'directory-structure': { enabled: true, skipIllustrative: true, illustrativePatterns: ['^custom-example'] } },
92
+ };
93
+ const results = await validator.validateBatch([makeRef('custom-example-dir')], doc, customConfig);
94
+ expect(results[0].skipped).toBe(true);
95
+ });
96
+ it('uses default severity when not configured', async () => {
97
+ const validator = new DirectoryValidator();
98
+ const minConfig = { rootDir: process.cwd() };
99
+ const results = await validator.validateBatch([makeRef('nonexistent-abc')], doc, minConfig);
100
+ expect(results[0].valid).toBe(false);
101
+ expect(results[0].severity).toBe('warning');
102
+ });
103
+ it('returns cached invalid result with correct fields', async () => {
104
+ const validator = new DirectoryValidator();
105
+ await validator.validateBatch([makeRef('xyz-cached-miss')], doc, config);
106
+ const results = await validator.validateBatch([makeRef('xyz-cached-miss')], doc, config);
107
+ expect(results[0].valid).toBe(false);
108
+ expect(results[0].message).toContain('not found');
109
+ expect(results[0].severity).toBe('warning');
110
+ });
111
+ it('suggests singular/plural matches', async () => {
112
+ const validator = new DirectoryValidator();
113
+ const results = await validator.validateBatch([makeRef('src/validator')], doc, config);
114
+ if (!results[0].valid && results[0].suggestion) {
115
+ expect(results[0].suggestion).toBeTruthy();
116
+ }
117
+ });
118
+ it('returns null suggestion when parent dir does not exist', async () => {
119
+ const validator = new DirectoryValidator();
120
+ const results = await validator.validateBatch([makeRef('zzznope/xyzabc123/deep/child')], doc, config);
121
+ expect(results[0].valid).toBe(false);
122
+ expect(results[0].suggestion).toBeNull();
123
+ });
124
+ it('reports illustrative not-found path with correct message when skipIllustrative is false', async () => {
125
+ const validator = new DirectoryValidator();
126
+ const noSkipConfig = {
127
+ ...config,
128
+ rules: { 'directory-structure': { enabled: true, skipIllustrative: false } },
129
+ };
130
+ const results = await validator.validateBatch([makeRef('ExampleProject/nonexistent-file-zzz.ts')], doc, noSkipConfig);
131
+ expect(results[0].valid).toBe(false);
132
+ expect(results[0].message).toContain('illustrative');
133
+ });
134
+ it('handles illustrative path escaping project root', async () => {
135
+ const validator = new DirectoryValidator();
136
+ const noSkipConfig = {
137
+ ...config,
138
+ rules: { 'directory-structure': { enabled: true, skipIllustrative: false } },
139
+ };
140
+ const results = await validator.validateBatch([makeRef('../../../../etc/YourProject')], doc, noSkipConfig);
141
+ expect(results[0].valid).toBe(false);
142
+ expect(results[0].message).toContain('escapes project root');
143
+ });
144
+ it('does not leak custom illustrative patterns across validations', async () => {
145
+ const validator = new DirectoryValidator();
146
+ const firstConfig = {
147
+ rootDir: process.cwd(),
148
+ rules: { 'directory-structure': { enabled: true, skipIllustrative: true, illustrativePatterns: ['^custom-leak-dir'] } },
149
+ };
150
+ const secondConfig = {
151
+ rootDir: process.cwd(),
152
+ rules: { 'directory-structure': { enabled: true, severity: 'warning', skipIllustrative: false } },
153
+ };
154
+ const first = await validator.validateBatch([makeRef('custom-leak-dir/path')], doc, firstConfig);
155
+ expect(first[0].skipped).toBe(true);
156
+ const second = await validator.validateBatch([makeRef('custom-leak-dir/path')], doc, secondConfig);
157
+ expect(second[0].valid).toBe(false);
158
+ expect(second[0].message).toContain('Directory/file not found:');
159
+ });
160
+ it('does not reuse cache across different document contexts', async () => {
161
+ const validator = new DirectoryValidator();
162
+ const root = path.join(process.cwd(), '.doc-freshness-cache', 'directory-context');
163
+ const docsA = path.join(root, 'docs-a');
164
+ const docsB = path.join(root, 'docs-b');
165
+ await fs.promises.mkdir(docsA, { recursive: true });
166
+ await fs.promises.mkdir(docsB, { recursive: true });
167
+ await fs.promises.writeFile(path.join(docsA, 'target.txt'), 'exists in docs-a only');
168
+ const firstDoc = {
169
+ ...doc,
170
+ path: 'docs-a/readme.md',
171
+ absolutePath: `${root}/docs-a/readme.md`,
172
+ };
173
+ const secondDoc = {
174
+ ...doc,
175
+ path: 'docs-b/readme.md',
176
+ absolutePath: `${root}/docs-b/readme.md`,
177
+ };
178
+ const contextConfig = {
179
+ ...config,
180
+ rootDir: root,
181
+ };
182
+ try {
183
+ const first = await validator.validateBatch([makeRef('./target.txt')], firstDoc, contextConfig);
184
+ expect(first[0].valid).toBe(true);
185
+ const second = await validator.validateBatch([makeRef('./target.txt')], secondDoc, contextConfig);
186
+ expect(second[0].valid).toBe(false);
187
+ }
188
+ finally {
189
+ await fs.promises.rm(root, { recursive: true, force: true }).catch(() => { });
190
+ }
191
+ });
192
+ });
193
+ //# sourceMappingURL=directoryValidator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directoryValidator.test.js","sourceRoot":"","sources":["../../src/validators/directoryValidator.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { DocFreshnessConfig, Document, Reference, ValidationResult } from '../types.js';
2
+ /**
3
+ * Validates that file path references exist
4
+ */
5
+ export declare class FileValidator {
6
+ private directoryCache;
7
+ private customPatterns;
8
+ constructor();
9
+ /**
10
+ * Initialize custom illustrative patterns from config
11
+ */
12
+ private initCustomPatterns;
13
+ validateBatch(references: Reference[], document: Document, config: DocFreshnessConfig): Promise<ValidationResult[]>;
14
+ private validateReference;
15
+ private findSuggestion;
16
+ }
@@ -0,0 +1,114 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { findSimilar } from '../utils/similarity.js';
4
+ import { isIllustrativePath, compilePatterns } from '../utils/illustrativePatterns.js';
5
+ import { isWithinRoot, resolveDocumentDir, resolveProjectRoot } from '../utils/pathSecurity.js';
6
+ import { createIllustrativeSkippedResult, getRuleSeverity, severityForIllustrative } from '../utils/validation.js';
7
+ /**
8
+ * Validates that file path references exist
9
+ */
10
+ export class FileValidator {
11
+ directoryCache;
12
+ customPatterns;
13
+ constructor() {
14
+ this.directoryCache = new Map();
15
+ this.customPatterns = [];
16
+ }
17
+ /**
18
+ * Initialize custom illustrative patterns from config
19
+ */
20
+ initCustomPatterns(config) {
21
+ const configPatterns = config.rules?.['file-path']?.illustrativePatterns;
22
+ this.customPatterns = configPatterns && configPatterns.length > 0 ? compilePatterns(configPatterns) : [];
23
+ }
24
+ async validateBatch(references, document, config) {
25
+ this.initCustomPatterns(config);
26
+ const results = [];
27
+ const rootDir = resolveProjectRoot(config.rootDir);
28
+ const docDir = resolveDocumentDir(rootDir, document.path);
29
+ const skipIllustrative = config.rules?.['file-path']?.skipIllustrative !== false;
30
+ for (const ref of references) {
31
+ // Check if this is an illustrative path
32
+ const illustrative = ref.isIllustrative || isIllustrativePath(ref.value, this.customPatterns);
33
+ if (illustrative && skipIllustrative) {
34
+ results.push(createIllustrativeSkippedResult(ref, 'Skipped: illustrative/example path'));
35
+ continue;
36
+ }
37
+ const result = await this.validateReference(ref, docDir, rootDir, config, illustrative);
38
+ results.push(result);
39
+ }
40
+ return results;
41
+ }
42
+ async validateReference(ref, docDir, rootDir, config, isIllustrative = false) {
43
+ // Handle both relative and absolute paths
44
+ let resolvedPath;
45
+ if (path.isAbsolute(ref.value)) {
46
+ resolvedPath = path.resolve(ref.value);
47
+ }
48
+ else {
49
+ resolvedPath = path.resolve(docDir, ref.value);
50
+ }
51
+ // Normalize path
52
+ resolvedPath = path.normalize(resolvedPath);
53
+ const baseSeverity = getRuleSeverity(config, 'file-path', 'error');
54
+ // Prevent probing files outside the configured project root
55
+ if (!isWithinRoot(resolvedPath, rootDir)) {
56
+ return {
57
+ reference: ref,
58
+ valid: false,
59
+ severity: severityForIllustrative(isIllustrative, baseSeverity),
60
+ message: isIllustrative ? `Path escapes project root (illustrative): ${ref.value}` : `Path escapes project root: ${ref.value}`,
61
+ suggestion: null,
62
+ resolvedPath,
63
+ };
64
+ }
65
+ try {
66
+ await fs.promises.access(resolvedPath);
67
+ return {
68
+ reference: ref,
69
+ valid: true,
70
+ resolvedPath,
71
+ };
72
+ }
73
+ catch {
74
+ // File doesn't exist - try to find similar files
75
+ const suggestion = await this.findSuggestion(ref.value, docDir, rootDir);
76
+ // Reduce severity for illustrative paths that weren't skipped
77
+ return {
78
+ reference: ref,
79
+ valid: false,
80
+ severity: severityForIllustrative(isIllustrative, baseSeverity),
81
+ message: isIllustrative ? `File not found (illustrative): ${ref.value}` : `File not found: ${ref.value}`,
82
+ suggestion: suggestion ? `Did you mean: ${suggestion}?` : null,
83
+ resolvedPath,
84
+ };
85
+ }
86
+ }
87
+ async findSuggestion(refPath, docDir, rootDir) {
88
+ const dir = path.dirname(path.resolve(docDir, refPath));
89
+ const fileName = path.basename(refPath);
90
+ if (!isWithinRoot(dir, rootDir)) {
91
+ return null;
92
+ }
93
+ // Check if directory exists
94
+ try {
95
+ await fs.promises.access(dir);
96
+ }
97
+ catch {
98
+ return null;
99
+ }
100
+ // Get cached directory listing or create new one
101
+ if (!this.directoryCache.has(dir)) {
102
+ try {
103
+ const files = await fs.promises.readdir(dir);
104
+ this.directoryCache.set(dir, files);
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
110
+ const files = this.directoryCache.get(dir);
111
+ return findSimilar(fileName, files);
112
+ }
113
+ }
114
+ //# sourceMappingURL=fileValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileValidator.js","sourceRoot":"","sources":["../../src/validators/fileValidator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,108 @@
1
+ import { FileValidator } from './fileValidator.js';
2
+ import { makeDoc as makeBaseDoc, makeRef as makeBaseRef } from '../test-utils/factories.js';
3
+ function makeRef(value, overrides = {}) {
4
+ return makeBaseRef('file-path', value, overrides);
5
+ }
6
+ function makeDoc(docPath = 'docs/README.md') {
7
+ return makeBaseDoc({ path: docPath, absolutePath: `/project/${docPath}` });
8
+ }
9
+ describe('FileValidator', () => {
10
+ const validator = new FileValidator();
11
+ const config = {
12
+ rootDir: process.cwd(),
13
+ rules: { 'file-path': { enabled: true, severity: 'error', skipIllustrative: true } },
14
+ };
15
+ it('validates existing files as valid', async () => {
16
+ const results = await validator.validateBatch([makeRef('../package.json')], makeDoc(), { ...config, rootDir: process.cwd() });
17
+ expect(results[0].valid).toBe(true);
18
+ });
19
+ it('marks missing files as invalid', async () => {
20
+ const results = await validator.validateBatch([makeRef('../nonexistent-xyz.json')], makeDoc(), { ...config, rootDir: process.cwd() });
21
+ expect(results[0].valid).toBe(false);
22
+ expect(results[0].severity).toBe('error');
23
+ expect(results[0].message).toContain('File not found');
24
+ });
25
+ it('skips illustrative paths when configured', async () => {
26
+ const results = await validator.validateBatch([makeRef('YourProject/file.ts')], makeDoc(), config);
27
+ expect(results[0].valid).toBe(true);
28
+ expect(results[0].skipped).toBe(true);
29
+ });
30
+ it('flags illustrative paths when skipIllustrative is false', async () => {
31
+ const noSkipConfig = {
32
+ ...config,
33
+ rules: { 'file-path': { enabled: true, severity: 'error', skipIllustrative: false } },
34
+ };
35
+ const results = await validator.validateBatch([makeRef('ExampleFile.ts')], makeDoc(), noSkipConfig);
36
+ expect(results[0].severity).toBe('info');
37
+ });
38
+ it('rejects paths that escape project root', async () => {
39
+ const results = await validator.validateBatch([makeRef('/etc/passwd')], makeDoc(), config);
40
+ expect(results[0].valid).toBe(false);
41
+ expect(results[0].message).toContain('escapes project root');
42
+ });
43
+ it('handles pre-marked illustrative references', async () => {
44
+ const results = await validator.validateBatch([makeRef('real-looking-path.ts', { isIllustrative: true })], makeDoc(), config);
45
+ expect(results[0].skipped).toBe(true);
46
+ });
47
+ it('suggests similar files for typos', async () => {
48
+ const results = await validator.validateBatch([makeRef('../package.jso')], makeDoc(), { ...config, rootDir: process.cwd() });
49
+ expect(results[0].valid).toBe(false);
50
+ if (results[0].suggestion) {
51
+ expect(results[0].suggestion).toContain('package.json');
52
+ }
53
+ });
54
+ it('returns null suggestion when file directory does not exist', async () => {
55
+ const results = await validator.validateBatch([makeRef('zzz-nonexistent-dir/some-file.ts')], makeDoc(), {
56
+ ...config,
57
+ rootDir: process.cwd(),
58
+ });
59
+ expect(results[0].valid).toBe(false);
60
+ });
61
+ it('reports illustrative path escaping project root', async () => {
62
+ const noSkipConfig = {
63
+ ...config,
64
+ rules: { 'file-path': { enabled: true, severity: 'error', skipIllustrative: false } },
65
+ };
66
+ const results = await validator.validateBatch([makeRef('/etc/YourProject/file.ts')], makeDoc(), noSkipConfig);
67
+ expect(results[0].valid).toBe(false);
68
+ expect(results[0].message).toContain('illustrative');
69
+ expect(results[0].message).toContain('escapes project root');
70
+ });
71
+ it('uses custom illustrative patterns from config', async () => {
72
+ const customConfig = {
73
+ rootDir: process.cwd(),
74
+ rules: { 'file-path': { enabled: true, skipIllustrative: true, illustrativePatterns: ['^custom-prefix'] } },
75
+ };
76
+ const validator2 = new FileValidator();
77
+ const results = await validator2.validateBatch([makeRef('custom-prefix-file.ts')], makeDoc(), customConfig);
78
+ expect(results[0].skipped).toBe(true);
79
+ });
80
+ it('caches directory listings for repeated lookups', async () => {
81
+ const validator2 = new FileValidator();
82
+ await validator2.validateBatch([makeRef('../package-typo.json')], makeDoc(), { ...config, rootDir: process.cwd() });
83
+ const results = await validator2.validateBatch([makeRef('../another-typo.json')], makeDoc(), { ...config, rootDir: process.cwd() });
84
+ expect(results[0].valid).toBe(false);
85
+ });
86
+ it('handles absolute paths within project root', async () => {
87
+ const absPath = `${process.cwd()}/package.json`;
88
+ const results = await validator.validateBatch([makeRef(absPath)], makeDoc(), { ...config, rootDir: process.cwd() });
89
+ expect(results[0].valid).toBe(true);
90
+ });
91
+ it('does not leak custom illustrative patterns across validations', async () => {
92
+ const validator2 = new FileValidator();
93
+ const firstConfig = {
94
+ rootDir: process.cwd(),
95
+ rules: { 'file-path': { enabled: true, skipIllustrative: true, illustrativePatterns: ['^custom-leak-test'] } },
96
+ };
97
+ const secondConfig = {
98
+ rootDir: process.cwd(),
99
+ rules: { 'file-path': { enabled: true, severity: 'error', skipIllustrative: false } },
100
+ };
101
+ const first = await validator2.validateBatch([makeRef('custom-leak-test-file.ts')], makeDoc(), firstConfig);
102
+ expect(first[0].skipped).toBe(true);
103
+ const second = await validator2.validateBatch([makeRef('custom-leak-test-file.ts')], makeDoc(), secondConfig);
104
+ expect(second[0].valid).toBe(false);
105
+ expect(second[0].message).toContain('File not found:');
106
+ });
107
+ });
108
+ //# sourceMappingURL=fileValidator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileValidator.test.js","sourceRoot":"","sources":["../../src/validators/fileValidator.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { DocFreshnessConfig, Document, Reference, UrlCacheEntry, ValidationResult } from '../types.js';
2
+ /**
3
+ * Validates external URLs are accessible
4
+ */
5
+ export declare class UrlValidator {
6
+ private cache;
7
+ constructor();
8
+ validateBatch(references: Reference[], _document: Document, config: DocFreshnessConfig): Promise<ValidationResult[]>;
9
+ private validateUrl;
10
+ private fetchWithTimeout;
11
+ /**
12
+ * Check if URL is a GitHub URL (repos can be private)
13
+ */
14
+ private isGitHubUrl;
15
+ /**
16
+ * Load cache from external source
17
+ */
18
+ loadCache(cacheData: Record<string, UrlCacheEntry>): void;
19
+ /**
20
+ * Export cache for persistence
21
+ */
22
+ exportCache(): Record<string, UrlCacheEntry>;
23
+ private resolvesToPrivateAddress;
24
+ private setCacheEntry;
25
+ }