@form8ion/project 22.0.0-beta.12 → 22.0.0-beta.14
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 +139 -102
- package/lib/index.js.map +1 -1
- package/package.json +9 -9
- package/src/ci-provider/prompt.js +17 -0
- package/src/ci-provider/prompt.test.js +27 -0
- package/src/ci-provider/schema.js +4 -0
- package/src/ci-provider/schema.test.js +43 -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/index.js +1 -0
- package/src/editorconfig/scaffolder.js +1 -1
- package/src/editorconfig/tester.js +5 -0
- package/src/editorconfig/tester.test.js +25 -0
- 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/lift.js +5 -0
- package/src/lift.test.js +23 -11
- package/src/options-validator.js +3 -1
- package/src/options-validator.test.js +3 -1
- package/src/prompts/index.js +7 -8
- package/src/prompts/question-names.js +19 -5
- package/src/scaffolder.js +5 -5
- package/src/scaffolder.test.js +6 -4
- 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,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,43 @@
|
|
|
1
|
+
import {validateOptions} from '@form8ion/core';
|
|
2
|
+
|
|
3
|
+
import {describe, expect, it} from 'vitest';
|
|
4
|
+
import any from '@travi/any';
|
|
5
|
+
|
|
6
|
+
import ciProviderPluginsSchema from './schema.js';
|
|
7
|
+
|
|
8
|
+
describe('ci-provider plugins schema', () => {
|
|
9
|
+
const key = any.word();
|
|
10
|
+
|
|
11
|
+
it('should return the validated options', () => {
|
|
12
|
+
const options = any.objectWithKeys(
|
|
13
|
+
any.listOf(any.string),
|
|
14
|
+
{factory: () => ({scaffold: foo => foo})}
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
expect(validateOptions(ciProviderPluginsSchema, options)).toEqual(options);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should require options to be provided as an object', () => {
|
|
21
|
+
expect(() => validateOptions(ciProviderPluginsSchema, {[key]: []}))
|
|
22
|
+
.toThrowError(`"${key}" must be of type object`);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should require a `scaffold` property to be included', () => {
|
|
26
|
+
expect(() => validateOptions(ciProviderPluginsSchema, {[key]: {}}))
|
|
27
|
+
.toThrowError(`"${key}.scaffold" is required`);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should require `scaffold` to be a function', () => {
|
|
31
|
+
expect(() => validateOptions(ciProviderPluginsSchema, {[key]: {scaffold: any.word()}}))
|
|
32
|
+
.toThrowError(`"${key}.scaffold" must be of type function`);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should require the scaffolder to accept a single argument', () => {
|
|
36
|
+
expect(() => validateOptions(ciProviderPluginsSchema, {[key]: {scaffold: () => undefined}}))
|
|
37
|
+
.toThrowError(`"${key}.scaffold" must have an arity greater or equal to 1`);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should default to an empty map when no updaters are provided', () => {
|
|
41
|
+
expect(validateOptions(ciProviderPluginsSchema)).toEqual({});
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -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
|
}
|
|
@@ -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,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/lift.js
CHANGED
|
@@ -2,9 +2,14 @@ import {applyEnhancers} from '@form8ion/core';
|
|
|
2
2
|
import {lift as liftReadme} from '@form8ion/readme';
|
|
3
3
|
import * as gitPlugin from '@form8ion/git';
|
|
4
4
|
|
|
5
|
+
import {scaffold as scaffoldEditorconfig, test as editorconfigInUse} from './editorconfig/index.js';
|
|
5
6
|
import * as licensePlugin from './license/index.js';
|
|
6
7
|
|
|
7
8
|
export default async function lift({projectRoot, results, enhancers, vcs, dependencies}) {
|
|
9
|
+
if (!await editorconfigInUse({projectRoot})) {
|
|
10
|
+
await scaffoldEditorconfig({projectRoot});
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
const enhancerResults = await applyEnhancers({
|
|
9
14
|
results,
|
|
10
15
|
enhancers: {...enhancers, gitPlugin, licensePlugin},
|
package/src/lift.test.js
CHANGED
|
@@ -2,29 +2,28 @@ import * as core from '@form8ion/core';
|
|
|
2
2
|
import * as readme from '@form8ion/readme';
|
|
3
3
|
import * as gitPlugin from '@form8ion/git';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {beforeEach, describe, expect, it, vi} from 'vitest';
|
|
6
6
|
import any from '@travi/any';
|
|
7
7
|
import {when} from 'vitest-when';
|
|
8
8
|
|
|
9
|
+
import {scaffold as scaffoldEditorconfig, test as editorconfigInUse} from './editorconfig/index.js';
|
|
9
10
|
import * as licensePlugin from './license/index.js';
|
|
10
11
|
import lift from './lift.js';
|
|
11
12
|
|
|
12
13
|
vi.mock('deepmerge');
|
|
13
14
|
vi.mock('@form8ion/core');
|
|
14
15
|
vi.mock('@form8ion/readme');
|
|
16
|
+
vi.mock('./editorconfig/index.js');
|
|
15
17
|
|
|
16
18
|
describe('lift', () => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
const projectRoot = any.string();
|
|
20
|
+
const results = any.simpleObject();
|
|
21
|
+
const enhancers = any.simpleObject();
|
|
22
|
+
const vcs = any.simpleObject();
|
|
23
|
+
const dependencies = any.simpleObject();
|
|
24
|
+
const enhancerResults = any.simpleObject();
|
|
20
25
|
|
|
21
|
-
|
|
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();
|
|
26
|
+
beforeEach(() => {
|
|
28
27
|
when(core.applyEnhancers)
|
|
29
28
|
.calledWith({
|
|
30
29
|
results,
|
|
@@ -33,8 +32,21 @@ describe('lift', () => {
|
|
|
33
32
|
dependencies
|
|
34
33
|
})
|
|
35
34
|
.thenResolve(enhancerResults);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should lift the README based on the provided results', async () => {
|
|
38
|
+
when(editorconfigInUse).calledWith({projectRoot}).thenResolve(true);
|
|
36
39
|
|
|
37
40
|
expect(await lift({projectRoot, results, enhancers, vcs, dependencies})).toEqual(enhancerResults);
|
|
38
41
|
expect(readme.lift).toHaveBeenCalledWith({projectRoot, results: enhancerResults});
|
|
42
|
+
expect(scaffoldEditorconfig).not.toHaveBeenCalled();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should scaffold editorconfig when it isnt already in use', async () => {
|
|
46
|
+
when(editorconfigInUse).calledWith({projectRoot}).thenResolve(false);
|
|
47
|
+
|
|
48
|
+
await lift({projectRoot, results, enhancers, vcs, dependencies});
|
|
49
|
+
|
|
50
|
+
expect(scaffoldEditorconfig).toHaveBeenCalledWith({projectRoot});
|
|
39
51
|
});
|
|
40
52
|
});
|
package/src/options-validator.js
CHANGED
|
@@ -4,13 +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 ciProviderPluginsSchema from './ci-provider/schema.js';
|
|
7
8
|
|
|
8
9
|
export function validate(options) {
|
|
9
10
|
return validateOptions(joi.object({
|
|
10
11
|
plugins: joi.object({
|
|
11
12
|
dependencyUpdaters: dependencyUpdaterPluginsSchema,
|
|
12
13
|
languages: languagePluginsSchema,
|
|
13
|
-
vcsHosts: vcsHostPluginsSchema
|
|
14
|
+
vcsHosts: vcsHostPluginsSchema,
|
|
15
|
+
ciProviders: ciProviderPluginsSchema
|
|
14
16
|
})
|
|
15
17
|
}), options) || {};
|
|
16
18
|
}
|
|
@@ -5,6 +5,7 @@ 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
10
|
import vcsHostPluginsSchema from './vcs/host/schema.js';
|
|
10
11
|
import dependencyUpdaterPluginsSchema from './dependency-updater/schema.js';
|
|
@@ -35,7 +36,8 @@ describe('options validator', () => {
|
|
|
35
36
|
.calledWith({
|
|
36
37
|
dependencyUpdaters: dependencyUpdaterPluginsSchema,
|
|
37
38
|
languages: languagePluginsSchema,
|
|
38
|
-
vcsHosts: vcsHostPluginsSchema
|
|
39
|
+
vcsHosts: vcsHostPluginsSchema,
|
|
40
|
+
ciProviders: ciProviderPluginsSchema
|
|
39
41
|
})
|
|
40
42
|
.thenReturn(pluginsSchema);
|
|
41
43
|
when(joi.object).calledWith({plugins: pluginsSchema}).thenReturn(fullSchema);
|
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
|
@@ -35,11 +35,11 @@ export async function scaffold(options, {prompt, logger}) {
|
|
|
35
35
|
scaffoldEditorConfig({projectRoot})
|
|
36
36
|
]);
|
|
37
37
|
|
|
38
|
-
const dependencyUpdaterResults = vcsResults.vcs
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
const [dependencyUpdaterResults] = vcsResults.vcs
|
|
39
|
+
? await Promise.all([
|
|
40
|
+
scaffoldDependencyUpdater(dependencyUpdaters, {projectRoot}, {prompt})
|
|
41
|
+
])
|
|
42
|
+
: [];
|
|
43
43
|
|
|
44
44
|
const language = await scaffoldLanguage(
|
|
45
45
|
languages,
|
package/src/scaffolder.test.js
CHANGED
|
@@ -33,6 +33,8 @@ vi.mock('./editorconfig');
|
|
|
33
33
|
vi.mock('./contributing');
|
|
34
34
|
vi.mock('./lift.js');
|
|
35
35
|
|
|
36
|
+
const {GIT_REPO} = questionNames.GIT_REPOSITORY;
|
|
37
|
+
|
|
36
38
|
describe('project scaffolder', () => {
|
|
37
39
|
const originalProcessCwd = process.cwd;
|
|
38
40
|
const options = any.simpleObject();
|
|
@@ -157,7 +159,7 @@ describe('project scaffolder', () => {
|
|
|
157
159
|
.calledWith(projectPath, {prompt})
|
|
158
160
|
.thenResolve({
|
|
159
161
|
[coreQuestionNames.DESCRIPTION]: description,
|
|
160
|
-
[
|
|
162
|
+
[GIT_REPO]: true,
|
|
161
163
|
[coreQuestionNames.PROJECT_NAME]: projectName,
|
|
162
164
|
[coreQuestionNames.VISIBILITY]: visibility
|
|
163
165
|
});
|
|
@@ -174,7 +176,7 @@ describe('project scaffolder', () => {
|
|
|
174
176
|
|
|
175
177
|
it('should not scaffold the git repo if not requested', async () => {
|
|
176
178
|
when(optionsValidator.validate).calledWith(options).thenReturn({plugins: {}});
|
|
177
|
-
prompts.promptForBaseDetails.mockResolvedValue({[
|
|
179
|
+
prompts.promptForBaseDetails.mockResolvedValue({[GIT_REPO]: false});
|
|
178
180
|
scaffoldReadme.mockResolvedValue();
|
|
179
181
|
scaffoldVcs.mockResolvedValue({});
|
|
180
182
|
|
|
@@ -208,7 +210,7 @@ describe('project scaffolder', () => {
|
|
|
208
210
|
prompts.promptForBaseDetails.mockResolvedValue({
|
|
209
211
|
[coreQuestionNames.PROJECT_NAME]: projectName,
|
|
210
212
|
[coreQuestionNames.VISIBILITY]: visibility,
|
|
211
|
-
[
|
|
213
|
+
[GIT_REPO]: true,
|
|
212
214
|
[coreQuestionNames.LICENSE]: license,
|
|
213
215
|
[coreQuestionNames.DESCRIPTION]: description
|
|
214
216
|
});
|
|
@@ -239,7 +241,7 @@ describe('project scaffolder', () => {
|
|
|
239
241
|
prompts.promptForBaseDetails.mockResolvedValue({
|
|
240
242
|
[coreQuestionNames.PROJECT_NAME]: projectName,
|
|
241
243
|
[coreQuestionNames.VISIBILITY]: visibility,
|
|
242
|
-
[
|
|
244
|
+
[GIT_REPO]: true,
|
|
243
245
|
[coreQuestionNames.LICENSE]: license,
|
|
244
246
|
[coreQuestionNames.DESCRIPTION]: description
|
|
245
247
|
});
|
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: []
|