UNPKG

delete-old-files

Version:

Delete files that were last updated too long time ago.

262 lines (229 loc) 9.36 kB
"use strict"; var fs = require("fs"); var path = require("path"); var deffy = require("deffy"); /** * deleteOldFiles * Deletes the old files in the specified directories. * * @name deleteOldFiles * @function * @param {Object} options The options object containing: * * - `directoryPaths` (Array): An array of directory paths to scan for old files. Default is `[]`. * - `age` (Number): The age in seconds that a file must be older than to be deleted. Default is `604800` (7 days). * - `checkInterval` (Number): The interval in seconds to check for old files. Default is `86400` (1 day). Set to `0` to disable periodic checks. * - `recursive` (Boolean): Whether to scan directories recursively. Default is `false`. * - `exclude` (Array): An array of file names or regex patterns to exclude from deletion. Default is `[]`. * - `include` (Array): An array of file names or regex patterns to include for deletion. If empty, all files are included unless excluded. Default is `[]`. * - `verbose` (Boolean): Whether to log detailed information about the process. Default is `false`. * - `dryRun` (Boolean): If `true`, files will not be deleted, but actions will be logged. Default is `false`. * - `onError` (Function): A callback function that is called when an error occurs. Receives the error as an argument. * - `onDelete` (Function): A callback function that is called when a file is deleted. Receives the file path as an argument. */ function deleteOldFiles() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; options = deffy(options, {}); options.directoryPaths = deffy(options.directoryPaths, []); options.age = deffy(options.age, 86400 * 7); // 7 days options.checkInterval = deffy(options.checkInterval, 86400); // seconds (1 day) options.recursive = deffy(options.recursive, false); options.exclude = deffy(options.exclude, []); options.include = deffy(options.include, []); options.verbose = deffy(options.verbose, false); options.dryRun = deffy(options.dryRun, false); if (typeof options.onError !== "function") { options.onError = function () {}; } if (typeof options.onDelete !== "function") { options.onDelete = function () {}; } if (!options.directoryPaths.length) { return; } if (options.age < 0) { throw new Error("The age option must be a positive number."); } var run = function run() { try { deleteOldFiles.run(options); } catch (err) { options.onError(err); } }; if (options.checkInterval > 0) { setInterval(run, options.checkInterval * 1000); } run(); } deleteOldFiles.matches = function (filePath) { var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref$include = _ref.include, include = _ref$include === undefined ? [] : _ref$include, _ref$exclude = _ref.exclude, exclude = _ref$exclude === undefined ? [] : _ref$exclude; if (!include.length && !exclude.length) { return true; } var included = !include.length; var baseName = path.basename(filePath); var matches = function matches(pattern) { return pattern instanceof RegExp ? pattern.test(filePath) : pattern === baseName; }; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = include[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var pattern = _step.value; if (matches(pattern)) { included = true; break; } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } if (!included) { return false; } var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = exclude[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var _pattern = _step2.value; if (matches(_pattern)) { return false; } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } return true; }; deleteOldFiles.run = async function (options) { var processDirectory = async function processDirectory(directoryPath) { if (options.verbose) { console.log("[delete-old-files] Processing directory: " + directoryPath); } var files = await fs.promises.readdir(directoryPath); var now = Date.now(); var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = files[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var file = _step3.value; var filePath = path.join(directoryPath, file); var stats = void 0; try { stats = await fs.promises.stat(filePath); } catch (err) { options.onError(err); continue; } if (stats.isDirectory()) { if (options.recursive) { await processDirectory(filePath); } continue; } var fileAge = Math.floor((now - stats.mtimeMs) / 1000); // in seconds var deleteFilters = { age: fileAge > options.age, matches: deleteOldFiles.matches(filePath, options) }; var shouldDelete = deleteFilters.age && deleteFilters.matches; if (shouldDelete) { if (options.dryRun) { if (options.verbose) { console.log("[delete-old-files] (dry run) Would delete file: " + filePath + " (" + fileAge + "s > " + options.age + "s)"); } } else { try { await fs.promises.unlink(filePath); if (options.verbose) { console.log("[delete-old-files] Deleted file: " + filePath + " (" + fileAge + "s > " + options.age + "s)"); } options.onDelete(filePath); } catch (err) { options.onError(err); } } } else { if (options.verbose) { console.log("[delete-old-files] Keeping file: " + filePath + " - " + (!deleteFilters.matches ? "not matched" : "age (" + fileAge + "s <= " + options.age + "s)")); } } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } if (options.verbose) { var finishedAt = new Date(); var diff = finishedAt - now; console.log("[delete-old-files] Finished processing directory: " + directoryPath + " in " + diff + "ms"); } }; var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = options.directoryPaths[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var directoryPath = _step4.value; try { await processDirectory(directoryPath); } catch (err) { options.onError(err); } } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } }; module.exports = deleteOldFiles;