Skip to content

Commit 4d90202

Browse files
committed
feat(ci-service): scaffold a qualified service rather than prompting for a choice
since the project is already set up for the service and the javascript-project specific additions can be added based on that context BREAKING CHANGE: the ci service is no longer chosen based on a prompt. instead it is scaffolded based on the `qualify` predicate of the plugin passing. this means that only plugins that provide a `qualify` predicate will still be possible to scaffold in this context
1 parent af5800c commit 4d90202

14 files changed

Lines changed: 366 additions & 1065 deletions

package-lock.json

Lines changed: 255 additions & 1000 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@
6969
"@form8ion/husky": "^8.0.0-beta.3",
7070
"@form8ion/javascript-core": "^13.0.0",
7171
"@form8ion/overridable-prompts": "^1.2.0",
72+
"@form8ion/plugins-core": "^1.0.0-beta.1",
7273
"@form8ion/prettier": "^3.0.0",
7374
"@hapi/hoek": "^11.0.0",
74-
"@travi/language-scaffolder-prompts": "^2.0.0-beta.1",
7575
"camelcase": "^9.0.0",
7676
"deepmerge": "^4.2.2",
7777
"execa": "^9.5.1",

src/index.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
import {questionNames as languageScaffolderPromptsQuestionNames} from '@travi/language-scaffolder-prompts';
2-
3-
import {questionNames as jsScaffolderQuestionNames} from './prompts/question-names.js';
4-
1+
export {questionNames} from './prompts/question-names.js';
52
export {scaffold as scaffoldUnitTesting} from './testing/unit/index.js';
63
export {default as scaffold} from './scaffolder.js';
74
export {default as lift} from './lifter.js';
85
export {default as test} from './tester.js';
9-
export const questionNames = {...languageScaffolderPromptsQuestionNames, ...jsScaffolderQuestionNames};

src/prompts/conditionals.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import {projectTypes} from '@form8ion/javascript-core';
2-
import {questionNames as commonQuestionNames} from '@travi/language-scaffolder-prompts';
32

43
import {questionNames} from './question-names.js';
54

@@ -32,8 +31,8 @@ export function scopePromptShouldBePresentedFactory(visibility) {
3231
}
3332

3433
export function lintingPromptShouldBePresented({
35-
[commonQuestionNames.UNIT_TESTS]: unitTested,
36-
[commonQuestionNames.INTEGRATION_TESTS]: integrationTested
34+
[questionNames.UNIT_TESTS]: unitTested,
35+
[questionNames.INTEGRATION_TESTS]: integrationTested
3736
}) {
3837
return !unitTested && !integrationTested;
3938
}

src/prompts/conditionals.test.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import {questionNames as commonQuestionNames} from '@travi/language-scaffolder-prompts';
21
import {projectTypes} from '@form8ion/javascript-core';
32

