runok
Version:
NPM scripts on steroids! Replace your scripts with pure JS
548 lines (364 loc) ⢠11.8 kB
Markdown
# š
runok
š„ No BASH-fu is required anymore!
## š” Write your shell scripts in JavaScript!
* * *
<p align="center">
<img
src="https://user-images.githubusercontent.com/220264/95273180-0a1a5780-084b-11eb-95ae-73e5f4af3ebb.png"
align="center"
/>
</p>
* * *
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.
```js
#!/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:
```js
// function definition:
async runMe(arg1, arg1, { print: false, retries: 3 })
```
š
```bash
./runok.js run:me value1 value2 --print --retries 1
```
4. Add a description of a command as the first comment in a function
```js
async runMe() {
// executes very important command
}
```
š
```bash
ā ./runok.js
Usage: <command> [options]
Options:
-V, --version output the version number
-h, --help output usage information
Commands:
run:me executes very important command
```
5. Import required [tasks](#tasks) from `runok` package.
6. 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`:
```js
const {
tasks: {
exec, writeToFile, npm
}
} = require('runok');
```
### Tasks API
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
##### Table of Contents
- [npmRun](#npmrun)
- [Parameters](#parameters)
- [npx](#npx)
- [Parameters](#parameters-1)
- [copy](#copy)
- [Parameters](#parameters-2)
- [git](#git)
- [Commands API](#commands-api)
- [Parameters](#parameters-3)
- [exec](#exec)
- [Parameters](#parameters-4)
- [writeToFile](#writetofile)
- [Config API](#config-api)
- [Parameters](#parameters-5)
- [GitConfig](#gitconfig)
- [tag](#tag)
- [Parameters](#parameters-6)
- [commit](#commit)
- [Parameters](#parameters-7)
- [pull](#pull)
- [Parameters](#parameters-8)
- [init](#init)
- [add](#add)
- [Parameters](#parameters-9)
- [clone](#clone)
- [Parameters](#parameters-10)
- [branch](#branch)
- [Parameters](#parameters-11)
- [checkout](#checkout)
- [Parameters](#parameters-12)
#### npmRun
Executes npm script
```js
await npmRun('deploy');
```
##### Parameters
- `command`
- `config` **ExecConfig**
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<Result>**
#### npx
Executes npx script
```js
await npx('create-codeceptjs .');
```
##### Parameters
- `command`
- `config` **ExecConfig**
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<Result>**
#### copy
Copies file or directory. copySync from 'fs-extra' is used.
```js
copy('src/', 'dst/');
```
##### Parameters
- `from` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `to` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `options` **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
#### git
Provides flexible interface to running multiple git commands:
```js
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](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<Result>**
#### exec
Executes shell command and returns a promise.
```js
await exec('ls -ll');
```
A second parameter can be used to pass in [ExecOptions](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) from "child_process" module:
```js
await exec('rails s', { env: { RAILS_ENV: 'production' } })
```
To hide output pass in `output: false`:
```js
await exec('docker build', { output: false });
```
##### Parameters
- `command` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `config` **execConfigType?**
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<Result>**
#### writeToFile
Writes a data to file.
Takes file name as first argument and config function as second.
```js
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](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/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
```js
await npmRun('deploy');
```
#### Parameters
- `command`
- `config` **ExecConfig**
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<Result>**
### npx
Executes npx script
```js
await npx('create-codeceptjs .');
```
#### Parameters
- `command`
- `config` **ExecConfig**
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<Result>**
### copy
Copies file or directory. copySync from 'fs-extra' is used.
```js
copy('src/', 'dst/');
```
#### Parameters
- `from` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `to` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `options` **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
### writeToFile
Writes a data to file.
Takes file name as first argument and config function as second.
```js
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](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/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](https://github.com/runok-js/runok/blob/master/src/result.ts) instance (or Promise<Result>)
- `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
```js
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](https://github.com/runok-js/runok/blob/master/src/tasks/npx.ts) command as an example.
Similar way you can create a task for running Docker scripts:
```ts
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
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### chdir
Changes directory for commands executed in callback function.
```js
// copy file in "base" directory
chdir('./base', () => copy('a.txt', 'b.txt')));
```
#### Parameters
- `workDir` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `callback` **CallableFunction**
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<any>**
### stopOnFail
Prevents execution of next tasks on fail:
```js
stopOnFail();
```
Ignore failures and continue:
```js
stopOnFail(false);
```
#### Parameters
- `stop` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
## Credits
Created by Michael Bodnarchuk @davertmik.
Inspired by [Robo PHP Task Runner](https://robo.li)
## LICENSE MIT