bun-downloader-manager
Version:
bun-download-manager is a simple yet powerful package manager-like download manager built with Bun.js. It allows you to download files sequentially or with a queue-based approach, handling retries and concurrency limits efficiently.
111 lines (110 loc) • 4.54 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const Queue_1 = __importDefault(require("./Queue"));
class DownloadManager {
downloadQueue; // Queue to handle multiple downloads
concurrencyLimit; // Maximum number of concurrent downloads
retries; // Max retries for failed downloads
method; // Download method
downloadFolder;
getFileName;
otherTaskFunction;
log;
overWriteFile;
constructor(options = {}) {
const { method = "queue", concurrencyLimit = 5, retries = 3, consoleLog = false, downloadFolder = "./downloads", overWriteFile = false, getFileName, otherTaskFunction, } = options;
this.method = method;
this.concurrencyLimit = concurrencyLimit;
this.retries = retries;
this.log = consoleLog;
this.downloadFolder = downloadFolder;
this.getFileName = getFileName;
this.otherTaskFunction = otherTaskFunction;
this.overWriteFile = overWriteFile;
// Initialize queue if the method is "queue"
if (this.method === "queue") {
this.downloadQueue = new Queue_1.default(this.concurrencyLimit, retries, this.log);
}
}
logger(message, type = "info") {
if (this.log || type === "error") {
console[type](`[${process.pid}] : [${new Date().toLocaleString()}] : `, message);
}
}
// Method to handle single URL download
async downloadFile(url, fileName) {
try {
const file = Bun.file(`${this.downloadFolder}/${fileName}`);
const isFileExists = await file.exists();
if (!isFileExists || this.overWriteFile) {
this.logger(`Download started from ${url}`);
const res = await fetch(url);
if (res.status !== 200) {
this.logger(`Could not download the file from ${url}, status ${res.status}`, "error");
throw new Error(`Download failed from ${url} with status ${res.status}`);
}
await file.write(res);
this.logger(`File ${fileName} downloaded successfully. Downloaded from ${url}`);
}
if (this.otherTaskFunction) {
this.logger("Running other task function");
await this.otherTaskFunction(url, fileName);
}
return true;
}
catch (error) {
this.logger(`Error downloading ${fileName} from ${url}. Error:- ${error}`, "error");
throw error;
}
}
// Method to add single download task to the queue
enqueueDownloadTask(url, fileName, priority = 1) {
this.logger(`${fileName} file downloading task added to Queue`);
const downloadableFile = {
id: `${Date.now()}-${fileName}`, // Unique task ID
priority, // Default priority is 1
retries: this.retries,
action: () => this.downloadFile(url, fileName),
};
this.downloadQueue.enqueue(downloadableFile);
}
createFileName(url) {
const fileName = this.getFileName
? this.getFileName(url)
: url.split("/").pop() ?? "file";
return fileName;
}
// Main method to handle multiple URL downloads
async download(urls) {
// If the method is "simple", download the files sequentially
if (this.method === "simple") {
if (typeof urls === "string") {
const fileName = this.createFileName(urls);
await this.downloadFile(urls, fileName);
}
else {
await Promise.all(urls.map((url) => {
const fileName = this.createFileName(url);
return this.downloadFile(url, fileName);
}));
}
}
// If the method is "queue", enqueue the download tasks
else if (this.method === "queue") {
if (typeof urls === "string") {
const fileName = this.createFileName(urls);
this.enqueueDownloadTask(urls, fileName);
}
else {
for await (const url of urls) {
const fileName = this.createFileName(url);
this.enqueueDownloadTask(url, fileName);
}
}
}
}
}
exports.default = DownloadManager;