architected

1.0.3 • Public • Published

Architected Codestyle fyi Build Status Build status

A tool for cli utilities.

About

Architected is a small wrapper around inquirer, listr and argi. It seamlessly manages arguments, user input and tasks.

Install

$ npm install --save architected

Usage

const architected = require('architected');
 
const config = {
  // Configuration for architected
  config: {
    name: 'my cli app'
  },
  // The user input you want to receive.
  input: {
    name: {
      message: 'A short description',
      default: 'My default',
      type: 'input'
    }
  },
  // Cli commands
  commands: {
    name: {
      message: 'A short description',
      hidden: false
    }
  }
}
 
architected(config).then((result) => {
  const { run, add } = result;
 
  // Add a task
  add('my first task', (ctx, task) => {
    // Do the things
  });
 
  add('my second task', (ctx, task) => {
    // Do other tings
  });
 
  // Run tasks
  run().catch((err) => {
    console.error(err);
  });
}).catch((err) => {
  console.error(err);
})

API

architected(config)

config

Configuration for architected.

name

Type: string

Required

The name of your project(will be used for --help).

args

Type: array

Default: process.argv.slice(2)

Custom arguments. You should only change this if you have to.

commands

Commands passed as arguments.

Example:

Terminal:

my-app init

Code:

const architected = require('architected');
 
const config = {
  config: {
    name: 'my app'
  },
  commands: {
    init: {
      message: 'Add readme.md file'
    }
  }
}
 
architected(config).then((result) => {
  const { run, add, ctx } = result;
 
  // User called init
  if (ctx.init) {
    add('init stuff', (ctx, task) => {
 
    });
  }
 
  run()
})

input

Input you want to receive.

name

Type: object

What the user input should be called. You need this to get the value of the user input.

  • message
    Type: sting
    A short description. It will be displayed in --help and in the input prompt.

  • default
    Type: every
    Will be used if the user does not specify a value.

  • save
    Type: boolean
    If set to true the user input will be saved and will be suggested next time the user executes your cli utility.

  • boolean
    Type: boolean
    Force input to be either true or false.
    Only for arguments.

  • alias
    Type: string, array
    Alternative name(eg. a short version).
    Only for arguments.

  • hidden
    Type: boolean
    Specify if the input should be displayed in --help.
    Only for arguments.

  • type
    Type: string
    Type of the user input, can be input, confirm, list, rawlist, expand, checkbox, password, editor.
    Only for prompt.
    Learn more

  • choices
    Type: array, function
    Choices for the user can only be used for certain types.
    Only for prompt.
    Learn more

  • validate
    Type: function
    Receives user input as the first argument. Should return true if input is valid or false if input is invalid.
    Only for prompt.

  • filter
    Type: function
    Receives user input as the first argument. Should return the filtered value.
    Only for prompt.

  • when
    Type: function
    Receives the previous user input as the first argument. Should return true if the prompt can be displayed.
    Only for prompt.

  • pageSize
    Type: number
    The number of lines that will be rendered. Can only be used for list, rawList, expand or checkbox.
    Only for prompt.

Returns

Type: promise

Will be called when all the user input is received and parsed.

ctx

Type: object

An object containing the user input.

Example:

...
    console.log(ctx.name);
    // Logs name input to the console.
...

add(name, [options], task)

Add a new task

Example:

...
  add('my-task', (ctx, task) => {
    // ctx = up to date user input
    // `task` can be used to control the task
    if (ctx.input === 'skip') {
      task.skip('reason');
    }
 
    ctx.enableOther = true;
  });
 
  add('my-task-2', { }, (ctx, task) => {
    if (ctx.input === 'skip') {
      task.skip('reason');
    }
  });
...
name

Type: string

The name of your task. Will be used for logging.

options

Type: object

Options for listr. Learn more

task

Type: function

You should do your stuff here.

Learn more

run([ctx])

Execute all tasks.

ctx

Type: object

Custom context. Will be Object.assigned to the user input.

Examples

Basic

A simple package.json generator.

#!/usr/bin/env node
 
const { writeFileSync, mkdirSync } = require('fs');
const { join } = require('path');
 
const architected = require('architected');
 
