Skip to content

Commit

Permalink
Explicitly export factory functions
Browse files Browse the repository at this point in the history
Co-authored-by: Wee Bit <aweebit64@gmail.com>
  • Loading branch information
shadowspawn and aweebit committed Sep 11, 2023
1 parent 7d23437 commit 26cb5a6
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 33 deletions.
24 changes: 18 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
122 changes: 95 additions & 27 deletions tests/ts-imports.test.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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('<foo>', '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('<foo>', '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('<foo>', '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('<foo>', 'description'), 'Argument');
});
});
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
Expand Down

0 comments on commit 26cb5a6

Please sign in to comment.