Skip to content

Commit

Permalink
refactor(kernel): ensure optional args comes at the end
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Apr 12, 2019
1 parent 35571b8 commit 83877b5
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
16 changes: 15 additions & 1 deletion packages/ace/src/Kernel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* file that was distributed with this source code.
*/

import { CommandConstructorContract, CommandFlag, GlobalFlagHandler } from '../Contracts'
import { CommandConstructorContract, CommandFlag, GlobalFlagHandler, CommandArg } from '../Contracts'
import { Parser } from '../Parser'

/**
Expand All @@ -18,11 +18,25 @@ export class Kernel {
public commands: { [name: string]: CommandConstructorContract } = {}
public flags: { [name: string]: CommandFlag & { handler: GlobalFlagHandler } } = {}

private _validateArgs (command: CommandConstructorContract) {
let optionalArg: CommandArg
command.args.forEach((arg) => {
if (optionalArg && arg.required) {
throw new Error(`Required argument {${arg.name}} cannot come after optional argument {${optionalArg.name}}`)
}

if (!arg.required) {
optionalArg = arg
}
})
}

/**
* Register an array of commands
*/
public register (commands: CommandConstructorContract[]): this {
commands.forEach((command) => {
this._validateArgs(command)
this.commands[command.commandName] = command
})

Expand Down
31 changes: 30 additions & 1 deletion packages/ace/test/kernel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,34 @@ import * as test from 'japa'
import { Kernel } from '../src/Kernel'
import { BaseCommand } from '../src/BaseCommand'

test.group('Kernel', () => {
test.group('Kernel | register', () => {
test('raise error when required argument comes after optional argument', (assert) => {
class Greet extends BaseCommand {
public static commandName = 'greet'
public static args = [
{
name: 'name',
required: false,
},
{
name: 'age',
required: true,
},
]
}

const kernel = new Kernel()
const fn = () => kernel.register([Greet])
assert.throw(fn, 'Required argument {age} cannot come after optional argument {name}')
})

test('return null when unable to find command', (assert) => {
const kernel = new Kernel()
assert.isNull(kernel.find(['greet']))
})
})

test.group('Kernel | find', () => {
test('find relevant command from the commands list', (assert) => {
class Greet extends BaseCommand {
public static commandName = 'greet'
Expand All @@ -27,7 +54,9 @@ test.group('Kernel', () => {
const kernel = new Kernel()
assert.isNull(kernel.find(['greet']))
})
})

test.group('Kernel | handle', () => {
test('raise exception when required argument is missing', async (assert) => {
assert.plan(1)

Expand Down

0 comments on commit 83877b5

Please sign in to comment.