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

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,30 +1,27 @@
1
- import * as prompts 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
- import {promptForDependencyUpdaterChoice} from './prompt.js';
5
+ import {DEPENDENCY_UPDATER_PROMPT_ID, promptForDependencyUpdaterChoice} from './prompt.js';
8
6
  import {questionNames} from '../index.js';
9
7
 
10
8
  vi.mock('@form8ion/overridable-prompts');
11
9
 
12
10
  describe('dependency updater prompt', () => {
13
- afterEach(() => {
14
- vi.clearAllMocks();
15
- });
16
-
17
11
  it('should enable choosing the preferred updater', async () => {
12
+ const prompt = vi.fn();
18
13
  const answers = any.simpleObject();
19
14
  const updaters = any.simpleObject();
20
- const decisions = any.simpleObject();
21
- when(prompts.prompt).calledWith([{
22
- name: questionNames.DEPENDENCY_UPDATER,
23
- type: 'list',
24
- message: 'Which dependency-update service do you want to manage this project?',
25
- choices: [...Object.keys(updaters), 'Other']
26
- }], decisions).thenResolve(answers);
15
+ when(prompt).calledWith({
16
+ id: DEPENDENCY_UPDATER_PROMPT_ID,
17
+ questions: [{
18
+ name: questionNames.DEPENDENCY_UPDATER,
19
+ type: 'list',
20
+ message: 'Which dependency-update service do you want to manage this project?',
21
+ choices: [...Object.keys(updaters), 'Other']
22
+ }]
23
+ }).thenResolve(answers);
27
24
 
28
- expect(await promptForDependencyUpdaterChoice(updaters, decisions)).toEqual(answers);
25
+ expect(await promptForDependencyUpdaterChoice(updaters, {prompt})).toEqual(answers);
29
26
  });
30
27
  });
@@ -1,11 +1,11 @@
1
1
  import {questionNames} from '../prompts/question-names.js';
2
2
  import {promptForDependencyUpdaterChoice} from './prompt.js';
3
3
 
