@rodbe/nsl
Version:
List, fuzzy search and run scripts from any type of project
242 lines (234 loc) • 8.64 kB
JavaScript
#!/usr/bin/env node
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { checkUpdates } from '@rodbe/check-updates';
import { g as getCacheFilePath, U as URL_DOCUMENTATION, 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-tTGo6WbU.js';
import { homedir, platform } from 'node:os';
import { version, arch } from 'node:process';
import chalk from 'chalk';
import { getCoreConfig, getConfig } from '@rodbe/get-config';
import boxen from 'boxen';
import figlet from 'figlet';
import { setTimeout } from 'node:timers/promises';
import search, { Separator } from '@inquirer/search';
import { compose, purge, 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("\u{1F4DA} Documentaci\xF3n ->"), URL_DOCUMENTATION);
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 answerSelected = 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 inputTexts = purge(input.split(" "));
const [scriptToSearch, projectToSearch] = inputTexts;
let filteredScriptsList;
if (projectToSearch) {
filteredScriptsList = Object.entries(groupedScriptsWithTable).reduce(
(acc, [folderContainer, currentScripts]) => {
const filteredScripts = fuzzySearch({
searchText: projectToSearch,
items: currentScripts,
key: "value.folderContainer"
});
acc[folderContainer] = filteredScripts;
return acc;
},
{}
);
const filtered2 = Object.entries(filteredScriptsList).reduce(
(acc, [folderContainer, currentScripts]) => {
const filteredScripts = fuzzySearch({
searchText: scriptToSearch,
items: currentScripts,
key: "name"
});
acc[folderContainer] = filteredScripts;
return acc;
},
{}
);
return getGroupedScriptsWithInquirerFormat(filtered2);
}
const filtered = Object.entries(groupedScriptsWithTable).reduce(
(acc, [folderContainer, currentScripts]) => {
const filteredScripts = fuzzySearch({
searchText: scriptToSearch,
items: currentScripts,
key: "name"
});
acc[folderContainer] = filteredScripts;
return acc;
},
{}
);
return getGroupedScriptsWithInquirerFormat(filtered);
}
});
const rootPkgManager = rootPackageJson?.packageManager;
execScript({ answerSelected, 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();