runok
v0.9.3
Published
NPM scripts on steroids! Replace your scripts with pure JS
Downloads
2,266
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.
Add async function to
module.exports
Name a function, function name will be transformed for CLI format:
myFunctionName => my:function-name
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
- 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
- Import required tasks from
runok
package. - 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
stringconfig
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 filecfg.textFromFile(file)
- loads a file and append its context to textcfg.line(text)
- appends a string to a text with "\n" aftercfg.append(text)
- appends a string to a text
Parameters
file
stringconfigFn
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 filecfg.textFromFile(file)
- loads a file and append its context to textcfg.line(text)
- appends a string to a text with "\n" aftercfg.append(text)
- appends a string to a text
Parameters
file
stringconfigFn
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 objectresult.success
must be called on finishresult.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
stringcallback
CallableFunction
Returns Promise<any>
stopOnFail
Prevents execution of next tasks on fail:
stopOnFail();
Ignore failures and continue:
stopOnFail(false);
Parameters
stop
boolean (optional, defaulttrue
)
Credits
Created by Michael Bodnarchuk @davertmik.
Inspired by Robo PHP Task Runner