Spinr

Minimalist task runner for Node that leverage the power of ES6 and ES7
#NoPlugin #NoAbstraction

Build Coverage Known Vulnerabilities


Installation

$ yarn add spinr

Features

Usage

  1. Create a spinfile.js at the root of your project.
  2. Export some functions from it, e.g. export function build() { ... }
  3. Launch them using the CLI, e.g. $ spin build

Example spinfile.js:

import del from 'del';
import { rollup } from 'rollup';

import config from './config';
import deployer from './tasks/deploy';

// $ spin clean
export async function clean() {
  await del(['build']);
}

// $ spin build
export async function build() {
  await Promise.all(config.bundles.map(bundle => {
    return rollup(bundle.options).then(output => {
      return output.write(options);
    });
  });
}

// $ spin deploy
export async function deploy({ from = 'master', to = 'origin/gh-pages' }) {
  await deployer.deploy(from, to);
}

// (default) $ spin
export async default build;

Launch clean then build:

$ spin clean build

Launch clean then build in parallel of lint:

$ spin --parallel clean+build lint

Learn more

Command Line Interface

Spinr uses the powerful liftoff command launcher together with yargs arguments parser. The Command Line Interface (CLI) of Spinr is named spin. An overview of the spin CLI options can be obtain by running:

$ spin --help

Task Definition

Spinr supports different task definition including: async/await, promise, stream and callback. Tasks are defined as simple function in a spinfile.js file. To be accessbile from Spinr, tasks must be exported. The signature of a task is the following:

export function [name]([options[, callback]]) {
   statements
}

All tasks receive CLI options as argument.

Custom Options

Lets for instance have a basic spinfile.js with the following task:

export function say(options) {
  console.log(options.message);
}

You can launch say with the custom message option by doing:

$ spin say --message "Hello World!"

Task with Async

Spinr supports Async/Await. The signature of such task is:

export async function [name]([options]) {
  await statements
}

Example:

function timeout(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// $ spin wait
export async function wait({ time = 1000 }) {
  console.log(`waiting ${time}ms`);
  await timeout(time);
}

Task with Promise

Spinr supports Promise. The signature of such task is:

export function [name]([options]) {
  return new Promise((resolve, reject) => {
    statements
  });
}

Example:

import fs from 'fs';
import postcss from 'postcss';
import cssnano from 'cssnano';
import prefixer from 'autoprefixer';

export function css() {
  const src = 'lib/app.css';
  const dst = 'dist/app.css';
  const css = fs.readFileSync(src).toString('utf8');
  return postcss([prefixer, cssnano])
    .process(css, { from: src, to: dst, map: true })
    .then((result) => {
      fs.writeFileSync(dst, result.css);
      if (result.map) fs.writeFileSync(`${dst}.map`, result.map);
    });
}

Task with Stream

Spinr supports Stream. The signature of such task is:

export function [name]([options]) {
  statements
  return stream;
}

For example, you can easily integrate Gulp to spinr:

import gulp from 'gulp';

export function build({ src = 'lib', dest = 'dist' }) {
  return gulp.src(src).pipe(gulp.dest(dest));
}

Task with Callback

Spinr supports Callback. The signature of such task is:

export function [name]([options[, callback]]) {
  statements
}

For example:

import path from 'path';
import ghpages from 'gh-pages';

export function publish({ silent, branch = 'origin' }, callback) {
  ghpages.publish(path.join(__dirname, 'dist'), {
    silent: options.slient,
    branch: options.branch,
    repo: 'https://github.com/space/repo.git',
  }, callback);
}

Babel

Spinr uses Babel with a setup adapted for Node 6. It is possible nevertheless to run Spinr without Babel or with a custom configuration.

Run without Babel

To disable Babel simply use babel option:

$ spin --babel false [options] <tasks ...>

You would then define a spinfile.js compatible with your Node features. For example a spinfile.js using require and module.exports:

const del = require('del');
const gulp = require('gulp');

function clean() {
  return del('dist')
}

function build() {
  return gulp.src('src').pipe(gulp.dest('dist'));
}

module.exports = {
  default: () => clean().then(() => build()),
  clean,
  build,
}

Custom Babel configuration

Depending on the Node version you use, or the functionalities you want to access; you can specify your own babelrc configuration:

$ spin --babelrc ./path/to/babelrc [options] <tasks ...>

Spinr supports Node 6 out of the box. The default Babel configuration is the following:

"babel": {
  "presets": [
    "node6"
  ],
  "plugins": [
    "transform-async-to-generator",
    "transform-object-rest-spread"
  ]
},

Tasks Orchestration

Spinr supports sequential, parallel and hybrid orchestration.

Sequential Orchestration

Sequential orchestration guarantees that tasks are executed one after the other. For example, to execute clean then build then test simply do:

$ spin clean build test

Parallel Orchestration

Parallel orchestration allows for tasks to be executed in parallel between each other’s. For example, to launch build in parallel of test simply do:

$ spin --parallel build test

Hybrid Orchestration

Spinr supports orchestrating groups of tasks. Each group will run in parallel with each other’s. A group can be composed of one or many tasks. To group tasks simply use the + sign, e.g. taskA+taskB+taskC.

For example, to exectute clean and build in parallel of test simple do:

$ spin --parallel clean+build test

Lets spin a yarn!