diff --git a/index.js b/index.js index 7563b1bac..b865789be 100644 --- a/index.js +++ b/index.js @@ -10,18 +10,30 @@ const { Option } = require('./lib/option.js'); * Expose the root command. */ -exports = module.exports = new Command(); -exports.program = exports; // More explicit access to global command. -// Implicit export of createArgument, createCommand, and createOption. +const program = new Command(); +exports = module.exports = program; // default export (deprecated) +exports.program = program; // more explicit access to global command /** * Expose classes */ -exports.Argument = Argument; exports.Command = Command; -exports.CommanderError = CommanderError; +exports.Option = Option; +exports.Argument = Argument; exports.Help = Help; + +exports.CommanderError = CommanderError; exports.InvalidArgumentError = InvalidArgumentError; exports.InvalidOptionArgumentError = InvalidArgumentError; // Deprecated -exports.Option = Option; + +/** + * Expose object factory functions. + * + * These are present implicitly, but need to be explicit + * to work with TypeScript whole module import (import * as foo) when esModuleInterop: true. + */ + +exports.createCommand = program.createCommand; +exports.createArgument = program.createArgument; +exports.createOption = program.createOption; diff --git a/tests/ts-imports.test.ts b/tests/ts-imports.test.ts index 5f6704e2d..95611b1b6 100644 --- a/tests/ts-imports.test.ts +++ b/tests/ts-imports.test.ts @@ -1,6 +1,18 @@ -import { program, Command, Option, CommanderError, InvalidArgumentError, InvalidOptionArgumentError, Help, createCommand } from '../'; +import { + program, + Command, + Option, + Argument, + Help, + CommanderError, + InvalidArgumentError, + InvalidOptionArgumentError, + createCommand, + createOption, + createArgument +} from '../'; -import * as commander from '../'; +import * as commander from '../'; // This does interesting things when esModuleInterop is true! // Do some simple checks that expected imports are available at runtime. // Similar tests to esm-imports-test.js @@ -11,38 +23,94 @@ function checkClass(obj: object, name: string): void { expect(obj.constructor.name).toEqual(name); } -test('legacy default export of global Command', () => { - checkClass(commander, 'Command'); -}); +describe('named imports', () => { + test('program', () => { + checkClass(program, 'Command'); + }); -test('program', () => { - checkClass(program, 'Command'); -}); + test('Command', () => { + checkClass(new Command('name'), 'Command'); + }); -test('createCommand', () => { - checkClass(createCommand(), 'Command'); -}); + test('Option', () => { + checkClass(new Option('-e, --example', 'description'), 'Option'); + }); -test('Command', () => { - checkClass(new Command('name'), 'Command'); -}); + test('Argument', () => { + checkClass(new Argument('', 'description'), 'Argument'); + }); -test('Option', () => { - checkClass(new Option('-e, --example', 'description'), 'Option'); -}); + test('Help', () => { + checkClass(new Help(), 'Help'); + }); -test('CommanderError', () => { - checkClass(new CommanderError(1, 'code', 'failed'), 'CommanderError'); -}); + test('CommanderError', () => { + checkClass(new CommanderError(1, 'code', 'failed'), 'CommanderError'); + }); -test('InvalidArgumentError', () => { - checkClass(new InvalidArgumentError('failed'), 'InvalidArgumentError'); -}); + test('InvalidArgumentError', () => { + checkClass(new InvalidArgumentError('failed'), 'InvalidArgumentError'); + }); + + test('InvalidOptionArgumentError', () => { // Deprecated + checkClass(new InvalidOptionArgumentError('failed'), 'InvalidArgumentError'); + }); + + test('createCommand', () => { + checkClass(createCommand('foo'), 'Command'); + }); + + test('createOption', () => { + checkClass(createOption('-e, --example', 'description'), 'Option'); + }); -test('InvalidOptionArgumentError', () => { // Deprecated - checkClass(new InvalidOptionArgumentError('failed'), 'InvalidArgumentError'); + test('createArgument', () => { + checkClass(createArgument('', 'description'), 'Argument'); + }); }); -test('Help', () => { - checkClass(new Help(), 'Help'); +describe('import * as commander', () => { + test('program', () => { + checkClass(commander.program, 'Command'); + }); + + test('Command', () => { + checkClass(new commander.Command('name'), 'Command'); + }); + + test('Option', () => { + checkClass(new commander.Option('-e, --example', 'description'), 'Option'); + }); + + test('Argument', () => { + checkClass(new commander.Argument('', 'description'), 'Argument'); + }); + + test('Help', () => { + checkClass(new commander.Help(), 'Help'); + }); + + test('CommanderError', () => { + checkClass(new commander.CommanderError(1, 'code', 'failed'), 'CommanderError'); + }); + + test('InvalidArgumentError', () => { + checkClass(new commander.InvalidArgumentError('failed'), 'InvalidArgumentError'); + }); + + test('InvalidOptionArgumentError', () => { // Deprecated + checkClass(new commander.InvalidOptionArgumentError('failed'), 'InvalidArgumentError'); + }); + + test('createCommand', () => { + checkClass(commander.createCommand('foo'), 'Command'); + }); + + test('createOption', () => { + checkClass(commander.createOption('-e, --example', 'description'), 'Option'); + }); + + test('createArgument', () => { + checkClass(commander.createArgument('', 'description'), 'Argument'); + }); }); diff --git a/tsconfig.json b/tsconfig.json index d2688174b..0fde675b6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,6 +11,7 @@ "node", "jest" ], + "esModuleInterop": true, // Mainly so can test an import problem which only occurs with this option on! "noEmit": true, "forceConsistentCasingInFileNames": true },