@devteks/downloader
Version:
Simple node.js file downloader
202 lines • 6.92 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.format = exports.delay = exports.getFilenameFromContentDisposition = exports.getFileNameFromOptions = exports.getRedirectUrl = exports.isFinishedState = exports.getRequestOptions = exports.getUniqueFileName = exports.closeStream = exports.canAccessFile = exports.getContentLength = exports.validateParams = void 0;
const tslib_1 = require("tslib");
const fs_1 = require("fs");
const promises_1 = require("fs/promises");
const url_1 = require("url");
const types_1 = require("./types");
// match everything after the specified encoding behind a case-insensitive `filename*=`
const RX_FILENAME_AND_ENCODING = /.*filename\*=.*?'.*?'([^"].+?[^"])(?:(?:;)|$)/i;
// match everything inside the quotes behind a case-insensitive `filename=`
const RX_FILENAME_WITH_QUOTES = /.*filename="(.*?)";?/i;
// match everything immediately after `filename=` that isn't surrounded by quotes and is followed by either a `;` or the end of the string
const RX_FILENAME_WITHOUT_QUOTES = /.*filename=([^"].+?[^"])(?:(?:;)|$)/i;
function validateParams(url, destFolder) {
if (typeof url !== 'string') {
throw new Error('URL should be an string');
}
if (!url) {
throw new Error("URL couldn't be empty");
}
if (typeof destFolder !== 'string') {
throw new Error('Destination Folder should be an string');
}
if (!destFolder) {
throw new Error("Destination Folder couldn't be empty");
}
if (!(0, fs_1.existsSync)(destFolder)) {
throw new Error('Destination Folder must exist');
}
const stats = (0, fs_1.statSync)(destFolder);
if (!stats.isDirectory()) {
throw new Error('Destination Folder must be a directory');
}
try {
(0, fs_1.accessSync)(destFolder, fs_1.constants.W_OK);
}
catch (e) {
throw new Error('Destination Folder must be writable');
}
return true;
}
exports.validateParams = validateParams;
;
function getContentLength(response) {
var _a;
if (response != null) {
const len = response.headers['content-length'];
if (len != null) {
return (_a = parseInt(len, 10)) !== null && _a !== void 0 ? _a : null;
}
}
return null;
}
exports.getContentLength = getContentLength;
;
function canAccessFile(path) {
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
try {
yield (0, promises_1.access)(path);
return true;
}
catch (ex) { }
return false;
});
}
exports.canAccessFile = canAccessFile;
;
function closeStream(stream, throwErrors = true) {
return new Promise((resolve, reject) => {
stream.close((err) => {
if (err) {
throwErrors ? reject(err) : resolve(false);
}
else {
resolve(true);
}
});
});
}
exports.closeStream = closeStream;
;
function getUniqueFileName(path) {
path !== null && path !== void 0 ? path : (path = '');
if (path === '')
return path;
try {
// if access fail, the file doesnt exist yet
(0, fs_1.accessSync)(path, fs_1.constants.F_OK);
let base = path;
let suffix = 0;
let ext = path.split('.').pop() || '';
const matches = path.match(/(.*)(\([0-9]+\))(\..*)$/);
if (matches) {
base = matches[1].trim();
suffix = parseInt(matches[2].replace(/\(|\)/, ''));
}
if (ext !== path && ext.length > 0) {
ext = '.' + ext;
base = base.replace(ext, '');
}
else {
ext = '';
}
// generate a new path until it doesn't exist
return getUniqueFileName(base + ' (' + ++suffix + ')' + ext);
}
catch (ex) { }
return path;
}
exports.getUniqueFileName = getUniqueFileName;
;
function getRequestOptions(method, url, headers = {}) {
const urlParse = new url_1.URL(url);
const options = {
protocol: urlParse.protocol,
host: urlParse.hostname,
port: urlParse.port,
path: urlParse.pathname,
method: method,
};
if (headers) {
options['headers'] = headers;
}
return options;
}
exports.getRequestOptions = getRequestOptions;
;
function isFinishedState(state) {
return (state !== types_1.DownloadState.PAUSED &&
state !== types_1.DownloadState.STOPPED &&
state !== types_1.DownloadState.RETRY &&
state !== types_1.DownloadState.FAILED);
}
exports.isFinishedState = isFinishedState;
;
function getRedirectUrl(response, url) {
var _a;
const code = (_a = response.statusCode) !== null && _a !== void 0 ? _a : 0;
if (code > 300 && code < 400) {
const location = response.headers.location;
if (location) {
if (/^https?:\/\//.test(location)) {
return location;
}
else {
return new url_1.URL(location, url).href;
}
}
}
return null;
}
exports.getRedirectUrl = getRedirectUrl;
;
function getFileNameFromOptions(fileName, fname) {
if (typeof fname === 'object') {
if (typeof fname.ext !== 'undefined') {
const { name, ext } = fname;
if (typeof ext === 'string') {
return `${name}.${ext}`;
}
else if (typeof ext === 'boolean') {
if (ext) {
return name;
}
else {
const _ext = fileName.includes('.') ? fileName.split('.').pop() : '';
return _ext !== '' ? `${name}.${_ext}` : name;
}
}
}
}
return fileName;
}
exports.getFileNameFromOptions = getFileNameFromOptions;
;
function getFilenameFromContentDisposition(headers) {
let fileName = (headers['content-disposition'] || '').trim();
if (fileName.length) {
let matches;
if ((matches = fileName.match(RX_FILENAME_AND_ENCODING))) {
fileName = matches[1];
}
else if ((matches = fileName.match(RX_FILENAME_WITH_QUOTES))) {
fileName = matches[1];
}
else if ((matches = fileName.match(RX_FILENAME_WITHOUT_QUOTES))) {
fileName = matches[1];
}
return fileName.replace(/[/\\]/g, '');
}
}
exports.getFilenameFromContentDisposition = getFilenameFromContentDisposition;
;
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
exports.delay = delay;
function format(s) { return `\x1b[37m[Downloader]\x1b[0m ${s}`; }
exports.format = format;
;
//# sourceMappingURL=utils.js.map
;