├── .gitignore ├── assets ├── demo.gif └── logo.png ├── bin ├── welcome.js ├── file-manager.js ├── detect-pkg-manager.js ├── prompts.js ├── main.js └── index.js ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Node 2 | node_modules/ 3 | 4 | # MacOS 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /assets/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danieldelcore/scriptpal/HEAD/assets/demo.gif -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danieldelcore/scriptpal/HEAD/assets/logo.png -------------------------------------------------------------------------------- /bin/welcome.js: -------------------------------------------------------------------------------- 1 | const gradient = require("gradient-string"); 2 | 3 | function welcome() { 4 | const logo = gradient.pastel("ScriptPal 🤘\n"); 5 | 6 | console.log(logo); 7 | } 8 | 9 | module.exports = welcome; 10 | -------------------------------------------------------------------------------- /bin/file-manager.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | const chalk = require("chalk"); 5 | const findConfig = require("find-config"); 6 | 7 | function getPackageJson(path = "package.json") { 8 | if (!hasFile(path)) { 9 | throw new Error(`${chalk.bgRed(path)} ${chalk.red("not found")}\n`); 10 | } 11 | 12 | const configRaw = findConfig.read(path); 13 | 14 | return JSON.parse(configRaw); 15 | } 16 | 17 | function hasFile(path) { 18 | try { 19 | return findConfig(path); 20 | } catch (error) { 21 | return false; 22 | } 23 | } 24 | 25 | module.exports = { 26 | getPackageJson, 27 | hasFile, 28 | }; 29 | -------------------------------------------------------------------------------- /bin/detect-pkg-manager.js: -------------------------------------------------------------------------------- 1 | const { hasFile } = require("./file-manager"); 2 | 3 | function getPackageManager() { 4 | const packageManagers = [ 5 | { id: "yarn", file: hasFile("yarn.lock") }, 6 | { id: "bun", file: hasFile("bun.lockb") }, 7 | { id: "pnpm", file: hasFile("pnpm-lock.yaml") }, 8 | { id: "npm", file: hasFile("package-lock.json") }, 9 | ]; 10 | 11 | let largest = packageManagers[0]; 12 | 13 | for (let i = 0; i < packageManagers.length; i++) { 14 | if ( 15 | packageManagers[i].file && 16 | packageManagers[i].file.split("/").length > largest 17 | ) { 18 | largest = i; 19 | } 20 | } 21 | 22 | return (largest && largest.id) || "npm"; 23 | } 24 | 25 | module.exports = { getPackageManager }; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scriptpal", 3 | "version": "1.4.3", 4 | "description": "A simple npm script palette for lazy people (like me)", 5 | "main": "./bin/index.js", 6 | "bin": { 7 | "scriptpal": "./bin/index.js", 8 | "spal": "./bin/index.js" 9 | }, 10 | "scripts": { 11 | "start": "node ./bin/index", 12 | "test": "echo \"Error: no test specified\"" 13 | }, 14 | "author": "Daniel Del Core", 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/danieldelcore/scriptpal.git" 18 | }, 19 | "license": "MIT", 20 | "keywords": [ 21 | "list", 22 | "ls", 23 | "npm-ls", 24 | "palette", 25 | "command", 26 | "picker", 27 | "search", 28 | "script" 29 | ], 30 | "dependencies": { 31 | "chalk": "^3.0.0", 32 | "clipboardy": "^2.1.0", 33 | "commander": "^8.2.0", 34 | "conf": "^6.2.1", 35 | "enquirer": "^2.3.2", 36 | "find-config": "^1.0.0", 37 | "gradient-string": "^1.2.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /bin/prompts.js: -------------------------------------------------------------------------------- 1 | const chalk = require("chalk"); 2 | const { AutoComplete, Snippet, Confirm } = require("enquirer"); 3 | 4 | const promptShouldRerunPrevious = async (previous) => { 5 | const previousCommand = `${previous.script} ${ 6 | previous.parameters || "" 7 | }`.trim(); 8 | 9 | return await new Confirm({ 10 | message: `Would you like to rerun the previous command?\n${chalk.greenBright( 11 | previousCommand 12 | )}`, 13 | }).run(); 14 | }; 15 | 16 | const promptGetCommand = async (choices) => { 17 | const script = await new AutoComplete({ 18 | message: "Which script would you like to run? 🤷♂️", 19 | limit: 18, 20 | choices, 21 | }).run(); 22 | 23 | const { 24 | values: { parameters }, 25 | } = await new Snippet({ 26 | message: "Would you like to add parameters?", 27 | required: false, 28 | fields: [ 29 | { 30 | name: "parameters", 31 | message: "parameters", 32 | }, 33 | ], 34 | template: `${script} \${parameters}`, 35 | }).run(); 36 | 37 | return { 38 | script, 39 | parameters, 40 | }; 41 | }; 42 | 43 | module.exports = { 44 | promptShouldRerunPrevious, 45 | promptGetCommand, 46 | }; 47 | -------------------------------------------------------------------------------- /bin/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const clipboardy = require("clipboardy"); 3 | const Conf = require("conf"); 4 | const welcome = require("./welcome"); 5 | const { promptShouldRerunPrevious, promptGetCommand } = require("./prompts"); 6 | const { getPackageManager } = require("./detect-pkg-manager"); 7 | const { packageJson } = require("."); 8 | 9 | async function main(flags) { 10 | if (!flags.nowelcome) welcome(); 11 | 12 | const choices = Object.keys(packageJson.scripts); 13 | 14 | const config = new Conf(); 15 | const previous = config.get(`${process.cwd()}.previous`); 16 | 17 | let shouldRerunPrevious = false; 18 | 19 | if (!previous && flags.last) { 20 | console.log("Previous command not found, continuing...\n"); 21 | } else if (previous && !flags.last) { 22 | shouldRerunPrevious = await promptShouldRerunPrevious(previous); 23 | } else { 24 | shouldRerunPrevious = true; 25 | } 26 | 27 | const { script, parameters } = 28 | (previous || flags.last) && shouldRerunPrevious 29 | ? previous 30 | : await promptGetCommand(choices); 31 | 32 | const pkgManager = getPackageManager(); 33 | let args = !pkgManager === "npm" ? ["run", script] : [script]; 34 | args = parameters ? [...args, parameters] : args; 35 | 36 | if (flags.clipboard) { 37 | await clipboardy.write(`${pkgManager} ${args.join(" ")}`); 38 | console.log("Copied to clipboard 👉 📋"); 39 | return 0; 40 | } 41 | 42 | // spawnScript(pkgManager, args); 43 | config.set(`${process.cwd()}.previous`, { script, parameters }); 44 | } 45 | exports.main = main; 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
14 |
15 |