@form8ion/project 22.0.0-beta.2 → 22.0.0-beta.21

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.
Files changed (55) hide show
  1. package/README.md +70 -26
  2. package/lib/index.js +207 -105
  3. package/lib/index.js.map +1 -1
  4. package/package.json +28 -29
  5. package/src/ci-provider/index.js +1 -0
  6. package/src/ci-provider/prompt.js +17 -0
  7. package/src/ci-provider/prompt.test.js +27 -0
  8. package/src/ci-provider/scaffolder.js +27 -0
  9. package/src/ci-provider/scaffolder.test.js +68 -0
  10. package/src/ci-provider/schema.js +4 -0
  11. package/src/ci-provider/schema.test.js +43 -0
  12. package/src/contributing/scaffolder.js +2 -2
  13. package/src/contributing/scaffolder.test.js +14 -2
  14. package/src/dependency-updater/prompt.js +14 -8
  15. package/src/dependency-updater/prompt.test.js +16 -17
  16. package/src/dependency-updater/scaffolder.js +4 -2
  17. package/src/dependency-updater/scaffolder.test.js +18 -15
  18. package/src/editorconfig/index.js +1 -0
  19. package/src/editorconfig/scaffolder.js +1 -1
  20. package/src/editorconfig/tester.js +5 -0
  21. package/src/editorconfig/tester.test.js +25 -0
  22. package/src/index.js +1 -7
  23. package/src/language/prompt.js +14 -9
  24. package/src/language/prompt.test.js +15 -16
  25. package/src/language/scaffolder.js +4 -2
  26. package/src/language/scaffolder.test.js +13 -8
  27. package/src/license/lifter.js +1 -1
  28. package/src/license/scaffolder.js +2 -3
  29. package/src/license/scaffolder.test.js +5 -8
  30. package/src/license/tester.js +1 -1
  31. package/src/lift.js +8 -2
  32. package/src/lift.test.js +26 -13
  33. package/src/options-validator.js +3 -3
  34. package/src/options-validator.test.js +4 -6
  35. package/src/prompts/index.js +20 -0
  36. package/src/prompts/question-names.js +19 -5
  37. package/src/prompts/questions.js +7 -3
  38. package/src/prompts/questions.test.js +5 -6
  39. package/src/scaffolder.js +18 -17
  40. package/src/scaffolder.test.js +39 -31
  41. package/src/template-path.js +1 -1
  42. package/src/vcs/git/remotes.js +6 -7
  43. package/src/vcs/git/remotes.test.js +21 -16
  44. package/src/vcs/host/prompt.js +15 -10
  45. package/src/vcs/host/prompt.test.js +31 -25
  46. package/src/vcs/host/scaffolder.js +4 -2
  47. package/src/vcs/host/scaffolder.test.js +9 -7
  48. package/src/vcs/prompt.js +11 -9
  49. package/src/vcs/prompt.test.js +15 -12
  50. package/src/vcs/scaffolder.js +9 -11
  51. package/src/vcs/scaffolder.test.js +10 -9
  52. package/src/options-schemas.js +0 -3
  53. package/src/options-schemas.test.js +0 -20
  54. package/src/prompts/conditionals.js +0 -13
  55. package/src/prompts/conditionals.test.js +0 -51
@@ -2,6 +2,6 @@ import {promises as fs} from 'node:fs';
2
2
 
3
3
  import determinePathToTemplateFile from '../template-path.js';
4
4
 
