@form8ion/project 22.0.0-beta.1 → 22.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,15 @@
1
- import {prompt} from '@form8ion/overridable-prompts';
2
-
3
1
  import {questionNames} from '../prompts/question-names.js';
4
2
 
5
- export default function (languages, decisions) {
6
- return prompt([{
7
- name: questionNames.PROJECT_LANGUAGE,
8
- type: 'list',
9
- message: 'What type of project is this?',
10
- choices: [...Object.keys(languages), 'Other']
11
- }], decisions);
3
+ export const PROJECT_LANGUAGE_PROMPT_ID = 'PROJECT_LANGUAGE';
4
+
5
+ export default function promptForProjectLanguage(languages, {prompt}) {
6
+ return prompt({
7
+ id: PROJECT_LANGUAGE_PROMPT_ID,
8
+ questions: [{
9
+ name: questionNames.PROJECT_LANGUAGE,
10
+ type: 'list',
11
+ message: 'What type of project is this?',
12
+ choices: [...Object.keys(languages), 'Other']
13
+ }]
14
+ });
12
15
  }
@@ -1,30 +1,27 @@
1
- import {prompt} from '@form8ion/overridable-prompts';
2
-
3
- import {afterEach, describe, expect, it, vi} from 'vitest';
1
+ import {describe, expect, it, vi} from 'vitest';
4
2
  import any from '@travi/any';
5
3
  import {when} from 'vitest-when';
6
4
 
7
5
  import {questionNames} from '../prompts/question-names.js';
8
- import promptForLanguageDetails from './prompt.js';
6
+ import promptForLanguageDetails, {PROJECT_LANGUAGE_PROMPT_ID} from './prompt.js';
9
7
 
10
8
  vi.mock('@form8ion/overridable-prompts');
11
9
 
12
10
  describe('language prompt', () => {
13
- afterEach(() => {
14
- vi.clearAllMocks();
15
- });
16
-
17
11
  it('should prompt for the language details', async () => {
12
+ const prompt = vi.fn();
18
13
  const answers = any.simpleObject();
19
- const decisions = any.simpleObject();
20
14
  const languages = any.simpleObject();
21
- when(prompt).calledWith([{
22
- name: questionNames.PROJECT_LANGUAGE,
23
- type: 'list',
24
- message: 'What type of project is this?',
25
- choices: [...Object.keys(languages), 'Other']
26
- }], decisions).thenResolve(answers);
15
+ when(prompt).calledWith({
16
+ id: PROJECT_LANGUAGE_PROMPT_ID,
17
+ questions: [{
18
+ name: questionNames.PROJECT_LANGUAGE,
19
+ type: 'list',
20
+ message: 'What type of project is this?',
21
+ choices: [...Object.keys(languages), 'Other']
22
+ }]
23
+ }).thenResolve(answers);
27
24
 
28
- expect(await promptForLanguageDetails(languages, decisions)).toEqual(answers);
25
+ expect(await promptForLanguageDetails(languages, {prompt})).toEqual(answers);
29
26
  });
30
27
  });
@@ -1,8 +1,8 @@
1
1
  import {questionNames} from '../prompts/question-names.js';
2
2
  import promptForLanguageDetails from './prompt.js';
3
3
 
4
- export default async function (languagePlugins, decisions, options) {
5
- const {[questionNames.PROJECT_LANGUAGE]: chosenLanguage} = await promptForLanguageDetails(languagePlugins, decisions);
4
+ export default async function (languagePlugins, options, {prompt}) {
5
+ const {[questionNames.PROJECT_LANGUAGE]: chosenLanguage} = await promptForLanguageDetails(languagePlugins, {prompt});
6
6
 
7
7
  const plugin = languagePlugins[chosenLanguage];
8
8
 
@@ -13,15 +13,15 @@ describe('language scaffolder', () => {
13
13
  const options = any.simpleObject();
14
14
  const chosenLanguage = any.word();
15
15
  const scaffolderResult = any.simpleObject();
16
- const decisions = any.simpleObject();
16
+ const prompt = () => undefined;
17
17
  const chosenLanguageScaffolder = vi.fn();
18
18
  const plugins = {...any.simpleObject(), [chosenLanguage]: {scaffold: chosenLanguageScaffolder}};
19
19
  when(languagePrompt.default)
20
- .calledWith(plugins, decisions)
20
+ .calledWith(plugins, {prompt})
21
21
  .thenResolve({[questionNames.PROJECT_LANGUAGE]: chosenLanguage});
22
22
  when(chosenLanguageScaffolder).calledWith(options).thenResolve(scaffolderResult);
23
23
 
24
- expect(await scaffold(plugins, decisions, options)).toEqual(scaffolderResult);
24
+ expect(await scaffold(plugins, options, {prompt})).toEqual(scaffolderResult);
25
25
  });
26
26
 
27
27
  it('should not result in an error when choosing a language without a defined scaffolder', async () => {
@@ -4,11 +4,9 @@ import joi from 'joi';
4
4
  import languagePluginsSchema from './language/schema.js';
5
5
  import vcsHostPluginsSchema from './vcs/host/schema.js';
6
6
  import dependencyUpdaterPluginsSchema from './dependency-updater/schema.js';
7
- import {decisionsSchema} from './options-schemas.js';
8
7
 
9
8
  export function validate(options) {
10
9
  return validateOptions(joi.object({
11
- decisions: decisionsSchema,
12
10
  plugins: joi.object({
13
11
  dependencyUpdaters: dependencyUpdaterPluginsSchema,
14
12
  languages: languagePluginsSchema,
@@ -6,7 +6,6 @@ import any from '@travi/any';
6
6
  import {when} from 'vitest-when';
7
7
 
8
8
  import languagePluginsSchema from './language/schema.js';
9
- import {decisionsSchema} from './options-schemas.js';
10
9
  import vcsHostPluginsSchema from './vcs/host/schema.js';
11
10
  import dependencyUpdaterPluginsSchema from './dependency-updater/schema.js';
12
11
  import {validate} from './options-validator.js';
@@ -39,10 +38,7 @@ describe('options validator', () => {
39
38
  vcsHosts: vcsHostPluginsSchema
40
39
  })
41
40
  .thenReturn(pluginsSchema);
42
- when(joi.object).calledWith({
43
- decisions: decisionsSchema,
44
- plugins: pluginsSchema
45
- }).thenReturn(fullSchema);
41
+ when(joi.object).calledWith({plugins: pluginsSchema}).thenReturn(fullSchema);
46
42
  when(core.validateOptions).calledWith(fullSchema, options).thenReturn(validatedOptions);
47
43
 
48
44
  expect(validate(options)).toEqual(validatedOptions);
@@ -0,0 +1,21 @@
1
+ import {questionNames as coreQuestionNames} from '@form8ion/core';
2
+
3
+ import {BASE_DETAILS_PROMPT_ID} from './questions.js';
4
+ import {GIT_REPOSITORY_PROMPT_ID} from '../vcs/prompt.js';
5
+ import {PROJECT_LANGUAGE_PROMPT_ID} from '../language/prompt.js';
6
+ import {REPOSITORY_HOST_PROMPT_ID} from '../vcs/host/prompt.js';
7
+ import {DEPENDENCY_UPDATER_PROMPT_ID} from '../dependency-updater/prompt.js';
8
+ import {questionNames as projectScaffolderQuestionNames} from './question-names.js';
9
+
10
+ export const ids = {
11
+ BASE_DETAILS: BASE_DETAILS_PROMPT_ID,
12
+ GIT_REPOSITORY: GIT_REPOSITORY_PROMPT_ID,
13
+ REPOSITORY_HOST: REPOSITORY_HOST_PROMPT_ID,
14
+ PROJECT_LANGUAGE: PROJECT_LANGUAGE_PROMPT_ID,
15
+ DEPENDENCY_UPDATER: DEPENDENCY_UPDATER_PROMPT_ID
16
+ };
17
+
18
+ export const questionNames = {
19
+ ...coreQuestionNames,
20
+ ...projectScaffolderQuestionNames
21
+ };
@@ -1,6 +1,10 @@
1
1
  import {questionsForBaseDetails} from '@form8ion/core';
2
- import {prompt} from '@form8ion/overridable-prompts';
3
2
 
4
- export function promptForBaseDetails(projectRoot, decisions) {
5
- return prompt(questionsForBaseDetails(decisions, projectRoot), decisions);
3
+ export const BASE_DETAILS_PROMPT_ID = 'BASE_DETAILS';
4
+
5
+ export function promptForBaseDetails(projectRoot, {prompt}) {
6
+ return prompt({
7
+ id: BASE_DETAILS_PROMPT_ID,
8
+ questions: questionsForBaseDetails(projectRoot)
9
+ });
6
10
  }
@@ -1,11 +1,10 @@
1
1
  import * as core from '@form8ion/core';
2
- import * as prompts from '@form8ion/overridable-prompts';
3
2
 
4
3
  import {describe, expect, it, vi} from 'vitest';
5
4
  import any from '@travi/any';
6
5
  import {when} from 'vitest-when';
7
6
 
8
- import {promptForBaseDetails} from './questions.js';
7
+ import {promptForBaseDetails, BASE_DETAILS_PROMPT_ID} from './questions.js';
9
8
 
10
9
  vi.mock('@form8ion/core');
11
10
  vi.mock('@form8ion/overridable-prompts');
@@ -13,13 +12,13 @@ vi.mock('@form8ion/overridable-prompts');
13
12
  describe('base details prompt', () => {
14
13
  const projectPath = any.string();
15
14
  const answers = any.simpleObject();
16
- const decisions = any.simpleObject();
17
15
  const questions = any.listOf(any.simpleObject);
16
+ const prompt = vi.fn();
18
17
 
19
18
  it('should prompt for the necessary details', async () => {
20
- when(core.questionsForBaseDetails).calledWith(decisions, projectPath).thenReturn(questions);
21
- when(prompts.prompt).calledWith(questions, decisions).thenResolve(answers);
19
+ when(core.questionsForBaseDetails).calledWith(projectPath).thenReturn(questions);
20
+ when(prompt).calledWith({id: BASE_DETAILS_PROMPT_ID, questions}).thenResolve(answers);
22
21
 
23
- expect(await promptForBaseDetails(projectPath, decisions)).toEqual(answers);
22
+ expect(await promptForBaseDetails(projectPath, {prompt})).toEqual(answers);
24
23
  });
25
24
  });
package/src/scaffolder.js CHANGED
@@ -15,9 +15,9 @@ import {scaffold as scaffoldEditorConfig} from './editorconfig/index.js';
15
15
  import {scaffold as scaffoldContributing} from './contributing/index.js';
16
16
  import lift from './lift.js';
17
17
 
18
- export async function scaffold(options) {
18
+ export async function scaffold(options, {prompt}) {
19
19
  const projectRoot = process.cwd();
20
- const {decisions, plugins: {dependencyUpdaters, languages, vcsHosts = {}}} = validate(options);
20
+ const {plugins: {dependencyUpdaters, languages, vcsHosts = {}}} = validate(options);
21
21
 
22
22
  const {
23
23
  [coreQuestionNames.PROJECT_NAME]: projectName,
@@ -26,11 +26,11 @@ export async function scaffold(options) {
26
26
  [coreQuestionNames.DESCRIPTION]: description,
27
27
  [coreQuestionNames.COPYRIGHT_YEAR]: copyrightYear,
28
28
  [coreQuestionNames.COPYRIGHT_HOLDER]: copyHolder
29
- } = await promptForBaseDetails(projectRoot, decisions);
29
+ } = await promptForBaseDetails(projectRoot, {prompt});
30
30
  const copyright = {year: copyrightYear, holder: copyHolder};
31
31
 
32
32
  const [vcsResults, contributing, license] = await Promise.all([
33
- scaffoldVcs({projectRoot, projectName, decisions, vcsHosts, visibility, description}),
33
+ scaffoldVcs({projectRoot, projectName, vcsHosts, visibility, description}, {prompt}),
34
34
  scaffoldContributing({visibility}),
35
35
  scaffoldLicense({projectRoot, license: chosenLicense, copyright}),
36
36
  scaffoldReadme({projectName, projectRoot, description}),
@@ -39,14 +39,14 @@ export async function scaffold(options) {
39
39
 
40
40
  const dependencyUpdaterResults = vcsResults.vcs && await scaffoldDependencyUpdater(
41
41
  dependencyUpdaters,
42
- decisions,
43
- {projectRoot, vcs: vcsResults.vcs}
42
+ {projectRoot},
43
+ {prompt}
44
44
  );
45
45
 
46
46
  const language = await scaffoldLanguage(
47
47
  languages,
48
- decisions,
49
- {projectRoot, projectName, vcs: vcsResults.vcs, visibility, license: chosenLicense || 'UNLICENSED', description}
48
+ {projectRoot, projectName, vcs: vcsResults.vcs, visibility, license: chosenLicense || 'UNLICENSED', description},
49
+ {prompt}
50
50
  );
51
51
 
52
52
  const mergedResults = deepmerge.all([
@@ -52,7 +52,7 @@ describe('project scaffolder', () => {
52
52
  const tags = any.listOf(any.word);
53
53
  const visibility = any.word();
54
54
  const vcsIgnore = any.simpleObject();
55
- const decisions = any.simpleObject();
55
+ const prompt = () => undefined;
56
56
 
57
57
  beforeEach(() => {
58
58
  process.cwd = vi.fn();
@@ -95,9 +95,9 @@ describe('project scaffolder', () => {
95
95
  ]);
96
96
  when(optionsValidator.validate)
97
97
  .calledWith(options)
98
- .thenReturn({decisions, plugins: {dependencyUpdaters, languages, vcsHosts}});
98
+ .thenReturn({plugins: {dependencyUpdaters, languages, vcsHosts}});
99
99
  when(prompts.promptForBaseDetails)
100
- .calledWith(projectPath, decisions)
100
+ .calledWith(projectPath, {prompt})
101
101
  .thenResolve({
102
102
  [coreQuestionNames.PROJECT_NAME]: projectName,
103
103
  [coreQuestionNames.LICENSE]: license,
@@ -107,25 +107,20 @@ describe('project scaffolder', () => {
107
107
  [coreQuestionNames.VISIBILITY]: visibility
108
108
  });
109
109
  when(scaffoldVcs)
110
- .calledWith({projectRoot: projectPath, projectName, decisions, vcsHosts, visibility, description})
110
+ .calledWith({projectRoot: projectPath, projectName, vcsHosts, visibility, description}, {prompt})
111
111
  .thenResolve(vcsResults);
112
112
  when(licenseScaffolder.default)
113
113
  .calledWith({projectRoot: projectPath, license, copyright})
114
114
  .thenResolve(licenseResults);
115
115
  scaffoldLanguage.mockResolvedValue(languageResults);
116
116
  when(dependencyUpdaterScaffolder.default)
117
- .calledWith(dependencyUpdaters, decisions, {projectRoot: projectPath, vcs})
117
+ .calledWith(dependencyUpdaters, {projectRoot: projectPath}, {prompt})
118
118
  .thenResolve(dependencyUpdaterResults);
119
119
  when(scaffoldContributing).calledWith({visibility}).thenReturn(contributingResults);
120
120
 
121
- await scaffold(options);
121
+ await scaffold(options, {prompt});
122
122
 
123
123
  expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
124
- expect(dependencyUpdaterScaffolder.default).toHaveBeenCalledWith(
125
- dependencyUpdaters,
126
- decisions,
127
- {projectRoot: projectPath, vcs}
128
- );
129
124
  expect(scaffoldEditorconfig).toHaveBeenCalledWith({projectRoot: projectPath});
130
125
  expect(lift).toHaveBeenCalledWith({
131
126
  projectRoot: projectPath,
@@ -160,7 +155,7 @@ describe('project scaffolder', () => {
160
155
  const languageResults = {badges: languageBadges, vcsIgnore, documentation};
161
156
  when(optionsValidator.validate).calledWith(options).thenReturn({plugins: {vcsHosts}});
162
157
  when(prompts.promptForBaseDetails)
163
- .calledWith(projectPath, undefined)
158
+ .calledWith(projectPath, {prompt})
164
159
  .thenResolve({
165
160
  [coreQuestionNames.DESCRIPTION]: description,
166
161
  [questionNames.GIT_REPO]: true,
@@ -173,7 +168,7 @@ describe('project scaffolder', () => {
173
168
  licenseScaffolder.default.mockResolvedValue({badges: licenseBadges});
174
169
  scaffoldVcs.mockResolvedValue(vcsResults);
175
170
 
176
- await scaffold(options);
171
+ await scaffold(options, {prompt});
177
172
 
178
173
  expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
179
174
  });
@@ -184,7 +179,7 @@ describe('project scaffolder', () => {
184
179
  scaffoldReadme.mockResolvedValue();
185
180
  scaffoldVcs.mockResolvedValue({});
186
181
 
187
- await scaffold(options);
182
+ await scaffold(options, {prompt});
188
183
 
189
184
  expect(dependencyUpdaterScaffolder.default).not.toHaveBeenCalled();
190
185
  });
@@ -209,9 +204,7 @@ describe('project scaffolder', () => {
209
204
  nextSteps: languageNextSteps,
210
205
  tags
211
206
  };
212
- when(optionsValidator.validate)
213
- .calledWith(options)
214
- .thenReturn({decisions, plugins: {languages, vcsHosts}});
207
+ when(optionsValidator.validate).calledWith(options).thenReturn({plugins: {languages, vcsHosts}});
215
208
  scaffoldVcs.mockResolvedValue(vcsResults);
216
209
  prompts.promptForBaseDetails.mockResolvedValue({
217
210
  [coreQuestionNames.PROJECT_NAME]: projectName,
@@ -220,20 +213,20 @@ describe('project scaffolder', () => {
220
213
  [coreQuestionNames.LICENSE]: license,
221
214
  [coreQuestionNames.DESCRIPTION]: description
222
215
  });
223
- when(scaffoldLanguage).calledWith(languages, decisions, {
216
+ when(scaffoldLanguage).calledWith(languages, {
224
217
  projectName,
225
218
  projectRoot: projectPath,
226
219
  visibility,
227
220
  license,
228
221
  vcs,
229
222
  description
230
- }).thenResolve(languageResults);
223
+ }, {prompt}).thenResolve(languageResults);
231
224
  when(execa).calledWith(verificationCommand, {shell: true}).thenReturn({stdout: {pipe: execaPipe}});
232
225
  dependencyUpdaterScaffolder.default.mockResolvedValue({});
233
226
  licenseScaffolder.default.mockResolvedValue({});
234
227
  scaffoldContributing.mockResolvedValue({});
235
228
 
236
- await scaffold(options);
229
+ await scaffold(options, {prompt});
237
230
 
238
231
  expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
239
232
  expect(execaPipe).toHaveBeenCalledWith(process.stdout);
@@ -243,7 +236,7 @@ describe('project scaffolder', () => {
243
236
  it('should consider the language details to be optional', async () => {
244
237
  when(optionsValidator.validate)
245
238
  .calledWith(options)
246
- .thenReturn({vcsHosts, decisions, plugins: {languages}});
239
+ .thenReturn({vcsHosts, plugins: {languages}});
247
240
  scaffoldVcs.mockResolvedValue(vcsResults);
248
241
  prompts.promptForBaseDetails.mockResolvedValue({
249
242
  [coreQuestionNames.PROJECT_NAME]: projectName,
@@ -257,22 +250,21 @@ describe('project scaffolder', () => {
257
250
  licenseScaffolder.default.mockResolvedValue({});
258
251
  scaffoldContributing.mockResolvedValue({});
259
252
 
260
- await scaffold(options);
253
+ await scaffold(options, {prompt});
261
254
 
262
255
  expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
263
256
  expect(execa).not.toHaveBeenCalled();
264
257
  });
265
258
 
266
259
  it('should pass the license to the language scaffolder as `UNLICENSED` when no license was chosen', async () => {
267
- when(optionsValidator.validate).calledWith(options).thenReturn({plugins: {languages}, decisions});
260
+ when(optionsValidator.validate).calledWith(options).thenReturn({plugins: {languages}});
268
261
  prompts.promptForBaseDetails.mockResolvedValue({});
269
262
  scaffoldVcs.mockResolvedValue(vcsResults);
270
263
 
271
- await scaffold(options);
264
+ await scaffold(options, {prompt});
272
265
 
273
266
  expect(scaffoldLanguage).toHaveBeenCalledWith(
274
267
  languages,
275
- decisions,
276
268
  {
277
269
  license: 'UNLICENSED',
278
270
  description: undefined,
@@ -280,7 +272,8 @@ describe('project scaffolder', () => {
280
272
  projectRoot: projectPath,
281
273
  vcs,
282
274
  visibility: undefined
283
- }
275
+ },
276
+ {prompt}
284
277
  );
285
278
  });
286
279
 
@@ -290,7 +283,7 @@ describe('project scaffolder', () => {
290
283
  scaffoldVcs.mockResolvedValue({});
291
284
  scaffoldLanguage.mockResolvedValue({badges: {}, projectDetails: {}});
292
285
 
293
- await scaffold(options);
286
+ await scaffold(options, {prompt});
294
287
 
295
288
  expect(execa).not.toHaveBeenCalled();
296
289
  });
@@ -1,14 +1,17 @@
1
- import {prompt} from '@form8ion/overridable-prompts';
2
-
3
1
  import {questionNames} from '../../prompts/question-names.js';
4
2
 
5
- export default async function (hosts, decisions) {
6
- const answers = await prompt([{
7
- name: questionNames.REPO_HOST,
8
- type: 'list',
9
- message: 'Where will the repository be hosted?',
10
- choices: Object.keys(hosts)
11
- }], decisions);
3
+ export const REPOSITORY_HOST_PROMPT_ID = 'REPOSITORY_HOST';
4
+
5
+ export default async function promptForVcsHostChoice(hosts, {prompt}) {
6
+ const answers = await prompt({
7
+ id: REPOSITORY_HOST_PROMPT_ID,
8
+ questions: [{
9
+ name: questionNames.REPO_HOST,
10
+ type: 'list',
11
+ message: 'Where will the repository be hosted?',
12
+ choices: Object.keys(hosts)
13
+ }]
14
+ });
12
15
  const host = hosts[answers[questionNames.REPO_HOST]];
13
16
 
14
17
  return {...answers, ...host};
@@ -1,21 +1,19 @@
1
- import * as prompts from '@form8ion/overridable-prompts';
2
-
3
- import {afterEach, describe, expect, it, vi} from 'vitest';
1
+ import {beforeEach, describe, expect, it, vi} from 'vitest';
4
2
  import any from '@travi/any';
5
3
  import {when} from 'vitest-when';
6
4
 
7
5
  import {questionNames} from '../../prompts/question-names.js';
8
- import promptForVcsHostDetails from './prompt.js';
6
+ import promptForVcsHostDetails, {REPOSITORY_HOST_PROMPT_ID} from './prompt.js';
9
7
 
10
8
  vi.mock('@form8ion/overridable-prompts');
11
9
  vi.mock('../../prompts/conditionals');
12
10
 
13
11
  describe('vcs host details prompt', () => {
12
+ let prompt;
14
13
  const answers = any.simpleObject();
15
- const decisions = any.simpleObject();
16
14
 
17
- afterEach(() => {
18
- vi.clearAllMocks();
15
+ beforeEach(() => {
16
+ prompt = vi.fn();
19
17
  });
20
18
 
21
19
  it('should prompt for the vcs hosting details', async () => {
@@ -23,25 +21,31 @@ describe('vcs host details prompt', () => {
23
21
  const hostNames = [...any.listOf(any.string), host];
24
22
  const hosts = any.objectWithKeys(hostNames, {factory: () => ({})});
25
23
  const answersWithHostChoice = {...answers, [questionNames.REPO_HOST]: host};
26
- when(prompts.prompt).calledWith([{
27
- name: questionNames.REPO_HOST,
28
- type: 'list',
29
- message: 'Where will the repository be hosted?',
30
- choices: hostNames
31
- }], decisions).thenResolve(answersWithHostChoice);
32
-
33
- expect(await promptForVcsHostDetails(hosts, decisions)).toEqual(answersWithHostChoice);
24
+ when(prompt).calledWith({
25
+ id: REPOSITORY_HOST_PROMPT_ID,
26
+ questions: [{
27
+ name: questionNames.REPO_HOST,
28
+ type: 'list',
29
+ message: 'Where will the repository be hosted?',
30
+ choices: hostNames
31
+ }]
32
+ }).thenResolve(answersWithHostChoice);
33
+
34
+ expect(await promptForVcsHostDetails(hosts, {prompt})).toEqual(answersWithHostChoice);
34
35
  });
35
36
 
36
37
  it('should not throw an error when `Other` is chosen as the host', async () => {
37
38
  const answersWithHostChoice = {...answers, [questionNames.REPO_HOST]: 'Other'};
38
- when(prompts.prompt).calledWith([{
39
- name: questionNames.REPO_HOST,
40
- type: 'list',
41
- message: 'Where will the repository be hosted?',
42
- choices: []
43
- }], decisions).thenResolve(answersWithHostChoice);
44
-
45
- expect(await promptForVcsHostDetails({}, decisions)).toEqual(answersWithHostChoice);
39
+ when(prompt).calledWith({
40
+ id: REPOSITORY_HOST_PROMPT_ID,
41
+ questions: [{
42
+ name: questionNames.REPO_HOST,
43
+ type: 'list',
44
+ message: 'Where will the repository be hosted?',
45
+ choices: []
46
+ }]
47
+ }).thenResolve(answersWithHostChoice);
48
+
49
+ expect(await promptForVcsHostDetails({}, {prompt})).toEqual(answersWithHostChoice);
46
50
  });
47
51
  });
@@ -1,8 +1,8 @@
1
1
  import {questionNames} from '../../prompts/question-names.js';
2
2
  import promptForVcsHostDetails from './prompt.js';
3
3
 
4
- export default async function scaffoldVcsHost(hosts, decisions, options) {
5
- const {[questionNames.REPO_HOST]: chosenHost} = await promptForVcsHostDetails(hosts, decisions);
4
+ export default async function scaffoldVcsHost(hosts, options, {prompt}) {
5
+ const {[questionNames.REPO_HOST]: chosenHost} = await promptForVcsHostDetails(hosts, {prompt});
6
6
 
7
7
  const lowercasedHosts = Object.fromEntries(
8
8
  Object.entries(hosts).map(([name, details]) => [name.toLowerCase(), details])
@@ -10,7 +10,7 @@ vi.mock('./prompt');
10
10
 
11
11
  describe('vcs host scaffolder', () => {
12
12
  const options = any.simpleObject();
13
- const decisions = any.simpleObject();
13
+ const prompt = () => undefined;
14
14
 
15
15
  it('should scaffold the chosen vcs host', async () => {
16
16
  const chosenHost = `${any.word()}CAPITAL${any.word()}`;
@@ -19,19 +19,19 @@ describe('vcs host scaffolder', () => {
19
19
  const hostPlugins = {...any.simpleObject(), [chosenHost.toLowerCase()]: {scaffold: chosenHostScaffolder}};
20
20
  const owner = any.word;
21
21
  when(promptForVcsHostDetails)
22
- .calledWith(hostPlugins, decisions)
22
+ .calledWith(hostPlugins, {prompt})
23
23
  .thenResolve({[questionNames.REPO_HOST]: chosenHost, [questionNames.REPO_OWNER]: owner});
24
24
  when(chosenHostScaffolder).calledWith(options).thenResolve(results);
25
25
 
26
- expect(await scaffoldVcsHost(hostPlugins, decisions, options)).toEqual(results);
26
+ expect(await scaffoldVcsHost(hostPlugins, options, {prompt})).toEqual(results);
27
27
  });
28
28
 
29
29
  it('should return empty `vcs` results when no matching host is available', async () => {
30
30
  const hostPlugins = any.simpleObject();
31
31
  when(promptForVcsHostDetails)
32
- .calledWith(hostPlugins, decisions)
32
+ .calledWith(hostPlugins, {prompt})
33
33
  .thenResolve({[questionNames.REPO_HOST]: any.word()});
34
34
 
35
- expect(await scaffoldVcsHost(hostPlugins, decisions, options)).toEqual({vcs: {}});
35
+ expect(await scaffoldVcsHost(hostPlugins, options, {prompt})).toEqual({vcs: {}});
36
36
  });
37
37
  });
package/src/vcs/prompt.js CHANGED
@@ -1,17 +1,17 @@
1
- import {prompt} from '@form8ion/overridable-prompts';
2
-
3
1
  import {questionNames} from '../prompts/question-names.js';
4
2
 
5
- export default async function promptForRepoCreation(decisions) {
6
- const {[questionNames.GIT_REPO]: gitRepoShouldBeCreated} = await prompt(
7
- [{
3
+ export const GIT_REPOSITORY_PROMPT_ID = 'GIT_REPOSITORY';
4
+
5
+ export default async function promptForRepoCreation({prompt}) {
6
+ const {[questionNames.GIT_REPO]: gitRepoShouldBeCreated} = await prompt({
7
+ id: GIT_REPOSITORY_PROMPT_ID,
8
+ questions: [{
8
9
  name: questionNames.GIT_REPO,
9
10
  type: 'confirm',
10
11
  default: true,
11
12
  message: 'Should a git repository be initialized?'
12
- }],
13
- decisions
14
- );
13
+ }]
14
+ });
15
15
 
16
16
  return gitRepoShouldBeCreated;
17
17
  }
@@ -1,27 +1,28 @@
1
- import {prompt} from '@form8ion/overridable-prompts';
2
-
3
1
  import {describe, vi, it, expect} from 'vitest';
4
2
  import {when} from 'vitest-when';
5
3
  import any from '@travi/any';
6
4
 
7
5
  import {questionNames} from '../prompts/question-names.js';
8
- import promptForRepoCreation from './prompt.js';
6
+ import promptForRepoCreation, {GIT_REPOSITORY_PROMPT_ID} from './prompt.js';
9
7
 
10
8
  vi.mock('@form8ion/overridable-prompts');
11
9
 
12
10
  describe('git prompt', () => {
13
11
  it('should ask whether a repository should be created', async () => {
14
- const decisions = any.simpleObject();
12
+ const prompt = vi.fn();
15
13
  const repoShouldBeCreated = any.boolean();
16
14
  when(prompt)
17
- .calledWith([{
18
- name: questionNames.GIT_REPO,
19
- type: 'confirm',
20
- default: true,
21
- message: 'Should a git repository be initialized?'
22
- }], decisions)
15
+ .calledWith({
16
+ id: GIT_REPOSITORY_PROMPT_ID,
17
+ questions: [{
18
+ name: questionNames.GIT_REPO,
19
+ type: 'confirm',
20
+ default: true,
21
+ message: 'Should a git repository be initialized?'
22
+ }]
23
+ })
23
24
  .thenResolve({[questionNames.GIT_REPO]: repoShouldBeCreated});
24
25
 
25
- expect(await promptForRepoCreation(decisions)).toBe(repoShouldBeCreated);
26
+ expect(await promptForRepoCreation({prompt})).toBe(repoShouldBeCreated);
26
27
  });
27
28
  });
@@ -5,8 +5,8 @@ import repositoryShouldBeCreated from './prompt.js';
5
5
  import {determineExistingVcsDetails, defineRemoteOrigin} from './git/index.js';
6
6
  import {scaffold as scaffoldVcsHost} from './host/index.js';
7
7
 
8
- export default async function scaffoldVcs({projectRoot, projectName, decisions, vcsHosts, visibility, description}) {
9
- if (await repositoryShouldBeCreated(decisions)) {
8
+ export default async function scaffoldVcs({projectRoot, projectName, vcsHosts, visibility, description}, {prompt}) {
9
+ if (await repositoryShouldBeCreated({prompt})) {
10
10
  if (await alreadyVersionedByGit({projectRoot})) {
11
11
  info('Git repository already exists');
12
12
 
@@ -14,11 +14,7 @@ export default async function scaffoldVcs({projectRoot, projectName, decisions,
14
14
  }
15
15
 
16
16
  const [{vcs: {host, owner, name, sshUrl}}] = await Promise.all([
17
- scaffoldVcsHost(
18
- vcsHosts,
19
- decisions,
20
- {projectName, projectRoot, description, visibility}
21
- ),
17
+ scaffoldVcsHost(vcsHosts, {projectName, projectRoot, description, visibility}, {prompt}),
22
18
  scaffoldGit({projectRoot})
23
19
  ]);
24
20