npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

runok

v0.9.3

Published

NPM scripts on steroids! Replace your scripts with pure JS

Downloads

2,549

Readme

🌅 runok

🥋 No BASH-fu is required anymore!

💡 Write your shell scripts in JavaScript!



Everyone ❤️ npm scripts. However, when you need to use conditionals, loops, regexp and parsers in yout scripts, you end up writing JavaScript.

runok gives you a tool to transform your JavaScript scripts into CLI commands.

Each exported function will be a command which can be executed from CLI. You can use full power of JavaScript & bundled tasks like:

  • exec
  • git
  • npmRun
  • npx
  • ...and others

🎁 Showcase

Write a CommonJS module that exports commands per function.

  • Each argument of function will be an argument of a command
  • If you provide options argument, with default value of an object, this will declate options.
#!/usr/bin/env node
const {
  tasks: { git, exec, npx },
  runok
} = require('runok');

module.exports = {

  async deploy(env = 'prod') {
    await this.test();
    await git(cmd => {
      cmd.add('-A');
      cmd.commit('releasing');
      cmd.pull();
      cmd.push();      
    });
    await exec(`ansible-playbook deploy.yml -i hosts ${env}`);
  }

  async test() {
    await npx('mocha');
  },
}

if (require.main === module) runok(module.exports);
  • Run ./runok to list all available commands
  • Run ./runok deploy to run a deploy script
  • Run ./runok deploy staging to run a deploy script to staging

🚀 Installation

npm i runok --save

Create a new runok scripts file:

npx runok init

Each exported function of this file will be command.

⌨ Usage

When file is created execute runok script to see all available commands:

./runok.js

Edit runok.js file.

  1. Add async function to module.exports

  2. Name a function, function name will be transformed for CLI format:

    myFunctionName => my:function-name

  3. Define function parameters:

  • function arguments will be used as command arguments
  • the last argument with object type will is set of options:
// function definition:
async runMe(arg1, arg1, { print: false, retries: 3 })

👇

./runok.js run:me value1 value2 --print --retries 1
  1. Add a description of a command as the first comment in a function
async runMe() {
  // executes very important command
}

👇

➜ ./runok.js     
Usage:  <command> [options]

Options:
  -V, --version                    output the version number
  -h, --help                       output usage information

Commands:
  run:me                            executes very important command
  1. Import required tasks from runok package.
  2. Implement your script!

Export to NPM Scripts

Export your runok scripts into your current package.json:

./runok export:npm

🧰 Tasks

Runok has a set of built-in tasks.

They can be imported in runio script via tasks property of runok:

const {
  tasks: {
    exec, writeToFile, npm
  }
} = require('runok');

Tasks API

Table of Contents

npmRun

Executes npm script

await npmRun('deploy');
Parameters
  • command
  • config ExecConfig

Returns Promise<Result>

npx

Executes npx script

await npx('create-codeceptjs .');
Parameters
  • command
  • config ExecConfig

Returns Promise<Result>

copy

Copies file or directory. copySync from 'fs-extra' is used.

copy('src/', 'dst/');
Parameters

git

Provides flexible interface to running multiple git commands:

await git(cmd => {
   cmd.pull();
   cmd.commit('-m updated');
   cmd.push();
})
Commands API
  • cmd.init
  • cmd.tag
  • cmd.branch
  • cmd.commit
  • cmd.pull
  • cmd.push
  • cmd.add
  • cmd.clone
  • cmd.cloneShallow
Parameters
  • configFn gitConfigType

Returns Promise<Result>

exec

Executes shell command and returns a promise.

await exec('ls -ll');

A second parameter can be used to pass in ExecOptions from "child_process" module:

await exec('rails s', { env: { RAILS_ENV: 'production' } })

To hide output pass in output: false:

await exec('docker build', { output: false });
Parameters
  • command string
  • config execConfigType?

Returns Promise<Result>

writeToFile

Writes a data to file.

Takes file name as first argument and config function as second.

writeToFile('blog-post.md', cfg => {
   cfg.line('---');
   cfg.line('title: My blogpost');
   cfg.line('---');
   cfg.line();
   cfg.textFromFile('blog-post.txt');
   cfg.text += '// copyright by me';
});

A second argument is a config function that passes in an object for text manipulation.

Config API
  • cfg.text - string to be written to file
  • cfg.textFromFile(file) - loads a file and append its context to text
  • cfg.line(text) - appends a string to a text with "\n" after
  • cfg.append(text) - appends a string to a text
Parameters
  • file string
  • configFn writeToFileCallback

Returns Result

GitConfig

Extends TaskConfig

Git Config Class

tag
Parameters
  • tag
commit

Commit params

Parameters
  • message (optional, default '')
pull
Parameters
  • branch (optional, default '')
init

Initialize git repository

add
Parameters
  • params (optional, default '')
clone
Parameters
  • url
  • path
branch
Parameters
  • command
checkout
Parameters
  • params

npmRun

Executes npm script

await npmRun('deploy');

Parameters

  • command
  • config ExecConfig

Returns Promise<Result>

npx

Executes npx script

await npx('create-codeceptjs .');

Parameters

  • command
  • config ExecConfig

Returns Promise<Result>

copy

Copies file or directory. copySync from 'fs-extra' is used.

copy('src/', 'dst/');

Parameters

writeToFile

Writes a data to file.

Takes file name as first argument and config function as second.

writeToFile('blog-post.md', cfg => {
   cfg.line('---');
   cfg.line('title: My blogpost');
   cfg.line('---');
   cfg.line();
   cfg.textFromFile('blog-post.txt');
   cfg.text += '// copyright by me';
});

A second argument is a config function that passes in an object for text manipulation.

Config API

  • cfg.text - string to be written to file
  • cfg.textFromFile(file) - loads a file and append its context to text
  • cfg.line(text) - appends a string to a text with "\n" after
  • cfg.append(text) - appends a string to a text

Parameters

  • file string
  • configFn writeToFileCallback

Returns Result

Adding Custom Tasks

Tasks in runok use similar API and must follow conventions to match the output:

  • task must be a function
  • task must return Result instance (or Promise)
  • Result.start must be called in the beginning of a function, to create result object
  • result.success must be called on finish
  • result.error(err) must be called on failure
const { Result } = require('runok');

module.exports = myTask(arg1, options) {
  const result = Result.start("Task Name", `argument: ${arg1}`);

  try {
    // do something
  } catch (err) {
    return result.error(err);
  }
  return result.success();  
}

Extending Custom Tasks

If you want to extend current task, for instamce add custom wrapper to exec command you can check npx command as an example.

Similar way you can create a task for running Docker scripts:

const { tasks: { exec } } = require('runok');

module.exports = (command, config) => {

  return exec(command, baseCfg => {
    baseCfg.TASK = 'docker'; // name of task
    baseCfg.prefix('docker'); // prefix to an executed command
    baseCfg.apply(config);
  });
}

Helpers

chdir

Changes directory for commands executed in callback function.

// copy file in "base" directory
chdir('./base', () => copy('a.txt', 'b.txt')));

Parameters

  • workDir string
  • callback CallableFunction

Returns Promise<any>

stopOnFail

Prevents execution of next tasks on fail:

stopOnFail();

Ignore failures and continue:

stopOnFail(false);

Parameters

  • stop boolean (optional, default true)

Credits

Created by Michael Bodnarchuk @davertmik.

Inspired by Robo PHP Task Runner

LICENSE MIT