4
- export default async function (plugins, decisions, options) {
4
+ export default async function (plugins, options, {prompt}) {
5
5
  if (!Object.keys(plugins).length) return undefined;
6
6
 
7
7
  const plugin = plugins[
8
- (await promptForDependencyUpdaterChoice(plugins, decisions))[questionNames.DEPENDENCY_UPDATER]
8
+ (await promptForDependencyUpdaterChoice(plugins, {prompt}))[questionNames.DEPENDENCY_UPDATER]
9
9
  ];
10
10
 
11
11
  if (plugin) return plugin.scaffold(options);
@@ -1,32 +1,28 @@
1
- import {afterEach, describe, expect, it, vi} from 'vitest';
1
+ import {describe, expect, it, vi} from 'vitest';
2
2
  import any from '@travi/any';
3
3
  import {when} from 'vitest-when';
4
4
 
5
- import * as prompt from './prompt.js';
5
+ import {promptForDependencyUpdaterChoice} from './prompt.js';
6
6
  import scaffoldUpdater from './scaffolder.js';
7
7
  import {questionNames} from '../index.js';
8
- import {promptForDependencyUpdaterChoice} from './prompt.js';
9
8
 
10
- vi.mock('./prompt');
9
+ vi.mock('./prompt.js');
11
10
 
12
11
  describe('dependency-updater scaffolder', () => {
13
- afterEach(() => {
14
- vi.clearAllMocks();
15
- });
12
+ const prompt = () => undefined;
16
13
 
17
14
  it('should execute the chosen scaffolder with the appropriate options', async () => {
18
- const decisions = any.simpleObject();
19
15
  const options = any.simpleObject();
20
16
  const chosenUpdater = any.word();
21
17
  const chosenUpdaterScaffolder = vi.fn();
22
18
  const plugins = {...any.simpleObject(), [chosenUpdater]: {scaffold: chosenUpdaterScaffolder}};
23
19
  const scaffolderResult = any.simpleObject();
24
- when(prompt.promptForDependencyUpdaterChoice)
25
- .calledWith(plugins, decisions)
20
+ when(promptForDependencyUpdaterChoice)
21
+ .calledWith(plugins, {prompt})
26
22
  .thenResolve({[questionNames.DEPENDENCY_UPDATER]: chosenUpdater});
27
23
  when(chosenUpdaterScaffolder).calledWith(options).thenResolve(scaffolderResult);
28
24
 
29
- expect(await scaffoldUpdater(plugins, decisions, options)).toEqual(scaffolderResult);
25
+ expect(await scaffoldUpdater(plugins, options, {prompt})).toEqual(scaffolderResult);
30
26
  });
31
27
 
32
28
  it('should not present a prompt if no updaters are registered', async () => {
package/src/index.js CHANGED
@@ -1,9 +1,7 @@
1
- import {questionNames as coreQuestionNames} from '@form8ion/core';
2
- import {questionNames as projectScaffolderQuestionNames} from './prompts/question-names.js';
1
+ import {ids} from './prompts/index.js';
3
2
 
4
3
  export * from './scaffolder.js';
5
4
  export {default as lift} from './lift.js';
6
- export const questionNames = {
7
- ...coreQuestionNames,
8
- ...projectScaffolderQuestionNames
9
- };
5
+ export const promptConstants = {ids};
6
+
7
+ export {questionNames} from './prompts/index.js';
@@ -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
@@ -1,7 +1,6 @@
1
1
  import deepmerge from 'deepmerge';
2
2
  import {execa} from 'execa';
3
3
  import {questionNames as coreQuestionNames} from '@form8ion/core';
4
- import {reportResults} from '@form8ion/results-reporter';
5
4
  import {scaffold as scaffoldReadme} from '@form8ion/readme';
6
5
  import {info} from '@travi/cli-messages';
7
6
 
@@ -15,9 +14,9 @@ import {scaffold as scaffoldEditorConfig} from './editorconfig/index.js';
15
14
  import {scaffold as scaffoldContributing} from './contributing/index.js';
16
15
  import lift from './lift.js';
17
16
 
18
- export async function scaffold(options) {
17
+ export async function scaffold(options, {prompt}) {
19
18
  const projectRoot = process.cwd();
20
- const {decisions, plugins: {dependencyUpdaters, languages, vcsHosts = {}}} = validate(options);
19
+ const {plugins: {dependencyUpdaters, languages, vcsHosts = {}}} = validate(options);
21
20
 
22
21
  const {
23
22
  [coreQuestionNames.PROJECT_NAME]: projectName,
@@ -26,11 +25,11 @@ export async function scaffold(options) {
26
25
  [coreQuestionNames.DESCRIPTION]: description,
27
26
  [coreQuestionNames.COPYRIGHT_YEAR]: copyrightYear,
28
27
  [coreQuestionNames.COPYRIGHT_HOLDER]: copyHolder
29
- } = await promptForBaseDetails(projectRoot, decisions);
28
+ } = await promptForBaseDetails(projectRoot, {prompt});
30
29
  const copyright = {year: copyrightYear, holder: copyHolder};
31
30
 
32
31
  const [vcsResults, contributing, license] = await Promise.all([
33
- scaffoldVcs({projectRoot, projectName, decisions, vcsHosts, visibility, description}),
32
+ scaffoldVcs({projectRoot, projectName, vcsHosts, visibility, description}, {prompt}),
34
33
  scaffoldContributing({visibility}),
35
34
  scaffoldLicense({projectRoot, license: chosenLicense, copyright}),
36
35
  scaffoldReadme({projectName, projectRoot, description}),
@@ -39,14 +38,14 @@ export async function scaffold(options) {
39
38
 
40
39
  const dependencyUpdaterResults = vcsResults.vcs && await scaffoldDependencyUpdater(
41
40
  dependencyUpdaters,
42
- decisions,
43
- {projectRoot, vcs: vcsResults.vcs}
41
+ {projectRoot},
42
+ {prompt}
44
43
  );
45
44
 
46
45
  const language = await scaffoldLanguage(
47
46
  languages,
48
- decisions,
49
- {projectRoot, projectName, vcs: vcsResults.vcs, visibility, license: chosenLicense || 'UNLICENSED', description}
47
+ {projectRoot, projectName, vcs: vcsResults.vcs, visibility, license: chosenLicense || 'UNLICENSED', description},
48
+ {prompt}
50
49
  );
51
50
 
52
51
  const mergedResults = deepmerge.all([
@@ -72,5 +71,5 @@ export async function scaffold(options) {
72
71
  await subprocess;
73
72
  }
74
73
 
75
- reportResults(mergedResults);
74
+ return mergedResults;
76
75
  }
@@ -2,7 +2,6 @@ import deepmerge from 'deepmerge';
2
2
  import {execa} from 'execa';
3
3
  import {questionNames as coreQuestionNames} from '@form8ion/core';
4
4
  import {scaffold as scaffoldReadme} from '@form8ion/readme';
5
- import * as resultsReporter from '@form8ion/results-reporter';
6
5
 
7
6
  import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
8
7
  import any from '@travi/any';
@@ -52,7 +51,7 @@ describe('project scaffolder', () => {
52
51
  const tags = any.listOf(any.word);
53
52
  const visibility = any.word();
54
53
  const vcsIgnore = any.simpleObject();
55
- const decisions = any.simpleObject();
54
+ const prompt = () => undefined;
56
55
 
57
56
  beforeEach(() => {
58
57
  process.cwd = vi.fn();
@@ -95,9 +94,9 @@ describe('project scaffolder', () => {
95
94
  ]);
96
95
  when(optionsValidator.validate)
97
96
  .calledWith(options)
98
- .thenReturn({decisions, plugins: {dependencyUpdaters, languages, vcsHosts}});
97
+ .thenReturn({plugins: {dependencyUpdaters, languages, vcsHosts}});
99
98
  when(prompts.promptForBaseDetails)
100
- .calledWith(projectPath, decisions)
99
+ .calledWith(projectPath, {prompt})
101
100
  .thenResolve({
102
101
  [coreQuestionNames.PROJECT_NAME]: projectName,
103
102
  [coreQuestionNames.LICENSE]: license,
@@ -107,25 +106,20 @@ describe('project scaffolder', () => {
107
106
  [coreQuestionNames.VISIBILITY]: visibility
108
107
  });
109
108
  when(scaffoldVcs)
110
- .calledWith({projectRoot: projectPath, projectName, decisions, vcsHosts, visibility, description})
109
+ .calledWith({projectRoot: projectPath, projectName, vcsHosts, visibility, description}, {prompt})
111
110
  .thenResolve(vcsResults);
112
111
  when(licenseScaffolder.default)
113
112
  .calledWith({projectRoot: projectPath, license, copyright})
114
113
  .thenResolve(licenseResults);
115
114
  scaffoldLanguage.mockResolvedValue(languageResults);
116
115
  when(dependencyUpdaterScaffolder.default)
117
- .calledWith(dependencyUpdaters, decisions, {projectRoot: projectPath, vcs})
116
+ .calledWith(dependencyUpdaters, {projectRoot: projectPath}, {prompt})
118
117
  .thenResolve(dependencyUpdaterResults);
119
118
  when(scaffoldContributing).calledWith({visibility}).thenReturn(contributingResults);
120
119
 
121
- await scaffold(options);
120
+ expect(await scaffold(options, {prompt})).toEqual(mergedResults);
122
121
 
123
122
  expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
124
- expect(dependencyUpdaterScaffolder.default).toHaveBeenCalledWith(
125
- dependencyUpdaters,
126
- decisions,
127
- {projectRoot: projectPath, vcs}
128
- );
129
123
  expect(scaffoldEditorconfig).toHaveBeenCalledWith({projectRoot: projectPath});
130
124
  expect(lift).toHaveBeenCalledWith({
131
125
  projectRoot: projectPath,
@@ -133,7 +127,6 @@ describe('project scaffolder', () => {
133
127
  results: mergedResults,
134
128
  enhancers: {...dependencyUpdaters, ...vcsHosts, ...languages}
135
129
  });
136
- expect(resultsReporter.reportResults).toHaveBeenCalledWith(mergedResults);
137
130
  });
138
131
 
139
132
  it('should pass the lists of badges from contributors to the readme', async () => {
@@ -160,7 +153,7 @@ describe('project scaffolder', () => {
160
153
  const languageResults = {badges: languageBadges, vcsIgnore, documentation};
161
154
  when(optionsValidator.validate).calledWith(options).thenReturn({plugins: {vcsHosts}});
162
155
  when(prompts.promptForBaseDetails)
163
- .calledWith(projectPath, undefined)
156
+ .calledWith(projectPath, {prompt})
164
157
  .thenResolve({
165
158
  [coreQuestionNames.DESCRIPTION]: description,
166
159
  [questionNames.GIT_REPO]: true,
@@ -173,7 +166,7 @@ describe('project scaffolder', () => {
173
166
  licenseScaffolder.default.mockResolvedValue({badges: licenseBadges});
174
167
  scaffoldVcs.mockResolvedValue(vcsResults);
175
168
 
176
- await scaffold(options);
169
+ await scaffold(options, {prompt});
177
170
 
178
171
  expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
179
172
  });
@@ -184,7 +177,7 @@ describe('project scaffolder', () => {
184
177
  scaffoldReadme.mockResolvedValue();
185
178
  scaffoldVcs.mockResolvedValue({});
186
179
 
187
- await scaffold(options);
180
+ await scaffold(options, {prompt});
188
181
 
189
182
  expect(dependencyUpdaterScaffolder.default).not.toHaveBeenCalled();
190
183
  });
@@ -209,9 +202,7 @@ describe('project scaffolder', () => {
209
202
  nextSteps: languageNextSteps,
210
203
  tags
211
204
  };
212
- when(optionsValidator.validate)
213
- .calledWith(options)
214
- .thenReturn({decisions, plugins: {languages, vcsHosts}});
205
+ when(optionsValidator.validate).calledWith(options).thenReturn({plugins: {languages, vcsHosts}});
215
206
  scaffoldVcs.mockResolvedValue(vcsResults);
216
207
  prompts.promptForBaseDetails.mockResolvedValue({
217
208
  [coreQuestionNames.PROJECT_NAME]: projectName,
@@ -220,30 +211,29 @@ describe('project scaffolder', () => {
220
211
  [coreQuestionNames.LICENSE]: license,
221
212
  [coreQuestionNames.DESCRIPTION]: description
222
213
  });
223
- when(scaffoldLanguage).calledWith(languages, decisions, {
214
+ when(scaffoldLanguage).calledWith(languages, {
224
215
  projectName,
225
216
  projectRoot: projectPath,
226
217
  visibility,
227
218
  license,
228
219
  vcs,
229
220
  description
230
- }).thenResolve(languageResults);
221
+ }, {prompt}).thenResolve(languageResults);
231
222
  when(execa).calledWith(verificationCommand, {shell: true}).thenReturn({stdout: {pipe: execaPipe}});
232
223
  dependencyUpdaterScaffolder.default.mockResolvedValue({});
233
224
  licenseScaffolder.default.mockResolvedValue({});
234
225
  scaffoldContributing.mockResolvedValue({});
235
226
 
236
- await scaffold(options);
227
+ await scaffold(options, {prompt});
237
228
 
238
229
  expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
239
230
  expect(execaPipe).toHaveBeenCalledWith(process.stdout);
240
- expect(resultsReporter.reportResults).toHaveBeenCalledWith(deepmerge.all([languageResults, vcsResults]));
241
231
  });
242
232
 
243
233
  it('should consider the language details to be optional', async () => {
244
234
  when(optionsValidator.validate)
245
235
  .calledWith(options)
246
- .thenReturn({vcsHosts, decisions, plugins: {languages}});
236
+ .thenReturn({vcsHosts, plugins: {languages}});
247
237
  scaffoldVcs.mockResolvedValue(vcsResults);
248
238
  prompts.promptForBaseDetails.mockResolvedValue({
249
239
  [coreQuestionNames.PROJECT_NAME]: projectName,
@@ -257,22 +247,21 @@ describe('project scaffolder', () => {
257
247
  licenseScaffolder.default.mockResolvedValue({});
258
248
  scaffoldContributing.mockResolvedValue({});
259
249
 
260
- await scaffold(options);
250
+ await scaffold(options, {prompt});
261
251
 
262
252
  expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
263
253
  expect(execa).not.toHaveBeenCalled();
264
254
  });
265
255
 
266
256
  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});
257
+ when(optionsValidator.validate).calledWith(options).thenReturn({plugins: {languages}});
268
258
  prompts.promptForBaseDetails.mockResolvedValue({});
269
259
  scaffoldVcs.mockResolvedValue(vcsResults);
270
260
 
271
- await scaffold(options);
261
+ await scaffold(options, {prompt});
272
262
 
273
263
  expect(scaffoldLanguage).toHaveBeenCalledWith(
274
264
  languages,
275
- decisions,
276
265
  {
277
266
  license: 'UNLICENSED',
278
267
  description: undefined,
@@ -280,7 +269,8 @@ describe('project scaffolder', () => {
280
269
  projectRoot: projectPath,
281
270
  vcs,
282
271
  visibility: undefined
283
- }
272
+ },
273
+ {prompt}
284
274
  );
285
275
  });
286
276
 
@@ -290,7 +280,7 @@ describe('project scaffolder', () => {
290
280
  scaffoldVcs.mockResolvedValue({});
291
281
  scaffoldLanguage.mockResolvedValue({badges: {}, projectDetails: {}});
292
282
 
293
- await scaffold(options);
283
+ await scaffold(options, {prompt});
294
284
 
295
285
  expect(execa).not.toHaveBeenCalled();
296
286
  });
@@ -1,5 +1,5 @@
1
1
  import {simpleGit} from 'simple-git';
2
- import hostedGitInfo from 'hosted-git-info';
2
+ import parseGitUrl from 'git-url-parse';
3
3
  import {warn} from '@travi/cli-messages';
4
4
 
5
5
  async function getExistingRemotes(git) {
@@ -17,9 +17,9 @@ async function getExistingRemotes(git) {
17
17
  export async function determineExistingVcsDetails({projectRoot}) {
18
18
  const git = simpleGit({baseDir: projectRoot});
19
19
  const remoteOrigin = await git.remote(['get-url', 'origin']);
20
- const {user, project, type} = hostedGitInfo.fromUrl(remoteOrigin);
20
+ const {owner, name, host} = parseGitUrl(remoteOrigin.trimEnd());
21
21
 
22
- return {vcs: {owner: user, name: project, host: type}};
22
+ return {vcs: {owner, name, host: 'github.com' === host ? 'github' : host}};
23
23
  }
24
24
 
25
25
  export async function defineRemoteOrigin(projectRoot, sshUrl) {
@@ -1,35 +1,54 @@
1
1
  import {simpleGit} from 'simple-git';
2
- import hostedGitInfo from 'hosted-git-info';
2
+ import parseGitUrl from 'git-url-parse';
3
3
 
4
- import {describe, vi, it, expect} from 'vitest';
4
+ import {describe, vi, it, expect, beforeEach} from 'vitest';
5
5
  import {when} from 'vitest-when';
6
6
  import any from '@travi/any';
7
7
 
8
8
  import {determineExistingVcsDetails, defineRemoteOrigin} from './remotes.js';
9
9
 
10
10
  vi.mock('simple-git');
11
- vi.mock('hosted-git-info');
11
+ vi.mock('git-url-parse');
12
12
 
13
13
  describe('Git remote', () => {
14
14
  const projectRoot = any.string();
15
15
 
16
16
  describe('determine', () => {
17
+ const remote = vi.fn();
18
+ const remoteOrigin = any.url();
19
+ const repoName = any.word();
20
+ const vcsHostAccount = any.word();
21
+
22
+ beforeEach(() => {
23
+ when(simpleGit).calledWith({baseDir: projectRoot}).thenReturn({remote});
24
+ });
25
+
17
26
  it('should determine existing vcs details from the remote origin definition of the local repository', async () => {
18
- const remote = vi.fn();
19
- const remoteOrigin = any.url();
20
- const repoName = any.word();
21
27
  const vcsHost = `F${any.word()})O${any.word()}O`;
22
- const vcsHostAccount = any.word();
23
- when(simpleGit).calledWith({baseDir: projectRoot}).thenReturn({remote});
24
- when(remote).calledWith(['get-url', 'origin']).thenResolve(remoteOrigin);
25
- when(hostedGitInfo.fromUrl)
28
+ when(remote).calledWith(['get-url', 'origin']).thenResolve(`${remoteOrigin}\n`);
29
+ when(parseGitUrl)
26
30
  .calledWith(remoteOrigin)
27
- .thenReturn({user: vcsHostAccount, project: repoName, type: vcsHost.toLowerCase()});
31
+ .thenReturn({owner: vcsHostAccount, name: repoName, host: vcsHost.toLowerCase()});
28
32
 
29
33
  const {vcs: hostDetails} = await determineExistingVcsDetails({projectRoot});
30
34
 
31
35
  expect(hostDetails).toEqual({host: vcsHost.toLowerCase(), owner: vcsHostAccount, name: repoName});
32
36
  });
37
+
38
+ it(
39
+ 'should return `github` when the host is determined to be `github.com` until that can be a breaking change',
40
+ async () => {
41
+ when(simpleGit).calledWith({baseDir: projectRoot}).thenReturn({remote});
42
+ when(remote).calledWith(['get-url', 'origin']).thenResolve(`${remoteOrigin}\n`);
43
+ when(parseGitUrl)
44
+ .calledWith(remoteOrigin)
45
+ .thenReturn({owner: vcsHostAccount, name: repoName, host: 'github.com'});
46
+
47
+ const {vcs: hostDetails} = await determineExistingVcsDetails({projectRoot});
48
+
49
+ expect(hostDetails).toEqual({host: 'github', owner: vcsHostAccount, name: repoName});
50
+ }
51
+ );
33
52
  });
34
53
 
35
54
  describe('define', () => {