UNPKG

kist

Version:

Lightweight Package Pipeline Processor with Plugin Architecture

157 lines 6.32 kB
import { __awaiter } from "tslib"; import fs from "fs"; import path from "path"; import { pipeline } from "stream/promises"; import { Action } from "../../core/pipeline/Action.js"; import { FileCache } from "../../core/cache/FileCache.js"; const STREAMING_THRESHOLD = 5 * 1024 * 1024; export class FileCopyAction extends Action { constructor() { super(); this.fileCache = FileCache.getInstance(); } execute(options) { return __awaiter(this, void 0, void 0, function* () { const srcFile = options.srcFile; const srcFiles = options.srcFiles; const destDir = options.destDir; const useCache = options.useCache; const parallel = options.parallel; if ((!srcFile && !srcFiles) || !destDir) { throw new Error("Missing required options: srcFile/srcFiles or destDir."); } if (srcFiles && srcFiles.length > 0) { yield this.copyMultipleFiles(srcFiles, destDir, { useCache, parallel, }); return; } if (srcFile) { yield this.copySingleFile(srcFile, destDir, { useCache }); } }); } copySingleFile(srcFile_1, destDir_1) { return __awaiter(this, arguments, void 0, function* (srcFile, destDir, options = {}) { if (options.useCache) { const hasChanged = yield this.fileCache.hasFileChanged(srcFile); if (!hasChanged) { this.logDebug(`Skipping unchanged file: ${srcFile}`); return; } } this.logInfo(`Copying file from ${srcFile} to ${destDir}.`); try { yield this.copyFileToDirectory(srcFile, destDir); if (options.useCache) { yield this.fileCache.updateFileEntry(srcFile); } this.logInfo(`File copied successfully from ${srcFile} to ${destDir}.`); } catch (error) { this.logError(`Error copying file from ${srcFile} to ${destDir}: ${error}`); throw error; } }); } copyMultipleFiles(srcFiles_1, destDir_1) { return __awaiter(this, arguments, void 0, function* (srcFiles, destDir, options = {}) { const startTime = performance.now(); let filesToCopy = srcFiles; if (options.useCache) { filesToCopy = yield this.fileCache.getChangedFiles(srcFiles); const skipped = srcFiles.length - filesToCopy.length; if (skipped > 0) { this.logInfo(`Skipping ${skipped} unchanged files.`); } } if (filesToCopy.length === 0) { this.logInfo("All files are up to date, nothing to copy."); return; } this.logInfo(`Copying ${filesToCopy.length} files to ${destDir}.`); try { if (options.parallel) { yield this.copyFilesInParallel(filesToCopy, destDir, 10); } else { for (const file of filesToCopy) { yield this.copyFileToDirectory(file, destDir); } } if (options.useCache) { yield this.fileCache.updateFileEntries(filesToCopy); } const duration = performance.now() - startTime; this.logInfo(`Copied ${filesToCopy.length} files in ${duration.toFixed(2)}ms.`); } catch (error) { this.logError(`Error copying files: ${error}`); throw error; } }); } copyFilesInParallel(srcFiles_1, destDir_1) { return __awaiter(this, arguments, void 0, function* (srcFiles, destDir, maxConcurrent = 10) { const executing = new Set(); for (const srcFile of srcFiles) { const copyPromise = this.copyFileToDirectory(srcFile, destDir).finally(() => executing.delete(copyPromise)); executing.add(copyPromise); if (executing.size >= maxConcurrent) { yield Promise.race(executing); } } yield Promise.all(executing); }); } copyFileToDirectory(srcFile, destDir) { return __awaiter(this, void 0, void 0, function* () { try { yield this.ensureDirectoryExists(destDir); const fileName = path.basename(srcFile); const destFilePath = path.join(destDir, fileName); const stat = yield fs.promises.stat(srcFile); if (stat.size > STREAMING_THRESHOLD) { yield this.streamCopyFile(srcFile, destFilePath); } else { yield fs.promises.copyFile(srcFile, destFilePath); } } catch (error) { this.logError(`Error copying file: ${error}`); throw error; } }); } streamCopyFile(srcFile, destFile) { return __awaiter(this, void 0, void 0, function* () { const readStream = fs.createReadStream(srcFile); const writeStream = fs.createWriteStream(destFile); yield pipeline(readStream, writeStream); }); } ensureDirectoryExists(dirPath) { return __awaiter(this, void 0, void 0, function* () { try { yield fs.promises.mkdir(dirPath, { recursive: true }); } catch (error) { if (error instanceof Error) { const nodeError = error; if (nodeError.code !== "EEXIST") { throw nodeError; } } else { throw error; } } }); } describe() { return "Copies a file from a source location to a destination directory, ensuring directories exist and handling errors gracefully."; } } //# sourceMappingURL=FileCopyAction.js.map