Skip to content

Commit

Permalink
feat(option): add isFromGlobal option
Browse files Browse the repository at this point in the history
  • Loading branch information
jlenon7 committed Jan 5, 2024
1 parent e097277 commit 54079fc
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 22 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@athenna/artisan",
"version": "4.22.0",
"version": "4.23.0",
"description": "The Athenna CLI application. Built on top of commander and inspired in @adonisjs/ace.",
"license": "MIT",
"author": "João Lenon <lenon@athenna.io>",
Expand Down
2 changes: 1 addition & 1 deletion src/annotations/Option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function Option(options?: OptionOptions): PropertyDecorator {
key = key.toString()

options = Options.create(options, {
isGlobal: false,
isFromGlobal: false,
signature: `--${String.toDashCase(key)}`
})

Expand Down
2 changes: 1 addition & 1 deletion src/artisan/ArtisanImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class ArtisanImpl {

/** Set options */
Annotation.getOptions(command).forEach(option => {
if (option.isGlobal) {
if (option.isFromGlobal) {
return
}

Expand Down
1 change: 0 additions & 1 deletion src/artisan/BaseCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ export abstract class BaseCommand {
argsMeta.forEach(arg => (this[arg.key] = args.shift()))
optsMeta.forEach(opt => (this[opt.key] = optsValues[opt.signatureName]))

// TODO test if handle will receive the args properly
return this.handle(...args)
}

Expand Down
32 changes: 22 additions & 10 deletions src/handlers/CommanderHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ export class CommanderHandler {
/**
* The commander instance.
*/
public static commander = new Commander()
public static commander = this.instantiate()

/**
* Simple helper to reconstruct the commander instance.
* Get a new commander instance with default options.
*/
public static reconstruct(): void {
CommanderHandler.commander = new Commander()
public static instantiate() {
return new Commander()
.addHelpCommand('help [command]', 'Display help for [command]')
.usage('[command] [arguments] [options]')
.option(
'--env',
'--env <env>',
'The environment the command should run under.',
Env('APP_ENV')
Env('APP_ENV') || Env('NODE_ENV', 'local')
)
.configureHelp({
sortSubcommands: true,
Expand All @@ -49,6 +49,13 @@ export class CommanderHandler {
})
}

/**
* Simple helper to reconstruct the commander instance.
*/
public static reconstruct(): void {
CommanderHandler.commander = this.instantiate()
}

/**
* Parse the command called in the console and execute.
*/
Expand Down Expand Up @@ -81,14 +88,19 @@ export class CommanderHandler {
}

if (version) {
CommanderHandler.commander.version(version, '-v, --version')
CommanderHandler.commander.version(
version,
'-v, --version',
'Output the application version.'
)

return this
}

CommanderHandler.commander.version(
'Athenna Framework v3.0.0',
'-v, --version'
'-v, --version',
'Output the framework version.'
)

return this
Expand Down Expand Up @@ -116,9 +128,9 @@ export class CommanderHandler {
* Get the option values of a command.
*/
public static getCommandOptsValues(name: string): OptionValues {
const commander: any = this.getCommand(name)
const commander = this.getCommand(name)

return commander.opts()
return commander.optsWithGlobals()
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/types/OptionOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
export type OptionOptions = {
signature?: string
default?: any
isGlobal?: boolean
isFromGlobal?: boolean
description?: string
}
26 changes: 26 additions & 0 deletions tests/fixtures/GlobalAnnotatedCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @athenna/artisan
*
* (c) João Lenon <lenon@athenna.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

import { Option, BaseCommand } from '#src'
import { FixtureDatabase } from './FixtureDatabase.js'

export class GlobalAnnotatedCommand extends BaseCommand {
@Option({ isFromGlobal: true, signature: '--env <env>' })
public env: string

public static signature() {
return 'globalAnnotated'
}

public async handle() {
FixtureDatabase.set('globalAnnotated:command', this.env)
}
}

export const globalAnnotatedCommand = new GlobalAnnotatedCommand()
13 changes: 9 additions & 4 deletions tests/unit/annotations/OptionTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,30 @@ export default class OptionTest extends BaseTest {

const opts = Reflect.getMetadata(OPTIONS_KEY, annotatedCommand)

assert.deepEqual(opts[0], { key: 'withName', isGlobal: false, signature: '--with-name', signatureName: 'withName' })
assert.deepEqual(opts[0], {
key: 'withName',
isFromGlobal: false,
signature: '--with-name',
signatureName: 'withName'
})
assert.deepEqual(opts[1], {
key: 'withAge',
isGlobal: false,
isFromGlobal: false,
signature: '--with-age',
signatureName: 'withAge',
description: 'Add the age of the person'
})
assert.deepEqual(opts[2], {
default: true,
isGlobal: false,
isFromGlobal: false,
key: 'withEmail',
signatureName: 'addEmail',
signature: '-am, --add-email',
description: 'Add the email of the person'
})
assert.deepEqual(opts[3], {
key: 'withFoo',
isGlobal: false,
isFromGlobal: false,
default: false,
signature: '--no-foo',
signatureName: 'foo'
Expand Down
14 changes: 14 additions & 0 deletions tests/unit/artisan/ArtisanTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,18 @@ export default class ArtisanTest extends BaseTest {

assert.isTrue(FixtureDatabase.has('simple:command'))
}

@Test()
public async shouldBeAbleToRegisterAnArtisanCommandWithGlobalOptions({ assert }: Context) {
const { GlobalAnnotatedCommand } = await this.import('#tests/fixtures/GlobalAnnotatedCommand')

Artisan.register(GlobalAnnotatedCommand)

const opts = CommanderHandler.getCommandOpts(GlobalAnnotatedCommand.signature())

await Artisan.parse(['node', 'artisan', 'globalAnnotated'])

assert.isEmpty(opts)
assert.deepEqual(FixtureDatabase.get('globalAnnotated:command'), 'local')
}
}
2 changes: 1 addition & 1 deletion tests/unit/handlers/CommanderHandlerTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export default class CommanderHandlerTest {
.action(() => {
const opts = CommanderHandler.getCommandOptsValues('test')

assert.deepEqual(opts, { age: true })
assert.deepEqual(opts, { age: true, env: 'local' })
})

await CommanderHandler.parse(['node', 'artisan', 'test', 'João Lenon', '--age'])
Expand Down

0 comments on commit 54079fc

Please sign in to comment.