UNPKG

@rodbe/nsl

Version:

List, fuzzy search and run scripts from any type of project

211 lines (203 loc) 7.39 kB
#!/usr/bin/env node import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import { checkUpdates } from '@rodbe/check-updates'; import { g as getCacheFilePath, a as getNslPkgJson, b as getNSLDistPath, R as RERUN_CACHE_NAME, S as SHORT_CONFIG_CACHE_NAME, L as LONG_CONFIG_CACHE_NAME, P as PAGE_SIZE, e as execScript, N as NPM_SCRIPTS_TO_IGNORE, i as initEvents, W as WEEK_IN_MS, c as getMainPkgJsonPath, D as DAY_IN_MS } from '../index-CM7OT-oh.js'; import { homedir, platform } from 'node:os'; import { version, arch } from 'node:process'; import chalk from 'chalk'; import boxen from 'boxen'; import figlet from 'figlet'; import { getCoreConfig, getConfig } from '@rodbe/get-config'; import { setTimeout } from 'node:timers/promises'; import search, { Separator } from '@inquirer/search'; import { compose, fuzzySearch } from '@rodbe/fn-utils'; import table from 'text-table'; import 'node:fs'; import { getAllPackageJsons } from '@rodbe/get-package-jsons'; import 'node:path'; import 'node:child_process'; import '@rodbe/lru-cache-fs'; import 'node:url'; const logNslBanner = () => { const box = boxen(chalk.magenta(figlet.textSync("- NSL -", { horizontalLayout: "full" })), { borderColor: "cyan", borderStyle: "classic", margin: 1, padding: 1, textAlignment: "center", title: "Node Script List", titleAlignment: "center" }); console.log(box); }; const getNodeVersion = () => { const nodeVersion = version.replace("v", ""); const [major, minor, patch] = nodeVersion.split("."); return { major: Number(major), minor: Number(minor), patch: Number(patch), version: nodeVersion }; }; const aboutNSL = (argv) => { const rerunCachePath = getCacheFilePath(RERUN_CACHE_NAME); const shortConfigCachePath = getCacheFilePath(SHORT_CONFIG_CACHE_NAME); const longConfigCachePath = getCacheFilePath(LONG_CONFIG_CACHE_NAME); logNslBanner(); console.log(chalk.black.bold.bgGreenBright("Current version ->"), getNslPkgJson().version); console.log(chalk.black.bold.bgGreenBright("NSL directory ->"), getNSLDistPath()); console.log( chalk.black.bold.bgGreenBright("ConfigFile ->"), getCoreConfig("nsl", { debug: true }) ); console.log(chalk.black.bold.bgGreenBright("Arguments ->"), JSON.stringify(argv)); console.log(chalk.black.bold.bgGreenBright("Home ->"), homedir()); console.log(chalk.black.bold.bgGreenBright("Machine ->"), arch); console.log(chalk.black.bold.bgGreenBright("Platform ->"), platform()); console.log(chalk.black.bold.bgGreenBright("rerunCachePath ->"), rerunCachePath); console.log(chalk.black.bold.bgGreenBright("shortConfigCachePath ->"), shortConfigCachePath); console.log(chalk.black.bold.bgGreenBright("longConfigCachePath ->"), longConfigCachePath); console.log(chalk.black.bold.bgGreenBright("NodeJS ->"), getNodeVersion().version); }; const scriptToRowTable = (script) => { return [script.scriptName, ">", script.scriptContent]; }; const getGroupedScriptsWithTableProp = (packageJsons) => { return Object.entries(packageJsons).reduce( (acc, [folderContainer, packageJson]) => { const { scripts = [], packageManager, name: packageName } = packageJson; const scriptsWithRowFormat = table(scripts.map(scriptToRowTable), { align: ["r", "c", "l"] }).split("\n"); acc[folderContainer] = scripts.map( ({ scriptContent, scriptName }, idx) => { return { name: scriptsWithRowFormat[idx], value: { folderContainer, packageManager, packageName, scriptContent, scriptName } }; } ); return acc; }, {} ); }; const getGroupedScriptsWithInquirerFormat = (groupedScripts) => { return Object.entries(groupedScripts).reduce( (acc, [folderContainer, currentScripts], idx) => { if (!currentScripts.length) { return acc; } if (idx >= 1) { acc.push(new Separator(" ")); } acc.push(new Separator(chalk.white.bold.bgMagenta(`\u{1F4E6} ${folderContainer}: `))); acc.push(...currentScripts); return acc; }, [] ); }; const getAllScriptsFromPackageJsons = (rootPath) => { const packageJsons = getAllPackageJsons({ cwd: rootPath }); if (!packageJsons) { console.log("No package.json files found."); process.exit(1); } return packageJsons; }; const DEBOUNCE_TIME = 300; const filterScripts = (all) => (config) => (packageJsons) => { if (all) { return packageJsons; } const scriptsToIgnore = NPM_SCRIPTS_TO_IGNORE.concat(config?.ignoreScripts || []); return Object.entries(packageJsons).reduce( (acc, [folderContainer, packageJson]) => { const scripts = packageJson.scripts; if (!scripts) { acc[folderContainer] = packageJson; return acc; } const filteredScripts = scripts.filter( (script) => !scriptsToIgnore.includes(script.scriptName) ); acc[folderContainer] = { ...packageJson, scripts: filteredScripts }; return acc; }, {} ); }; const findAndExecScript = async ({ all, debug, print }) => { const cwd = process.cwd(); const config = await getConfig("nsl", { debug }); const groupedScripts = compose(filterScripts(all)(config), getAllScriptsFromPackageJsons)(cwd); const groupedScriptsWithTable = getGroupedScriptsWithTableProp(groupedScripts); const groupedScriptsWithInquirerFormat = getGroupedScriptsWithInquirerFormat(groupedScriptsWithTable); const rootPackageJson = groupedScripts?.Root; const answer = await search({ message: "Select or search a script to run:", pageSize: PAGE_SIZE, source: async (input) => { if (!input) { return groupedScriptsWithInquirerFormat; } await setTimeout(DEBOUNCE_TIME); const filtered = Object.entries(groupedScriptsWithTable).reduce( (acc, [folderContainer, currentScripts]) => { const filteredScripts = fuzzySearch({ searchText: input, items: currentScripts, key: "name" }); acc[folderContainer] = filteredScripts; return acc; }, {} ); return getGroupedScriptsWithInquirerFormat(filtered); } }); const rootPkgManager = rootPackageJson?.packageManager; execScript({ answer, cwd, debug, print, rootPkgManager }); }; initEvents(); const init = async () => { const argv = await yargs(hideBin(process.argv)).version(false).options({ all: { alias: "a", type: "boolean", default: false }, debug: { alias: "d", type: "boolean", default: false }, info: { alias: "i", type: "boolean", default: false }, print: { alias: "p", type: "boolean", default: false }, update: { alias: "u", type: "boolean", default: false }, version: { alias: "v", type: "boolean", default: false } }).argv; const { update, checkNewVersion } = checkUpdates({ askToUpdate: true, dontAskCheckInterval: DAY_IN_MS, packageJsonPath: getMainPkgJsonPath(), updateCheckInterval: WEEK_IN_MS }); if (argv.update) { update?.(); process.exit(0); } if (argv.info) { aboutNSL(argv); process.exit(0); } if (argv.version) { console.log(getNslPkgJson().version); process.exit(0); } await checkNewVersion?.(); await findAndExecScript(argv); }; init();