5
- export default function ({projectRoot}) {
5
+ export default function scaffoldEditorConfig({projectRoot}) {
6
6
  return fs.copyFile(determinePathToTemplateFile('editorconfig.ini'), `${projectRoot}/.editorconfig`);
7
7
  }
@@ -0,0 +1,5 @@
1
+ import {fileExists} from '@form8ion/core';
2
+
3
+ export default function editorconfigInUse({projectRoot}) {
4
+ return fileExists(`${projectRoot}/.editorconfig`);
5
+ }
@@ -0,0 +1,25 @@
1
+ import {fileExists} from '@form8ion/core';
2
+
3
+ import {describe, it, vi, expect} from 'vitest';
4
+ import {when} from 'vitest-when';
5
+ import any from '@travi/any';
6
+
7
+ import editorconfigInUse from './tester.js';
8
+
9
+ vi.mock('@form8ion/core');
10
+
11
+ describe('editorconfig tester', () => {
12
+ const projectRoot = any.string();
13
+
14
+ it('should return `true` if an `.editorconfig` file exists', async () => {
15
+ when(fileExists).calledWith(`${projectRoot}/.editorconfig`).thenResolve(true);
16
+
17
+ expect(await editorconfigInUse({projectRoot})).toBe(true);
18
+ });
19
+
20
+ it('should return `false` if an `.editorconfig` file does not exist', async () => {
21
+ when(fileExists).calledWith(`${projectRoot}/.editorconfig`).thenResolve(false);
22
+
23
+ expect(await editorconfigInUse({projectRoot})).toBe(false);
24
+ });
25
+ });
package/src/index.js CHANGED
@@ -1,9 +1,3 @@
1
- import {questionNames as coreQuestionNames} from '@form8ion/core';
2
- import {questionNames as projectScaffolderQuestionNames} from './prompts/question-names.js';
3
-
4
1
  export * from './scaffolder.js';
5
2
  export {default as lift} from './lift.js';
6
- export const questionNames = {
7
- ...coreQuestionNames,
8
- ...projectScaffolderQuestionNames
9
- };
3
+ export {constants as promptConstants} from './prompts/index.js';
@@ -1,12 +1,17 @@
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
+ const {PROJECT_LANGUAGE} = questionNames.PROJECT_LANGUAGE;
6
+
7
+ export default function promptForProjectLanguage(languages, {prompt}) {
8
+ return prompt({
9
+ id: PROJECT_LANGUAGE_PROMPT_ID,
10
+ questions: [{
11
+ name: PROJECT_LANGUAGE,
12
+ type: 'list',
13
+ message: 'What type of project is this?',
14
+ choices: [...Object.keys(languages), 'Other']
15
+ }]
16
+ });
12
17
  }
@@ -1,30 +1,29 @@
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
- describe('language prompt', () => {
13
- afterEach(() => {
14
- vi.clearAllMocks();
15
- });
10
+ const {PROJECT_LANGUAGE} = questionNames.PROJECT_LANGUAGE;
16
11
 
12
+ describe('language prompt', () => {
17
13
  it('should prompt for the language details', async () => {
14
+ const prompt = vi.fn();
18
15
  const answers = any.simpleObject();
19
- const decisions = any.simpleObject();
20
16
  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);
17
+ when(prompt).calledWith({
18
+ id: PROJECT_LANGUAGE_PROMPT_ID,
19
+ questions: [{
20
+ name: PROJECT_LANGUAGE,
21
+ type: 'list',
22
+ message: 'What type of project is this?',
23
+ choices: [...Object.keys(languages), 'Other']
24
+ }]
25
+ }).thenResolve(answers);
27
26
 
28
- expect(await promptForLanguageDetails(languages, decisions)).toEqual(answers);
27
+ expect(await promptForLanguageDetails(languages, {prompt})).toEqual(answers);
29
28
  });
30
29
  });
@@ -1,8 +1,10 @@
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
+ const {PROJECT_LANGUAGE} = questionNames.PROJECT_LANGUAGE;
5
+
6
+ export default async function scaffoldLanguage(languagePlugins, options, {prompt}) {
7
+ const {[PROJECT_LANGUAGE]: chosenLanguage} = await promptForLanguageDetails(languagePlugins, {prompt});
6
8
 
7
9
  const plugin = languagePlugins[chosenLanguage];
8
10
 
@@ -2,31 +2,36 @@ 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 languagePrompt from './prompt.js';
5
+ import promptForProjectLanguage from './prompt.js';
6
6
  import {questionNames} from '../prompts/question-names.js';
7
7
  import scaffold from './scaffolder.js';
8
8
 
9
9
  vi.mock('./prompt.js');
10
10
 
11
+ const {PROJECT_LANGUAGE} = questionNames.PROJECT_LANGUAGE;
12
+
11
13
  describe('language scaffolder', () => {
12
14
  it('should scaffold the chosen language', async () => {
13
15
  const options = any.simpleObject();
14
16
  const chosenLanguage = any.word();
15
17
  const scaffolderResult = any.simpleObject();
16
- const decisions = any.simpleObject();
18
+ const prompt = () => undefined;
17
19
  const chosenLanguageScaffolder = vi.fn();
18
20
  const plugins = {...any.simpleObject(), [chosenLanguage]: {scaffold: chosenLanguageScaffolder}};
19
- when(languagePrompt.default)
20
- .calledWith(plugins, decisions)
21
- .thenResolve({[questionNames.PROJECT_LANGUAGE]: chosenLanguage});
21
+ when(promptForProjectLanguage)
22
+ .calledWith(plugins, {prompt})
23
+ .thenResolve({[PROJECT_LANGUAGE]: chosenLanguage});
22
24
  when(chosenLanguageScaffolder).calledWith(options).thenResolve(scaffolderResult);
23
25
 
24
- expect(await scaffold(plugins, decisions, options)).toEqual(scaffolderResult);
26
+ expect(await scaffold(plugins, options, {prompt})).toEqual(scaffolderResult);
25
27
  });
26
28
 
27
29
  it('should not result in an error when choosing a language without a defined scaffolder', async () => {
28
- languagePrompt.default.mockResolvedValue({[questionNames.PROJECT_LANGUAGE]: any.word()});
30
+ const plugins = any.simpleObject();
31
+ const options = any.simpleObject();
32
+ const dependencies = {prompt: undefined};
33
+ when(promptForProjectLanguage).calledWith(plugins, dependencies).thenResolve({[PROJECT_LANGUAGE]: any.word()});
29
34
 
30
- await scaffold(any.simpleObject(), any.simpleObject(), any.simpleObject());
35
+ await scaffold(plugins, options, dependencies);
31
36
  });
32
37
  });
@@ -2,7 +2,7 @@ function repositoryIsHostedOnGithub(vcs) {
2
2
  return vcs && 'github' === vcs.host;
3
3
  }
4
4
 
5
- export default function ({vcs}) {
5
+ export default function liftLicense({vcs}) {
6
6
  return {
7
7
  ...repositoryIsHostedOnGithub(vcs) && {
8
8
  badges: {
@@ -3,11 +3,10 @@ import wrap from 'word-wrap';
3
3
  import mustache from 'mustache';
4
4
  // eslint-disable-next-line import/extensions
5
5
  import spdxLicenseList from 'spdx-license-list/full.js';
6
- import {info} from '@travi/cli-messages';
7
6
 
8
- export default async function ({projectRoot, license, copyright}) {
7
+ export default async function scaffoldLicense({projectRoot, license, copyright}, {logger}) {
9
8
  if (license) {
10
- info('Generating License');
9
+ logger.info('Generating License');
11
10
 
12
11
  const licenseContent = spdxLicenseList[license].licenseText;
13
12
 
@@ -3,7 +3,7 @@ import wrap from 'word-wrap';
3
3
  import spdxLicenseListWithContent from 'spdx-license-list/full';
4
4
  import spdxLicenseList from 'spdx-license-list/simple';
5
5
 
6
- import {afterEach, describe, expect, it, vi} from 'vitest';
6
+ import {describe, expect, it, vi} from 'vitest';
7
7
  import any from '@travi/any';
8
8
 
9
9
  import scaffoldLicense from './scaffolder.js';
@@ -16,19 +16,16 @@ describe('license', () => {
16
16
  const copyrightHolders = any.sentence();
17
17
  const copyright = {year, holder: copyrightHolders};
18
18
  const projectRoot = any.string();
19
-
20
- afterEach(() => {
21
- vi.clearAllMocks();
22
- });
19
+ const logger = {info: () => {}};
23
20
 
24
21
  it('should not generate a license file when no license was chosen', async () => {
25
- await scaffoldLicense({});
22
+ await scaffoldLicense({}, {logger});
26
23
 
27
24
  expect(fs.writeFile).not.toHaveBeenCalled();
28
25
  });
29
26
 
30
27
  it('should write the contents for the chosen license to LICENSE', async () => {
31
- expect(await scaffoldLicense({projectRoot, license, copyright, vcs: {}})).toEqual({});
28
+ expect(await scaffoldLicense({projectRoot, license, copyright, vcs: {}}, {logger})).toEqual({});
32
29
 
33
30
  expect(fs.writeFile).toHaveBeenCalledWith(
34
31
  `${projectRoot}/LICENSE`,
@@ -43,7 +40,7 @@ describe('license', () => {
43
40
  });
44
41
 
45
42
  it('should write the common version of the MIT license to LICENSE, when chosen', async () => {
46
- expect(await scaffoldLicense({projectRoot, license: 'MIT', copyright, vcs: {}})).toEqual({});
43
+ expect(await scaffoldLicense({projectRoot, license: 'MIT', copyright, vcs: {}}, {logger})).toEqual({});
47
44
 
48
45
  expect(fs.writeFile).toHaveBeenCalledWith(
49
46
  `${projectRoot}/LICENSE`,
@@ -1,5 +1,5 @@
1
1
  import {fileExists} from '@form8ion/core';
2
2
 
3
- export default function ({projectRoot}) {
3
+ export default function licenseDefined({projectRoot}) {
4
4
  return fileExists(`${projectRoot}/LICENSE`);
5
5
  }
package/src/lift.js CHANGED
@@ -1,13 +1,19 @@
1
1
  import {applyEnhancers} from '@form8ion/core';
2
2
  import {lift as liftReadme} from '@form8ion/readme';
3
3
  import * as gitPlugin from '@form8ion/git';
4
+ import * as misePlugin from '@form8ion/mise';
4
5
 
6
+ import {scaffold as scaffoldEditorconfig, test as editorconfigInUse} from './editorconfig/index.js';
5
7
  import * as licensePlugin from './license/index.js';
6
8
 
7
- export default async function ({projectRoot, results, enhancers, vcs, dependencies}) {
9
+ export default async function lift({projectRoot, results, enhancers, vcs}, dependencies) {
10
+ if (!await editorconfigInUse({projectRoot})) {
11
+ await scaffoldEditorconfig({projectRoot});
12
+ }
13
+
8
14
  const enhancerResults = await applyEnhancers({
9
15
  results,
10
- enhancers: {...enhancers, gitPlugin, licensePlugin},
16
+ enhancers: {...enhancers, gitPlugin, licensePlugin, misePlugin},
11
17
  options: {projectRoot, vcs},
12
18
  dependencies
13
19
  });
package/src/lift.test.js CHANGED
@@ -1,40 +1,53 @@
1
1
  import * as core from '@form8ion/core';
2
2
  import * as readme from '@form8ion/readme';
3
3
  import * as gitPlugin from '@form8ion/git';
4
+ import * as misePlugin from '@form8ion/mise';
4
5
 
5
- import {afterEach, describe, expect, it, vi} from 'vitest';
6
+ import {beforeEach, describe, expect, it, vi} from 'vitest';
6
7
  import any from '@travi/any';
7
8
  import {when} from 'vitest-when';
8
9
 
10
+ import {scaffold as scaffoldEditorconfig, test as editorconfigInUse} from './editorconfig/index.js';
9
11
  import * as licensePlugin from './license/index.js';
10
12
  import lift from './lift.js';
11
13
 
12
14
  vi.mock('deepmerge');
13
15
  vi.mock('@form8ion/core');
14
16
  vi.mock('@form8ion/readme');
17
+ vi.mock('./editorconfig/index.js');
15
18
 
16
19
  describe('lift', () => {
17
- afterEach(() => {
18
- vi.clearAllMocks();
19
- });
20
+ const projectRoot = any.string();
21
+ const results = any.simpleObject();
22
+ const enhancers = any.simpleObject();
23
+ const vcs = any.simpleObject();
24
+ const dependencies = any.simpleObject();
25
+ const enhancerResults = any.simpleObject();
20
26
 
21
- it('should lift the README based on the provided results', async () => {
22
- const projectRoot = any.string();
23
- const enhancers = any.simpleObject();
24
- const dependencies = any.simpleObject();
25
- const vcs = any.simpleObject();
26
- const results = any.simpleObject();
27
- const enhancerResults = any.simpleObject();
27
+ beforeEach(() => {
28
28
  when(core.applyEnhancers)
29
29
  .calledWith({
30
30
  results,
31
- enhancers: {...enhancers, gitPlugin, licensePlugin},
31
+ enhancers: {...enhancers, gitPlugin, licensePlugin, misePlugin},
32
32
  options: {projectRoot, vcs},
33
33
  dependencies
34
34
  })
35
35
  .thenResolve(enhancerResults);
36
+ });
37
+
38
+ it('should lift the README based on the provided results', async () => {
39
+ when(editorconfigInUse).calledWith({projectRoot}).thenResolve(true);
36
40
 
37
- expect(await lift({projectRoot, results, enhancers, vcs, dependencies})).toEqual(enhancerResults);
41
+ expect(await lift({projectRoot, results, enhancers, vcs}, dependencies)).toEqual(enhancerResults);
38
42
  expect(readme.lift).toHaveBeenCalledWith({projectRoot, results: enhancerResults});
43
+ expect(scaffoldEditorconfig).not.toHaveBeenCalled();
44
+ });
45
+
46
+ it('should scaffold editorconfig when it isnt already in use', async () => {
47
+ when(editorconfigInUse).calledWith({projectRoot}).thenResolve(false);
48
+
49
+ await lift({projectRoot, results, enhancers, vcs, dependencies});
50
+
51
+ expect(scaffoldEditorconfig).toHaveBeenCalledWith({projectRoot});
39
52
  });
40
53
  });
@@ -4,15 +4,15 @@ 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';
7
+ import ciProviderPluginsSchema from './ci-provider/schema.js';
8
8
 
9
9
  export function validate(options) {
10
10
  return validateOptions(joi.object({
11
- decisions: decisionsSchema,
12
11
  plugins: joi.object({
13
12
  dependencyUpdaters: dependencyUpdaterPluginsSchema,
14
13
  languages: languagePluginsSchema,
15
- vcsHosts: vcsHostPluginsSchema
14
+ vcsHosts: vcsHostPluginsSchema,
15
+ ciProviders: ciProviderPluginsSchema
16
16
  })
17
17
  }), options) || {};
18
18
  }
@@ -5,8 +5,8 @@ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
5
5
  import any from '@travi/any';
6
6
  import {when} from 'vitest-when';
7
7
 
8
+ import ciProviderPluginsSchema from './ci-provider/schema.js';
8
9
  import languagePluginsSchema from './language/schema.js';
9
- import {decisionsSchema} from './options-schemas.js';
10
10
  import vcsHostPluginsSchema from './vcs/host/schema.js';
11
11
  import dependencyUpdaterPluginsSchema from './dependency-updater/schema.js';
12
12
  import {validate} from './options-validator.js';
@@ -36,13 +36,11 @@ describe('options validator', () => {
36
36
  .calledWith({
37
37
  dependencyUpdaters: dependencyUpdaterPluginsSchema,
38
38
  languages: languagePluginsSchema,
39
- vcsHosts: vcsHostPluginsSchema
39
+ vcsHosts: vcsHostPluginsSchema,
40
+ ciProviders: ciProviderPluginsSchema
40
41
  })
41
42
  .thenReturn(pluginsSchema);
42
- when(joi.object).calledWith({
43
- decisions: decisionsSchema,
44
- plugins: pluginsSchema
45
- }).thenReturn(fullSchema);
43
+ when(joi.object).calledWith({plugins: pluginsSchema}).thenReturn(fullSchema);
46
44
  when(core.validateOptions).calledWith(fullSchema, options).thenReturn(validatedOptions);
47
45
 
48
46
  expect(validate(options)).toEqual(validatedOptions);
@@ -0,0 +1,20 @@
1
+ import {BASE_DETAILS_PROMPT_ID} from './questions.js';
2
+ import {GIT_REPOSITORY_PROMPT_ID} from '../vcs/prompt.js';
3
+ import {PROJECT_LANGUAGE_PROMPT_ID} from '../language/prompt.js';
4
+ import {REPOSITORY_HOST_PROMPT_ID} from '../vcs/host/prompt.js';
5
+ import {DEPENDENCY_UPDATER_PROMPT_ID} from '../dependency-updater/prompt.js';
6
+ import {CI_PROVIDER_PROMPT_ID} from '../ci-provider/prompt.js';
7
+ import {questionNames} from './question-names.js';
8
+
9
+ export const ids = {
10
+ BASE_DETAILS: BASE_DETAILS_PROMPT_ID,
11
+ GIT_REPOSITORY: GIT_REPOSITORY_PROMPT_ID,
12
+ REPOSITORY_HOST: REPOSITORY_HOST_PROMPT_ID,
13
+ PROJECT_LANGUAGE: PROJECT_LANGUAGE_PROMPT_ID,
14
+ DEPENDENCY_UPDATER: DEPENDENCY_UPDATER_PROMPT_ID,
15
+ CI_PROVIDER: CI_PROVIDER_PROMPT_ID
16
+ };
17
+
18
+ export {questionNames};
19
+
20
+ export const constants = {ids, questionNames};
@@ -1,7 +1,21 @@
1
+ import {questionNames as coreQuestionNames} from '@form8ion/core';
2
+
1
3
  export const questionNames = {
2
- GIT_REPO: 'gitRepo',
3
- REPO_HOST: 'repoHost',
4
- REPO_OWNER: 'repoOwner',
5
- PROJECT_LANGUAGE: 'projectLanguage',
6
- DEPENDENCY_UPDATER: 'dependencyUpdater'
4
+ BASE_DETAILS: coreQuestionNames,
5
+ GIT_REPOSITORY: {
6
+ GIT_REPO: 'gitRepo'
7
+ },
8
+ REPOSITORY_HOST: {
9
+ REPO_HOST: 'repoHost',
10
+ REPO_OWNER: 'repoOwner'
11
+ },
12
+ PROJECT_LANGUAGE: {
13
+ PROJECT_LANGUAGE: 'projectLanguage'
14
+ },
15
+ DEPENDENCY_UPDATER: {
16
+ DEPENDENCY_UPDATER: 'dependencyUpdater'
17
+ },
18
+ CI_PROVIDER: {
19
+ CI_PROVIDER: 'ciProvider'
20
+ }
7
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,23 +1,23 @@
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
- import {info} from '@travi/cli-messages';
7
5
 
8
6
  import {scaffold as scaffoldLanguage} from './language/index.js';
9
7
  import {scaffold as scaffoldVcs} from './vcs/index.js';
10
8
  import {scaffold as scaffoldLicense} from './license/index.js';
11
9
  import scaffoldDependencyUpdater from './dependency-updater/scaffolder.js';
10
+ import {scaffold as scaffoldCiProvider} from './ci-provider/index.js';
12
11
  import {promptForBaseDetails} from './prompts/questions.js';
13
12
  import {validate} from './options-validator.js';
14
13
  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, dependencies) {
19
18
  const projectRoot = process.cwd();
20
- const {decisions, plugins: {dependencyUpdaters, languages, vcsHosts = {}}} = validate(options);
19
+ const {plugins: {dependencyUpdaters, ciProviders, languages, vcsHosts = {}}} = validate(options);
20
+ const {prompt, logger} = dependencies;
21
21
 
22
22
  const {
23
23
  [coreQuestionNames.PROJECT_NAME]: projectName,
@@ -26,27 +26,28 @@ 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, logger}),
34
34
  scaffoldContributing({visibility}),
35
- scaffoldLicense({projectRoot, license: chosenLicense, copyright}),
35
+ scaffoldLicense({projectRoot, license: chosenLicense, copyright}, {logger}),
36
36
  scaffoldReadme({projectName, projectRoot, description}),
37
37
  scaffoldEditorConfig({projectRoot})
38
38
  ]);
39
39
 
40
- const dependencyUpdaterResults = vcsResults.vcs && await scaffoldDependencyUpdater(
41
- dependencyUpdaters,
42
- decisions,
43
- {projectRoot}
44
- );
40
+ const [dependencyUpdaterResults] = vcsResults.vcs
41
+ ? await Promise.all([
42
+ scaffoldDependencyUpdater(dependencyUpdaters, {projectRoot}, {prompt}),
43
+ scaffoldCiProvider(ciProviders, {projectRoot}, {prompt})
44
+ ])
45
+ : [];
45
46
 
46
47
  const language = await scaffoldLanguage(
47
48
  languages,
48
- decisions,
49
- {projectRoot, projectName, vcs: vcsResults.vcs, visibility, license: chosenLicense || 'UNLICENSED', description}
49
+ {projectRoot, projectName, vcs: vcsResults.vcs, visibility, license: chosenLicense || 'UNLICENSED', description},
50
+ {prompt}
50
51
  );
51
52
 
52
53
  const mergedResults = deepmerge.all([
@@ -62,15 +63,15 @@ export async function scaffold(options) {
62
63
  vcs: vcsResults.vcs,
63
64
  results: mergedResults,
64
65
  enhancers: {...dependencyUpdaters, ...languages, ...vcsHosts}
65
- });
66
+ }, dependencies);
66
67
 
67
68
  if (language && language.verificationCommand) {
68
- info('Verifying the generated project');
69
+ logger.info('Verifying the generated project');
69
70
 
70
71
  const subprocess = execa(language.verificationCommand, {shell: true});
71
72
  subprocess.stdout.pipe(process.stdout);
72
73
  await subprocess;
73
74
  }
74
75
 
75
- reportResults(mergedResults);
76
+ return mergedResults;
76
77
  }