Skip to content

Commit ee930cc

Browse files
committedMar 11, 2018
feat(CLI): begin adding extra configuration options
1 parent c93c9db commit ee930cc

File tree

3 files changed

+89
-31
lines changed

3 files changed

+89
-31
lines changed
 

‎src/cli/inquire.ts

+55-17
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Runner, TypescriptStarterUserOptions, validateName } from './utils';
44
export async function inquire(): Promise<TypescriptStarterUserOptions> {
55
const packageNameQuestion: Question = {
66
filter: (answer: string) => answer.trim(),
7-
message: 'Enter the new package name:',
7+
message: '📦 Enter the new package name:',
88
name: 'projectName',
99
type: 'input',
1010
validate: validateName
@@ -19,14 +19,14 @@ export async function inquire(): Promise<TypescriptStarterUserOptions> {
1919
{ name: 'Node.js application', value: ProjectType.Node },
2020
{ name: 'Javascript library', value: ProjectType.Library }
2121
],
22-
message: 'What are you making?',
22+
message: '🔨 What are you making?',
2323
name: 'type',
2424
type: 'list'
2525
};
2626

2727
const packageDescriptionQuestion: Question = {
2828
filter: (answer: string) => answer.trim(),
29-
message: 'Enter the package description:',
29+
message: '💬 Enter the package description:',
3030
name: 'description',
3131
type: 'input',
3232
validate: (answer: string) => answer.length > 0
@@ -37,71 +37,109 @@ export async function inquire(): Promise<TypescriptStarterUserOptions> {
3737
{ name: 'npm', value: Runner.Npm },
3838
{ name: 'yarn', value: Runner.Yarn }
3939
],
40-
message: 'Will this project use npm or yarn?',
40+
message: '🚄 Will this project use npm or yarn?',
4141
name: 'runner',
4242
type: 'list'
4343
};
4444

4545
enum TypeDefinitions {
4646
none = 'none',
47-
Node = 'node',
48-
DOM = 'dom',
49-
NodeAndDOM = 'both'
47+
node = 'node',
48+
dom = 'dom',
49+
nodeAndDom = 'both'
5050
}
5151

5252
const typeDefsQuestion: Question = {
5353
choices: [
5454
{
5555
name: `None — the library won't use any globals or modules from Node.js or the DOM`,
56-
value: '0'
56+
value: TypeDefinitions.none
5757
},
5858
{
5959
name: `Node.js — parts of the library require access to Node.js globals or built-in modules`,
60-
value: '1'
60+
value: TypeDefinitions.node
6161
},
6262
{
6363
name: `DOM — parts of the library require access to the Document Object Model (DOM)`,
64-
value: '2'
64+
value: TypeDefinitions.dom
6565
},
6666
{
6767
name: `Both Node.js and DOM — some parts of the library require Node.js, other parts require DOM access`,
68-
value: '3'
68+
value: TypeDefinitions.nodeAndDom
6969
}
7070
],
71-
message: 'Which global type definitions do you want to include?',
71+
message: '📚 Which global type definitions do you want to include?',
7272
name: 'definitions',
7373
type: 'list',
7474
when: (answers: any) => answers.type === ProjectType.Library
7575
};
7676

77+
enum Extras {
78+
strict = 'strict',
79+
immutable = 'immutable',
80+
vscode = 'vscode'
81+
}
82+
const extrasQuestion: Question = {
83+
choices: [
84+
{
85+
name: 'Enable stricter type-checking',
86+
value: Extras.strict
87+
},
88+
{
89+
checked: true,
90+
name: 'Enable tslint-immutable',
91+
value: Extras.immutable
92+
},
93+
{
94+
checked: true,
95+
name: 'Include VS Code debugging config',
96+
value: Extras.vscode
97+
}
98+
],
99+
message: '🚀 More fun stuff:',
100+
name: 'extras',
101+
type: 'checkbox'
102+
};
103+
77104
return prompt([
78105
packageNameQuestion,
79106
projectTypeQuestion,
80107
packageDescriptionQuestion,
81108
runnerQuestion,
82-
typeDefsQuestion
109+
typeDefsQuestion,
110+
extrasQuestion
83111
]).then(answers => {
84-
const { definitions, description, projectName, runner } = answers as {
112+
const {
113+
definitions,
114+
description,
115+
extras,
116+
projectName,
117+
runner
118+
} = answers as {
85119
readonly definitions?: TypeDefinitions;
86120
readonly description: string;
121+
readonly extras: ReadonlyArray<string>;
87122
readonly projectName: string;
88123
readonly runner: Runner;
89124
};
90125
return {
91126
description,
92127
domDefinitions: definitions
93-
? [TypeDefinitions.DOM, TypeDefinitions.NodeAndDOM].includes(
128+
? [TypeDefinitions.dom, TypeDefinitions.nodeAndDom].includes(
94129
definitions
95130
)
96131
: false,
132+
immutable: extras.includes(Extras.immutable),
97133
install: true,
98134
nodeDefinitions: definitions
99-
? [TypeDefinitions.Node, TypeDefinitions.NodeAndDOM].includes(
135+
? [TypeDefinitions.node, TypeDefinitions.nodeAndDom].includes(
100136
definitions
101137
)
102138
: false,
103139
projectName,
104-
runner
140+
runner,
141+
strict: extras.includes(Extras.strict),
142+
vscode: extras.includes(Extras.vscode)
105143
};
106144
});
107145
}

‎src/cli/tests/cli.integration.spec.ts

+31-14
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ async function testInteractive(
205205
projectName: string,
206206
entry: ReadonlyArray<string | ReadonlyArray<string>>
207207
): Promise<execa.ExecaReturns> {
208-
const lastCheck = entry[3] !== undefined;
208+
const typeDefs = entry[3] !== '';
209209
const proc = execa(`../bin/typescript-starter`, ['--noinstall'], {
210210
cwd: buildDir,
211211
env: {
@@ -247,45 +247,54 @@ async function testInteractive(
247247
clearBuffer();
248248
type(`${entry[1]}${enter}`);
249249
await ms(200);
250-
checkBuffer(new RegExp(`${entry[1]}[\\s\\S]*npm or yarn?`));
250+
checkBuffer(new RegExp(`${entry[1]}[\\s\\S]*npm or yarn\\?`));
251251
clearBuffer();
252252
type(`${entry[2][0]}${enter}`);
253253
await ms(200);
254-
const search = `${entry[2][1]}[\\s\\S]*global type definitions`;
255-
const exp = lastCheck
254+
const search = `\\? ${entry[2][1]}`;
255+
const exp = typeDefs
256256
? new RegExp(`${search}`) // should match
257257
: new RegExp(`(?!${search})`); // should not match
258258
checkBuffer(exp);
259259
// tslint:disable-next-line:no-if-statement
260-
if (lastCheck) {
260+
if (typeDefs) {
261261
clearBuffer();
262262
type(`${entry[3][0]}${enter}`);
263263
await ms(200);
264-
checkBuffer(new RegExp(`${entry[3][1]}`));
264+
checkBuffer(new RegExp(`${entry[3][1]}[\\s\\S]*More fun stuff`));
265265
}
266+
clearBuffer();
267+
type(`${entry[4][0]}${enter}`);
268+
await ms(200);
269+
checkBuffer(new RegExp(`${entry[4][1]}`));
266270
return proc;
267271
}
268272

269273
test(`${
270274
TestDirectories.three
271275
}: interactive mode: javascript library`, async t => {
272-
t.plan(7);
276+
t.plan(8);
273277
const proc = await testInteractive(t, `${TestDirectories.three}`, [
274278
[`${down}${up}${down}`, `Javascript library`],
275279
`integration test 3 description`,
276280
[`${down}${up}${down}${enter}`, `yarn`],
277-
[`${down}${down}${down}${enter}`, `Both Node.js and DOM`]
281+
[`${down}${down}${down}${enter}`, `Both Node.js and DOM`],
282+
[' ', 'stricter type-checking[\\s\\S]*tslint-immutable[\\s\\S]*VS Code']
278283
]);
279284
await proc;
280285
const map = await hashAllTheThings(TestDirectories.three);
281286
t.deepEqual(map, {
282287
'test-3/README.md': 'c52631ebf78f6b030af9a109b769b647',
283288
'test-3/bin/typescript-starter': 'a4ad3923f37f50df986b43b1adb9f6b3',
284-
'test-3/src/index.ts': '5991bedc40ac87a01d880c6db16fe349',
289+
'test-3/src/index.ts': 'fbc67c2cbf3a7d37e4e02583bf06eec9',
290+
'test-3/src/lib/async.spec.ts': '1e83b84de3f3b068244885219acb42bd',
291+
'test-3/src/lib/async.ts': '9012c267bb25fa98ad2561929de3d4e2',
292+
'test-3/src/lib/hash.spec.ts': '87bfca3c0116fd86a353750fcf585ecf',
293+
'test-3/src/lib/hash.ts': 'a4c552897f25da5963f410e375264bd1',
285294
'test-3/src/lib/number.spec.ts': '40ebb014eb7871d1f810c618aba1d589',
286295
'test-3/src/lib/number.ts': '43756f90e6ac0b1c4ee6c81d8ab969c7',
287296
'test-3/src/types/example.d.ts': '4221812f6f0434eec77ccb1fba1e3759',
288-
'test-3/tsconfig.json': 'f36dc6407fc898f41a23cb620b2f4884',
297+
'test-3/tsconfig.json': '43817952d399db9e44977b3703edd7cf',
289298
'test-3/tsconfig.module.json': '2fda4c8760c6cfa3462b40df0645850d',
290299
'test-3/tslint.json': '7ac167ffbcb724a6c270e8dc4e747067'
291300
});
@@ -294,11 +303,13 @@ test(`${
294303
test(`${
295304
TestDirectories.four
296305
}: interactive mode: node.js application`, async t => {
297-
t.plan(6);
306+
t.plan(7);
298307
const proc = await testInteractive(t, `${TestDirectories.four}`, [
299308
[`${down}${up}`, `Node.js application`],
300309
`integration test 4 description`,
301-
[`${down}${up}${enter}`, `npm`]
310+
[`${down}${up}${enter}`, `npm`],
311+
'',
312+
[`${down} `, 'VS Code']
302313
]);
303314
await proc;
304315
const map = await hashAllTheThings(TestDirectories.four);
@@ -347,10 +358,13 @@ test(`${
347358
domDefinitions: false,
348359
email: 'email@example.com',
349360
fullName: 'Satoshi Nakamoto',
361+
immutable: true,
350362
install: true,
351363
nodeDefinitions: false,
352364
projectName: TestDirectories.five,
353-
runner: Runner.Npm
365+
runner: Runner.Npm,
366+
strict: true,
367+
vscode: false
354368
};
355369
const log = console.log;
356370
// tslint:disable-next-line:no-object-mutation
@@ -384,10 +398,13 @@ test(`${TestDirectories.six}: Sandboxed: yarn, no initial commit`, async t => {
384398
domDefinitions: true,
385399
email: Placeholders.email,
386400
fullName: Placeholders.name,
401+
immutable: true,
387402
install: true,
388403
nodeDefinitions: true,
389404
projectName: TestDirectories.six,
390-
runner: Runner.Yarn
405+
runner: Runner.Yarn,
406+
strict: false,
407+
vscode: true
391408
};
392409
const log = console.log;
393410
// tslint:disable-next-line:no-object-mutation

‎src/cli/utils.ts

+3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ export enum Runner {
99
export interface TypescriptStarterUserOptions {
1010
readonly description: string;
1111
readonly domDefinitions: boolean;
12+
readonly immutable: boolean;
1213
readonly install: boolean;
1314
readonly nodeDefinitions: boolean;
1415
readonly projectName: string;
1516
readonly runner: Runner;
17+
readonly strict: boolean;
18+
readonly vscode: boolean;
1619
}
1720

1821
export interface TypescriptStarterInferredOptions {

0 commit comments

Comments
 (0)
Please sign in to comment.