43
import {describe, expect, it} from 'vitest';
@@ -99,17 +98,17 @@ describe('javascript prompt conditionals', () => {
9998

10099
describe('transpilation/linting', () => {
101100
it('should not show the prompt if the project is unit tested ', () => {
102-
expect(lintingPromptShouldBePresented({[commonQuestionNames.UNIT_TESTS]: true})).toBe(false);
101+
expect(lintingPromptShouldBePresented({[questionNames.UNIT_TESTS]: true})).toBe(false);
103102
});
104103

105104
it('should not show the prompt if the project is integration tested', () => {
106-
expect(lintingPromptShouldBePresented({[commonQuestionNames.INTEGRATION_TESTS]: true})).toBe(false);
105+
expect(lintingPromptShouldBePresented({[questionNames.INTEGRATION_TESTS]: true})).toBe(false);
107106
});
108107

109108
it('should show the prompt if the project is not tested', () => {
110109
expect(lintingPromptShouldBePresented({
111-
[commonQuestionNames.INTEGRATION_TESTS]: false,
112-
[commonQuestionNames.UNIT_TESTS]: false
110+
[questionNames.INTEGRATION_TESTS]: false,
111+
[questionNames.UNIT_TESTS]: false
113112
})).toBe(true);
114113
});
115114
});

src/prompts/question-names.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
export const questionNames = {
2+
UNIT_TESTS: 'unitTests',
3+
INTEGRATION_TESTS: 'integrationTests',
24
UNIT_TEST_FRAMEWORK: 'unitTestFramework',
35
INTEGRATION_TEST_FRAMEWORK: 'integrationTestFramework',
46
NODE_VERSION_CATEGORY: 'nodeVersionCategory',

src/prompts/questions.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {packageManagers, projectTypes} from '@form8ion/javascript-core';
22
import {prompt as promptWithInquirer} from '@form8ion/overridable-prompts';
3-
import {questionNames as commonQuestionNames, questions as commonQuestions} from '@travi/language-scaffolder-prompts';
43

54
import {execa} from 'execa';
65
import npmConfFactory from '../../thirdparty-wrappers/npm-conf.js';
@@ -36,7 +35,6 @@ function authorQuestions({name, email, url}) {
3635
}
3736

3837
export async function prompt(
39-
ciServices,
4038
hosts,
4139
visibility,
4240
vcs,
@@ -58,10 +56,9 @@ export async function prompt(
5856
}
5957

6058
const {
61-
[commonQuestionNames.UNIT_TESTS]: unitTested,
62-
[commonQuestionNames.INTEGRATION_TESTS]: integrationTested,
59+
[questionNames.UNIT_TESTS]: unitTested,
60+
[questionNames.INTEGRATION_TESTS]: integrationTested,
6361
[questionNames.PROJECT_TYPE]: projectType,
64-
[commonQuestionNames.CI_SERVICE]: ci,
6562
[questionNames.HOST]: chosenHost,
6663
[questionNames.SCOPE]: scope,
6764
[questionNames.NODE_VERSION_CATEGORY]: nodeVersionCategory,
@@ -120,7 +117,18 @@ export async function prompt(
120117
email: npmConf.get('init.author.email'),
121118
url: npmConf.get('init.author.url')
122119
}),
123-
...commonQuestions(({vcs, ciServices, pathWithinParent})),
120+
{
121+
name: questionNames.UNIT_TESTS,
122+
message: 'Will this project be unit tested?',
123+
type: 'confirm',
124+
default: true
125+
},
126+
{
127+
name: questionNames.INTEGRATION_TESTS,
128+
message: 'Will this project be integration tested?',
129+
type: 'confirm',
130+
default: true
131+
},
124132
{
125133
name: questionNames.CONFIGURE_LINTING,
126134
message: 'Will there be source code that should be linted?',
@@ -145,7 +153,6 @@ export async function prompt(
145153
return {
146154
tests: {unit: unitTested, integration: integrationTested},
147155
projectType,
148-
ci,
149156
chosenHost,
150157
scope,
151158
nodeVersionCategory,

src/prompts/questions.test.js

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import {execa} from 'execa';
2-
import * as commonPrompts from '@travi/language-scaffolder-prompts';
32
import * as prompts from '@form8ion/overridable-prompts';
43
import {packageManagers, projectTypes} from '@form8ion/javascript-core';
54

6-
import {expect, describe, it, vi, beforeEach} from 'vitest';
5+
import {describe, expect, it, vi} from 'vitest';
76
import any from '@travi/any';
87
import {when} from 'vitest-when';
98

@@ -15,19 +14,16 @@ import {prompt} from './questions.js';
1514
import * as validators from './validators.js';
1615

1716
vi.mock('execa');
18-
vi.mock('@travi/language-scaffolder-prompts');
1917
vi.mock('@form8ion/overridable-prompts');
2018
vi.mock('../../thirdparty-wrappers/npm-conf.js');
2119
vi.mock('../dialects/prompt-choices.js');
2220
vi.mock('./validators.js');
2321
vi.mock('./conditionals.js');
2422

2523
describe('prompts', () => {
26-
const commonQuestions = any.listOf(any.simpleObject);
2724
const decisions = any.simpleObject();
2825
const vcs = any.simpleObject();
2926
const pathWithinParent = any.string();
30-
const ciServices = any.simpleObject();
3127
const visibility = any.word();
3228
const integrationTested = any.boolean();
3329
const unitTested = any.boolean();
@@ -45,10 +41,10 @@ describe('prompts', () => {
4541
const scope = any.word();
4642
const provideExample = any.boolean();
4743
const answers = {
48-
[commonPrompts.questionNames.UNIT_TESTS]: unitTested,
49-
[commonPrompts.questionNames.INTEGRATION_TESTS]: integrationTested,
44+
[questionNames.UNIT_TESTS]: unitTested,
45+
[questionNames.INTEGRATION_TESTS]: integrationTested,
5046
[questionNames.PROJECT_TYPE]: projectType,
51-
[commonPrompts.questionNames.CI_SERVICE]: ci,
47+
[questionNames.CI_SERVICE]: ci,
5248
[questionNames.HOST]: chosenHost,
5349
[questionNames.SCOPE]: scope,
5450
[questionNames.NODE_VERSION_CATEGORY]: nodeVersionCategory,
@@ -61,12 +57,6 @@ describe('prompts', () => {
6157
};
6258
const logger = {info: () => undefined, warn: () => undefined};
6359

64-
beforeEach(() => {
65-
when(commonPrompts.questions)
66-
.calledWith({vcs, ciServices, pathWithinParent: undefined})
67-
.thenReturn(commonQuestions);
68-
});
69-
7060
it('should prompt the user for the necessary details', async () => {
7161
const npmUser = any.word();
7262
const get = vi.fn();
@@ -144,7 +134,18 @@ describe('prompts', () => {
144134
message: 'What is the author\'s website url?',
145135
default: authorUrl
146136
},
147-
...commonQuestions,
137+
{
138+
name: questionNames.UNIT_TESTS,
139+
message: 'Will this project be unit tested?',
140+
type: 'confirm',
141+
default: true
142+
},
143+
{
144+
name: questionNames.INTEGRATION_TESTS,
145+
message: 'Will this project be integration tested?',
146+
type: 'confirm',
147+
default: true
148+
},
148149
{
149150
name: questionNames.CONFIGURE_LINTING,
150151
message: 'Will there be source code that should be linted?',
@@ -167,10 +168,9 @@ describe('prompts', () => {
167168
], decisions)
168169
.thenResolve({...answers, [questionNames.CONFIGURE_LINTING]: any.word()});
169170

170-
expect(await prompt(ciServices, hosts, visibility, vcs, decisions, configs, undefined, {logger})).toEqual({
171+
expect(await prompt(hosts, visibility, vcs, decisions, configs, undefined, {logger})).toEqual({
171172
tests,
172173
projectType,
173-
ci,
174174
chosenHost,
175175
scope,
176176
nodeVersionCategory,
@@ -189,10 +189,9 @@ describe('prompts', () => {
189189
when(execa).calledWith('npm', ['whoami']).thenResolve({stdout: npmUser});
190190
prompts.prompt.mockResolvedValue({...answers, [questionNames.CONFIGURE_LINTING]: false});
191191

192-
expect(await prompt(ciServices, {}, visibility, vcs, decisions, undefined, undefined, {logger})).toEqual({
192+
expect(await prompt({}, visibility, vcs, decisions, undefined, undefined, {logger})).toEqual({
193193
tests,
194194
projectType,
195-
ci,
196195
chosenHost,
197196
scope,
198197
nodeVersionCategory,
@@ -207,12 +206,9 @@ describe('prompts', () => {
207206
it('should not ask about node version for sub-projects since the parent project already defines', async () => {
208207
when(execa).calledWith('npm', ['whoami']).thenResolve({stdout: any.word()});
209208
npmConfFactory.mockReturnValue({get: () => undefined});
210-
when(commonPrompts.questions)
211-
.calledWith({vcs, ciServices, pathWithinParent})
212-
.thenReturn(commonQuestions);
213209
prompts.prompt.mockResolvedValue(answers);
214210

215-
await prompt(ciServices, {}, 'CS', vcs, null, null, pathWithinParent, {logger});
211+
await prompt({}, 'CS', vcs, null, null, pathWithinParent, {logger});
216212

217213
const [questions] = prompts.prompt.mock.lastCall;
218214
expect(questions.filter(question => questionNames.NODE_VERSION_CATEGORY === question.name).length).toEqual(0);
@@ -221,12 +217,9 @@ describe('prompts', () => {
221217
it('should not ask whether closed source packages should be scoped', async () => {
222218
when(execa).calledWith('npm', ['whoami']).thenResolve({stdout: any.word()});
223219
npmConfFactory.mockReturnValue({get: () => undefined});
224-
when(commonPrompts.questions)
225-
.calledWith({vcs, ciServices, pathWithinParent})
226-
.thenReturn(commonQuestions);
227220
prompts.prompt.mockResolvedValue(answers);
228221

229-
await prompt(ciServices, {}, 'CS', vcs, null, null, pathWithinParent, {logger});
222+
await prompt({}, 'CS', vcs, null, null, pathWithinParent, {logger});
230223

231224
const [questions] = prompts.prompt.mock.lastCall;
232225
expect(questions.filter(question => questionNames.SHOULD_BE_SCOPED === question.name).length).toEqual(0);
@@ -235,12 +228,9 @@ describe('prompts', () => {
235228
it('should not ask whether inner source packages should be scoped', async () => {
236229
when(execa).calledWith('npm', ['whoami']).thenResolve({stdout: any.word()});
237230
npmConfFactory.mockReturnValue({get: () => undefined});
238-
when(commonPrompts.questions)
239-
.calledWith({vcs, ciServices, pathWithinParent})
240-
.thenReturn(commonQuestions);
241231
prompts.prompt.mockResolvedValue(answers);
242232

243-
await prompt(ciServices, {}, 'ISS', vcs, null, null, pathWithinParent, {logger});
233+
await prompt({}, 'ISS', vcs, null, null, pathWithinParent, {logger});
244234

245235
const [questions] = prompts.prompt.mock.lastCall;
246236
expect(questions.filter(question => questionNames.SHOULD_BE_SCOPED === question.name).length).toEqual(0);
@@ -249,12 +239,9 @@ describe('prompts', () => {
249239
it('should handle a non-logged-in user gracefully', async () => {
250240
when(execa).calledWith('npm', ['whoami']).thenReject(new Error());
251241
npmConfFactory.mockReturnValue({get: () => undefined});
252-
when(commonPrompts.questions)
253-
.calledWith({vcs, ciServices, pathWithinParent})
254-
.thenReturn(commonQuestions);
255242
prompts.prompt.mockResolvedValue(answers);
256243

257-
await prompt(ciServices, {}, 'OSS', vcs, {}, null, pathWithinParent, {logger});
244+
await prompt({}, 'OSS', vcs, {}, null, pathWithinParent, {logger});
258245

259246
const [questions] = prompts.prompt.mock.lastCall;
260247
expect(questions.filter(question => questionNames.SHOULD_BE_SCOPED === question.name).length).toEqual(1);

src/scaffolder.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import deepmerge from 'deepmerge';
22
import {projectTypes, scaffoldChoice} from '@form8ion/javascript-core';
3+
import {scaffold as scaffoldPlugins} from '@form8ion/plugins-core';
34
import {scaffold as scaffoldCommitConvention} from '@form8ion/commit-convention';
45

56
import {validate} from './options/validator.js';
@@ -45,7 +46,6 @@ export default async function scaffoldJavascript(options, {logger}) {
4546
const {
4647
tests,
4748
projectType,
48-
ci,
4949
chosenHost,
5050
scope,
5151
nodeVersionCategory,
@@ -54,7 +54,7 @@ export default async function scaffoldJavascript(options, {logger}) {
5454
provideExample,
5555
packageManager,
5656
dialect
57-
} = await prompt(ciServices, hosts, visibility, vcs, decisions, configs, pathWithinParent, {logger});
57+
} = await prompt(hosts, visibility, vcs, decisions, configs, pathWithinParent, {logger});
5858

5959
logger.info('Writing project files', {level: 'secondary'});
6060

@@ -134,7 +134,10 @@ export default async function scaffoldJavascript(options, {logger}) {
134134
chosenHost,
135135
{buildDirectory: `./${projectTypeResults.buildDirectory}`, projectRoot, projectName, nodeVersion}
136136
),
137-
scaffoldChoice(ciServices, ci, {projectRoot, vcs, visibility, projectType, projectName, nodeVersion, tests}),
137+
scaffoldPlugins.qualifiedOption(
138+
ciServices,
139+
{projectRoot, vcs, visibility, projectType, projectName, nodeVersion, tests}
140+
),
138141
scaffoldCommitConvention({projectRoot, projectType, configs, pathWithinParent})
139142
])),
140143
projectTypeResults,

src/scaffolder.test.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import deepmerge from 'deepmerge';
22
import {projectTypes, scaffoldChoice} from '@form8ion/javascript-core';
3+
import {scaffold as scaffoldPlugins} from '@form8ion/plugins-core';
34
import {scaffold as scaffoldCommitConvention} from '@form8ion/commit-convention';
45

56
import {beforeEach, describe, expect, it, vi} from 'vitest';
@@ -24,6 +25,7 @@ import scaffold from './scaffolder.js';
2425

2526
vi.mock('deepmerge');
2627
vi.mock('@form8ion/javascript-core');
28+
vi.mock('@form8ion/plugins-core');
2729
vi.mock('@form8ion/commit-convention');
2830
vi.mock('./package/index.js');
2931
vi.mock('./code-style/index.js');
@@ -122,7 +124,7 @@ describe('javascript project scaffolder', () => {
122124
}
123125
});
124126
when(prompt)
125-
.calledWith(ciServices, hosts, visibility, vcs, decisions, configs, pathWithinParent, {logger})
127+
.calledWith(hosts, visibility, vcs, decisions, configs, pathWithinParent, {logger})
126128
.thenResolve({
127129
packageManager,
128130
dialect,
@@ -184,10 +186,9 @@ describe('javascript project scaffolder', () => {
184186
when(scaffoldCodeStyle)
185187
.calledWith({projectRoot, projectType, configs, vcs, configureLinting})
186188
.thenResolve(codeStyleResults);
187-
when(scaffoldChoice)
189+
when(scaffoldPlugins.qualifiedOption)
188190
.calledWith(
189191
ciServices,
190-
ciChoice,
191192
{projectRoot, vcs, visibility, projectType, projectName, nodeVersion: nodeVersionResults, tests}
192193
)
193194
.thenResolve(ciServiceResults);

0 commit comments

Comments
 (0)