UNPKG

update-modules

Version:

This module is used to update all modules in the project.

153 lines (124 loc) 5.72 kB
#!/usr/bin/env node require('colors'); const debug = process.argv?.pop() == '--debug'; const { SingleBar, Presets } = require('cli-progress'); const { exec } = require('node:child_process'); const { createInterface } = require('readline'); const dir = __dirname.split('node_modules')[0].replaceAll(`\\`, '/') + '/'; const package = require(dir + 'package.json'); const checkingUpdateBar = new SingleBar({ barCompleteChar: '●', barIncompleteChar: '○', fps: 1, clearOnComplete: true, hideCursor: true, format: '▲ update-modules (controlling): '.green + '{bar} ({value} / {total})'.blue, }, Presets.shades_grey); const moduleInstallingBar = new SingleBar({ barCompleteChar: '●', barIncompleteChar: '○', fps: 1, clearOnComplete: false, hideCursor: true, format: '▲ update-modules (installing): '.green + '{bar} ({value} / {total})'.blue, }, Presets.shades_grey); const ignored_modules = package?.updateModulesConfig?.ignore || []; const dependencies = Object?.keys(package?.dependencies || []); const devDependencies = Object?.keys(package?.devDependencies || []); const normaly_modules = dependencies?.map(name => ({ name, version: package?.dependencies?.[name]?.replace('^', ''), dev: false })); const dev_modules = devDependencies?.map(name => ({ name, version: package?.devDependencies?.[name]?.replace('^', ''), dev: true })); const modules = [...normaly_modules, ...dev_modules]; /** * Fetches the module data from the npm registry. * * @param {String} name This is the module name. * @returns */ const fetchModule = async (name) => { let output = null; const addresses = [ 'registry.npmjs.org/{name}', 'cdn.jsdelivr.net/npm/{name}@latest/package.json' ]; for (let address of addresses) { try { output = await fetch('https://' + address.replaceAll('{name}', name)).then(res => res?.json()); if (output) break; } catch (error) { if (debug) console.log('▲ update-modules: '.green + `Error: ${error}`.red); } } return output; } (async () => { checkingUpdateBar.start(modules?.length || 0, 0); checkingUpdateBar.increment(); let updatebleModules = (await Promise.all(modules.map(async (module, i) => { checkingUpdateBar.update(i + 1); const data = await fetchModule(module.name); if (!data) return null; const newVersion = data?.['dist-tags']?.latest || data?.version; if (!newVersion) return { ...module, latest: null }; const updateble = newVersion != module.version && !ignored_modules.includes(module.name); if (updateble) return { ...module, latest: newVersion }; else return null; }))).filter(f => f !== null); checkingUpdateBar.stop(); if (updatebleModules.length == 0) return console.log('▲ update-modules: '.green + 'No updates available.'.green); const nameLength = Math.max(...updatebleModules.map(module => module?.name?.length)); const versionLength = Math.max(...updatebleModules.map(module => module?.version?.length)); const notFoundModules = updatebleModules.filter(f => !f.latest); if (notFoundModules.length > 0) { console.log('▲ update-modules: '.green + `Please remove ${notFoundModules.length > 0 ? notFoundModules.map(m => `"${m?.name}"`).join(', ') : "None"} modules. Because the latest version could not be found.`.red); return; } updatebleModules = updatebleModules.filter(f => f.latest); const arrow = '─'.repeat(nameLength + versionLength + 20); console.log(arrow.cyan); console.log(`▲ ${'Module'.padEnd(nameLength)} ${'Version'.padEnd(versionLength)} Latest`.cyan); for (let module of updatebleModules) { var name = module.name + ' '.repeat(nameLength - module.name.length); var version = module.version + ' '.repeat(versionLength - module.version.length); console.log(`▲ ${name} : ${version}${module.latest}`.yellow); } console.log(arrow.cyan); const client = createInterface({ input: process.stdin, output: process.stdout }); client.question('▲ update-modules: '.green + 'Do you want to update? (yes / no) \n'.blue + '> '.blue, async (answer) => { const acceptAnswers = ['yes', 'y', 'true']; if (!acceptAnswers.includes(answer.toLowerCase())) { return client.close(); } moduleInstallingBar.start(updatebleModules.length, 0); moduleInstallingBar.increment(); for (let i = 0; i < updatebleModules.length; i++) { moduleInstallingBar.update(i + 1); const update = await moduleUpdate(updatebleModules[i].name, 'latest'); if (!update) { console.log('▲ update-modules: '.green + `An error occurred while updating the "${updatebleModules[i].name}" module.`.red); } } moduleInstallingBar.stop(); client.close(); }); client.on('close', () => { process.exit(); }); })(); /** * Updates the module. * * @param {String} name This is the module name. * @param {String} verison This is the module version. * @returns */ async function moduleUpdate(name, verison) { return await new Promise((resolve, reject) => { exec(`npm install ${name}@${verison}`, (error) => { if (error) { setTimeout(() => reject(error), 200) } else { setTimeout(() => resolve(true), 200) } }); }); }