@form8ion/project 22.0.0-beta.13 → 22.0.0-beta.15
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.
- package/README.md +43 -11
- package/lib/index.js +162 -102
- package/lib/index.js.map +1 -1
- package/package.json +9 -9
- package/src/ci-provider/index.js +1 -0
- package/src/ci-provider/prompt.js +17 -0
- package/src/ci-provider/prompt.test.js +27 -0
- package/src/ci-provider/scaffolder.js +23 -0
- package/src/ci-provider/scaffolder.test.js +55 -0
- package/src/contributing/scaffolder.js +1 -1
- package/src/dependency-updater/prompt.js +3 -1
- package/src/dependency-updater/prompt.test.js +4 -2
- package/src/dependency-updater/scaffolder.js +4 -2
- package/src/dependency-updater/scaffolder.test.js +11 -4
- package/src/editorconfig/scaffolder.js +1 -1
- package/src/index.js +1 -5
- package/src/language/prompt.js +3 -1
- package/src/language/prompt.test.js +3 -1
- package/src/language/scaffolder.js +4 -2
- package/src/language/scaffolder.test.js +10 -5
- package/src/license/lifter.js +1 -1
- package/src/license/tester.js +1 -1
- package/src/prompts/index.js +7 -8
- package/src/prompts/question-names.js +19 -5
- package/src/scaffolder.js +8 -6
- package/src/scaffolder.test.js +16 -5
- package/src/template-path.js +1 -1
- package/src/vcs/host/prompt.js +4 -2
- package/src/vcs/host/prompt.test.js +6 -4
- package/src/vcs/host/scaffolder.js +3 -1
- package/src/vcs/host/scaffolder.test.js +4 -2
- package/src/vcs/prompt.js +4 -2
- package/src/vcs/prompt.test.js +4 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {questionNames} from '../prompts/question-names.js';
|
|
2
|
+
|
|
3
|
+
export const CI_PROVIDER_PROMPT_ID = 'CI_PROVIDER';
|
|
4
|
+
|
|
5
|
+
const {CI_PROVIDER} = questionNames.CI_PROVIDER;
|
|
6
|
+
|
|
7
|
+
export default function promptForCiProvider(providers, {prompt}) {
|
|
8
|
+
return prompt({
|
|
9
|
+
id: CI_PROVIDER_PROMPT_ID,
|
|
10
|
+
questions: [{
|
|
11
|
+
name: CI_PROVIDER,
|
|
12
|
+
type: 'list',
|
|
13
|
+
message: 'Which CI service do you want use with this project?',
|
|
14
|
+
choices: [...Object.keys(providers), 'Other']
|
|
15
|
+
}]
|
|
16
|
+
});
|
|
17
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {describe, it, expect, vi} from 'vitest';
|
|
2
|
+
import any from '@travi/any';
|
|
3
|
+
import {when} from 'vitest-when';
|
|
4
|
+
|
|
5
|
+
import promptForCiProvider, {CI_PROVIDER_PROMPT_ID} from './prompt.js';
|
|
6
|
+
import {questionNames} from '../prompts/index.js';
|
|
7
|
+
|
|
8
|
+
const {CI_PROVIDER} = questionNames.CI_PROVIDER;
|
|
9
|
+
|
|
10
|
+
describe('ci-provider-prompt', () => {
|
|
11
|
+
it('should prompt for the provider choice', async () => {
|
|
12
|
+
const prompt = vi.fn();
|
|
13
|
+
const answers = any.simpleObject();
|
|
14
|
+
const providers = any.simpleObject();
|
|
15
|
+
when(prompt).calledWith({
|
|
16
|
+
id: CI_PROVIDER_PROMPT_ID,
|
|
17
|
+
questions: [{
|
|
18
|
+
name: CI_PROVIDER,
|
|
19
|
+
type: 'list',
|
|
20
|
+
message: 'Which CI service do you want use with this project?',
|
|
21
|
+
choices: [...Object.keys(providers), 'Other']
|
|
22
|
+
}]
|
|
23
|
+
}).thenResolve(answers);
|
|
24
|
+
|
|
25
|
+
expect(await promptForCiProvider(providers, {prompt})).toEqual(answers);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {questionNames} from '../prompts/question-names.js';
|
|
2
|
+
import promptForCiProvider from './prompt.js';
|
|
3
|
+
|
|
4
|
+
const {CI_PROVIDER} = questionNames.CI_PROVIDER;
|
|
5
|
+
|
|
6
|
+
export default async function scaffoldCiProvider(plugins, options, {prompt}) {
|
|
7
|
+
if (!Object.keys(plugins).length) return undefined;
|
|
8
|
+
|
|
9
|
+
const {projectRoot} = options;
|
|
10
|
+
|
|
11
|
+
const qualifiedPlugins = Object.fromEntries(
|
|
12
|
+
(await Promise.all(
|
|
13
|
+
Object.entries(plugins).map(async ([name, plugin]) => [name, plugin, await plugin.qualify({projectRoot})])
|
|
14
|
+
)).filter(([, , qualified]) => qualified).map(([name, plugin]) => [name, plugin])
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const chosen = (await promptForCiProvider(qualifiedPlugins, {prompt}))[CI_PROVIDER];
|
|
18
|
+
const plugin = qualifiedPlugins[chosen];
|
|
19
|
+
|
|
20
|
+
if (plugin) return plugin.scaffold(options);
|
|
21
|
+
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {describe, expect, it, vi} from 'vitest';
|
|
2
|
+
import any from '@travi/any';
|
|
3
|
+
import {when} from 'vitest-when';
|
|
4
|
+
|
|
5
|
+
import promptForCiProvider from './prompt.js';
|
|
6
|
+
import scaffoldCiProvider from './scaffolder.js';
|
|
7
|
+
import {questionNames} from '../prompts/index.js';
|
|
8
|
+
|
|
9
|
+
vi.mock('./prompt.js');
|
|
10
|
+
|
|
11
|
+
const {CI_PROVIDER} = questionNames.CI_PROVIDER;
|
|
12
|
+
|
|
13
|
+
describe('ci-provider scaffolder', () => {
|
|
14
|
+
const prompt = () => undefined;
|
|
15
|
+
const projectRoot = any.string();
|
|
16
|
+
const options = {projectRoot};
|
|
17
|
+
|
|
18
|
+
it('should qualify each plugin and prompt only with those that qualify', async () => {
|
|
19
|
+
const qualifiedProviderName = any.word();
|
|
20
|
+
const unqualifiedProviderName = any.word();
|
|
21
|
+
const qualifiedScaffolder = vi.fn();
|
|
22
|
+
const qualifiedPlugin = {qualify: vi.fn(), scaffold: qualifiedScaffolder};
|
|
23
|
+
const unqualifiedPlugin = {qualify: vi.fn(), scaffold: vi.fn()};
|
|
24
|
+
const scaffolderResult = any.simpleObject();
|
|
25
|
+
when(qualifiedPlugin.qualify).calledWith({projectRoot}).thenResolve(true);
|
|
26
|
+
when(unqualifiedPlugin.qualify).calledWith({projectRoot}).thenResolve(false);
|
|
27
|
+
when(promptForCiProvider)
|
|
28
|
+
.calledWith({[qualifiedProviderName]: qualifiedPlugin}, {prompt})
|
|
29
|
+
.thenResolve({[CI_PROVIDER]: qualifiedProviderName});
|
|
30
|
+
when(qualifiedScaffolder).calledWith(options).thenResolve(scaffolderResult);
|
|
31
|
+
|
|
32
|
+
expect(await scaffoldCiProvider(
|
|
33
|
+
{[qualifiedProviderName]: qualifiedPlugin, [unqualifiedProviderName]: unqualifiedPlugin},
|
|
34
|
+
options,
|
|
35
|
+
{prompt}
|
|
36
|
+
)).toEqual(scaffolderResult);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should not present a prompt when no plugins are registered', async () => {
|
|
40
|
+
expect(await scaffoldCiProvider({}, options, {prompt})).toBe(undefined);
|
|
41
|
+
expect(promptForCiProvider).not.toHaveBeenCalled();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should return undefined when Other is chosen', async () => {
|
|
45
|
+
const providerName = any.word();
|
|
46
|
+
const plugin = {qualify: vi.fn(), scaffold: vi.fn()};
|
|
47
|
+
when(plugin.qualify).calledWith({projectRoot}).thenResolve(true);
|
|
48
|
+
when(promptForCiProvider)
|
|
49
|
+
.calledWith({[providerName]: plugin}, {prompt})
|
|
50
|
+
.thenResolve({[CI_PROVIDER]: 'Other'});
|
|
51
|
+
|
|
52
|
+
expect(await scaffoldCiProvider({[providerName]: plugin}, options, {prompt})).toEqual({});
|
|
53
|
+
expect(plugin.scaffold).not.toHaveBeenCalled();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -2,11 +2,13 @@ import {questionNames} from '../prompts/question-names.js';
|
|
|
2
2
|
|
|
3
3
|
export const DEPENDENCY_UPDATER_PROMPT_ID = 'DEPENDENCY_UPDATER';
|
|
4
4
|
|
|
5
|
+
const {DEPENDENCY_UPDATER} = questionNames.DEPENDENCY_UPDATER;
|
|
6
|
+
|
|
5
7
|
export async function promptForDependencyUpdaterChoice(updaters, {prompt}) {
|
|
6
8
|
return prompt({
|
|
7
9
|
id: DEPENDENCY_UPDATER_PROMPT_ID,
|
|
8
10
|
questions: [{
|
|
9
|
-
name:
|
|
11
|
+
name: DEPENDENCY_UPDATER,
|
|
10
12
|
type: 'list',
|
|
11
13
|
message: 'Which dependency-update service do you want to manage this project?',
|
|
12
14
|
choices: [...Object.keys(updaters), 'Other']
|
|
@@ -3,10 +3,12 @@ import any from '@travi/any';
|
|
|
3
3
|
import {when} from 'vitest-when';
|
|
4
4
|
|
|
5
5
|
import {DEPENDENCY_UPDATER_PROMPT_ID, promptForDependencyUpdaterChoice} from './prompt.js';
|
|
6
|
-
import {questionNames} from '../index.js';
|
|
6
|
+
import {questionNames} from '../prompts/index.js';
|
|
7
7
|
|
|
8
8
|
vi.mock('@form8ion/overridable-prompts');
|
|
9
9
|
|
|
10
|
+
const {DEPENDENCY_UPDATER} = questionNames.DEPENDENCY_UPDATER;
|
|
11
|
+
|
|
10
12
|
describe('dependency updater prompt', () => {
|
|
11
13
|
it('should enable choosing the preferred updater', async () => {
|
|
12
14
|
const prompt = vi.fn();
|
|
@@ -15,7 +17,7 @@ describe('dependency updater prompt', () => {
|
|
|
15
17
|
when(prompt).calledWith({
|
|
16
18
|
id: DEPENDENCY_UPDATER_PROMPT_ID,
|
|
17
19
|
questions: [{
|
|
18
|
-
name:
|
|
20
|
+
name: DEPENDENCY_UPDATER,
|
|
19
21
|
type: 'list',
|
|
20
22
|
message: 'Which dependency-update service do you want to manage this project?',
|
|
21
23
|
choices: [...Object.keys(updaters), 'Other']
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {questionNames} from '../prompts/question-names.js';
|
|
2
2
|
import {promptForDependencyUpdaterChoice} from './prompt.js';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const {DEPENDENCY_UPDATER} = questionNames.DEPENDENCY_UPDATER;
|
|
5
|
+
|
|
6
|
+
export default async function scaffoldDependencyUpdater(plugins, options, {prompt}) {
|
|
5
7
|
if (!Object.keys(plugins).length) return undefined;
|
|
6
8
|
|
|
7
9
|
const plugin = plugins[
|
|
8
|
-
(await promptForDependencyUpdaterChoice(plugins, {prompt}))[
|
|
10
|
+
(await promptForDependencyUpdaterChoice(plugins, {prompt}))[DEPENDENCY_UPDATER]
|
|
9
11
|
];
|
|
10
12
|
|
|
11
13
|
if (plugin) return plugin.scaffold(options);
|
|
@@ -4,10 +4,12 @@ import {when} from 'vitest-when';
|
|
|
4
4
|
|
|
5
5
|
import {promptForDependencyUpdaterChoice} from './prompt.js';
|
|
6
6
|
import scaffoldUpdater from './scaffolder.js';
|
|
7
|
-
import {questionNames} from '../index.js';
|
|
7
|
+
import {questionNames} from '../prompts/index.js';
|
|
8
8
|
|
|
9
9
|
vi.mock('./prompt.js');
|
|
10
10
|
|
|
11
|
+
const {DEPENDENCY_UPDATER} = questionNames.DEPENDENCY_UPDATER;
|
|
12
|
+
|
|
11
13
|
describe('dependency-updater scaffolder', () => {
|
|
12
14
|
const prompt = () => undefined;
|
|
13
15
|
|
|
@@ -19,7 +21,7 @@ describe('dependency-updater scaffolder', () => {
|
|
|
19
21
|
const scaffolderResult = any.simpleObject();
|
|
20
22
|
when(promptForDependencyUpdaterChoice)
|
|
21
23
|
.calledWith(plugins, {prompt})
|
|
22
|
-
.thenResolve({[
|
|
24
|
+
.thenResolve({[DEPENDENCY_UPDATER]: chosenUpdater});
|
|
23
25
|
when(chosenUpdaterScaffolder).calledWith(options).thenResolve(scaffolderResult);
|
|
24
26
|
|
|
25
27
|
expect(await scaffoldUpdater(plugins, options, {prompt})).toEqual(scaffolderResult);
|
|
@@ -31,8 +33,13 @@ describe('dependency-updater scaffolder', () => {
|
|
|
31
33
|
});
|
|
32
34
|
|
|
33
35
|
it('should not result in an error when choosing an updater without a defined scaffolder', async () => {
|
|
34
|
-
|
|
36
|
+
const plugins = any.simpleObject();
|
|
37
|
+
const options = any.simpleObject();
|
|
38
|
+
const context = {prompt: undefined};
|
|
39
|
+
when(promptForDependencyUpdaterChoice)
|
|
40
|
+
.calledWith(plugins, context)
|
|
41
|
+
.thenResolve({[DEPENDENCY_UPDATER]: any.word()});
|
|
35
42
|
|
|
36
|
-
expect(await scaffoldUpdater(
|
|
43
|
+
expect(await scaffoldUpdater(plugins, options, context)).toBe(undefined);
|
|
37
44
|
});
|
|
38
45
|
});
|
|
@@ -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
|
}
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {ids} from './prompts/index.js';
|
|
2
|
-
|
|
3
1
|
export * from './scaffolder.js';
|
|
4
2
|
export {default as lift} from './lift.js';
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
export {questionNames} from './prompts/index.js';
|
|
3
|
+
export {constants as promptConstants} from './prompts/index.js';
|
package/src/language/prompt.js
CHANGED
|
@@ -2,11 +2,13 @@ import {questionNames} from '../prompts/question-names.js';
|
|
|
2
2
|
|
|
3
3
|
export const PROJECT_LANGUAGE_PROMPT_ID = 'PROJECT_LANGUAGE';
|
|
4
4
|
|
|
5
|
+
const {PROJECT_LANGUAGE} = questionNames.PROJECT_LANGUAGE;
|
|
6
|
+
|
|
5
7
|
export default function promptForProjectLanguage(languages, {prompt}) {
|
|
6
8
|
return prompt({
|
|
7
9
|
id: PROJECT_LANGUAGE_PROMPT_ID,
|
|
8
10
|
questions: [{
|
|
9
|
-
name:
|
|
11
|
+
name: PROJECT_LANGUAGE,
|
|
10
12
|
type: 'list',
|
|
11
13
|
message: 'What type of project is this?',
|
|
12
14
|
choices: [...Object.keys(languages), 'Other']
|
|
@@ -7,6 +7,8 @@ import promptForLanguageDetails, {PROJECT_LANGUAGE_PROMPT_ID} from './prompt.js'
|
|
|
7
7
|
|
|
8
8
|
vi.mock('@form8ion/overridable-prompts');
|
|
9
9
|
|
|
10
|
+
const {PROJECT_LANGUAGE} = questionNames.PROJECT_LANGUAGE;
|
|
11
|
+
|
|
10
12
|
describe('language prompt', () => {
|
|
11
13
|
it('should prompt for the language details', async () => {
|
|
12
14
|
const prompt = vi.fn();
|
|
@@ -15,7 +17,7 @@ describe('language prompt', () => {
|
|
|
15
17
|
when(prompt).calledWith({
|
|
16
18
|
id: PROJECT_LANGUAGE_PROMPT_ID,
|
|
17
19
|
questions: [{
|
|
18
|
-
name:
|
|
20
|
+
name: PROJECT_LANGUAGE,
|
|
19
21
|
type: 'list',
|
|
20
22
|
message: 'What type of project is this?',
|
|
21
23
|
choices: [...Object.keys(languages), 'Other']
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {questionNames} from '../prompts/question-names.js';
|
|
2
2
|
import promptForLanguageDetails from './prompt.js';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
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,12 +2,14 @@ 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
|
|
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();
|
|
@@ -16,17 +18,20 @@ describe('language scaffolder', () => {
|
|
|
16
18
|
const prompt = () => undefined;
|
|
17
19
|
const chosenLanguageScaffolder = vi.fn();
|
|
18
20
|
const plugins = {...any.simpleObject(), [chosenLanguage]: {scaffold: chosenLanguageScaffolder}};
|
|
19
|
-
when(
|
|
21
|
+
when(promptForProjectLanguage)
|
|
20
22
|
.calledWith(plugins, {prompt})
|
|
21
|
-
.thenResolve({[
|
|
23
|
+
.thenResolve({[PROJECT_LANGUAGE]: chosenLanguage});
|
|
22
24
|
when(chosenLanguageScaffolder).calledWith(options).thenResolve(scaffolderResult);
|
|
23
25
|
|
|
24
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
|
-
|
|
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(
|
|
35
|
+
await scaffold(plugins, options, dependencies);
|
|
31
36
|
});
|
|
32
37
|
});
|
package/src/license/lifter.js
CHANGED
package/src/license/tester.js
CHANGED
package/src/prompts/index.js
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
import {questionNames as coreQuestionNames} from '@form8ion/core';
|
|
2
|
-
|
|
3
1
|
import {BASE_DETAILS_PROMPT_ID} from './questions.js';
|
|
4
2
|
import {GIT_REPOSITORY_PROMPT_ID} from '../vcs/prompt.js';
|
|
5
3
|
import {PROJECT_LANGUAGE_PROMPT_ID} from '../language/prompt.js';
|
|
6
4
|
import {REPOSITORY_HOST_PROMPT_ID} from '../vcs/host/prompt.js';
|
|
7
5
|
import {DEPENDENCY_UPDATER_PROMPT_ID} from '../dependency-updater/prompt.js';
|
|
8
|
-
import {
|
|
6
|
+
import {CI_PROVIDER_PROMPT_ID} from '../ci-provider/prompt.js';
|
|
7
|
+
import {questionNames} from './question-names.js';
|
|
9
8
|
|
|
10
9
|
export const ids = {
|
|
11
10
|
BASE_DETAILS: BASE_DETAILS_PROMPT_ID,
|
|
12
11
|
GIT_REPOSITORY: GIT_REPOSITORY_PROMPT_ID,
|
|
13
12
|
REPOSITORY_HOST: REPOSITORY_HOST_PROMPT_ID,
|
|
14
13
|
PROJECT_LANGUAGE: PROJECT_LANGUAGE_PROMPT_ID,
|
|
15
|
-
DEPENDENCY_UPDATER: DEPENDENCY_UPDATER_PROMPT_ID
|
|
14
|
+
DEPENDENCY_UPDATER: DEPENDENCY_UPDATER_PROMPT_ID,
|
|
15
|
+
CI_PROVIDER: CI_PROVIDER_PROMPT_ID
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
};
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
};
|
package/src/scaffolder.js
CHANGED
|
@@ -7,6 +7,7 @@ import {scaffold as scaffoldLanguage} from './language/index.js';
|
|
|
7
7
|
import {scaffold as scaffoldVcs} from './vcs/index.js';
|
|
8
8
|
import {scaffold as scaffoldLicense} from './license/index.js';
|
|
9
9
|
import scaffoldDependencyUpdater from './dependency-updater/scaffolder.js';
|
|
10
|
+
import {scaffold as scaffoldCiProvider} from './ci-provider/index.js';
|
|
10
11
|
import {promptForBaseDetails} from './prompts/questions.js';
|
|
11
12
|
import {validate} from './options-validator.js';
|
|
12
13
|
import {scaffold as scaffoldEditorConfig} from './editorconfig/index.js';
|
|
@@ -15,7 +16,7 @@ import lift from './lift.js';
|
|
|
15
16
|
|
|
16
17
|
export async function scaffold(options, {prompt, logger}) {
|
|
17
18
|
const projectRoot = process.cwd();
|
|
18
|
-
const {plugins: {dependencyUpdaters, languages, vcsHosts = {}}} = validate(options);
|
|
19
|
+
const {plugins: {dependencyUpdaters, ciProviders, languages, vcsHosts = {}}} = validate(options);
|
|
19
20
|
|
|
20
21
|
const {
|
|
21
22
|
[coreQuestionNames.PROJECT_NAME]: projectName,
|
|
@@ -35,11 +36,12 @@ export async function scaffold(options, {prompt, logger}) {
|
|
|
35
36
|
scaffoldEditorConfig({projectRoot})
|
|
36
37
|
]);
|
|
37
38
|
|
|
38
|
-
const dependencyUpdaterResults = vcsResults.vcs
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
const [dependencyUpdaterResults] = vcsResults.vcs
|
|
40
|
+
? await Promise.all([
|
|
41
|
+
scaffoldDependencyUpdater(dependencyUpdaters, {projectRoot}, {prompt}),
|
|
42
|
+
scaffoldCiProvider(ciProviders, {projectRoot}, {prompt})
|
|
43
|
+
])
|
|
44
|
+
: [];
|
|
43
45
|
|
|
44
46
|
const language = await scaffoldLanguage(
|
|
45
47
|
languages,
|
package/src/scaffolder.test.js
CHANGED
|
@@ -11,6 +11,7 @@ import {scaffold as scaffoldVcs} from './vcs/index.js';
|
|
|
11
11
|
import * as licenseScaffolder from './license/scaffolder.js';
|
|
12
12
|
import scaffoldLanguage from './language/scaffolder.js';
|
|
13
13
|
import * as dependencyUpdaterScaffolder from './dependency-updater/scaffolder.js';
|
|
14
|
+
import {scaffold as scaffoldCiProvider} from './ci-provider/index.js';
|
|
14
15
|
import * as optionsValidator from './options-validator.js';
|
|
15
16
|
import * as prompts from './prompts/questions.js';
|
|
16
17
|
import {questionNames} from './prompts/question-names.js';
|
|
@@ -27,12 +28,15 @@ vi.mock('./vcs/index.js');
|
|
|
27
28
|
vi.mock('./license/scaffolder');
|
|
28
29
|
vi.mock('./language/scaffolder');
|
|
29
30
|
vi.mock('./dependency-updater/scaffolder');
|
|
31
|
+
vi.mock('./ci-provider/index.js');
|
|
30
32
|
vi.mock('./options-validator');
|
|
31
33
|
vi.mock('./prompts/questions');
|
|
32
34
|
vi.mock('./editorconfig');
|
|
33
35
|
vi.mock('./contributing');
|
|
34
36
|
vi.mock('./lift.js');
|
|
35
37
|
|
|
38
|
+
const {GIT_REPO} = questionNames.GIT_REPOSITORY;
|
|
39
|
+
|
|
36
40
|
describe('project scaffolder', () => {
|
|
37
41
|
const originalProcessCwd = process.cwd;
|
|
38
42
|
const options = any.simpleObject();
|
|
@@ -71,6 +75,7 @@ describe('project scaffolder', () => {
|
|
|
71
75
|
const holder = any.sentence();
|
|
72
76
|
const copyright = {year, holder};
|
|
73
77
|
const dependencyUpdaters = any.simpleObject();
|
|
78
|
+
const ciProviders = any.simpleObject();
|
|
74
79
|
const dependencyUpdaterNextSteps = any.listOf(any.simpleObject);
|
|
75
80
|
const dependencyUpdaterContributionBadges = any.simpleObject();
|
|
76
81
|
const dependencyUpdaterResults = {
|
|
@@ -95,7 +100,7 @@ describe('project scaffolder', () => {
|
|
|
95
100
|
]);
|
|
96
101
|
when(optionsValidator.validate)
|
|
97
102
|
.calledWith(options)
|
|
98
|
-
.thenReturn({plugins: {dependencyUpdaters, languages, vcsHosts}});
|
|
103
|
+
.thenReturn({plugins: {dependencyUpdaters, ciProviders, languages, vcsHosts}});
|
|
99
104
|
when(prompts.promptForBaseDetails)
|
|
100
105
|
.calledWith(projectPath, {prompt})
|
|
101
106
|
.thenResolve({
|
|
@@ -122,6 +127,11 @@ describe('project scaffolder', () => {
|
|
|
122
127
|
|
|
123
128
|
expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
|
|
124
129
|
expect(scaffoldEditorconfig).toHaveBeenCalledWith({projectRoot: projectPath});
|
|
130
|
+
expect(scaffoldCiProvider).toHaveBeenCalledWith(
|
|
131
|
+
ciProviders,
|
|
132
|
+
{projectRoot: projectPath},
|
|
133
|
+
{prompt}
|
|
134
|
+
);
|
|
125
135
|
expect(lift).toHaveBeenCalledWith({
|
|
126
136
|
projectRoot: projectPath,
|
|
127
137
|
vcs,
|
|
@@ -157,7 +167,7 @@ describe('project scaffolder', () => {
|
|
|
157
167
|
.calledWith(projectPath, {prompt})
|
|
158
168
|
.thenResolve({
|
|
159
169
|
[coreQuestionNames.DESCRIPTION]: description,
|
|
160
|
-
[
|
|
170
|
+
[GIT_REPO]: true,
|
|
161
171
|
[coreQuestionNames.PROJECT_NAME]: projectName,
|
|
162
172
|
[coreQuestionNames.VISIBILITY]: visibility
|
|
163
173
|
});
|
|
@@ -174,13 +184,14 @@ describe('project scaffolder', () => {
|
|
|
174
184
|
|
|
175
185
|
it('should not scaffold the git repo if not requested', async () => {
|
|
176
186
|
when(optionsValidator.validate).calledWith(options).thenReturn({plugins: {}});
|
|
177
|
-
prompts.promptForBaseDetails.mockResolvedValue({[
|
|
187
|
+
prompts.promptForBaseDetails.mockResolvedValue({[GIT_REPO]: false});
|
|
178
188
|
scaffoldReadme.mockResolvedValue();
|
|
179
189
|
scaffoldVcs.mockResolvedValue({});
|
|
180
190
|
|
|
181
191
|
await scaffold(options, {prompt});
|
|
182
192
|
|
|
183
193
|
expect(dependencyUpdaterScaffolder.default).not.toHaveBeenCalled();
|
|
194
|
+
expect(scaffoldCiProvider).not.toHaveBeenCalled();
|
|
184
195
|
});
|
|
185
196
|
|
|
186
197
|
it('should scaffold the details of the chosen language plugin', async () => {
|
|
@@ -208,7 +219,7 @@ describe('project scaffolder', () => {
|
|
|
208
219
|
prompts.promptForBaseDetails.mockResolvedValue({
|
|
209
220
|
[coreQuestionNames.PROJECT_NAME]: projectName,
|
|
210
221
|
[coreQuestionNames.VISIBILITY]: visibility,
|
|
211
|
-
[
|
|
222
|
+
[GIT_REPO]: true,
|
|
212
223
|
[coreQuestionNames.LICENSE]: license,
|
|
213
224
|
[coreQuestionNames.DESCRIPTION]: description
|
|
214
225
|
});
|
|
@@ -239,7 +250,7 @@ describe('project scaffolder', () => {
|
|
|
239
250
|
prompts.promptForBaseDetails.mockResolvedValue({
|
|
240
251
|
[coreQuestionNames.PROJECT_NAME]: projectName,
|
|
241
252
|
[coreQuestionNames.VISIBILITY]: visibility,
|
|
242
|
-
[
|
|
253
|
+
[GIT_REPO]: true,
|
|
243
254
|
[coreQuestionNames.LICENSE]: license,
|
|
244
255
|
[coreQuestionNames.DESCRIPTION]: description
|
|
245
256
|
});
|
package/src/template-path.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {resolve} from 'path';
|
|
2
2
|
import filedirname from 'filedirname';
|
|
3
3
|
|
|
4
|
-
export default function (fileName) {
|
|
4
|
+
export default function determinePathToTemplate(fileName) {
|
|
5
5
|
const [, __dirname] = filedirname();
|
|
6
6
|
|
|
7
7
|
return resolve(__dirname, '..', 'templates', fileName);
|
package/src/vcs/host/prompt.js
CHANGED
|
@@ -2,17 +2,19 @@ import {questionNames} from '../../prompts/question-names.js';
|
|
|
2
2
|
|
|
3
3
|
export const REPOSITORY_HOST_PROMPT_ID = 'REPOSITORY_HOST';
|
|
4
4
|
|
|
5
|
+
const {REPO_HOST} = questionNames.REPOSITORY_HOST;
|
|
6
|
+
|
|
5
7
|
export default async function promptForVcsHostChoice(hosts, {prompt}) {
|
|
6
8
|
const answers = await prompt({
|
|
7
9
|
id: REPOSITORY_HOST_PROMPT_ID,
|
|
8
10
|
questions: [{
|
|
9
|
-
name:
|
|
11
|
+
name: REPO_HOST,
|
|
10
12
|
type: 'list',
|
|
11
13
|
message: 'Where will the repository be hosted?',
|
|
12
14
|
choices: Object.keys(hosts)
|
|
13
15
|
}]
|
|
14
16
|
});
|
|
15
|
-
const host = hosts[answers[
|
|
17
|
+
const host = hosts[answers[REPO_HOST]];
|
|
16
18
|
|
|
17
19
|
return {...answers, ...host};
|
|
18
20
|
}
|
|
@@ -8,6 +8,8 @@ import promptForVcsHostDetails, {REPOSITORY_HOST_PROMPT_ID} from './prompt.js';
|
|
|
8
8
|
vi.mock('@form8ion/overridable-prompts');
|
|
9
9
|
vi.mock('../../prompts/conditionals');
|
|
10
10
|
|
|
11
|
+
const {REPO_HOST} = questionNames.REPOSITORY_HOST;
|
|
12
|
+
|
|
11
13
|
describe('vcs host details prompt', () => {
|
|
12
14
|
let prompt;
|
|
13
15
|
const answers = any.simpleObject();
|
|
@@ -20,11 +22,11 @@ describe('vcs host details prompt', () => {
|
|
|
20
22
|
const host = any.string();
|
|
21
23
|
const hostNames = [...any.listOf(any.string), host];
|
|
22
24
|
const hosts = any.objectWithKeys(hostNames, {factory: () => ({})});
|
|
23
|
-
const answersWithHostChoice = {...answers, [
|
|
25
|
+
const answersWithHostChoice = {...answers, [REPO_HOST]: host};
|
|
24
26
|
when(prompt).calledWith({
|
|
25
27
|
id: REPOSITORY_HOST_PROMPT_ID,
|
|
26
28
|
questions: [{
|
|
27
|
-
name:
|
|
29
|
+
name: REPO_HOST,
|
|
28
30
|
type: 'list',
|
|
29
31
|
message: 'Where will the repository be hosted?',
|
|
30
32
|
choices: hostNames
|
|
@@ -35,11 +37,11 @@ describe('vcs host details prompt', () => {
|
|
|
35
37
|
});
|
|
36
38
|
|
|
37
39
|
it('should not throw an error when `Other` is chosen as the host', async () => {
|
|
38
|
-
const answersWithHostChoice = {...answers, [
|
|
40
|
+
const answersWithHostChoice = {...answers, [REPO_HOST]: 'Other'};
|
|
39
41
|
when(prompt).calledWith({
|
|
40
42
|
id: REPOSITORY_HOST_PROMPT_ID,
|
|
41
43
|
questions: [{
|
|
42
|
-
name:
|
|
44
|
+
name: REPO_HOST,
|
|
43
45
|
type: 'list',
|
|
44
46
|
message: 'Where will the repository be hosted?',
|
|
45
47
|
choices: []
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {questionNames} from '../../prompts/question-names.js';
|
|
2
2
|
import promptForVcsHostDetails from './prompt.js';
|
|
3
3
|
|
|
4
|
+
const {REPO_HOST} = questionNames.REPOSITORY_HOST;
|
|
5
|
+
|
|
4
6
|
export default async function scaffoldVcsHost(hosts, options, {prompt}) {
|
|
5
|
-
const {[
|
|
7
|
+
const {[REPO_HOST]: chosenHost} = await promptForVcsHostDetails(hosts, {prompt});
|
|
6
8
|
|
|
7
9
|
const lowercasedHosts = Object.fromEntries(
|
|
8
10
|
Object.entries(hosts).map(([name, details]) => [name.toLowerCase(), details])
|
|
@@ -8,6 +8,8 @@ import scaffoldVcsHost from './scaffolder.js';
|
|
|
8
8
|
|
|
9
9
|
vi.mock('./prompt');
|
|
10
10
|
|
|
11
|
+
const {REPO_HOST, REPO_OWNER} = questionNames.REPOSITORY_HOST;
|
|
12
|
+
|
|
11
13
|
describe('vcs host scaffolder', () => {
|
|
12
14
|
const options = any.simpleObject();
|
|
13
15
|
const prompt = () => undefined;
|
|
@@ -20,7 +22,7 @@ describe('vcs host scaffolder', () => {
|
|
|
20
22
|
const owner = any.word;
|
|
21
23
|
when(promptForVcsHostDetails)
|
|
22
24
|
.calledWith(hostPlugins, {prompt})
|
|
23
|
-
.thenResolve({[
|
|
25
|
+
.thenResolve({[REPO_HOST]: chosenHost, [REPO_OWNER]: owner});
|
|
24
26
|
when(chosenHostScaffolder).calledWith(options).thenResolve(results);
|
|
25
27
|
|
|
26
28
|
expect(await scaffoldVcsHost(hostPlugins, options, {prompt})).toEqual(results);
|
|
@@ -30,7 +32,7 @@ describe('vcs host scaffolder', () => {
|
|
|
30
32
|
const hostPlugins = any.simpleObject();
|
|
31
33
|
when(promptForVcsHostDetails)
|
|
32
34
|
.calledWith(hostPlugins, {prompt})
|
|
33
|
-
.thenResolve({[
|
|
35
|
+
.thenResolve({[REPO_HOST]: any.word()});
|
|
34
36
|
|
|
35
37
|
expect(await scaffoldVcsHost(hostPlugins, options, {prompt})).toEqual({vcs: {}});
|
|
36
38
|
});
|