From 45f59b319d13022f83e91b1fc8a6b0e56e2a9eff Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Tue, 23 Aug 2022 22:59:12 -0700 Subject: [PATCH 1/7] feat: convert to TypeScript ``` pnpm i -g jsdoc2flow @khanacademy/flow-to-ts jsdoc2flow -i .\lib --overwrite flow-to-ts .\lib\*.js --prettier --write --delete-source mv ./lib ./src ``` --- .gitignore | 3 + lib/createSfx.js | 213 -------------- lib/index.js | 552 ------------------------------------ lib/utility.js | 253 ----------------- package-lock.json | 22 +- package.json | 7 +- src/createSfx.ts | 210 ++++++++++++++ src/index.ts | 700 ++++++++++++++++++++++++++++++++++++++++++++++ src/utility.ts | 265 ++++++++++++++++++ tsconfig.json | 30 ++ 10 files changed, 1234 insertions(+), 1021 deletions(-) delete mode 100644 lib/createSfx.js delete mode 100644 lib/index.js delete mode 100644 lib/utility.js create mode 100644 src/createSfx.ts create mode 100644 src/index.ts create mode 100644 src/utility.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 2ea9c66..45530ba 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ pids *.seed .tmp +# typescript output +lib/ + # Directory for instrumented libs generated by jscoverage/JSCover lib-cov diff --git a/lib/createSfx.js b/lib/createSfx.js deleted file mode 100644 index 518182c..0000000 --- a/lib/createSfx.js +++ /dev/null @@ -1,213 +0,0 @@ -'use strict'; - -import { createArchive } from './index.js'; -import when from 'when'; -import { - fileURLToPath -} from 'url'; -import { - dirname, - sep, - join -} from 'path'; -import fs from 'fs-extra'; -import { Binary } from './utility.js'; -import { isArray, isWindows } from 'node-sys'; - -const platformTitle = { - win32: 'Windows OS', - darwin: 'Apple macOS', - linux: 'Linux OS' -}; -const title = ' installation package created on ' + platformTitle[process.platform] + '.'; -const prompt = 'Do you want to install '; - -const __filename = fileURLToPath( - import.meta.url); -const __dirname = dirname(__filename); - -// our parent folder path -const pwd = __dirname.split(sep); - -/* c8 ignore next 18 */ -function getPath(module, folder = pwd) { - if (folder.length < 1) { - return null; - } - - const nodePath = folder.concat(["node_modules"]).join(sep); - const parent = module ? join(nodePath, module) : nodePath; - if (fs.existsSync(parent)) { - return parent.includes('node_modules') ? join(parent, '..' + sep + '..') : nodePath; - } - - let find = getPath(module, folder.slice(0, -1)); - if (!find) { - console.error('Could not find NPM node_modules for: ' + module); - return join(__dirname, '..'); - } - - return find; -}; - -/** -let config = fs.createReadStream('configFile', { - flags: 'r', - encoding: "binary", -}); -let archive = fs.createReadStream('archiveFile', { - flags: 'r', - encoding: "binary", -}); - -let SfxDirectory = fs.createWriteStream('Sfx', { - flags: 'w', - encoding: "binary", -}); - -config.pipe(SfxDirectory, { - end: false -}); -archive.pipe(SfxDirectory, { - end: false -}); -*/ - -/** - * Creates self extracting archive, an Installation Package. - * - * @param {String} name Application name. - * @param {Array} files Files to add. - * @param {String} destination Application root for the `SfxPackages` directory, will default to package root. - * - All Sfx package archives are stored in the **created** `SfxPackages` directory. - * - The `destination` directory must already exists. - * @param {Object} options Object for Installer config and 7-zip switch options. - * - * `{` - * - * `title:` - Window title message, Default "`name` installation package created on `Current running platform OS`" - * - * `beginPrompt:` - Begin Prompt message, Default "Do you want to install `name`?"" - * - * `progress:` - Value can be "yes" or "no". Default value is "yes". - * - * `runProgram:` - Command for executing. Default value is "setup.exe". - * Substring `% % T` will be replaced with path to temporary folder, - * where files were extracted - * - * `directory:` - Directory prefix for `RunProgram`. Default value is `.\` - * - * `executeFile:` Name of file for executing - * - * `executeParameters:` Parameters for `ExecuteFile` - * - * `}` - * - * `NOTE:` There are two ways to run program: `RunProgram` and `ExecuteFile`. - * - Use `RunProgram`, if you want to run some program from .7z archive. - * - Use `ExecuteFile`, if you want to open some document from .7z archive or - * if you want to execute some command from Windows. - * @param {String} type Application type `gui` or `console`. Default `gui`. Only `console` possible on **Linux** and **Mac** OS. - * @param {String} platform What platform application targeting? Either `win32`, `darwin`, or `linux`. - * @param {String} extension Binary extension name. - * - * @resolve {array} Arguments passed to the child-process. - * @progress {array} Listed files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const createSfx = function ( - name, - files, - destination = '', - options = { - title: null, - beginPrompt: null, - progress: null - }, - type = 'gui', - platform = 'win32', - extension = '.exe') { - return when.promise(function (resolve, reject, progress) { - let directory = (destination != '' && fs.existsSync(destination)) ? destination : getPath('when'); - let SfxDirectory = join(directory, 'SfxPackages'); - fs.ensureDirSync(SfxDirectory); - let override = (isWindows() && (platform == 'linux' || platform == 'darwin')); - let binaryDirectory = Binary(override); - let configFile = join(binaryDirectory.path, 'config.txt'); - //let configFile = join(SfxDirectory, 'config.txt'); - let config = fs.createWriteStream(configFile, { - flags: 'w+', - encoding: 'utf8' - }); - - let text = ''; - config.write(';!@Install@!UTF-8!' + "\n"); - text = options.title || name + title; - config.write('Title=' + text + "\n"); - text = options.prompt || options.beginPrompt || prompt + name; - config.write('BeginPrompt=' + text + "?\n"); - text = options.progress || 'no'; - config.write('Progress=' + text + "\n"); - - text = options.runProgram || options.run || null; - if (text) - config.write('RunProgram=' + text + "\n"); - - if (options.directory) - config.write('Directory=' + options.directory + "\n"); - - text = options.executeFile || options.execute || null; - if (text) - config.write('ExecuteFile=' + text + "\n"); - - text = options.executeParameters || options.parameters || null; - if (text) - config.write('ExecuteParameters=' + text + "\n"); - - config.write(';!@InstallEnd@!' + "\n"); - config.close(); - - delete options.title; - delete options.prompt; - delete options.beginPrompt; - delete options.progress; - delete options.run; - delete options.runProgram; - delete options.directory; - delete options.execute; - delete options.executeFile; - delete options.parameters; - delete options.executeParameters; - - let sfxModule = (type == 'gui') ? '7zwin32.sfx' : '7zCon' + platform + '.sfx'; - let sfx = name.includes(extension) ? name : name + extension; - let list = isArray(files) ? [configFile].concat(files) : configFile + ' ' + files; - sfx = join(SfxDirectory, sfx); - let params = Object.assign(options, { - sfx: sfxModule - }); - - createArchive(sfx, list, params, override) - .progress((data) => { - return progress(data); - }) - .then((data) => { - fs.unlink(configFile, (err) => { - if (err) console.error(err); - if (fs.existsSync(sfx)) { - return resolve(sfx); - /* c8 ignore next 4 */ - } else { - console.error(data); - return reject('Failed! The Sfx application could not be created!'); - } - }); - }) - .catch((err) => { - fs.removeSync(configFile); - return reject(err); - }); - }); -} diff --git a/lib/index.js b/lib/index.js deleted file mode 100644 index 14d3cd8..0000000 --- a/lib/index.js +++ /dev/null @@ -1,552 +0,0 @@ -'use strict'; - -import when from 'when'; -import { Files, ReplaceNativeSeparator, Run } from './utility.js'; - -import { createSfx } from './createSfx.js'; -import { isWindows } from 'node-sys'; - -function retry(command, options, override, progress, onprogress, resolve, reject, archive) { - // Start the command - return Run('7z', command, options, override) - .progress(function (data) { - return progress(onprogress(data)); - }) - - // When all is done resolve the Promise. - .then(function (args) { - return resolve(args); - }) - - // Catch the error and pass it to the reject function of the Promise. - .catch(function () { - console.error(archive + ' failed using `7z`, retying with `7za`.'); - Run('7za', command, options, override) - .progress(function (data) { - return progress(onprogress(data)); - }) - - .then(function (args) { - return resolve(args); - }) - .catch(function (err) { - return reject(err); - }); - }); -}; - - -/** - * Create/add content to an archive. - * - * @param filepath {string} Path to the archive. - * @param files {string|array} Files to add. - * @param options {Object} An object of acceptable 7-zip switch options. - * @param override {boolean} should binary directory change? - * - * @resolve {array} Arguments passed to the child-process. - * @progress {array} Listed files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const createArchive = SevenZip.createArchive = SevenZip.add = function (filepath, files, options, override = false) { - return when.promise(function (resolve, reject, progress) { - /** - * When a stdout is emitted, parse each line and search for a pattern.When - * the pattern is found, extract the file (or directory) name from it and - * pass it to an array. Finally returns this array. - */ - function onprogress(data) { - let entries = []; - data.split('\n').forEach(function (line) { - if (line.substr(0, 1) === '+') { - entries.push(ReplaceNativeSeparator(line.substr(2, line.length))); - } - }); - return entries; - } - - // Convert array of files into a string if needed. - files = Files(files); - - // Create a string that can be parsed by `run`. - let command = 'a "' + filepath + '" ' + files; - - // Start the command - return retry(command, options, override, progress, onprogress, resolve, reject, 'CreateArchive'); - }); -}; - -/** - * Delete content from an archive. - * - * @param filepath {string} Path to the archive. - * @param files {string|array} Files to remove. - * @param options {Object} An object of acceptable 7-zip switch options. - * @param override {boolean} should binary directory change? - * - * @resolve {array} Arguments passed to the child-process. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const deleteArchive = SevenZip.deleteArchive = SevenZip.delete = function (filepath, files, options, override = false) { - return new Promise(function (resolve, reject) { - - // Convert array of files into a string if needed. - files = Files(files); - - // Create a string that can be parsed by `run`. - let command = 'd "' + filepath + '" ' + files; - - // Start the command - Run('7z', command, options, override) - - // When all is done resolve the Promise. - .then(function (args) { - return resolve(args); - }) - - // Catch the error and pass it to the reject function of the Promise. - .catch(function () { - console.error('DeleteArchive failed using `7z`, retying with `7za`.'); - Run('7za', command, options, override) - .then(function (args) { - return resolve(args); - }) - .catch(function (err) { - return reject(err); - }); - }); - }); -}; - -/** - * Extract an archive. - * - * @param {string} archive Path to the archive. - * @param {string} dest Destination. - * @param options {Object} An object of acceptable 7-zip switch options. - * @param override {boolean} should binary directory change? - * - * @resolve {array} Arguments passed to the child-process. - * @progress {array} Extracted files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const extractArchive = SevenZip.extractArchive = SevenZip.extract = function (filepath, dest = '*', options = {}, override = false) { - return when.promise(function (resolve, reject, progress) { - /** - * When a stdout is emitted, parse each line and search for a pattern.When - * the pattern is found, extract the file (or directory) name from it and - * pass it to an array. Finally returns this array. - */ - function onprogress(data) { - let entries = []; - data.split('\n').forEach(function (line) { - if (line.substr(0, 1) === '-') { - entries.push(ReplaceNativeSeparator(line.substr(2, line.length))); - } - }); - return entries; - } - - // Create a string that can be parsed by `run`. - let command = 'e "' + filepath + '" -o"' + dest + '" '; - - // Start the command - return retry(command, options, override, progress, onprogress, resolve, reject, 'ExtractArchive'); - }); -}; - -/** - * Extract an archive with full paths. - * - * @param filepath {string} Path to the archive. - * @param dest {string} Destination. - * @param options {Object} An object of acceptable 7-zip switch options. - * @param override {boolean} should binary directory change? - * - * @resolve {array} Arguments passed to the child-process. - * @progress {array} Extracted files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const fullArchive = SevenZip.fullArchive = SevenZip.extractFull = function (filepath, dest = '*', options = {}, override = false) { - return when.promise(function (resolve, reject, progress) { - /** - * When a stdout is emitted, parse each line and search for a pattern.When - * the pattern is found, extract the file (or directory) name from it and - * pass it to an array. Finally returns this array. - */ - function onprogress(data) { - let entries = []; - data.split('\n').forEach(function (line) { - if (line.substr(0, 1) === '-') { - entries.push(ReplaceNativeSeparator(line.substr(2, line.length))); - } - }); - return entries; - } - - // Create a string that can be parsed by `run`. - let command = 'x "' + filepath + '" -o"' + dest + '" '; - - return retry(command, options, override, progress, onprogress, resolve, reject, 'FullArchive'); - }); -}; - -/** - * List contents of archive. - * - * @param filepath {string} Path to the archive. - * @param options {Object} An object of acceptable 7-zip switch options. - * @param override {boolean} should binary directory change? - * - * @progress {array} Listed files and directories. - * @resolve {Object} Tech spec about the archive. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const listArchive = SevenZip.listArchive = SevenZip.list = function (filepath, options, override = false) { - return when.promise(function (resolve, reject, progress) { - let spec = {}; - /* jshint maxlen: 130 */ - let regex = /(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) ([\.D][\.R][\.H][\.S][\.A]) +(\d+) +(\d+)? +(.+)/; - /* jshint maxlen: 80 */ - - let buffer = ""; //Store incomplete line of a progress data. - - /** - * When a stdout is emitted, parse each line and search for a pattern.When - * the pattern is found, extract the file (or directory) name from it and - * pass it to an array. Finally returns this array. - */ - function onprogress(data) { - let entries = []; - if (buffer.length > 0) { - data = buffer + data; - buffer = ""; - } - - data.split('\n').forEach(function (line) { - // Populate the tech specs of the archive that are passed to the - // resolve handler. - if (line.substr(0, 7) === 'Path = ') { - spec.path = line.substr(7, line.length); - } else if (line.substr(0, 7) === 'Type = ') { - spec.type = line.substr(7, line.length); - } else if (line.substr(0, 9) === 'Method = ') { - spec.method = line.substr(9, line.length); - } else if (line.substr(0, 16) === 'Physical Size = ') { - spec.physicalSize = parseInt(line.substr(16, line.length), 10); - } else if (line.substr(0, 15) === 'Headers Size = ') { - spec.headersSize = parseInt(line.substr(15, line.length), 10); - } else { - // Parse the stdout to find entries - let res = regex.exec(line); - if (res) { - let e = { - date: new Date(res[1]), - attr: res[2], - size: parseInt(res[3], 10), - name: ReplaceNativeSeparator(res[5]) - }; - entries.push(e); - } - // Line may be incomplete, Save it to the buffer. - else buffer = line; - } - }); - return entries; - } - - // Create a string that can be parsed by `run`. - let command = 'l "' + filepath + '" '; - - Run((isWindows() ? '7z' : '7za'), command, options, override) - .progress(function (data) { - return progress(onprogress(data)); - }) - .then(function () { - return resolve(spec); - }) - .catch(function (err) { - if (isWindows()) { - console.error('ListArchive failed using `7z`, retying with `7za`.'); - Run('7za', command, options, override) - .progress(function (data) { - return progress(onprogress(data)); - }) - .then(function (args) { - return resolve(args); - }) - .catch(function (err) { - return reject(err); - }); - } else { - return reject(err); - } - }); - }); -}; - -/** - * Extract only selected files from archive. - * - * @param {string} filepath Path to the archive. - * @param {string} dest Destination. - * @param {string|array} files Files in archive to extract. - * @param options {Object} An object of acceptable 7-zip switch options. - * @param override {boolean} should binary directory change? - * - * @resolve {array} Arguments passed to the child-process. - * @progress {array} Extracted files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const onlyArchive = SevenZip.onlyArchive = SevenZip.only = function (filepath, dest, files, options = {}, override = false) { - return when.promise(function (resolve, reject, progress) { - options = Object.assign(options, { files: files }); - - /** - * When a stdout is emitted, parse each line and search for a pattern.When - * the pattern is found, extract the file (or directory) name from it and - * pass it to an array. Finally returns this array. - */ - function onprogress(data) { - let entries = []; - data.split('\n').forEach(function (line) { - if (line.substr(0, 1) === '-') { - entries.push(ReplaceNativeSeparator(line.substr(2, line.length))); - } - }); - return entries; - } - - // Create a string that can be parsed by `run`. - let command = 'e "' + filepath + '" -o"' + dest + '"'; - - // Start the command - return retry(command, options, override, progress, onprogress, resolve, reject, 'OnlyArchive'); - }); -}; - -/** - * Renames files in archive. - * - * @param filepath {string} Path to the archive. - * @param files {string} Files pairs to rename in archive. - * @param options {Object} An object of acceptable 7-zip switch options. - * @param override {boolean} should binary directory change? - * - * @resolve {array} Arguments passed to the child-process. - * @progress {array} Listed files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const renameArchive = SevenZip.renameArchive = SevenZip.rename = function (filepath, files, options, override = false) { - return when.promise(function (resolve, reject, progress) { - /** - * When a stdout is emitted, parse each line and search for a pattern.When - * the pattern is found, extract the file (or directory) name from it and - * pass it to an array. Finally returns this array. - */ - function onprogress(data) { - let entries = []; - data.split('\n').forEach(function (line) { - if (line.substr(0, 1) === 'U') { - entries.push(ReplaceNativeSeparator(line.substr(2, line.length))); - } - }); - return entries; - } - - // Convert array of files into a string if needed. - files = Files(files); - - // Create a string that can be parsed by `run`. - let command = 'rn "' + filepath + '" ' + files; - - // Start the command - return retry(command, options, override, progress, onprogress, resolve, reject, 'RenameArchive'); - }); -}; - -/** - * Test integrity of archive. - * - * @param filepath {string} Path to the archive. - * @param options {Object} An object of acceptable 7-zip switch options. - * @param override {boolean} should binary directory change? - * - * @resolve {array} Arguments passed to the child-process. - * @progress {array} Extracted files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const testArchive = SevenZip.testArchive = SevenZip.test = function (filepath, options, override = false) { - return when.promise(function (resolve, reject, progress) { - /** - * When a stdout is emitted, parse each line and search for a pattern.When - * the pattern is found, extract the file (or directory) name from it and - * pass it to an array. Finally returns this array. - */ - function onprogress(data) { - let entries = []; - data.split('\n').forEach(function (line) { - if (line.substr(0, 1) === 'T') { - entries.push(ReplaceNativeSeparator(line.substr(2, line.length))); - } - }); - return entries; - } - - // Create a string that can be parsed by `run`. - let command = 't "' + filepath + '"'; - - // Start the command - return retry(command, options, override, progress, onprogress, resolve, reject, 'TestArchive'); - }); -}; - -/** - * Update content to an archive. - * - * @param filepath {string} Path to the archive. - * @param files {string} Files to update. - * @param options {Object} An object of acceptable 7-zip switch options. - * @param override {boolean} should binary directory change? - * - * @resolve {array} Arguments passed to the child-process. - * @progress {array} Listed files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const updateArchive = SevenZip.updateArchive = SevenZip.update = function (filepath, files, options, override = false) { - return when.promise(function (resolve, reject, progress) { - /** - * When a stdout is emitted, parse each line and search for a pattern.When - * the pattern is found, extract the file (or directory) name from it and - * pass it to an array. Finally returns this array. - */ - function onprogress(data) { - let entries = []; - data.split('\n').forEach(function (line) { - if (line.substr(0, 1) === 'U') { - entries.push(ReplaceNativeSeparator(line.substr(2, line.length))); - } - }); - return entries; - } - - // Convert array of files into a string if needed. - files = Files(files); - - // Create a string that can be parsed by `run`. - let command = 'u "' + filepath + '" ' + files; - - // Start the command - return retry(command, options, override, progress, onprogress, resolve, reject, 'UpdateArchive'); - }); -}; - -/** - * Creates Windows self extracting archive, an Installation Package. - * - * @param {String} name Application name. - * @param {Array} files Files to add. - * @param {String} destination Application root for the `SfxPackages` directory, will default to package root. - * - All Sfx package archives are stored in the **created** `SfxPackages` directory. - * - The `destination` directory must already exists. - * @param {Object} options Object for Installer config and 7-zip switch options. - * - * `{` - * - * `title:` - Window title message, Default "`name` installation package created on `Current running platform OS`" - * - * `beginPrompt:` - Begin Prompt message, Default "Do you want to install `name`?"" - * - * `progress:` - Value can be "yes" or "no". Default value is "yes". - * - * `runProgram:` - Command for executing. Default value is "setup.exe". - * Substring `% % T` will be replaced with path to temporary folder, - * where files were extracted - * - * `directory:` - Directory prefix for `RunProgram`. Default value is `.\` - * - * `executeFile:` Name of file for executing - * - * `executeParameters:` Parameters for `ExecuteFile` - * - * `}` - * - * `NOTE:` There are two ways to run program: `RunProgram` and `ExecuteFile`. - * - Use `RunProgram`, if you want to run some program from .7z archive. - * - Use `ExecuteFile`, if you want to open some document from .7z archive or - * if you want to execute some command from Windows. - * @param {String} type Application type `gui` or `console`. Default `gui`. Only `console` possible on **Linux** and **Mac** OS. - * - * @resolve {string} full filepath - * @progress {array} Listed files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const createSfxWindows = SevenZip.windowsSfx = function (name, files, destination, options, type) { - return createSfx(name, files, destination, options, type, 'win32', '.exe'); -}; - -/** - * Creates Linux self extracting archive. - * - * @param {String} name Application name. - * @param {Array} files Files to add. - * @param {String} destination Application root for the `SfxPackages` directory, will default to package root. - * - All Sfx package archives are stored in the **created** `SfxPackages` directory. - * - The `destination` directory must already exists. - * @param {Object} options Object for 7-zip switch options. - * - * @resolve {string} full filepath - * @progress {array} Listed files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const createSfxLinux = SevenZip.linuxSfx = function (name, files, destination, options) { - return createSfx(name, files, destination, options, 'console', 'linux', '.elf'); -}; - -/** - * Creates Apple macOS self extracting archive. - * - * @param {String} name Application name. - * @param {Array} files Files to add. - * @param {String} destination Application root for the `SfxPackages` directory, will default to package root. - * - All Sfx package archives are stored in the **created** `SfxPackages` directory. - * - The `destination` directory must already exists. - * @param {Object} options Object for 7-zip switch options. - * - * @resolve {string} full filepath - * @progress {array} Listed files and directories. - * @reject {Error} The error as issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const createSfxMac = SevenZip.macSfx = function (name, files, destination, options) { - return createSfx(name, files, destination, options, 'console', 'darwin', '.pkg'); -}; - -function SevenZip() { }; - -export default SevenZip; - -export const Zip = SevenZip; diff --git a/lib/utility.js b/lib/utility.js deleted file mode 100644 index f746918..0000000 --- a/lib/utility.js +++ /dev/null @@ -1,253 +0,0 @@ -'use strict'; - -import when from 'when'; -import { EOL } from 'os'; -import { fileURLToPath } from 'url'; -import { dirname, join, sep, sep as nativeSeparator, normalize } from 'path'; -import { spawning, isUndefined, isArray, isString, isWindows, isBool } from 'node-sys'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -export const Binary = function (override = false, binary = '7z') { - let path = join(__dirname, '..', "binaries", (override === true ? process.platform + sep + 'other32' : process.platform)); - let filename = isWindows() ? binary + '.exe' : binary; - return { - path: path, - filename: filename, - filepath: join(path, filename) - } -}; - -/** - * Transform a list of files that can be an array or a string into a string - * that can be passed to the `run` function as part of the `command` parameter. - * @param {string|array} files - * @return {string} - */ -export const Files = function (files) { - - if (isUndefined(files)) { - return ''; - } - - let toProcess = ''; - if (isArray(files)) { - files.forEach(function (f) { - toProcess += '"' + f + '" '; - }); - toProcess = toProcess.trim(); - } else { - toProcess = '"' + files + '"'; - } - - return toProcess; -}; - -/** - * @param {string} path A path with the native directory separator. - * @return {string} A path with / for directory separator. - */ -export const ReplaceNativeSeparator = function (path) { - let result = path, next; - while ((next = result.replace(nativeSeparator, '/')) !== result) { - result = next; - } - - return result; -}; - -/** - * @param {string} binary which binary to use. - * @param {string} command The command to run. - * @param {Array} switches Options for 7-Zip as an array. - * @param {boolean} override should binary directory change? - * - * @progress {string} stdout message. - * @reject {Error} The error issued by 7-Zip. - * @reject {number} Exit code issued by 7-Zip. - * - * @returns {Promise} Promise - */ -export const Run = function (binary = '7z', command = null, switches = {}, override = false) { - return when.promise(function (fulfill, reject, progress) { - - // Parse the command variable. If the command is not a string reject the - // Promise. Otherwise transform the command into two variables: the command - // name and the arguments. - if (!isString(command) || !isString(binary)) { - return reject(new Error('Command and Binary must be a string')); - } - - // add platform binary to command - let sevenBinary = Binary(override, binary); - let cmd = sevenBinary.filepath; - let args = [command.split(' ')[0]]; - - // Parse and add command (non-switches parameters) to `args`. - let regexpCommands = /"((?:\\.|[^"\\])*)"/g; - let commands = command.match(regexpCommands); - if (commands) { - commands.forEach(function (c) { - c = c.replace(/\//g, sep); - c = c.replace(/\\/g, sep); - c = normalize(c); - args.push(c); - }); - } - - // Special treatment for the output switch because it is exposed as a - // parameter in the API and not as a option. Plus wildcards can be passed. - let regexpOutput = /-o"((?:\\.|[^"\\])*)"/g; - let output = command.match(regexpOutput); - if (output) { - args.pop(); - let o = output[0]; - o = o.replace(/\//g, sep); - o = o.replace(/\\/g, sep); - o = o.replace(/"/g, ''); - o = normalize(o); - args.push(o); - } - - if (switches.files) { - let files = switches.files; - delete switches.files; - if (isArray(files)) { - files.forEach(function (s) { - args.push(s); - }); - } else { - args.push(files); - } - - args.push('-r'); - args.push('-aoa'); - } - - // Add switches to the `args` array. - let switchesArray = Switches(switches); - switchesArray.forEach(function (s) { - args.push(s); - }); - - // Remove now double quotes. If present in the spawned process 7-Zip will - // read them as part of the paths (e.g.: create a `"archive.7z"` with - // quotes in the file-name); - args.forEach(function (e, i) { - if (!isString(e)) { - return; - } - if (e.substr(0, 1) !== '-') { - e = e.replace(/^"/, ''); - e = e.replace(/"$/, ''); - args[i] = e; - } - }); - - // Add bb2 to args array so we get file info - args.push('-bb2'); - - // When an stdout is emitted, parse it. If an error is detected in the body - // of the stdout create an new error with the 7-Zip error message as the - // error's message. Otherwise progress with stdout message. - let err; - let reg = new RegExp('Error:(' + EOL + '|)?(.*)', 'i'); - let onprogress = (object) => { - progress(object.output); - return args; - }; - - let onerror = (data) => { - let res = reg.exec(data); - if (res) { - err = new Error(res[2].substr(0, res[2].length - 1)); - return err; - } - }; - - let res = { - cmd: cmd, - args: args, - options: { - stdio: 'pipe', - onprogress: onprogress, - onerror: onerror - } - }; - - spawning(res.cmd, res.args, res.options) - .then((data) => { - if (data === args) - return fulfill(args); - - return reject(err); - }) - .catch((err) => { - return reject(err); - }); - }); -}; - - -/** - * Transform an object of options into an array that can be passed to the - * spawned child process. - * @param {Object} switches An object of options - * @return {array} Array to pass to the `run` function. - */ -export const Switches = function (switches) { - - // Default value for switches - switches = switches || {}; - - var a = []; - // Set default values of boolean switches - switches.so = (switches.so === true) ? true : false; - switches.spl = (switches.spl === true) ? true : false; - switches.ssc = (switches.ssc === false) ? false : true; - switches.ssw = (switches.ssw === true) ? true : false; - switches.y = (switches.y === false) ? false : true; - - var s; - /*jshint forin:false*/ - for (s in switches) { - - // Switches that are set or not. Just add them to the array if they are - // present. Differ the `ssc` switch treatment to later in the function. - if (switches[s] === true && s !== 'ssc') { - a.push('-' + s); - } - - // Switches with a value. Detect if the value contains a space. If it does - // wrap the value with double quotes. Else just add the switch and its value - // to the string. Doubles quotes are used for parsing with a RegExp later. - if (!isBool(switches[s])) { - - // Special treatment for wildcards - if (s === 'wildcards') { - a.unshift(switches.wildcards); - } - - // Allow raw switches to be added to the command, repeating switches like - // -i is not possible otherwise. - else if (s === 'raw') { - switches.raw.forEach(function (rawValue) { - a.push(rawValue); - }); - } else if (switches[s].indexOf(' ') === -1) { - a.push('-' + s + switches[s]); - } else { - a.push('-' + s + '"' + switches[s] + '"'); - } - } - - // Special treatment for `-ssc` - if (s === 'ssc') { - a.push((switches.ssc === true) ? '-ssc' : '-ssc-'); - } - - } - - return a; -}; diff --git a/package-lock.json b/package-lock.json index 0a9108e..ad850da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,7 +32,8 @@ }, "devDependencies": { "chai": "^4.3.6", - "mocha": "^8.4.0" + "mocha": "^8.4.0", + "typescript": "^4.7.4" }, "engines": { "node": ">=12.0.0" @@ -1094,6 +1095,19 @@ "node": ">=4" } }, + "node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -2084,6 +2098,12 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", diff --git a/package.json b/package.json index 1340e65..f402c54 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "test": "mocha --recursive test/ --timeout=0", "report": "npx c8 npm test", "coverage": "npx c8 --reporter json npm test && npx codecov -f coverage/coverage-final.json", - "install": "node installer.mjs" + "install": "node installer.mjs", + "build": "tsc -p ./ || echo done", + "prepare": "npm run build" }, "repository": { "type": "git", @@ -82,6 +84,7 @@ }, "devDependencies": { "chai": "^4.3.6", - "mocha": "^8.4.0" + "mocha": "^8.4.0", + "typescript": "^4.7.4" } } diff --git a/src/createSfx.ts b/src/createSfx.ts new file mode 100644 index 0000000..8593a80 --- /dev/null +++ b/src/createSfx.ts @@ -0,0 +1,210 @@ +'use strict'; + +import { createArchive } from './index'; +import when from 'when'; +import { fileURLToPath } from 'url'; +import { dirname, sep, join } from 'path'; +import fs from 'fs-extra'; +import { Binary } from './utility'; +import { isArray, isWindows } from 'node-sys'; +const platformTitle = { + win32: 'Windows OS', + darwin: 'Apple macOS', + linux: 'Linux OS', +}; +const title = + ' installation package created on ' + platformTitle[process.platform] + '.'; +const prompt = 'Do you want to install '; + +const __filename = fileURLToPath(import.meta.url); + +const __dirname = dirname(__filename); + +// our parent folder path +const pwd = __dirname.split(sep); + +/* c8 ignore next 18 */ +function getPath(module, folder = pwd) { + if (folder.length < 1) { + return null; + } + + const nodePath = folder.concat(['node_modules']).join(sep); + const parent = module ? join(nodePath, module) : nodePath; + + if (fs.existsSync(parent)) { + return parent.includes('node_modules') + ? join(parent, '..' + sep + '..') + : nodePath; + } + + let find = getPath(module, folder.slice(0, -1)); + + if (!find) { + console.error('Could not find NPM node_modules for: ' + module); + return join(__dirname, '..'); + } + + return find; +} + +/** +let config = fs.createReadStream('configFile', { + flags: 'r', + encoding: "binary", +}); +let archive = fs.createReadStream('archiveFile', { + flags: 'r', + encoding: "binary", +}); + +let SfxDirectory = fs.createWriteStream('Sfx', { + flags: 'w', + encoding: "binary", +}); + +config.pipe(SfxDirectory, { + end: false +}); +archive.pipe(SfxDirectory, { + end: false +}); +*/ + +/** + * Creates self extracting archive, an Installation Package. + * + * @param {String} name Application name. + * @param {Array} files Files to add. + * @param {String} destination Application root for the `SfxPackages` directory, will default to package root. + * - All Sfx package archives are stored in the **created** `SfxPackages` directory. + * - The `destination` directory must already exists. + * @param {Object} options Object for Installer config and 7-zip switch options. + * + * `{` + * + * `title:` - Window title message, Default "`name` installation package created on `Current running platform OS`" + * + * `beginPrompt:` - Begin Prompt message, Default "Do you want to install `name`?"" + * + * `progress:` - Value can be "yes" or "no". Default value is "yes". + * + * `runProgram:` - Command for executing. Default value is "setup.exe". + * Substring `% % T` will be replaced with path to temporary folder, + * where files were extracted + * + * `directory:` - Directory prefix for `RunProgram`. Default value is `.\` + * + * `executeFile:` Name of file for executing + * + * `executeParameters:` Parameters for `ExecuteFile` + * + * `}` + * + * `NOTE:` There are two ways to run program: `RunProgram` and `ExecuteFile`. + * - Use `RunProgram`, if you want to run some program from .7z archive. + * - Use `ExecuteFile`, if you want to open some document from .7z archive or + * if you want to execute some command from Windows. + * @param {String} type Application type `gui` or `console`. Default `gui`. Only `console` possible on **Linux** and **Mac** OS. + * @param {String} platform What platform application targeting? Either `win32`, `darwin`, or `linux`. + * @param {String} extension Binary extension name. + * + * @resolve {array} Arguments passed to the child-process. + * @progress {array} Listed files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const createSfx = function ( + name: String, + files: Array, + destination: String = '', + options: {} = { + title: null, + beginPrompt: null, + progress: null, + }, + type: String = 'gui', + platform: String = 'win32', + extension: String = '.exe' +): Promise { + return when.promise(function (resolve, reject, progress) { + let directory = + destination != '' && fs.existsSync(destination) + ? destination + : getPath('when'); + let SfxDirectory = join(directory, 'SfxPackages'); + fs.ensureDirSync(SfxDirectory); + let override = + isWindows() && (platform == 'linux' || platform == 'darwin'); + let binaryDirectory = Binary(override); + let configFile = join(binaryDirectory.path, 'config.txt'); + //let configFile = join(SfxDirectory, 'config.txt'); + let config = fs.createWriteStream(configFile, { + flags: 'w+', + encoding: 'utf8', + }); + let text = ''; + config.write(';!@Install@!UTF-8!' + '\n'); + text = options.title || name + title; + config.write('Title=' + text + '\n'); + text = options.prompt || options.beginPrompt || prompt + name; + config.write('BeginPrompt=' + text + '?\n'); + text = options.progress || 'no'; + config.write('Progress=' + text + '\n'); + text = options.runProgram || options.run || null; + if (text) config.write('RunProgram=' + text + '\n'); + if (options.directory) + config.write('Directory=' + options.directory + '\n'); + text = options.executeFile || options.execute || null; + if (text) config.write('ExecuteFile=' + text + '\n'); + text = options.executeParameters || options.parameters || null; + if (text) config.write('ExecuteParameters=' + text + '\n'); + config.write(';!@InstallEnd@!' + '\n'); + config.close(); + delete options.title; + delete options.prompt; + delete options.beginPrompt; + delete options.progress; + delete options.run; + delete options.runProgram; + delete options.directory; + delete options.execute; + delete options.executeFile; + delete options.parameters; + delete options.executeParameters; + let sfxModule = + type == 'gui' ? '7zwin32.sfx' : '7zCon' + platform + '.sfx'; + let sfx = name.includes(extension) ? name : name + extension; + let list = isArray(files) + ? [configFile].concat(files) + : configFile + ' ' + files; + sfx = join(SfxDirectory, sfx); + let params = Object.assign(options, { + sfx: sfxModule, + }); + createArchive(sfx, list, params, override) + .progress((data) => { + return progress(data); + }) + .then((data) => { + fs.unlink(configFile, (err) => { + if (err) console.error(err); + + if (fs.existsSync(sfx)) { + return resolve(sfx); + /* c8 ignore next 4 */ + } else { + console.error(data); + return reject( + 'Failed! The Sfx application could not be created!' + ); + } + }); + }) + .catch((err) => { + fs.removeSync(configFile); + return reject(err); + }); + }); +}; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..a84d247 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,700 @@ +'use strict'; + +import when from 'when'; +import { Files, ReplaceNativeSeparator, Run } from './utility'; +import { createSfx } from './createSfx'; +import { isWindows } from 'node-sys'; + +function retry( + command, + options, + override, + progress, + onprogress, + resolve, + reject, + archive +) { + // Start the command + return Run('7z', command, options, override) + .progress(function (data) { + return progress(onprogress(data)); + }) // When all is done resolve the Promise. + .then(function (args) { + return resolve(args); + }) // Catch the error and pass it to the reject function of the Promise. + .catch(function () { + console.error(archive + ' failed using `7z`, retying with `7za`.'); + Run('7za', command, options, override) + .progress(function (data) { + return progress(onprogress(data)); + }) + .then(function (args) { + return resolve(args); + }) + .catch(function (err) { + return reject(err); + }); + }); +} + +/** + * Create/add content to an archive. + * + * @param filepath {string} Path to the archive. + * @param files {string|array} Files to add. + * @param options {Object} An object of acceptable 7-zip switch options. + * @param override {boolean} should binary directory change? + * + * @resolve {array} Arguments passed to the child-process. + * @progress {array} Listed files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const createArchive = + (SevenZip.createArchive = + SevenZip.add = + function (filepath, files, options, override = false) { + return when.promise(function (resolve, reject, progress) { + /** + * When a stdout is emitted, parse each line and search for a pattern.When + * the pattern is found, extract the file (or directory) name from it and + * pass it to an array. Finally returns this array. + */ + function onprogress(data) { + let entries = []; + data.split('\n').forEach(function (line) { + if (line.substr(0, 1) === '+') { + entries.push( + ReplaceNativeSeparator( + line.substr(2, line.length) + ) + ); + } + }); + return entries; + } + + // Convert array of files into a string if needed. + files = Files(files); + // Create a string that can be parsed by `run`. + let command = 'a "' + filepath + '" ' + files; + // Start the command + return retry( + command, + options, + override, + progress, + onprogress, + resolve, + reject, + 'CreateArchive' + ); + }); + }); + +/** + * Delete content from an archive. + * + * @param filepath {string} Path to the archive. + * @param files {string|array} Files to remove. + * @param options {Object} An object of acceptable 7-zip switch options. + * @param override {boolean} should binary directory change? + * + * @resolve {array} Arguments passed to the child-process. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const deleteArchive = + (SevenZip.deleteArchive = + SevenZip.delete = + function (filepath, files, options, override = false) { + return new Promise(function (resolve, reject) { + // Convert array of files into a string if needed. + files = Files(files); + // Create a string that can be parsed by `run`. + let command = 'd "' + filepath + '" ' + files; + // Start the command + Run('7z', command, options, override) // When all is done resolve the Promise. + .then(function (args) { + return resolve(args); + }) // Catch the error and pass it to the reject function of the Promise. + .catch(function () { + console.error( + 'DeleteArchive failed using `7z`, retying with `7za`.' + ); + Run('7za', command, options, override) + .then(function (args) { + return resolve(args); + }) + .catch(function (err) { + return reject(err); + }); + }); + }); + }); + +/** + * Extract an archive. + * + * @param {string} archive Path to the archive. + * @param {string} dest Destination. + * @param options {Object} An object of acceptable 7-zip switch options. + * @param override {boolean} should binary directory change? + * + * @resolve {array} Arguments passed to the child-process. + * @progress {array} Extracted files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const extractArchive = + (SevenZip.extractArchive = + SevenZip.extract = + function (filepath, dest = '*', options = {}, override = false) { + return when.promise(function (resolve, reject, progress) { + /** + * When a stdout is emitted, parse each line and search for a pattern.When + * the pattern is found, extract the file (or directory) name from it and + * pass it to an array. Finally returns this array. + */ + function onprogress(data) { + let entries = []; + data.split('\n').forEach(function (line) { + if (line.substr(0, 1) === '-') { + entries.push( + ReplaceNativeSeparator( + line.substr(2, line.length) + ) + ); + } + }); + return entries; + } + + // Create a string that can be parsed by `run`. + let command = 'e "' + filepath + '" -o"' + dest + '" '; + // Start the command + return retry( + command, + options, + override, + progress, + onprogress, + resolve, + reject, + 'ExtractArchive' + ); + }); + }); + +/** + * Extract an archive with full paths. + * + * @param filepath {string} Path to the archive. + * @param dest {string} Destination. + * @param options {Object} An object of acceptable 7-zip switch options. + * @param override {boolean} should binary directory change? + * + * @resolve {array} Arguments passed to the child-process. + * @progress {array} Extracted files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const fullArchive = + (SevenZip.fullArchive = + SevenZip.extractFull = + function (filepath, dest = '*', options = {}, override = false) { + return when.promise(function (resolve, reject, progress) { + /** + * When a stdout is emitted, parse each line and search for a pattern.When + * the pattern is found, extract the file (or directory) name from it and + * pass it to an array. Finally returns this array. + */ + function onprogress(data) { + let entries = []; + data.split('\n').forEach(function (line) { + if (line.substr(0, 1) === '-') { + entries.push( + ReplaceNativeSeparator( + line.substr(2, line.length) + ) + ); + } + }); + return entries; + } + + // Create a string that can be parsed by `run`. + let command = 'x "' + filepath + '" -o"' + dest + '" '; + return retry( + command, + options, + override, + progress, + onprogress, + resolve, + reject, + 'FullArchive' + ); + }); + }); + +/** + * List contents of archive. + * + * @param filepath {string} Path to the archive. + * @param options {Object} An object of acceptable 7-zip switch options. + * @param override {boolean} should binary directory change? + * + * @progress {array} Listed files and directories. + * @resolve {Object} Tech spec about the archive. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const listArchive = + (SevenZip.listArchive = + SevenZip.list = + function (filepath, options, override = false) { + return when.promise(function (resolve, reject, progress) { + let spec = {}; + + /* jshint maxlen: 130 */ + let regex = + /(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) ([\.D][\.R][\.H][\.S][\.A]) +(\d+) +(\d+)? +(.+)/; + + /* jshint maxlen: 80 */ + let buffer = ''; //Store incomplete line of a progress data. + + /** + * When a stdout is emitted, parse each line and search for a pattern.When + * the pattern is found, extract the file (or directory) name from it and + * pass it to an array. Finally returns this array. + */ + function onprogress(data) { + let entries = []; + + if (buffer.length > 0) { + data = buffer + data; + buffer = ''; + } + + data.split('\n').forEach(function (line) { + // Populate the tech specs of the archive that are passed to the + // resolve handler. + if (line.substr(0, 7) === 'Path = ') { + spec.path = line.substr(7, line.length); + } else if (line.substr(0, 7) === 'Type = ') { + spec.type = line.substr(7, line.length); + } else if (line.substr(0, 9) === 'Method = ') { + spec.method = line.substr(9, line.length); + } else if (line.substr(0, 16) === 'Physical Size = ') { + spec.physicalSize = parseInt( + line.substr(16, line.length), + 10 + ); + } else if (line.substr(0, 15) === 'Headers Size = ') { + spec.headersSize = parseInt( + line.substr(15, line.length), + 10 + ); + } else { + // Parse the stdout to find entries + let res = regex.exec(line); + + if (res) { + let e = { + date: new Date(res[1]), + attr: res[2], + size: parseInt(res[3], 10), + name: ReplaceNativeSeparator(res[5]), + }; + entries.push(e); + } // Line may be incomplete, Save it to the buffer. + else buffer = line; + } + }); + return entries; + } + + // Create a string that can be parsed by `run`. + let command = 'l "' + filepath + '" '; + Run(isWindows() ? '7z' : '7za', command, options, override) + .progress(function (data) { + return progress(onprogress(data)); + }) + .then(function () { + return resolve(spec); + }) + .catch(function (err) { + if (isWindows()) { + console.error( + 'ListArchive failed using `7z`, retying with `7za`.' + ); + Run('7za', command, options, override) + .progress(function (data) { + return progress(onprogress(data)); + }) + .then(function (args) { + return resolve(args); + }) + .catch(function (err) { + return reject(err); + }); + } else { + return reject(err); + } + }); + }); + }); + +/** + * Extract only selected files from archive. + * + * @param {string} filepath Path to the archive. + * @param {string} dest Destination. + * @param {string|array} files Files in archive to extract. + * @param options {Object} An object of acceptable 7-zip switch options. + * @param override {boolean} should binary directory change? + * + * @resolve {array} Arguments passed to the child-process. + * @progress {array} Extracted files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const onlyArchive = + (SevenZip.onlyArchive = + SevenZip.only = + function (filepath, dest, files, options = {}, override = false) { + return when.promise(function (resolve, reject, progress) { + options = Object.assign(options, { + files: files, + }); + + /** + * When a stdout is emitted, parse each line and search for a pattern.When + * the pattern is found, extract the file (or directory) name from it and + * pass it to an array. Finally returns this array. + */ + function onprogress(data) { + let entries = []; + data.split('\n').forEach(function (line) { + if (line.substr(0, 1) === '-') { + entries.push( + ReplaceNativeSeparator( + line.substr(2, line.length) + ) + ); + } + }); + return entries; + } + + // Create a string that can be parsed by `run`. + let command = 'e "' + filepath + '" -o"' + dest + '"'; + // Start the command + return retry( + command, + options, + override, + progress, + onprogress, + resolve, + reject, + 'OnlyArchive' + ); + }); + }); + +/** + * Renames files in archive. + * + * @param filepath {string} Path to the archive. + * @param files {string} Files pairs to rename in archive. + * @param options {Object} An object of acceptable 7-zip switch options. + * @param override {boolean} should binary directory change? + * + * @resolve {array} Arguments passed to the child-process. + * @progress {array} Listed files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const renameArchive = + (SevenZip.renameArchive = + SevenZip.rename = + function (filepath, files, options, override = false) { + return when.promise(function (resolve, reject, progress) { + /** + * When a stdout is emitted, parse each line and search for a pattern.When + * the pattern is found, extract the file (or directory) name from it and + * pass it to an array. Finally returns this array. + */ + function onprogress(data) { + let entries = []; + data.split('\n').forEach(function (line) { + if (line.substr(0, 1) === 'U') { + entries.push( + ReplaceNativeSeparator( + line.substr(2, line.length) + ) + ); + } + }); + return entries; + } + + // Convert array of files into a string if needed. + files = Files(files); + // Create a string that can be parsed by `run`. + let command = 'rn "' + filepath + '" ' + files; + // Start the command + return retry( + command, + options, + override, + progress, + onprogress, + resolve, + reject, + 'RenameArchive' + ); + }); + }); + +/** + * Test integrity of archive. + * + * @param filepath {string} Path to the archive. + * @param options {Object} An object of acceptable 7-zip switch options. + * @param override {boolean} should binary directory change? + * + * @resolve {array} Arguments passed to the child-process. + * @progress {array} Extracted files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const testArchive = + (SevenZip.testArchive = + SevenZip.test = + function (filepath, options, override = false) { + return when.promise(function (resolve, reject, progress) { + /** + * When a stdout is emitted, parse each line and search for a pattern.When + * the pattern is found, extract the file (or directory) name from it and + * pass it to an array. Finally returns this array. + */ + function onprogress(data) { + let entries = []; + data.split('\n').forEach(function (line) { + if (line.substr(0, 1) === 'T') { + entries.push( + ReplaceNativeSeparator( + line.substr(2, line.length) + ) + ); + } + }); + return entries; + } + + // Create a string that can be parsed by `run`. + let command = 't "' + filepath + '"'; + // Start the command + return retry( + command, + options, + override, + progress, + onprogress, + resolve, + reject, + 'TestArchive' + ); + }); + }); + +/** + * Update content to an archive. + * + * @param filepath {string} Path to the archive. + * @param files {string} Files to update. + * @param options {Object} An object of acceptable 7-zip switch options. + * @param override {boolean} should binary directory change? + * + * @resolve {array} Arguments passed to the child-process. + * @progress {array} Listed files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const updateArchive = + (SevenZip.updateArchive = + SevenZip.update = + function (filepath, files, options, override = false) { + return when.promise(function (resolve, reject, progress) { + /** + * When a stdout is emitted, parse each line and search for a pattern.When + * the pattern is found, extract the file (or directory) name from it and + * pass it to an array. Finally returns this array. + */ + function onprogress(data) { + let entries = []; + data.split('\n').forEach(function (line) { + if (line.substr(0, 1) === 'U') { + entries.push( + ReplaceNativeSeparator( + line.substr(2, line.length) + ) + ); + } + }); + return entries; + } + + // Convert array of files into a string if needed. + files = Files(files); + // Create a string that can be parsed by `run`. + let command = 'u "' + filepath + '" ' + files; + // Start the command + return retry( + command, + options, + override, + progress, + onprogress, + resolve, + reject, + 'UpdateArchive' + ); + }); + }); + +/** + * Creates Windows self extracting archive, an Installation Package. + * + * @param {String} name Application name. + * @param {Array} files Files to add. + * @param {String} destination Application root for the `SfxPackages` directory, will default to package root. + * - All Sfx package archives are stored in the **created** `SfxPackages` directory. + * - The `destination` directory must already exists. + * @param {Object} options Object for Installer config and 7-zip switch options. + * + * `{` + * + * `title:` - Window title message, Default "`name` installation package created on `Current running platform OS`" + * + * `beginPrompt:` - Begin Prompt message, Default "Do you want to install `name`?"" + * + * `progress:` - Value can be "yes" or "no". Default value is "yes". + * + * `runProgram:` - Command for executing. Default value is "setup.exe". + * Substring `% % T` will be replaced with path to temporary folder, + * where files were extracted + * + * `directory:` - Directory prefix for `RunProgram`. Default value is `.\` + * + * `executeFile:` Name of file for executing + * + * `executeParameters:` Parameters for `ExecuteFile` + * + * `}` + * + * `NOTE:` There are two ways to run program: `RunProgram` and `ExecuteFile`. + * - Use `RunProgram`, if you want to run some program from .7z archive. + * - Use `ExecuteFile`, if you want to open some document from .7z archive or + * if you want to execute some command from Windows. + * @param {String} type Application type `gui` or `console`. Default `gui`. Only `console` possible on **Linux** and **Mac** OS. + * + * @resolve {string} full filepath + * @progress {array} Listed files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const createSfxWindows = (SevenZip.windowsSfx = function ( + name, + files, + destination, + options, + type +) { + return createSfx(name, files, destination, options, type, 'win32', '.exe'); +}); + +/** + * Creates Linux self extracting archive. + * + * @param {String} name Application name. + * @param {Array} files Files to add. + * @param {String} destination Application root for the `SfxPackages` directory, will default to package root. + * - All Sfx package archives are stored in the **created** `SfxPackages` directory. + * - The `destination` directory must already exists. + * @param {Object} options Object for 7-zip switch options. + * + * @resolve {string} full filepath + * @progress {array} Listed files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const createSfxLinux = (SevenZip.linuxSfx = function ( + name, + files, + destination, + options +) { + return createSfx( + name, + files, + destination, + options, + 'console', + 'linux', + '.elf' + ); +}); + +/** + * Creates Apple macOS self extracting archive. + * + * @param {String} name Application name. + * @param {Array} files Files to add. + * @param {String} destination Application root for the `SfxPackages` directory, will default to package root. + * - All Sfx package archives are stored in the **created** `SfxPackages` directory. + * - The `destination` directory must already exists. + * @param {Object} options Object for 7-zip switch options. + * + * @resolve {string} full filepath + * @progress {array} Listed files and directories. + * @reject {Error} The error as issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const createSfxMac = (SevenZip.macSfx = function ( + name, + files, + destination, + options +) { + return createSfx( + name, + files, + destination, + options, + 'console', + 'darwin', + '.pkg' + ); +}); + +function SevenZip() {} + +export default SevenZip; +export const Zip = SevenZip; diff --git a/src/utility.ts b/src/utility.ts new file mode 100644 index 0000000..5d63ace --- /dev/null +++ b/src/utility.ts @@ -0,0 +1,265 @@ +'use strict'; + +import when from 'when'; +import { EOL } from 'os'; +import { fileURLToPath } from 'url'; +import { dirname, join, sep, sep as nativeSeparator, normalize } from 'path'; +import { + spawning, + isUndefined, + isArray, + isString, + isWindows, + isBool, +} from 'node-sys'; + +const __filename = fileURLToPath(import.meta.url); + +const __dirname = dirname(__filename); + +export const Binary = function (override = false, binary = '7z') { + let path = join( + __dirname, + '..', + 'binaries', + override === true + ? process.platform + sep + 'other32' + : process.platform + ); + let filename = isWindows() ? binary + '.exe' : binary; + return { + path: path, + filename: filename, + filepath: join(path, filename), + }; +}; + +/** + * Transform a list of files that can be an array or a string into a string + * that can be passed to the `run` function as part of the `command` parameter. + * @param {string|array} files + * @return {string} + */ +export const Files = function (files: string | array): string { + if (isUndefined(files)) { + return ''; + } + + let toProcess = ''; + + if (isArray(files)) { + files.forEach(function (f) { + toProcess += '"' + f + '" '; + }); + toProcess = toProcess.trim(); + } else { + toProcess = '"' + files + '"'; + } + + return toProcess; +}; + +/** + * @param {string} path A path with the native directory separator. + * @return {string} A path with / for directory separator. + */ +export const ReplaceNativeSeparator = function (path: string): string { + let result = path, + next; + + while ((next = result.replace(nativeSeparator, '/')) !== result) { + result = next; + } + + return result; +}; + +/** + * @param {string} binary which binary to use. + * @param {string} command The command to run. + * @param {Array} switches Options for 7-Zip as an array. + * @param {boolean} override should binary directory change? + * + * @progress {string} stdout message. + * @reject {Error} The error issued by 7-Zip. + * @reject {number} Exit code issued by 7-Zip. + * + * @returns {Promise} Promise + */ +export const Run = function ( + binary: string = '7z', + command: string = null, + switches: Array = {}, + override: boolean = false +): Promise { + return when.promise(function (fulfill, reject, progress) { + // Parse the command variable. If the command is not a string reject the + // Promise. Otherwise transform the command into two variables: the command + // name and the arguments. + if (!isString(command) || !isString(binary)) { + return reject(new Error('Command and Binary must be a string')); + } + + // add platform binary to command + let sevenBinary = Binary(override, binary); + let cmd = sevenBinary.filepath; + let args = [command.split(' ')[0]]; + // Parse and add command (non-switches parameters) to `args`. + let regexpCommands = /"((?:\\.|[^"\\])*)"/g; + let commands = command.match(regexpCommands); + + if (commands) { + commands.forEach(function (c) { + c = c.replace(/\//g, sep); + c = c.replace(/\\/g, sep); + c = normalize(c); + args.push(c); + }); + } + + // Special treatment for the output switch because it is exposed as a + // parameter in the API and not as a option. Plus wildcards can be passed. + let regexpOutput = /-o"((?:\\.|[^"\\])*)"/g; + let output = command.match(regexpOutput); + + if (output) { + args.pop(); + let o = output[0]; + o = o.replace(/\//g, sep); + o = o.replace(/\\/g, sep); + o = o.replace(/"/g, ''); + o = normalize(o); + args.push(o); + } + + if (switches.files) { + let files = switches.files; + delete switches.files; + + if (isArray(files)) { + files.forEach(function (s) { + args.push(s); + }); + } else { + args.push(files); + } + + args.push('-r'); + args.push('-aoa'); + } + + // Add switches to the `args` array. + let switchesArray = Switches(switches); + switchesArray.forEach(function (s) { + args.push(s); + }); + // Remove now double quotes. If present in the spawned process 7-Zip will + // read them as part of the paths (e.g.: create a `"archive.7z"` with + // quotes in the file-name); + args.forEach(function (e, i) { + if (!isString(e)) { + return; + } + + if (e.substr(0, 1) !== '-') { + e = e.replace(/^"/, ''); + e = e.replace(/"$/, ''); + args[i] = e; + } + }); + // Add bb2 to args array so we get file info + args.push('-bb2'); + // When an stdout is emitted, parse it. If an error is detected in the body + // of the stdout create an new error with the 7-Zip error message as the + // error's message. Otherwise progress with stdout message. + let err; + let reg = new RegExp('Error:(' + EOL + '|)?(.*)', 'i'); + + let onprogress = (object) => { + progress(object.output); + return args; + }; + + let onerror = (data) => { + let res = reg.exec(data); + + if (res) { + err = new Error(res[2].substr(0, res[2].length - 1)); + return err; + } + }; + + let res = { + cmd: cmd, + args: args, + options: { + stdio: 'pipe', + onprogress: onprogress, + onerror: onerror, + }, + }; + spawning(res.cmd, res.args, res.options) + .then((data) => { + if (data === args) return fulfill(args); + return reject(err); + }) + .catch((err) => { + return reject(err); + }); + }); +}; + +/** + * Transform an object of options into an array that can be passed to the + * spawned child process. + * @param {Object} switches An object of options + * @return {array} Array to pass to the `run` function. + */ +export const Switches = function (switches: {}): array { + // Default value for switches + switches = switches || {}; + var a = []; + // Set default values of boolean switches + switches.so = switches.so === true ? true : false; + switches.spl = switches.spl === true ? true : false; + switches.ssc = switches.ssc === false ? false : true; + switches.ssw = switches.ssw === true ? true : false; + switches.y = switches.y === false ? false : true; + var s; + + /*jshint forin:false*/ + for (s in switches) { + // Switches that are set or not. Just add them to the array if they are + // present. Differ the `ssc` switch treatment to later in the function. + if (switches[s] === true && s !== 'ssc') { + a.push('-' + s); + } + + // Switches with a value. Detect if the value contains a space. If it does + // wrap the value with double quotes. Else just add the switch and its value + // to the string. Doubles quotes are used for parsing with a RegExp later. + if (!isBool(switches[s])) { + // Special treatment for wildcards + if (s === 'wildcards') { + a.unshift(switches.wildcards); + } // Allow raw switches to be added to the command, repeating switches like + // -i is not possible otherwise. + else if (s === 'raw') { + switches.raw.forEach(function (rawValue) { + a.push(rawValue); + }); + } else if (switches[s].indexOf(' ') === -1) { + a.push('-' + s + switches[s]); + } else { + a.push('-' + s + '"' + switches[s] + '"'); + } + } + + // Special treatment for `-ssc` + if (s === 'ssc') { + a.push(switches.ssc === true ? '-ssc' : '-ssc-'); + } + } + + return a; +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..7209a90 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "strict": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noImplicitAny": true, + "noImplicitThis": true, + "noFallthroughCasesInSwitch": true, + "declaration": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "incremental": true, + "inlineSourceMap": false, + "inlineSources": false, + "preserveSymlinks": true, + "removeComments": false, + "lib": ["ES2020"], + "target": "ES2020", + "allowJs": true, + "esModuleInterop": true, + "module": "EsNext", + "moduleResolution": "node", + "importHelpers": false, + "outDir": "./lib" + }, + "compileOnSave": false, + "include": ["src"] +} From f45abe4adb3de35985182bedcd853d639337ac95 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Tue, 23 Aug 2022 23:01:20 -0700 Subject: [PATCH 2/7] chore: install types for the packages --- package-lock.json | 83 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 6 ++++ 2 files changed, 89 insertions(+) diff --git a/package-lock.json b/package-lock.json index ad850da..132d747 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,11 @@ "updateArchive": "cli/update.js" }, "devDependencies": { + "@types/chai": "^4.3.3", + "@types/fs-extra": "^9.0.13", + "@types/minimist": "1.2.2", + "@types/mocha": "^9.1.1", + "@types/when": "^2.4.34", "chai": "^4.3.6", "mocha": "^8.4.0", "typescript": "^4.7.4" @@ -39,6 +44,45 @@ "node": ">=12.0.0" } }, + "node_modules/@types/chai": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", + "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", + "dev": true + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz", + "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.7.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.12.tgz", + "integrity": "sha512-caqFX7GwvZ4KLnhpI9CfiMkgHKp6kvFAIgpkha0cjO7bAQvB6dWe+q3fTHmm7fQvv59pd4tPj77nriq2M6U2dw==", + "dev": true + }, + "node_modules/@types/when": { + "version": "2.4.34", + "resolved": "https://registry.npmjs.org/@types/when/-/when-2.4.34.tgz", + "integrity": "sha512-sSf48zGtIioUoAi4JeqtyKoT7jgPG1ua6Zb95Es+nHELDrOF9q3LI136MDEr7ig7y3wSc+/FDCPzZomW9oVbtQ==", + "dev": true + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -1340,6 +1384,45 @@ } }, "dependencies": { + "@types/chai": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", + "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", + "dev": true + }, + "@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "@types/mocha": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz", + "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", + "dev": true + }, + "@types/node": { + "version": "18.7.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.12.tgz", + "integrity": "sha512-caqFX7GwvZ4KLnhpI9CfiMkgHKp6kvFAIgpkha0cjO7bAQvB6dWe+q3fTHmm7fQvv59pd4tPj77nriq2M6U2dw==", + "dev": true + }, + "@types/when": { + "version": "2.4.34", + "resolved": "https://registry.npmjs.org/@types/when/-/when-2.4.34.tgz", + "integrity": "sha512-sSf48zGtIioUoAi4JeqtyKoT7jgPG1ua6Zb95Es+nHELDrOF9q3LI136MDEr7ig7y3wSc+/FDCPzZomW9oVbtQ==", + "dev": true + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", diff --git a/package.json b/package.json index f402c54..c4c9a2b 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,12 @@ "when": "^3.7.8" }, "devDependencies": { + "@types/chai": "^4.3.3", + "@types/fs-extra": "^9.0.13", + "@types/minimist": "1.2.2", + "@types/mocha": "^9.1.1", + "@types/node": "^18.7.12", + "@types/when": "^2.4.34", "chai": "^4.3.6", "mocha": "^8.4.0", "typescript": "^4.7.4" From ecc86b75a963b8ddbcdcca7b3f2d1803d8da290d Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Tue, 23 Aug 2022 23:27:33 -0700 Subject: [PATCH 3/7] fix: fix the type errors --- src/createSfx.ts | 40 +++++----- src/index.ts | 202 ++++++++++++++++++++++++++++++++--------------- src/types.d.ts | 15 ++++ src/utility.ts | 47 ++++++----- 4 files changed, 196 insertions(+), 108 deletions(-) create mode 100644 src/types.d.ts diff --git a/src/createSfx.ts b/src/createSfx.ts index 8593a80..621bbdb 100644 --- a/src/createSfx.ts +++ b/src/createSfx.ts @@ -6,12 +6,12 @@ import { fileURLToPath } from 'url'; import { dirname, sep, join } from 'path'; import fs from 'fs-extra'; import { Binary } from './utility'; -import { isArray, isWindows } from 'node-sys'; +import { isWindows } from 'node-sys'; const platformTitle = { win32: 'Windows OS', darwin: 'Apple macOS', linux: 'Linux OS', -}; +} as Record; const title = ' installation package created on ' + platformTitle[process.platform] + '.'; const prompt = 'Do you want to install '; @@ -24,7 +24,7 @@ const __dirname = dirname(__filename); const pwd = __dirname.split(sep); /* c8 ignore next 18 */ -function getPath(module, folder = pwd) { +function getPath(module: string, folder = pwd): string | null { if (folder.length < 1) { return null; } @@ -115,20 +115,24 @@ archive.pipe(SfxDirectory, { * * @returns {Promise} Promise */ -export const createSfx = function ( - name: String, - files: Array, - destination: String = '', - options: {} = { +export function createSfx( + name: string, + files: Array, + destination: string = '', + options: Record = { title: null, beginPrompt: null, progress: null, }, - type: String = 'gui', - platform: String = 'win32', - extension: String = '.exe' -): Promise { - return when.promise(function (resolve, reject, progress) { + type: string = 'gui', + platform: string = 'win32', + extension: string = '.exe' +) { + return when.promise(function ( + resolve: (arg0: string) => void, + reject: (arg0: string) => void, + progress: (arg0: any) => any + ) { let directory = destination != '' && fs.existsSync(destination) ? destination @@ -176,7 +180,7 @@ export const createSfx = function ( let sfxModule = type == 'gui' ? '7zwin32.sfx' : '7zCon' + platform + '.sfx'; let sfx = name.includes(extension) ? name : name + extension; - let list = isArray(files) + let list = Array.isArray(files) ? [configFile].concat(files) : configFile + ' ' + files; sfx = join(SfxDirectory, sfx); @@ -184,10 +188,10 @@ export const createSfx = function ( sfx: sfxModule, }); createArchive(sfx, list, params, override) - .progress((data) => { + .progress((data: any) => { return progress(data); }) - .then((data) => { + .then((data: any) => { fs.unlink(configFile, (err) => { if (err) console.error(err); @@ -202,9 +206,9 @@ export const createSfx = function ( } }); }) - .catch((err) => { + .catch((err: string) => { fs.removeSync(configFile); return reject(err); }); }); -}; +} diff --git a/src/index.ts b/src/index.ts index a84d247..602f1f4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,33 +6,33 @@ import { createSfx } from './createSfx'; import { isWindows } from 'node-sys'; function retry( - command, - options, - override, - progress, - onprogress, - resolve, - reject, - archive + command: string | undefined, + options: {}, + override: boolean | undefined, + progress: (arg0: any) => void, + onprogress: (data: any) => any[], + resolve: (arg0: any) => void, + reject: (arg0: any) => void, + archive: string ) { // Start the command return Run('7z', command, options, override) - .progress(function (data) { + .progress(function (data: any) { return progress(onprogress(data)); }) // When all is done resolve the Promise. - .then(function (args) { + .then(function (args: any) { return resolve(args); }) // Catch the error and pass it to the reject function of the Promise. .catch(function () { console.error(archive + ' failed using `7z`, retying with `7za`.'); Run('7za', command, options, override) - .progress(function (data) { + .progress(function (data: any) { return progress(onprogress(data)); }) - .then(function (args) { + .then(function (args: any) { return resolve(args); }) - .catch(function (err) { + .catch(function (err: any) { return reject(err); }); }); @@ -55,15 +55,24 @@ function retry( export const createArchive = (SevenZip.createArchive = SevenZip.add = - function (filepath, files, options, override = false) { - return when.promise(function (resolve, reject, progress) { + function ( + filepath: string, + files: string | string[], + options: any, + override = false + ) { + return when.promise(function ( + resolve: (value: any) => void, + reject: (reason: any) => void, + progress: (arg0: any) => any + ) { /** * When a stdout is emitted, parse each line and search for a pattern.When * the pattern is found, extract the file (or directory) name from it and * pass it to an array. Finally returns this array. */ - function onprogress(data) { - let entries = []; + function onprogress(data: string) { + let entries: string[] = []; data.split('\n').forEach(function (line) { if (line.substr(0, 1) === '+') { entries.push( @@ -110,7 +119,12 @@ export const createArchive = export const deleteArchive = (SevenZip.deleteArchive = SevenZip.delete = - function (filepath, files, options, override = false) { + function ( + filepath: string, + files: string | string[], + options: { files?: string[] | undefined } | undefined, + override = false + ) { return new Promise(function (resolve, reject) { // Convert array of files into a string if needed. files = Files(files); @@ -153,15 +167,24 @@ export const deleteArchive = export const extractArchive = (SevenZip.extractArchive = SevenZip.extract = - function (filepath, dest = '*', options = {}, override = false) { - return when.promise(function (resolve, reject, progress) { + function ( + filepath: string, + dest = '*', + options = {}, + override = false + ) { + return when.promise(function ( + resolve: (value: any) => void, + reject: (reason: any) => void, + progress: (arg0: any) => any + ) { /** * When a stdout is emitted, parse each line and search for a pattern.When * the pattern is found, extract the file (or directory) name from it and * pass it to an array. Finally returns this array. */ - function onprogress(data) { - let entries = []; + function onprogress(data: string) { + let entries: string[] = []; data.split('\n').forEach(function (line) { if (line.substr(0, 1) === '-') { entries.push( @@ -207,15 +230,24 @@ export const extractArchive = export const fullArchive = (SevenZip.fullArchive = SevenZip.extractFull = - function (filepath, dest = '*', options = {}, override = false) { - return when.promise(function (resolve, reject, progress) { + function ( + filepath: string, + dest = '*', + options = {}, + override = false + ) { + return when.promise(function ( + resolve: (value: any) => void, + reject: (reason: any) => void, + progress: (arg0: any) => any + ) { /** * When a stdout is emitted, parse each line and search for a pattern.When * the pattern is found, extract the file (or directory) name from it and * pass it to an array. Finally returns this array. */ - function onprogress(data) { - let entries = []; + function onprogress(data: string) { + let entries: string[] = []; data.split('\n').forEach(function (line) { if (line.substr(0, 1) === '-') { entries.push( @@ -259,9 +291,17 @@ export const fullArchive = export const listArchive = (SevenZip.listArchive = SevenZip.list = - function (filepath, options, override = false) { - return when.promise(function (resolve, reject, progress) { - let spec = {}; + function ( + filepath: string, + options: { files?: string[] | undefined } | undefined, + override = false + ) { + return when.promise(function ( + resolve: (value: any) => void, + reject: (reason: any) => void, + progress: (arg0: any) => any + ) { + let spec: Record = {}; /* jshint maxlen: 130 */ let regex = @@ -275,8 +315,8 @@ export const listArchive = * the pattern is found, extract the file (or directory) name from it and * pass it to an array. Finally returns this array. */ - function onprogress(data) { - let entries = []; + function onprogress(data: string) { + let entries: string[] = []; if (buffer.length > 0) { data = buffer + data; @@ -324,25 +364,25 @@ export const listArchive = // Create a string that can be parsed by `run`. let command = 'l "' + filepath + '" '; Run(isWindows() ? '7z' : '7za', command, options, override) - .progress(function (data) { + .progress(function (data: string) { return progress(onprogress(data)); }) .then(function () { return resolve(spec); }) - .catch(function (err) { + .catch(function (err: any) { if (isWindows()) { console.error( 'ListArchive failed using `7z`, retying with `7za`.' ); Run('7za', command, options, override) - .progress(function (data) { + .progress(function (data: string) { return progress(onprogress(data)); }) - .then(function (args) { + .then(function (args: any) { return resolve(args); }) - .catch(function (err) { + .catch(function (err: any) { return reject(err); }); } else { @@ -370,8 +410,18 @@ export const listArchive = export const onlyArchive = (SevenZip.onlyArchive = SevenZip.only = - function (filepath, dest, files, options = {}, override = false) { - return when.promise(function (resolve, reject, progress) { + function ( + filepath: string, + dest: string, + files: any, + options = {}, + override = false + ) { + return when.promise(function ( + resolve: (value: any) => void, + reject: (reason: any) => void, + progress: (arg0: any) => any + ) { options = Object.assign(options, { files: files, }); @@ -381,8 +431,8 @@ export const onlyArchive = * the pattern is found, extract the file (or directory) name from it and * pass it to an array. Finally returns this array. */ - function onprogress(data) { - let entries = []; + function onprogress(data: string) { + let entries: string[] = []; data.split('\n').forEach(function (line) { if (line.substr(0, 1) === '-') { entries.push( @@ -428,15 +478,24 @@ export const onlyArchive = export const renameArchive = (SevenZip.renameArchive = SevenZip.rename = - function (filepath, files, options, override = false) { - return when.promise(function (resolve, reject, progress) { + function ( + filepath: string, + files: string | string[], + options: {}, + override = false + ) { + return when.promise(function ( + resolve: (value: any) => void, + reject: (reason: any) => void, + progress: (arg0: any) => any + ) { /** * When a stdout is emitted, parse each line and search for a pattern.When * the pattern is found, extract the file (or directory) name from it and * pass it to an array. Finally returns this array. */ - function onprogress(data) { - let entries = []; + function onprogress(data: string) { + let entries: string[] = []; data.split('\n').forEach(function (line) { if (line.substr(0, 1) === 'U') { entries.push( @@ -483,15 +542,19 @@ export const renameArchive = export const testArchive = (SevenZip.testArchive = SevenZip.test = - function (filepath, options, override = false) { - return when.promise(function (resolve, reject, progress) { + function (filepath: string, options: {}, override = false) { + return when.promise(function ( + resolve: (value: any) => void, + reject: (reason: any) => void, + progress: (arg0: any) => any + ) { /** * When a stdout is emitted, parse each line and search for a pattern.When * the pattern is found, extract the file (or directory) name from it and * pass it to an array. Finally returns this array. */ - function onprogress(data) { - let entries = []; + function onprogress(data: string) { + let entries: string[] = []; data.split('\n').forEach(function (line) { if (line.substr(0, 1) === 'T') { entries.push( @@ -537,15 +600,24 @@ export const testArchive = export const updateArchive = (SevenZip.updateArchive = SevenZip.update = - function (filepath, files, options, override = false) { - return when.promise(function (resolve, reject, progress) { + function ( + filepath: string, + files: string | string[], + options: {}, + override = false + ) { + return when.promise(function ( + resolve: (value: any) => void, + reject: (reason: any) => void, + progress: (arg0: any) => any + ) { /** * When a stdout is emitted, parse each line and search for a pattern.When * the pattern is found, extract the file (or directory) name from it and * pass it to an array. Finally returns this array. */ - function onprogress(data) { - let entries = []; + function onprogress(data: string) { + let entries: string[] = []; data.split('\n').forEach(function (line) { if (line.substr(0, 1) === 'U') { entries.push( @@ -619,11 +691,11 @@ export const updateArchive = * @returns {Promise} Promise */ export const createSfxWindows = (SevenZip.windowsSfx = function ( - name, - files, - destination, - options, - type + name: string, + files: string[], + destination: string | undefined, + options: Record | undefined, + type: string | undefined ) { return createSfx(name, files, destination, options, type, 'win32', '.exe'); }); @@ -645,10 +717,10 @@ export const createSfxWindows = (SevenZip.windowsSfx = function ( * @returns {Promise} Promise */ export const createSfxLinux = (SevenZip.linuxSfx = function ( - name, - files, - destination, - options + name: string, + files: string[], + destination: string | undefined, + options: Record | undefined ) { return createSfx( name, @@ -678,10 +750,10 @@ export const createSfxLinux = (SevenZip.linuxSfx = function ( * @returns {Promise} Promise */ export const createSfxMac = (SevenZip.macSfx = function ( - name, - files, - destination, - options + name: string, + files: string[], + destination: string | undefined, + options: Record | undefined ) { return createSfx( name, diff --git a/src/types.d.ts b/src/types.d.ts new file mode 100644 index 0000000..7302a0d --- /dev/null +++ b/src/types.d.ts @@ -0,0 +1,15 @@ +declare module 'node-sys' { + export function isString(input: any): boolean; + export function isUndefined(input: any): boolean; + export function isWindows(): boolean; + export function isBool(input: any): boolean; + export function spawning( + cmd: string, + args: string[], + options: { + stdio: string; + onprogress: (object: { output: any }) => string[]; + onerror: (data: string) => Error | undefined; + } + ): Promise; +} diff --git a/src/utility.ts b/src/utility.ts index 5d63ace..2292319 100644 --- a/src/utility.ts +++ b/src/utility.ts @@ -4,14 +4,7 @@ import when from 'when'; import { EOL } from 'os'; import { fileURLToPath } from 'url'; import { dirname, join, sep, sep as nativeSeparator, normalize } from 'path'; -import { - spawning, - isUndefined, - isArray, - isString, - isWindows, - isBool, -} from 'node-sys'; +import { spawning, isUndefined, isString, isWindows, isBool } from 'node-sys'; const __filename = fileURLToPath(import.meta.url); @@ -40,14 +33,14 @@ export const Binary = function (override = false, binary = '7z') { * @param {string|array} files * @return {string} */ -export const Files = function (files: string | array): string { +export const Files = function (files: string | string[]): string { if (isUndefined(files)) { return ''; } let toProcess = ''; - if (isArray(files)) { + if (Array.isArray(files)) { files.forEach(function (f) { toProcess += '"' + f + '" '; }); @@ -86,17 +79,21 @@ export const ReplaceNativeSeparator = function (path: string): string { * * @returns {Promise} Promise */ -export const Run = function ( +export function Run( binary: string = '7z', - command: string = null, - switches: Array = {}, + command: string | null = null, + switches: { files?: string[] } = {}, override: boolean = false -): Promise { - return when.promise(function (fulfill, reject, progress) { +) { + return when.promise(function ( + fulfill: (arg0: string[]) => void, + reject: (arg0: Error) => void, + progress: (arg0: any) => void + ) { // Parse the command variable. If the command is not a string reject the // Promise. Otherwise transform the command into two variables: the command // name and the arguments. - if (!isString(command) || !isString(binary)) { + if (typeof command !== 'string' || !isString(binary)) { return reject(new Error('Command and Binary must be a string')); } @@ -136,7 +133,7 @@ export const Run = function ( let files = switches.files; delete switches.files; - if (isArray(files)) { + if (Array.isArray(files)) { files.forEach(function (s) { args.push(s); }); @@ -172,15 +169,15 @@ export const Run = function ( // When an stdout is emitted, parse it. If an error is detected in the body // of the stdout create an new error with the 7-Zip error message as the // error's message. Otherwise progress with stdout message. - let err; + let err: Error; let reg = new RegExp('Error:(' + EOL + '|)?(.*)', 'i'); - let onprogress = (object) => { + let onprogress = (object: { output: any }) => { progress(object.output); return args; }; - let onerror = (data) => { + let onerror = (data: string) => { let res = reg.exec(data); if (res) { @@ -199,15 +196,15 @@ export const Run = function ( }, }; spawning(res.cmd, res.args, res.options) - .then((data) => { + .then((data: string[]) => { if (data === args) return fulfill(args); return reject(err); }) - .catch((err) => { + .catch((err: Error) => { return reject(err); }); }); -}; +} /** * Transform an object of options into an array that can be passed to the @@ -215,7 +212,7 @@ export const Run = function ( * @param {Object} switches An object of options * @return {array} Array to pass to the `run` function. */ -export const Switches = function (switches: {}): array { +export const Switches = function (switches: Record) { // Default value for switches switches = switches || {}; var a = []; @@ -245,7 +242,7 @@ export const Switches = function (switches: {}): array { } // Allow raw switches to be added to the command, repeating switches like // -i is not possible otherwise. else if (s === 'raw') { - switches.raw.forEach(function (rawValue) { + switches.raw.forEach(function (rawValue: any) { a.push(rawValue); }); } else if (switches[s].indexOf(' ') === -1) { From 51e1c88f90e3acd1419971ae010249d84c9c6d2b Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Tue, 23 Aug 2022 23:51:58 -0700 Subject: [PATCH 4/7] test: build before running the tests + add js file extension in the imports --- package.json | 2 +- src/createSfx.ts | 4 ++-- src/index.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c4c9a2b..0dd6067 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "main": "lib/index.js", "scripts": { - "test": "mocha --recursive test/ --timeout=0", + "test": "npm run build && mocha --recursive test/ --timeout=0", "report": "npx c8 npm test", "coverage": "npx c8 --reporter json npm test && npx codecov -f coverage/coverage-final.json", "install": "node installer.mjs", diff --git a/src/createSfx.ts b/src/createSfx.ts index 621bbdb..5eec2ed 100644 --- a/src/createSfx.ts +++ b/src/createSfx.ts @@ -1,11 +1,11 @@ 'use strict'; -import { createArchive } from './index'; +import { createArchive } from './index.js'; import when from 'when'; import { fileURLToPath } from 'url'; import { dirname, sep, join } from 'path'; import fs from 'fs-extra'; -import { Binary } from './utility'; +import { Binary } from './utility.js'; import { isWindows } from 'node-sys'; const platformTitle = { win32: 'Windows OS', diff --git a/src/index.ts b/src/index.ts index 602f1f4..4bd60aa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,8 @@ 'use strict'; import when from 'when'; -import { Files, ReplaceNativeSeparator, Run } from './utility'; -import { createSfx } from './createSfx'; +import { Files, ReplaceNativeSeparator, Run } from './utility.js'; +import { createSfx } from './createSfx.js'; import { isWindows } from 'node-sys'; function retry( From 6d4651c65a1b9d0bcc736d78cd39c407a2482273 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Wed, 24 Aug 2022 00:18:48 -0700 Subject: [PATCH 5/7] fix: update dependencies --- package-lock.json | 412 +++++++++++++++++++++------------------------- package.json | 6 +- 2 files changed, 188 insertions(+), 230 deletions(-) diff --git a/package-lock.json b/package-lock.json index 132d747..c1ee4f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,11 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "fs-extra": "^10.0.0", + "fs-extra": "^10.1.0", "minimist": "1.2.6", "node-sys": "^1.1.7", "node-unar": "^1.0.8", - "node-wget-fetch": "^1.1.2", + "node-wget-fetch": "^1.1.3", "when": "^3.7.8" }, "bin": { @@ -35,9 +35,10 @@ "@types/fs-extra": "^9.0.13", "@types/minimist": "1.2.2", "@types/mocha": "^9.1.1", + "@types/node": "^18.7.12", "@types/when": "^2.4.34", "chai": "^4.3.6", - "mocha": "^8.4.0", + "mocha": "^10.0.0", "typescript": "^4.7.4" }, "engines": { @@ -98,15 +99,6 @@ "node": ">=6" } }, - "node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -175,13 +167,12 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -270,24 +261,30 @@ } }, "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "glob-parent": "~5.1.0", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { - "fsevents": "~2.3.1" + "fsevents": "~2.3.2" } }, "node_modules/cliui": { @@ -370,9 +367,9 @@ "dev": true }, "node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -541,9 +538,9 @@ } }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -572,20 +569,33 @@ "node": ">= 6" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=4.x" + "node": "*" } }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -641,15 +651,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -680,15 +681,27 @@ "node": ">=8" } }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -724,15 +737,19 @@ } }, "node_modules/log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/loupe": { @@ -745,15 +762,15 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=10" } }, "node_modules/minimist": { @@ -762,43 +779,40 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "node_modules/mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", + "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", + "glob": "7.2.0", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.2.1", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "bin": { "_mocha": "bin/_mocha", - "mocha": "bin/mocha" + "mocha": "bin/mocha.js" }, "engines": { - "node": ">= 10.12.0" + "node": ">= 14.0.0" }, "funding": { "type": "opencollective", @@ -812,9 +826,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -1012,9 +1026,9 @@ } }, "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { "picomatch": "^2.2.1" @@ -1053,39 +1067,14 @@ ] }, "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "dependencies": { "randombytes": "^2.1.0" } }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -1193,19 +1182,10 @@ "node": ">= 8" } }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, "node_modules/workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", "dev": true }, "node_modules/wrap-ansi": { @@ -1272,7 +1252,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, "node_modules/y18n": { @@ -1435,12 +1415,6 @@ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1491,13 +1465,12 @@ "dev": true }, "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "braces": { @@ -1564,19 +1537,19 @@ "dev": true }, "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" } }, "cliui": { @@ -1646,9 +1619,9 @@ "dev": true }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -1762,9 +1735,9 @@ "dev": true }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -1773,6 +1746,27 @@ "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, "glob-parent": { @@ -1789,12 +1783,6 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1838,12 +1826,6 @@ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true - }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -1865,15 +1847,21 @@ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { "argparse": "^2.0.1" @@ -1898,12 +1886,13 @@ } }, "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, "loupe": { @@ -1916,12 +1905,12 @@ } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" } }, "minimist": { @@ -1930,33 +1919,30 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", + "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", + "glob": "7.2.0", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.2.1", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -1969,9 +1955,9 @@ "dev": true }, "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true }, "node-fetch": { @@ -2098,9 +2084,9 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" @@ -2119,33 +2105,14 @@ "dev": true }, "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.0" } }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -2219,19 +2186,10 @@ "isexe": "^2.0.0" } }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", "dev": true }, "wrap-ansi": { @@ -2282,7 +2240,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, "y18n": { diff --git a/package.json b/package.json index 0dd6067..19da17e 100644 --- a/package.json +++ b/package.json @@ -75,11 +75,11 @@ "node": ">=12.0.0" }, "dependencies": { - "fs-extra": "^10.0.0", + "fs-extra": "^10.1.0", "minimist": "1.2.6", "node-sys": "^1.1.7", "node-unar": "^1.0.8", - "node-wget-fetch": "^1.1.2", + "node-wget-fetch": "^1.1.3", "when": "^3.7.8" }, "devDependencies": { @@ -90,7 +90,7 @@ "@types/node": "^18.7.12", "@types/when": "^2.4.34", "chai": "^4.3.6", - "mocha": "^8.4.0", + "mocha": "^10.0.0", "typescript": "^4.7.4" } } From 02b538dd81eb3cfd5d9600fc6bc7818ea229591e Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Wed, 24 Aug 2022 00:58:20 -0700 Subject: [PATCH 6/7] fix: add @types/when to the optional dependencies due to .d.ts files --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 19da17e..f9ff3f3 100644 --- a/package.json +++ b/package.json @@ -82,13 +82,15 @@ "node-wget-fetch": "^1.1.3", "when": "^3.7.8" }, + "optionalDependencies": { + "@types/when": "^2.4.34" + }, "devDependencies": { "@types/chai": "^4.3.3", "@types/fs-extra": "^9.0.13", "@types/minimist": "1.2.2", "@types/mocha": "^9.1.1", "@types/node": "^18.7.12", - "@types/when": "^2.4.34", "chai": "^4.3.6", "mocha": "^10.0.0", "typescript": "^4.7.4" From b4aba4e637694996f4e8f65590a7b34efe193879 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Wed, 24 Aug 2022 15:05:16 -0700 Subject: [PATCH 7/7] chore: add my name to the contributors [skip ci] --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index f9ff3f3..453fba2 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,8 @@ "redx25 ", "Quentin Rossetti ", "František Gič ", - "Oskar Larsson Högfeldt " + "Oskar Larsson Högfeldt ", + "Amin Yahyaabadi " ], "license": "MIT", "bugs": {