Skip to content

Commit 384f17b

Browse files
shadowspawnaweebit
andauthored
Explicitly export factory functions (#2013)
Co-authored-by: Wee Bit <[email protected]>
1 parent 58820a4 commit 384f17b

File tree

3 files changed

+114
-33
lines changed

3 files changed

+114
-33
lines changed

index.js

+18-6
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,30 @@ const { Option } = require('./lib/option.js');
1010
* Expose the root command.
1111
*/
1212

13-
exports = module.exports = new Command();
14-
exports.program = exports; // More explicit access to global command.
15-
// Implicit export of createArgument, createCommand, and createOption.
13+
const program = new Command();
14+
exports = module.exports = program; // default export (deprecated)
15+
exports.program = program; // more explicit access to global command
1616

1717
/**
1818
* Expose classes
1919
*/
2020

21-
exports.Argument = Argument;
2221
exports.Command = Command;
23-
exports.CommanderError = CommanderError;
22+
exports.Option = Option;
23+
exports.Argument = Argument;
2424
exports.Help = Help;
25+
26+
exports.CommanderError = CommanderError;
2527
exports.InvalidArgumentError = InvalidArgumentError;
2628
exports.InvalidOptionArgumentError = InvalidArgumentError; // Deprecated
27-
exports.Option = Option;
29+
30+
/**
31+
* Expose object factory functions.
32+
*
33+
* These are present implicitly, but need to be explicit
34+
* to work with TypeScript whole module import (import * as foo) when esModuleInterop: true.
35+
*/
36+
37+
exports.createCommand = program.createCommand;
38+
exports.createArgument = program.createArgument;
39+
exports.createOption = program.createOption;

tests/ts-imports.test.ts

+95-27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
1-
import { program, Command, Option, CommanderError, InvalidArgumentError, InvalidOptionArgumentError, Help, createCommand } from '../';
1+
import {
2+
program,
3+
Command,
4+
Option,
5+
Argument,
6+
Help,
7+
CommanderError,
8+
InvalidArgumentError,
9+
InvalidOptionArgumentError,
10+
createCommand,
11+
createOption,
12+
createArgument
13+
} from '../';
214

3-
import * as commander from '../';
15+
import * as commander from '../'; // This does interesting things when esModuleInterop is true!
416

517
// Do some simple checks that expected imports are available at runtime.
618
// Similar tests to esm-imports-test.js
@@ -11,38 +23,94 @@ function checkClass(obj: object, name: string): void {
1123
expect(obj.constructor.name).toEqual(name);
1224
}
1325

14-
test('legacy default export of global Command', () => {
15-
checkClass(commander, 'Command');
16-
});
26+
describe('named imports', () => {
27+
test('program', () => {
28+
checkClass(program, 'Command');
29+
});
1730

18-
test('program', () => {
19-
checkClass(program, 'Command');
20-
});
31+
test('Command', () => {
32+
checkClass(new Command('name'), 'Command');
33+
});
2134

22-
test('createCommand', () => {
23-
checkClass(createCommand(), 'Command');
24-
});
35+
test('Option', () => {
36+
checkClass(new Option('-e, --example', 'description'), 'Option');
37+
});
2538

26-
test('Command', () => {
27-
checkClass(new Command('name'), 'Command');
28-
});
39+
test('Argument', () => {
40+
checkClass(new Argument('<foo>', 'description'), 'Argument');
41+
});
2942

30-
test('Option', () => {
31-
checkClass(new Option('-e, --example', 'description'), 'Option');
32-
});
43+
test('Help', () => {
44+
checkClass(new Help(), 'Help');
45+
});
3346

34-
test('CommanderError', () => {
35-
checkClass(new CommanderError(1, 'code', 'failed'), 'CommanderError');
36-
});
47+
test('CommanderError', () => {
48+
checkClass(new CommanderError(1, 'code', 'failed'), 'CommanderError');
49+
});
3750

38-
test('InvalidArgumentError', () => {
39-
checkClass(new InvalidArgumentError('failed'), 'InvalidArgumentError');
40-
});
51+
test('InvalidArgumentError', () => {
52+
checkClass(new InvalidArgumentError('failed'), 'InvalidArgumentError');
53+
});
54+
55+
test('InvalidOptionArgumentError', () => { // Deprecated
56+
checkClass(new InvalidOptionArgumentError('failed'), 'InvalidArgumentError');
57+
});
58+
59+
test('createCommand', () => {
60+
checkClass(createCommand('foo'), 'Command');
61+
});
62+
63+
test('createOption', () => {
64+
checkClass(createOption('-e, --example', 'description'), 'Option');
65+
});
4166

42-
test('InvalidOptionArgumentError', () => { // Deprecated
43-
checkClass(new InvalidOptionArgumentError('failed'), 'InvalidArgumentError');
67+
test('createArgument', () => {
68+
checkClass(createArgument('<foo>', 'description'), 'Argument');
69+
});
4470
});
4571

46-
test('Help', () => {
47-
checkClass(new Help(), 'Help');
72+
describe('import * as commander', () => {
73+
test('program', () => {
74+
checkClass(commander.program, 'Command');
75+
});
76+
77+
test('Command', () => {
78+
checkClass(new commander.Command('name'), 'Command');
79+
});
80+
81+
test('Option', () => {
82+
checkClass(new commander.Option('-e, --example', 'description'), 'Option');
83+
});
84+
85+
test('Argument', () => {
86+
checkClass(new commander.Argument('<foo>', 'description'), 'Argument');
87+
});
88+
89+
test('Help', () => {
90+
checkClass(new commander.Help(), 'Help');
91+
});
92+
93+
test('CommanderError', () => {
94+
checkClass(new commander.CommanderError(1, 'code', 'failed'), 'CommanderError');
95+
});
96+
97+
test('InvalidArgumentError', () => {
98+
checkClass(new commander.InvalidArgumentError('failed'), 'InvalidArgumentError');
99+
});
100+
101+
test('InvalidOptionArgumentError', () => { // Deprecated
102+
checkClass(new commander.InvalidOptionArgumentError('failed'), 'InvalidArgumentError');
103+
});
104+
105+
test('createCommand', () => {
106+
checkClass(commander.createCommand('foo'), 'Command');
107+
});
108+
109+
test('createOption', () => {
110+
checkClass(commander.createOption('-e, --example', 'description'), 'Option');
111+
});
112+
113+
test('createArgument', () => {
114+
checkClass(commander.createArgument('<foo>', 'description'), 'Argument');
115+
});
48116
});

tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"node",
1212
"jest"
1313
],
14+
"esModuleInterop": true, // Mainly so can test an import problem which only occurs with this option on!
1415
"noEmit": true,
1516
"forceConsistentCasingInFileNames": true
1617
},

0 commit comments

Comments
 (0)