find-duplicate-strings
Advanced tools
Comparing version 2.1.4 to 2.1.5
@@ -14,2 +14,4 @@ "use strict"; | ||
const scanner_1 = require("../scanner"); | ||
const inquirer_1 = require("inquirer"); | ||
const bottomBar = new inquirer_1.ui.BottomBar(); | ||
const program = new commander_1.Command(); | ||
@@ -26,4 +28,4 @@ program | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield new scanner_1.Scanner(Object.assign(Object.assign({}, options), { path })).scan().catch((e) => console.error(e)); | ||
yield new scanner_1.Scanner(Object.assign(Object.assign({}, options), { path }), bottomBar).scan().catch((e) => console.error(e)); | ||
}); | ||
} |
@@ -1,7 +0,7 @@ | ||
export { DirectoryQuestion } from './directory'; | ||
export { PathQuestion } from './path'; | ||
export { ExclusionsQuestion } from './exclusions'; | ||
export { ExtensionsQuestion } from './extensions'; | ||
export { OutputQuestion } from './output'; | ||
export { ConfirmDirectoryQuestion } from './confirm-directory'; | ||
export { ConfirmScannedDirQuestion } from './confirm-scanned-dir'; | ||
export { ConfirmPathQuestion } from './confirm-path'; | ||
export { ConfirmDuplicatePathQuestion } from './confirm-duplicate-path'; | ||
export { ThresholdQuestion } from './threshold'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ThresholdQuestion = exports.ConfirmScannedDirQuestion = exports.ConfirmDirectoryQuestion = exports.OutputQuestion = exports.ExtensionsQuestion = exports.ExclusionsQuestion = exports.DirectoryQuestion = void 0; | ||
var directory_1 = require("./directory"); | ||
Object.defineProperty(exports, "DirectoryQuestion", { enumerable: true, get: function () { return directory_1.DirectoryQuestion; } }); | ||
exports.ThresholdQuestion = exports.ConfirmDuplicatePathQuestion = exports.ConfirmPathQuestion = exports.OutputQuestion = exports.ExtensionsQuestion = exports.ExclusionsQuestion = exports.PathQuestion = void 0; | ||
var path_1 = require("./path"); | ||
Object.defineProperty(exports, "PathQuestion", { enumerable: true, get: function () { return path_1.PathQuestion; } }); | ||
var exclusions_1 = require("./exclusions"); | ||
@@ -12,7 +12,7 @@ Object.defineProperty(exports, "ExclusionsQuestion", { enumerable: true, get: function () { return exclusions_1.ExclusionsQuestion; } }); | ||
Object.defineProperty(exports, "OutputQuestion", { enumerable: true, get: function () { return output_1.OutputQuestion; } }); | ||
var confirm_directory_1 = require("./confirm-directory"); | ||
Object.defineProperty(exports, "ConfirmDirectoryQuestion", { enumerable: true, get: function () { return confirm_directory_1.ConfirmDirectoryQuestion; } }); | ||
var confirm_scanned_dir_1 = require("./confirm-scanned-dir"); | ||
Object.defineProperty(exports, "ConfirmScannedDirQuestion", { enumerable: true, get: function () { return confirm_scanned_dir_1.ConfirmScannedDirQuestion; } }); | ||
var confirm_path_1 = require("./confirm-path"); | ||
Object.defineProperty(exports, "ConfirmPathQuestion", { enumerable: true, get: function () { return confirm_path_1.ConfirmPathQuestion; } }); | ||
var confirm_duplicate_path_1 = require("./confirm-duplicate-path"); | ||
Object.defineProperty(exports, "ConfirmDuplicatePathQuestion", { enumerable: true, get: function () { return confirm_duplicate_path_1.ConfirmDuplicatePathQuestion; } }); | ||
var threshold_1 = require("./threshold"); | ||
Object.defineProperty(exports, "ThresholdQuestion", { enumerable: true, get: function () { return threshold_1.ThresholdQuestion; } }); |
export declare class Directory { | ||
private readonly path; | ||
private readonly exclusions; | ||
private readonly extensions; | ||
private readonly path; | ||
constructor(directory: string, exclusions: string[], extensions: string[]); | ||
constructor(path: string, exclusions: string[], extensions: string[]); | ||
getFiles(): AsyncGenerator<string, void, unknown>; | ||
private readdirRecursively; | ||
} |
@@ -31,12 +31,6 @@ "use strict"; | ||
class Directory { | ||
constructor(directory, exclusions, extensions) { | ||
constructor(path, exclusions, extensions) { | ||
this.path = path; | ||
this.exclusions = exclusions; | ||
this.extensions = extensions; | ||
this.path = (0, path_1.normalize)((0, path_1.resolve)(process.cwd(), directory)); | ||
if (!(0, fs_1.existsSync)(this.path)) { | ||
throw new Error('Directory does not exist, please pass a valid path.'); | ||
} | ||
if (!(0, fs_1.statSync)(this.path).isDirectory()) { | ||
throw new Error('Path does not point to a directory.'); | ||
} | ||
} | ||
@@ -46,3 +40,2 @@ getFiles() { | ||
} | ||
// TODO: support reading single file | ||
readdirRecursively(path) { | ||
@@ -49,0 +42,0 @@ return __asyncGenerator(this, arguments, function* readdirRecursively_1() { |
@@ -1,7 +0,5 @@ | ||
/// <reference types="node" /> | ||
import { Interface } from 'readline'; | ||
export declare class File { | ||
private name; | ||
private readonly name; | ||
constructor(name: string); | ||
processContent(): Interface; | ||
processContent(): Promise<any>; | ||
private processLine; | ||
@@ -8,0 +6,0 @@ private storeMatch; |
@@ -12,5 +12,9 @@ "use strict"; | ||
processContent() { | ||
const rl = this.readlineInterface(); | ||
rl.on('line', (line) => this.processLine(line)); | ||
return rl; | ||
return new Promise((resolve) => { | ||
const rl = this.readlineInterface(); | ||
rl.on('line', (line) => this.processLine(line)); | ||
rl.on('close', () => { | ||
resolve(true); | ||
}); | ||
}); | ||
} | ||
@@ -36,4 +40,3 @@ processLine(line) { | ||
} | ||
value.count++; | ||
store_1.Store.update(key, { key, count: value.count, files: value.files }); | ||
store_1.Store.update(key, { key, count: (value.count += 1), files: value.files }); | ||
} | ||
@@ -40,0 +43,0 @@ readlineInterface() { |
@@ -0,1 +1,2 @@ | ||
import BottomBar from 'inquirer/lib/ui/bottom-bar'; | ||
interface Options { | ||
@@ -9,2 +10,4 @@ silent?: boolean; | ||
export declare class Scanner { | ||
private bottomBar; | ||
private loaderInterval; | ||
private readonly scannedDirs; | ||
@@ -16,7 +19,10 @@ private exclusions; | ||
private path; | ||
constructor(options: Options); | ||
constructor(options: Options, bottomBar: BottomBar, loaderInterval?: number); | ||
scan(): Promise<void>; | ||
private startScan; | ||
private scanDir; | ||
private scanFile; | ||
private getDuplicates; | ||
private initScan; | ||
} | ||
export {}; |
@@ -18,2 +18,5 @@ "use strict"; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -28,4 +31,10 @@ exports.Scanner = void 0; | ||
const questions_1 = require("./cli/questions"); | ||
const fs_1 = require("fs"); | ||
const path_1 = require("path"); | ||
const path_2 = require("./cli/questions/path"); | ||
const process_1 = __importDefault(require("process")); | ||
class Scanner { | ||
constructor(options) { | ||
constructor(options, bottomBar, loaderInterval = 1000) { | ||
this.bottomBar = bottomBar; | ||
this.loaderInterval = loaderInterval; | ||
this.scannedDirs = []; | ||
@@ -46,3 +55,3 @@ if (options.exclusions) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const path = this.path.length ? this.path : yield new questions_1.DirectoryQuestion().getAnswer(); | ||
const path = this.path.length ? this.path : yield new path_2.PathQuestion().getAnswer(); | ||
if (!this.exclusions) { | ||
@@ -62,10 +71,10 @@ const answer = yield new questions_1.ExclusionsQuestion().getAnswer(); | ||
if (this.scannedDirs.includes(path)) { | ||
shouldScan = yield new questions_1.ConfirmScannedDirQuestion().getAnswer(); | ||
shouldScan = yield new questions_1.ConfirmDuplicatePathQuestion().getAnswer(); | ||
} | ||
if (shouldScan) { | ||
yield this.scanDir(path); | ||
this.scannedDirs.push(path); | ||
yield this.initScan(path); | ||
} | ||
const continueScanning = yield new questions_1.ConfirmDirectoryQuestion().getAnswer(); | ||
const continueScanning = yield new questions_1.ConfirmPathQuestion().getAnswer(); | ||
if (continueScanning) { | ||
this.path = ''; | ||
return this.scan(); | ||
@@ -81,6 +90,25 @@ } | ||
} | ||
scanDir(dirName) { | ||
startScan(path) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const fullPath = (0, path_1.normalize)((0, path_1.resolve)(process_1.default.cwd(), path)); | ||
const noSuchDirectoryOrFileError = new Error('Invalid path: No such directory or file.'); | ||
if (!(0, fs_1.existsSync)(fullPath)) { | ||
throw noSuchDirectoryOrFileError; | ||
} | ||
const lstat = (0, fs_1.statSync)(fullPath); | ||
if (lstat.isFile()) { | ||
yield this.scanFile(fullPath); | ||
return; | ||
} | ||
if (lstat.isDirectory()) { | ||
yield this.scanDir(fullPath); | ||
return; | ||
} | ||
throw noSuchDirectoryOrFileError; | ||
}); | ||
} | ||
scanDir(path) { | ||
var e_1, _a; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const directory = new directory_1.Directory(dirName, this.exclusions, this.extensions); | ||
const directory = new directory_1.Directory(path, this.exclusions, this.extensions); | ||
const files = directory.getFiles(); | ||
@@ -90,3 +118,3 @@ try { | ||
const file = files_1_1.value; | ||
new file_1.File(file).processContent(); | ||
yield this.scanFile(file); | ||
} | ||
@@ -103,6 +131,40 @@ } | ||
} | ||
scanFile(path) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield new file_1.File(path).processContent(); | ||
}); | ||
} | ||
getDuplicates() { | ||
return store_1.Store.getAll().filter((value) => value.count > this.threshold); | ||
} | ||
initScan(path) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let count = 0; | ||
const loader = setInterval(() => { | ||
count++; | ||
if (count > 10) { | ||
count = 0; | ||
} | ||
this.bottomBar.updateBottomBar('.'.repeat(count)); | ||
}, this.loaderInterval); | ||
const clearLoader = () => { | ||
clearInterval(loader); | ||
process_1.default.removeAllListeners('SIGTERM'); | ||
}; | ||
process_1.default.on('SIGTERM', () => { | ||
clearInterval(loader); | ||
}); | ||
try { | ||
yield this.startScan(path); | ||
} | ||
catch (error) { | ||
clearLoader(); | ||
throw error; | ||
} | ||
clearLoader(); | ||
this.bottomBar.updateBottomBar(''); | ||
this.scannedDirs.push(path); | ||
}); | ||
} | ||
} | ||
exports.Scanner = Scanner; |
@@ -0,7 +1,8 @@ | ||
import { Finding } from './finding'; | ||
export declare class Store { | ||
private static readonly store; | ||
static add(key: string, value: unknown): void; | ||
static update(key: string, value: unknown): void; | ||
static find(key: string): unknown | null; | ||
static getAll(): unknown[]; | ||
static add(key: string, value: Finding): void; | ||
static update(key: string, value: Finding): void; | ||
static find(key: string): Finding | null; | ||
static getAll(): Finding[]; | ||
} |
{ | ||
"name": "find-duplicate-strings", | ||
"version": "2.1.4", | ||
"version": "2.1.5", | ||
"description": "Easy to use CLI that finds duplicate strings in a directory and stores them in a external file for easy reference", | ||
@@ -43,14 +43,14 @@ "author": "Erwin Heitzman", | ||
"@types/inquirer": "^8.1.3", | ||
"@types/jest": "^27.0.2", | ||
"@types/node": "^16.11.6", | ||
"@typescript-eslint/eslint-plugin": "^5.3.0", | ||
"@typescript-eslint/parser": "^5.3.0", | ||
"eslint": "^8.1.0", | ||
"@types/jest": "^27.0.3", | ||
"@types/node": "^16.11.10", | ||
"@typescript-eslint/eslint-plugin": "^5.4.0", | ||
"@typescript-eslint/parser": "^5.4.0", | ||
"eslint": "^8.3.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"husky": "^7.0.4", | ||
"jest": "^27.3.1", | ||
"lint-staged": "^11.2.6", | ||
"lint-staged": "^12.1.2", | ||
"prettier": "^2.4.1", | ||
"ts-jest": "^27.0.7", | ||
"typescript": "^4.4.4" | ||
"typescript": "^4.5.2" | ||
}, | ||
@@ -57,0 +57,0 @@ "lint-staged": { |
44577
902
4