architected({
  config: {
    name: 'basic-example'
  },
  input: {
    path: {
      message: 'Where your project should be',
      default: process.cwd(),
      forceCli: true
    },
    name: {
      message: 'Whats the name',
      type: 'input',
      forceInput: true
    },
    description: {
      message: 'Whats your project about',
      type: 'input'
    }
  }
}).then((result) => {
  const { run, add } = result;
 
  add('generate package.json', (ctx, task) => {
    ctx.pkg = `{
  "name": "${ ctx.name }",
  "description": "${ ctx.description }",
  "version": "0.0.0",
  "license": "MIT"
}`
  });
 
  add('create project directory', (ctx, task) => {
    ctx.created = true;
 
    try {
      mkdirSync(join(ctx.path, ctx.name));
    } catch (err) {
      ctx.created = false;
      throw new Error(`Could not create project dir\n${ err }`);
    }
  });
 
  add('write package.json', { enabled: (ctx) => ctx.created }, (ctx, task) => {
    try {
      writeFileSync(join(ctx.path, ctx.name, 'package.json'), ctx.pkg);
    } catch (err) {
      throw new Error(`Could not create package.json\n${ err }`);
    }
  });
 
  run().catch((err) => {
    console.error(err);
  })
}).catch((err) => {
  console.error(err);
});

Observable

A simple node.js project boilerplate. Built using observables.

#!/usr/bin/env node
 
const { writeFileSync, mkdirSync } = require('fs');
const { join } = require('path');
 
const Observable = require('zen-observable');
const delay = require('delay'); // For a cool effect
 
const architected = require('architected');
 
architected({
  config: {
    name: 'observable-example'
  },
  input: {
    path: {
      message: 'Where your project should be',
      default: process.cwd(),
      forceCli: true
    },
    name: {
      message: 'Whats the name',
      type: 'input',
      forceInput: true
    },
    description: {
      message: 'Whats your project about',
      type: 'input'
    },
    cli: {
      message: 'Do you need a cli',
      type: 'confirm',
      default: false,
      boolean: true
    }
  }
}).then((result) => {
  const { run, add } = result;
 
  add('generate files', (ctx, task) => (
    new Observable(observer => {
      delay(100)
        .then(() => {
          observer.next('Generating package.json');
 
          ctx.pkg = `{
  "name": "${ ctx.name }",
  "description": "${ ctx.description }",
  "version": "0.0.0",
  "license": "MIT"${ ctx.cli ? ',\n  "bin": "./cli.js"' : '' }
}`;
 
          return delay(300);
        }).then(() => {
          observer.next('Generating index.js');
 
          ctx.i = `module.exports = () => {
  return {
    name: '${ ctx.name }'
  }
};`;
 
          return delay(300);
        }).then(() => {
          if (ctx.cli) {
            observer.next('Generating cli.js');
 
            ctx.clijs = `const ${ ctx.name } = require('./');
 
${ ctx.name }();`;
          }
 
          observer.complete();
        });
    })
  ));
 
  add('create project directory', (ctx, task) => {
    ctx.created = true;
 
    mkdirSync(join(ctx.path, ctx.name));
    try {
    } catch (err) {
      ctx.created = false;
      throw new Error(`Could not create project dir\n${ err }`);
    }
  });
 
  add('write files', { enabled: (ctx) => ctx.created }, (ctx, task) => (
    new Observable(observer => {
      delay(0)
        .then(() => {
          observer.next('Write package.json');
          writeFileSync(join(ctx.path, ctx.name, 'package.json'), ctx.pkg);
 
          return delay(300);
        }).then(() => {
          observer.next('Write index.js');
          writeFileSync(join(ctx.path, ctx.name, 'index.js'), ctx.i);
 
          return delay(300);
        }).then(() => {
          if (ctx.cli) {
            observer.next('Write cli.js');
            writeFileSync(join(ctx.path, ctx.name, 'cli.js'), ctx.clijs);
          }
 
          observer.complete();
        });
    })
  ));
 
  run().catch((err) => {
    console.error(err);
  })
}).catch((err) => {
  console.error(err);
});

License

MIT © Tobias Herber

Package Sidebar

Install

npm i architected

Weekly Downloads

1

Version

1.0.3

License

MIT

Last publish

Collaborators

  • tobihrbr