@rodbe/nsl
Version:
List, fuzzy search and run scripts from any type of project
175 lines (165 loc) • 5.31 kB
JavaScript
import { join, parse, dirname } from 'node:path';
import { execSync } from 'node:child_process';
import chalk from 'chalk';
import { tryCatch } from '@rodbe/fn-utils';
import { fsCache } from '@rodbe/lru-cache-fs';
import { fileURLToPath } from 'node:url';
import { readFileSync } from 'node:fs';
import { homedir } from 'node:os';
import process$1 from 'node:process';
const PAGE_SIZE = 20;
const BASE_CACHE_KEY = "nsl";
const RERUN_CACHE_NAME = `${BASE_CACHE_KEY}-rerun-cache`;
const SHORT_CONFIG_CACHE_NAME = `${BASE_CACHE_KEY}-short-config-cache`;
const LONG_CONFIG_CACHE_NAME = `${BASE_CACHE_KEY}-long-config-cache`;
const MINUTE_IN_MS = 60 * 1e3;
const HOUR_IN_MS = 60 * MINUTE_IN_MS;
const DAY_IN_MS = 24 * HOUR_IN_MS;
const WEEK_IN_MS = 7 * DAY_IN_MS;
const MONTH_IN_MS = 30 * DAY_IN_MS;
const QUATER_IN_MS = 3 * MONTH_IN_MS;
const NPM_SCRIPTS_TO_IGNORE = [
"dependencies",
"install",
"postinstall",
"postpack",
"postprepare",
"postpublish",
"postrestart",
"poststart",
"poststop",
"posttest",
"postversion",
"preinstall",
"prepack",
"prepare",
"preprepare",
"prepublish",
"prepublishOnly",
"prerestart",
"prestart,",
"prestop",
"pretest",
"preversion",
"publish",
"restart"
];
const nslCachePath = join(homedir(), ".nsl");
const getCacheFilePath = (cacheName) => join(nslCachePath, cacheName);
const getNSLDistPath = () => {
const filename = fileURLToPath(import.meta.url);
return dirname(filename);
};
const getMainPkgJsonPath = () => {
let currentFolderPath = getNSLDistPath();
let pkgJsonPath = "";
while (true) {
const { base, dir } = parse(currentFolderPath);
if (base === "dist") {
pkgJsonPath = dir;
break;
}
currentFolderPath = join(currentFolderPath, "..");
}
return join(pkgJsonPath, "package.json");
};
const getNslPkgJson = () => {
return JSON.parse(readFileSync(getMainPkgJsonPath(), "utf8"));
};
const rerunCache = () => {
return fsCache({
cacheName: RERUN_CACHE_NAME,
cachePath: nslCachePath,
max: 200,
ttl: QUATER_IN_MS
});
};
const DEFAULT_RUNNER = "npm";
const getPackageManager = (packageManager) => {
if (!packageManager) {
return DEFAULT_RUNNER;
}
const regex = /npm|pnpm|yarn|bun/;
const match = regex.exec(packageManager);
if (match) {
return match[0];
}
return DEFAULT_RUNNER;
};
const voltaExists = () => {
const [err] = tryCatch(() => {
execSync("volta --version", { stdio: "ignore" });
return true;
});
return !err;
};
const getCommandToRunFromRoot = (answerSelected, rootPackageManager) => {
const { folderContainer, packageManager, scriptName, packageName } = answerSelected;
const runner = getPackageManager(packageManager ?? rootPackageManager);
if (folderContainer === "Root") {
return `${runner} run ${scriptName}`;
}
if (runner === "pnpm") {
return `pnpm -F ${packageName} ${scriptName}`;
}
if (runner === "yarn") {
return `yarn workspace ${packageName} ${scriptName}`;
}
return `npm run ${scriptName} -w ${folderContainer}`;
};
const getCommandToRunFromFolder = (answerSelected, rootPackageManager) => {
const { packageManager, scriptName } = answerSelected;
const runner = getPackageManager(packageManager ?? rootPackageManager);
const commandToRun = `${runner} run ${scriptName}`;
if (voltaExists()) {
return `volta run npm run ${scriptName}`;
}
return commandToRun;
};
const getCommandToRun = (answerSelected, rootPackageManager) => {
const commandToRunFromRoot = getCommandToRunFromRoot(answerSelected, rootPackageManager);
const commandToRunFromFolder = getCommandToRunFromFolder(answerSelected, rootPackageManager);
return {
root: commandToRunFromRoot,
folder: commandToRunFromFolder
};
};
const execScript = ({ answer, cwd, debug, print, rootPkgManager }) => {
const { syncFs } = rerunCache();
const commandToRun = getCommandToRun(answer, rootPkgManager);
syncFs.setItem(cwd, { answer, rootPkgManager, debug, print, commandToRun });
const scriptPath = answer.folderContainer === "Root" ? cwd : join(cwd, answer.folderContainer);
console.log(chalk.black.bold.bgGreenBright(commandToRun.root));
if (debug) {
console.log({ commandToRun, scriptPath });
}
if (print) {
process.exit(0);
}
const [err] = tryCatch(() => {
execSync(commandToRun.folder, {
cwd: scriptPath,
stdio: [process.stdin, process.stdout, process.stderr]
});
});
if (err) {
console.log(chalk.white.bold.bgMagenta(`Ups, try to run the script manually `));
console.log(commandToRun);
}
};
const initEvents = () => {
process$1.stdin.on("keypress", (_, key) => {
if (key && key.name === "escape") {
console.log("\u{1F44B} until next time!");
process$1.exit(0);
}
});
process$1.on("uncaughtException", (error) => {
if (error instanceof Error && error.name === "ExitPromptError") {
console.log("\u{1F44B} until next time!");
} else {
throw error;
}
});
};
export { DAY_IN_MS as D, LONG_CONFIG_CACHE_NAME as L, NPM_SCRIPTS_TO_IGNORE as N, PAGE_SIZE as P, RERUN_CACHE_NAME as R, SHORT_CONFIG_CACHE_NAME as S, WEEK_IN_MS as W, getNslPkgJson as a, getNSLDistPath as b, getMainPkgJsonPath as c, execScript as e, getCacheFilePath as g, initEvents as i, rerunCache as r };