UNPKG

18.5 kBTypeScriptView Raw
1/// <reference types="node" />
2import * as fs from "fs";
3/**
4 * Comparison options.
5 */
6export interface Options {
7 /**
8 * Properties to be used in various extension points ie. result builder.
9 */
10 [key: string]: any;
11 /**
12 * Compares files by size. Defaults to 'false'.
13 *
14 * Usually one of `compareSize` or `compareContent` options has to be activated. Otherwise files are compared by name disregarding size or content.
15 */
16 compareSize?: boolean;
17 /**
18 * Compares files by content. Defaults to 'false'.
19 *
20 * Usually one of `compareSize` or `compareContent` options has to be activated. Otherwise files are compared by name disregarding size or content.
21 */
22 compareContent?: boolean;
23 /**
24 * Compares files by date of modification (stat.mtime). Defaults to 'false'.
25 *
26 * Also see {@link Options.dateTolerance}.
27 */
28 compareDate?: boolean;
29 /**
30 * Two files are considered to have the same date if the difference between their modification dates fits within date tolerance. Defaults to 1000 ms.
31 */
32 dateTolerance?: number;
33 /**
34 * Compares entries by symlink. Defaults to 'false'.
35
36 * If this option is enabled two entries must have the same type in order to be considered equal.
37 * They have to be either two fies, two directories or two symlinks.
38 *
39 * If left entry is a file and right entry is a symlink, they are considered distinct disregarding the content of the file.
40 *
41 * Further if both entries are symlinks they need to have the same link value. For example if one symlink points to '/x/b.txt' and the other to '/x/../x/b.txt' the symlinks are considered distinct even if they point to the same file.
42 */
43 compareSymlink?: boolean;
44 /**
45 * Skips sub directories. Defaults to 'false'.
46 */
47 skipSubdirs?: boolean;
48 /**
49 * Ignore empty directories. Defaults to 'false'.
50 */
51 skipEmptyDirs?: boolean;
52 /**
53 * Ignore symbolic links. Defaults to 'false'.
54 */
55 skipSymlinks?: boolean;
56 /**
57 * Ignores case when comparing names. Defaults to 'false'.
58 */
59 ignoreCase?: boolean;
60 /**
61 * Toggles presence of diffSet in output. If true, only statistics are provided. Use this when comparing large number of files to avoid out of memory situations. Defaults to 'false'.
62 */
63 noDiffSet?: boolean;
64 /**
65 * File name filter. Comma separated minimatch patterns. See [Glob patterns](https://github.com/gliviu/dir-compare#glob-patterns).
66 */
67 includeFilter?: string;
68 /**
69 * File/directory name exclude filter. Comma separated minimatch patterns. See [Glob patterns](https://github.com/gliviu/dir-compare#glob-patterns).
70 */
71 excludeFilter?: string;
72 /**
73 * Handle permission denied errors. Defaults to 'false'.
74 *
75 * By default when some entry cannot be read due to `EACCES` error the comparison will
76 * stop immediately with an exception.
77 *
78 * If `handlePermissionDenied` is set to true the comparison will continue when unreadable entries are encountered.
79 *
80 * Offending entries will be reported within {@link Difference.permissionDeniedState}, {@link Difference.reason} and {@link Result.permissionDenied}.
81 *
82 * Lets consider we want to compare two identical folders `A` and `B` with `B/dir2` being unreadable for the current user.
83 * ```
84 * A B
85 * ├── dir1 ├── dir1
86 * ├──── file1 ├──── file1
87 * ├── dir2 ├── dir2 (permission denied)
88 * └─────file2 └─────file2
89 * ```
90 *
91 * {@link Result.diffSet} will look like:
92 *
93 * |relativePath |path1 |path2 | state |reason |permissionDeniedState|
94 * |--------------|---------|---------|------------|------------------------|---------------------|
95 * |[/] |dir1 |dir1 |`equal` | | |
96 * |[/dir1] |file1 |file1 |`equal` | | |
97 * |[/] |dir2 |dir2 |`distinct` | `permission-denied` |`access-error-right` |
98 * |[/dir2] |file2 |missing |`left` | | |
99 *
100 * And {@link Result.permissionDenied} statistics look like
101 * ```json
102 * {
103 * leftPermissionDenied: 0,
104 * rightPermissionDenied: 1,
105 * distinctPermissionDenied: 0,
106 * totalPermissionDenied: 1
107 * }
108 * ```
109 */
110 handlePermissionDenied?: boolean;
111 /**
112 * Extension point used for constructing the {@link Result} object.
113 *
114 * See [Result builder](https://github.com/gliviu/dir-compare#result-builder).
115 */
116 resultBuilder?: ResultBuilder;
117 /**
118 * Extension point used to perform sync file content comparison.
119 *
120 * See [File comparators](https://github.com/gliviu/dir-compare#file-content-comparators).
121 */
122 compareFileSync?: CompareFileSync;
123 /**
124 * Extension point used to perform async file content comparison.
125 *
126 * See [File comparators](https://github.com/gliviu/dir-compare#file-content-comparators).
127 */
128 compareFileAsync?: CompareFileAsync;
129 /**
130 * Extension point used to compare files or directories names.
131 *
132 * See [Name comparators](https://github.com/gliviu/dir-compare#name-comparators).
133 */
134 compareNameHandler?: CompareNameHandler;
135 /**
136 * Extension point used to control which files or directories should be included in the comparison.
137 *
138 * See [Glob filter](https://github.com/gliviu/dir-compare#glob-filter).
139 */
140 filterHandler?: FilterHandler;
141}
142/**
143 * List of differences occurred during comparison.
144 */
145export type DiffSet = Array<Difference>;
146/**
147 * @internal
148 */
149export type OptionalDiffSet = DiffSet | undefined;
150export type EntryOrigin = 'left' | 'right';
151export interface Entry {
152 name: string;
153 absolutePath: string;
154 path: string;
155 /**
156 * Whether this entry originated from the left or the right dir.
157 */
158 origin: EntryOrigin;
159 stat: fs.Stats;
160 lstat: fs.Stats;
161 isDirectory: boolean;
162 isSymlink: boolean;
163 isBrokenLink: boolean;
164 /**
165 * True when this entry is not readable.
166 * This value is set only when {@link Options.handlePermissionDenied} is enabled.
167 */
168 isPermissionDenied: boolean;
169}
170/**
171 * Comparison result.
172 */
173export interface Result extends Statistics {
174 /**
175 * Detailed list of comparison results.
176 * Present if {@link Options.noDiffSet} is false.
177 */
178 diffSet?: DiffSet;
179}
180/**
181 * Basic statistics information. Does not have any computed fields.
182 */
183export interface InitialStatistics {
184 /**
185 * Any property is allowed if default result builder is not used.
186 */
187 [key: string]: any;
188 /**
189 * Number of distinct entries.
190 */
191 distinct: number;
192 /**
193 * Number of equal entries.
194 */
195 equal: number;
196 /**
197 * Number of entries only in path1.
198 */
199 left: number;
200 /**
201 * Number of entries only in path2.
202 */
203 right: number;
204 /**
205 * Number of distinct files.
206 */
207 distinctFiles: number;
208 /**
209 * Number of equal files.
210 */
211 equalFiles: number;
212 /**
213 * Number of files only in path1.
214 */
215 leftFiles: number;
216 /**
217 * Number of files only in path2
218 */
219 rightFiles: number;
220 /**
221 * Number of distinct directories.
222 */
223 distinctDirs: number;
224 /**
225 * Number of equal directories.
226 */
227 equalDirs: number;
228 /**
229 * Number of directories only in path1.
230 */
231 leftDirs: number;
232 /**
233 * Number of directories only in path2.
234 */
235 rightDirs: number;
236 /**
237 * Stats about broken links.
238 */
239 brokenLinks: BrokenLinksStatistics;
240 /**
241 * Statistics available if 'compareSymlink' options is used.
242 */
243 symlinks?: SymlinkStatistics;
244 /**
245 * Stats about entries that could not be accessed.
246 */
247 permissionDenied: PermissionDeniedStatistics;
248}
249/**
250 * In addition to fields inherited from {@link InitialStatistics} this class
251 * adds fields computed at the final stage of the comparison.
252 */
253export interface Statistics extends InitialStatistics {
254 /**
255 * True if directories are identical.
256 */
257 same: boolean;
258 /**
259 * Total number of differences (distinct+left+right).
260 */
261 differences: number;
262 /**
263 * Total number of entries (differences+equal).
264 */
265 total: number;
266 /**
267 * Total number of different files (distinctFiles+leftFiles+rightFiles).
268 */
269 differencesFiles: number;
270 /**
271 * Total number of files (differencesFiles+equalFiles).
272 */
273 totalFiles: number;
274 /**
275 * Total number of different directories (distinctDirs+leftDirs+rightDirs).
276 */
277 differencesDirs: number;
278 /**
279 * Total number of directories (differencesDirs+equalDirs).
280 */
281 totalDirs: number;
282}
283export interface BrokenLinksStatistics {
284 /**
285 * Number of broken links only in path1
286 */
287 leftBrokenLinks: number;
288 /**
289 * Number of broken links only in path2
290 */
291 rightBrokenLinks: number;
292 /**
293 * Number of broken links with same name appearing in both path1 and path2 (leftBrokenLinks + rightBrokenLinks + distinctBrokenLinks)
294 */
295 distinctBrokenLinks: number;
296 /**
297 * Total number of broken links
298 */
299 totalBrokenLinks: number;
300}
301export interface PermissionDeniedStatistics {
302 /**
303 * Number of forbidden entries found only in path1
304 */
305 leftPermissionDenied: number;
306 /**
307 * Number of forbidden entries found only in path2
308 */
309 rightPermissionDenied: number;
310 /**
311 * Number of forbidden entries with same name appearing in both path1 and path2 (leftPermissionDenied + rightPermissionDenied + distinctPermissionDenied)
312 */
313 distinctPermissionDenied: number;
314 /**
315 * Total number of forbidden entries
316 */
317 totalPermissionDenied: number;
318}
319export interface SymlinkStatistics {
320 /**
321 * Number of distinct links.
322 */
323 distinctSymlinks: number;
324 /**
325 * Number of equal links.
326 */
327 equalSymlinks: number;
328 /**
329 * Number of links only in path1.
330 */
331 leftSymlinks: number;
332 /**
333 * Number of links only in path2
334 */
335 rightSymlinks: number;
336 /**
337 * Total number of different links (distinctSymlinks+leftSymlinks+rightSymlinks).
338 */
339 differencesSymlinks: number;
340 /**
341 * Total number of links (differencesSymlinks+equalSymlinks).
342 */
343 totalSymlinks: number;
344}
345/**
346 * State of left/right entries relative to each other.
347 * * `equal` - Identical entries are found in both left/right dirs.
348 * * `left` - Entry is found only in left dir.
349 * * `right` - Entry is found only in right dir.
350 * * `distinct` - Entries exist in both left/right dir but have different content. See {@link Difference.reason} to understan why entries are considered distinct.
351 */
352export type DifferenceState = "equal" | "left" | "right" | "distinct";
353/**
354 * Permission related state of left/right entries. Available only when {@link Options.handlePermissionDenied} is enabled.
355 * * `access-ok` - Both entries are accessible.
356 * * `access-error-both` - Neither entry can be accessed.
357 * * `access-error-left` - Left entry cannot be accessed.
358 * * `access-error-right` - Right entry cannot be accessed.
359 */
360export type PermissionDeniedState = "access-ok" | "access-error-both" | "access-error-left" | "access-error-right";
361/**
362 * Type of entry.
363 */
364export type DifferenceType = "missing" | "file" | "directory" | "broken-link";
365/**
366 * Provides reason when two identically named entries are distinct.
367 *
368 * Not available if entries are equal.
369 *
370 * * `different-size` - Files differ in size.
371 * * `different-date - Entry dates are different. Used when {@link Options.compareDate} is `true`.
372 * * `different-content` - File contents are different. Used when {@link Options.compareContent} is `true`.
373 * * `broken-link` - Both left/right entries are broken links.
374 * * `different-symlink` - Symlinks are different. See {@link Options.compareSymlink} for details.
375 * * `permission-denied` - One or both left/right entries are not accessible. See {@link Options.handlePermissionDenied} for details.
376 */
377export type Reason = undefined | "different-size" | "different-date" | "different-content" | "broken-link" | 'different-symlink' | 'permission-denied';
378export interface Difference {
379 /**
380 * Any property is allowed if default result builder is not used.
381 */
382 [key: string]: any;
383 /**
384 * Path not including file/directory name; can be relative or absolute depending on call to compare().
385 * Is undefined if missing on the left side.
386 */
387 path1?: string;
388 /**
389 * Path not including file/directory name; can be relative or absolute depending on call to compare().
390 * Is undefined if missing on the right side.
391 */
392 path2?: string;
393 /**
394 * Path relative to the root directory of the comparison.
395 */
396 relativePath: string;
397 /**
398 * Left file/directory name.
399 * Is undefined if missing on the left side.
400 */
401 name1?: string;
402 /**
403 * Right file/directory name.
404 * Is undefined if missing on the right side.
405 */
406 name2?: string;
407 /**
408 * See {@link DifferenceState}
409 */
410 state: DifferenceState;
411 /**
412 * Permission related state of left/right entries.
413 */
414 permissionDeniedState: PermissionDeniedState;
415 /**
416 * Type of left entry.
417 * Is undefined if missing on the left side.
418 */
419 type1: DifferenceType;
420 /**
421 * Type of right entry.
422 * Is undefined if missing on the right side.
423 */
424 type2: DifferenceType;
425 /**
426 * Left file size.
427 * Is undefined if missing on the left side.
428 */
429 size1?: number;
430 /**
431 * Right file size.
432 * Is undefined if missing on the right side.
433 */
434 size2?: number;
435 /**
436 * Left entry modification date (stat.mtime).
437 * Is undefined if missing on the left side.
438 */
439 date1?: Date;
440 /**
441 * Right entry modification date (stat.mtime).
442 * Is undefined if missing on the right side.
443 */
444 date2?: Date;
445 /**
446 * Depth level relative to root dir.
447 */
448 level: number;
449 /**
450 * Provides reason when two identically named entries are distinct.
451 */
452 reason: Reason;
453}
454/**
455 * Extension point used for constructing the {@link Result} object.
456 * Called for each compared entry pair.
457 * Updates 'statistics' and 'diffSet'.
458 * @param entry1 Left entry.
459 * @param entry2 Right entry.
460 * @param state See {@link DifferenceState}.
461 * @param level Depth level relative to root dir.
462 * @param relativePath Path relative to the root directory of the comparison.
463 * @param statistics Statistics to be updated.
464 * @param diffSet Status per each entry to be appended.
465 * Do not append if {@link Options.noDiffSet} is false.
466 * @param reason See {@link Reason}. Not available if entries are equal.
467 */
468export type ResultBuilder = (entry1: Entry | undefined, entry2: Entry | undefined, state: DifferenceState, level: number, relativePath: string, options: Options, statistics: InitialStatistics, diffSet: DiffSet | undefined, reason: Reason | undefined, permissionDeniedState: PermissionDeniedState) => void;
469/**
470 * Extension point used to perform sync file content comparison.
471 */
472export type CompareFileSync = (path1: string, stat1: fs.Stats, path2: string, stat2: fs.Stats, options: Options) => boolean;
473/**
474 * Extension point used to perform async file content comparison.
475 */
476export type CompareFileAsync = (path1: string, stat1: fs.Stats, path2: string, stat2: fs.Stats, options: Options) => Promise<boolean>;
477export interface CompareFileHandler {
478 compareSync: CompareFileSync;
479 compareAsync: CompareFileAsync;
480}
481/**
482 * Extension point used to compare files or directories names.
483 * The comparison should be dependent on received options (ie. case sensitive, ...).
484 * Returns 0 if names are identical, -1 if name1<name2, 1 if name1>name2.
485 */
486export type CompareNameHandler = (name1: string, name2: string, options: Options) => 0 | 1 | -1;
487/**
488 * Extension point used to control which files or directories should be included in the comparison.
489 *
490 * @param entry Filesystem entry to include or ignore.
491 * @param relativePath Path relative to the root directory of the comparison. It depends on {@link Entry.origin}.
492 * @param option Comparison options.
493 * @returns Returns true if the entry is to be processed or false to ignore it.
494 */
495export type FilterHandler = (entry: Entry, relativePath: string, options: Options) => boolean;
496export interface FileCompareHandlers {
497 /**
498 * Compares files based on their binary content.
499 *
500 * This is the default file content comparator.
501 * It is used when {@link Options.compareContent} is true and custom file comparator
502 * is not specified (ie. {@link Options.compareFileSync} or {@link Options.compareFileAsync} are 'undefined').
503 */
504 defaultFileCompare: CompareFileHandler;
505 /**
506 * Compares files line by line.
507 *
508 * These additional options are available:
509 * * ignoreLineEnding - true/false (default: false) - Ignore cr/lf line endings
510 * * ignoreWhiteSpaces - true/false (default: false) - Ignore white spaces at the beginning and ending of a line (similar to 'diff -b')
511 * * ignoreAllWhiteSpaces - true/false (default: false) - Ignore all white space differences (similar to 'diff -w')
512 * * ignoreEmptyLines - true/false (default: false) - Ignores differences caused by empty lines (similar to 'diff -B')
513 */
514 lineBasedFileCompare: CompareFileHandler;
515}
516export interface CompareNameHandlers {
517 /**
518 * Compares file or directory names using the 'strcmp' function.
519 * It is used if {@link Options.compareNameHandler} is not specified.
520 */
521 defaultNameCompare: CompareNameHandler;
522}
523export interface FilterHandlers {
524 /**
525 * Uses minimatch to include/ignore files based on {@link Options.includeFilter} and {@link Options.excludeFilter}.
526 * It is used if {@link Options.filterHandler} is not specified.
527 */
528 defaultFilterHandler: FilterHandler;
529}
530//# sourceMappingURL=types.d.ts.map
\No newline at end of file