From 3ecf6c5a03709f0d0defa193330a800b6e2572ab Mon Sep 17 00:00:00 2001 From: Harminder virk Date: Tue, 28 May 2019 14:53:03 +0530 Subject: [PATCH] feat: add decorators and docs --- README.md | 142 ++++++++++++++++++++++++++++++++++++++-- example/index.ts | 51 +++++---------- index.ts | 14 ++++ src/Decorators/arg.ts | 22 +++++++ src/Decorators/flags.ts | 39 +++++++++++ tsconfig.json | 4 +- 6 files changed, 231 insertions(+), 41 deletions(-) create mode 100644 index.ts create mode 100644 src/Decorators/arg.ts create mode 100644 src/Decorators/flags.ts diff --git a/README.md b/README.md index 3174a31..5a12c59 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,148 @@ +
+ +
+ +# Ace +> Node.js framework for creating command line applications. Used by AdonisJs + +[![circleci-image]][circleci-url] [![npm-image]][npm-url] ![](https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript) + ## Table of contents -- [`ace`](#ace) - - [Usage](#usage) +- [Usage](#usage) +- [Displaying help](#displaying-help) +- [Decorators](#decorators) + - [arg](#arg) + - [flags.boolean](#flagsboolean) + - [flags.string](#flagsstring) + - [flags.array](#flagsarray) -# `ace` +## Usage +Install the package from npm registry as follows: -> TODO: description +```sh +npm i @adonisjs/ace -## Usage +# yarn +yarn add @adonisjs/ace +``` + +And then use it as follows: + +```ts +import { + Kernel, + BaseCommand, + arg, + flags +} from '@adonisjs/ace' + +class Make extends BaseCommand { + @arg() + public resource: string + + @arg() + public name: string + @flags.boolean() + public overwrite: boolean + + public static commandName = 'make' + public static description = 'Make a new resource' + + // called when the command is executed + async handle () { + console.log(this.name) + console.log(this.resource) + console.log(this.overwrite) + } +} + +const kernel = new Kernel() +kernel.register([Make]) + +kernel.handle(process.argv.splice(2)) ``` -const ace = require('ace'); -// TODO: DEMONSTRATE API +## Displaying help + +The module comes with handful of helpers to display help for a single command or all commands. + +We keep the event of displaying help decoupled from the internals of `ace`, giving you more freedom on how and when to display the help. + +```ts +import { + Kernel, + BaseCommand, + printHelpFor, + printHelp +} from '@adonisjs/ace' + +const kernel = new Kernel() +kernel.flag('help', (value, options, command) => { + if (command) { + printHelpFor(command) + } else { + printHelp(kernel.commands) + } + + process.exit(0) +}) + +kernel.handle(process.argv.splice(2)) ``` + +## Decorators +The module comes with ES6 decorators to define arguments and flags for a given command. + +#### arg +Define an argument. To make the argument optional, you can set the `required` property to false + +```ts +arg({ required: false }) +``` + +You can also define the argument description as follows: + +```ts +arg({ description: 'The resource type to create' }) +``` + +#### flags.boolean + +Define a flag that accepts a `boolean` value. + +#### flags.string + +Define a flag that accepts a `string` value. + +#### flags.array + +Define a flag that accepts an array of values. + +You can also define description for a flag, similar to the arg. Also, a flag can define aliases and the default values. + +```ts +class Make extends BaseCommand { + + flags.string({ + alias: 'r', + description: 'The resource name', + default: 'controller', + }) + resource: string +} +``` + + +MIT License, see the included [MIT](LICENSE.md) file. + +[circleci-image]: https://img.shields.io/circleci/project/github/adonisjs/ace/master.svg?style=for-the-badge&logo=circleci +[circleci-url]: https://circleci.com/gh/adonisjs/ace "circleci" + +[npm-image]: https://img.shields.io/npm/v/@adonisjs/ace.svg?style=for-the-badge&logo=npm +[npm-url]: https://npmjs.org/package/@adonisjs/ace "npm" diff --git a/example/index.ts b/example/index.ts index d8e153d..942ecd2 100644 --- a/example/index.ts +++ b/example/index.ts @@ -7,43 +7,30 @@ * file that was distributed with this source code. */ -import { printHelp } from '../src/utils/help' +import { printHelpFor } from '../src/utils/help' import { BaseCommand } from '../src/BaseCommand' import { Kernel } from '../src/Kernel' +import { arg } from '../src/Decorators/arg' +import { flags } from '../src/Decorators/flags' class Greet extends BaseCommand { public static commandName = 'greet' public static description = 'Greet a user with their name' - public static args = [ - { - name: 'name', - description: 'The name of the person you want to greet', - required: true, - }, - { - name: 'age', - required: false, - }, - ] - public static flags = [ - { - name: 'env', - description: 'The environment to use to specialize certain commands', - type: 'boolean', - }, - { - name: 'entrypoint', - description: 'The main HTML file that will be requested', - type: 'string', - }, - { - name: 'fragment', - alias: 'f', - description: 'HTML fragments loaded on demand', - type: 'array', - }, - ] + @arg({ description: 'The name of the person you want to greet' }) + public name: string + + @arg() + public age: number + + @flags.string({ description: 'The environment to use to specialize certain commands' }) + public env: string + + @flags.string({ description: 'The main HTML file that will be requested' }) + public entrypoint: string + + @flags.array({ description: 'HTML fragments loaded on demand', alias: 'f' }) + public fragment: string } class MakeController extends BaseCommand { @@ -67,6 +54,4 @@ kernel.flag('env', (value) => { process.env.NODE_ENV = value }, { type: 'string' }) -printHelp([Greet, MakeController, MakeModel], Object.keys(kernel.flags).map((flag) => { - return kernel.flags[flag] -})) +printHelpFor(Greet) diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..3960b10 --- /dev/null +++ b/index.ts @@ -0,0 +1,14 @@ +/* +* @adonisjs/ace +* +* (c) Harminder Virk +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +export { Kernel } from './src/Kernel' +export { BaseCommand } from './src/BaseCommand' +export { arg } from './src/Decorators/arg' +export { flags } from './src/Decorators/flags' +export { printHelp, printHelpFor } from './src/utils/help' diff --git a/src/Decorators/arg.ts b/src/Decorators/arg.ts new file mode 100644 index 0000000..cfdb150 --- /dev/null +++ b/src/Decorators/arg.ts @@ -0,0 +1,22 @@ +/* +* @adonisjs/ace +* +* (c) Harminder Virk +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +import { CommandArg } from '../Contracts' + +export function arg (options?: Partial) { + options = Object.assign({ required: true }, options) + return function argDecorator (target: any, propertyKey: string) { + target.constructor.args = target.constructor.args || [] + target.constructor.args.push({ + name: options!.name || propertyKey, + description: options!.description, + required: options!.required, + }) + } +} diff --git a/src/Decorators/flags.ts b/src/Decorators/flags.ts new file mode 100644 index 0000000..d2e734a --- /dev/null +++ b/src/Decorators/flags.ts @@ -0,0 +1,39 @@ +/* +* @adonisjs/ace +* +* (c) Harminder Virk +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +import { CommandFlag } from '../Contracts' + +type DecoratorFlag = Partial>> + +function addFlag (target: any, propertyKey: string, options: DecoratorFlag) { + target.constructor.flags = target.constructor.flags || [] + target.constructor.flags.push(Object.assign({ + name: propertyKey, + }, options)) +} + +export const flags = { + string (options?: DecoratorFlag) { + return function flagStringDecorator (target: any, propertyKey: string) { + addFlag(target, propertyKey, Object.assign({ type: 'string' }, options)) + } + }, + + boolean (options?: DecoratorFlag) { + return function flagStringDecorator (target: any, propertyKey: string) { + addFlag(target, propertyKey, Object.assign({ type: 'boolean' }, options)) + } + }, + + array (options?: DecoratorFlag) { + return function flagStringDecorator (target: any, propertyKey: string) { + addFlag(target, propertyKey, Object.assign({ type: 'array' }, options)) + } + }, +} diff --git a/tsconfig.json b/tsconfig.json index f2a7972..24ba5a5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "./node_modules/@adonisjs/mrm-preset/_tsconfig", "compilerOptions": { - "outDir": "./build" + "outDir": "./build", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, }, "include": [ "**/*"