@form8ion/javascript 15.8.3 → 16.0.0-beta.2
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 +4 -4
- package/example.js +2 -2
- package/lib/index.js +77 -63
- package/lib/index.js.map +1 -1
- package/package.json +18 -18
- package/src/code-style/lifter.js +2 -2
- package/src/dependencies/installer.js +5 -5
- package/src/dependencies/installer.test.js +8 -22
- package/src/dependencies/processor.js +10 -8
- package/src/dependencies/processor.test.js +31 -18
- package/src/dependencies/remover.js +2 -3
- package/src/dependencies/remover.test.js +4 -2
- package/src/lifter.js +8 -5
- package/src/lifter.test.js +12 -11
- package/src/node-version/scaffolder.js +4 -5
- package/src/node-version/scaffolder.test.js +5 -4
- package/src/node-version/tasks.js +4 -6
- package/src/node-version/tasks.test.js +5 -8
- package/src/options/schemas.js +2 -1
- package/src/options/schemas.test.js +12 -6
- package/src/options/validator.js +2 -1
- package/src/options/validator.test.js +2 -1
- package/src/package/lifter.js +3 -4
- package/src/package/lifter.test.js +8 -4
- package/src/package/scaffolder.js +2 -3
- package/src/package/scaffolder.test.js +3 -1
- package/src/project-type/application/scaffolder.js +2 -3
- package/src/project-type/application/scaffolder.test.js +3 -5
- package/src/project-type/monorepo/scaffolder.js +2 -3
- package/src/project-type/monorepo/scaffolder.test.js +3 -6
- package/src/project-type/package/scaffolder.js +2 -3
- package/src/project-type/package/scaffolder.test.js +6 -5
- package/src/project-type/publishable/access-level.js +1 -1
- package/src/project-type/publishable/access-level.test.js +6 -4
- package/src/project-type/scaffolder.js +4 -4
- package/src/project-type/scaffolder.test.js +15 -16
- package/src/prompts/conditionals.js +1 -1
- package/src/prompts/conditionals.test.js +27 -6
- package/src/prompts/questions.js +4 -4
- package/src/prompts/questions.test.js +21 -6
- package/src/prompts/validators.js +7 -2
- package/src/prompts/validators.test.js +9 -6
- package/src/scaffolder.js +7 -8
- package/src/scaffolder.test.js +6 -5
- package/src/tester.js +2 -4
- package/src/tester.test.js +5 -8
|
@@ -68,7 +68,8 @@ describe('options validator', () => {
|
|
|
68
68
|
packageTypes: pluginsSchema,
|
|
69
69
|
monorepoTypes: pluginsSchema,
|
|
70
70
|
hosts: pluginsSchema,
|
|
71
|
-
ciServices: pluginsSchema
|
|
71
|
+
ciServices: pluginsSchema,
|
|
72
|
+
registries: pluginsSchema
|
|
72
73
|
}
|
|
73
74
|
})
|
|
74
75
|
.thenReturn({required: joiRequiredObject});
|
package/src/package/lifter.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {promises as fs} from 'node:fs';
|
|
2
2
|
import deepmerge from 'deepmerge';
|
|
3
|
-
import {info} from '@travi/cli-messages';
|
|
4
3
|
import {writePackageJson} from '@form8ion/javascript-core';
|
|
5
4
|
|
|
6
5
|
import sortPackageProperties from './property-sorter.js';
|
|
@@ -17,8 +16,8 @@ export default async function liftPackageJson({
|
|
|
17
16
|
packageManager,
|
|
18
17
|
vcs,
|
|
19
18
|
pathWithinParent
|
|
20
|
-
}) {
|
|
21
|
-
info('Updating `package.json`', {level: 'secondary'});
|
|
19
|
+
}, {logger}) {
|
|
20
|
+
logger.info('Updating `package.json`', {level: 'secondary'});
|
|
22
21
|
|
|
23
22
|
const existingPackageJsonContents = JSON.parse(await fs.readFile(`${projectRoot}/package.json`, 'utf-8'));
|
|
24
23
|
const {scripts: liftedScripts, dependencies: scriptDependencies} = liftScripts({
|
|
@@ -43,5 +42,5 @@ export default async function liftPackageJson({
|
|
|
43
42
|
devDependencies,
|
|
44
43
|
projectRoot,
|
|
45
44
|
packageManager
|
|
46
|
-
});
|
|
45
|
+
}, {logger});
|
|
47
46
|
}
|
|
@@ -34,6 +34,7 @@ describe('package.json lifter', () => {
|
|
|
34
34
|
const config = any.simpleObject();
|
|
35
35
|
const tags = any.listOf(any.word);
|
|
36
36
|
const scriptDependencies = any.simpleObject();
|
|
37
|
+
const logger = {info: () => undefined};
|
|
37
38
|
|
|
38
39
|
beforeEach(() => {
|
|
39
40
|
when(defineVcsHostDetails).calledWith(vcs, pathWithinParent).thenReturn(vcsDetails);
|
|
@@ -53,7 +54,10 @@ describe('package.json lifter', () => {
|
|
|
53
54
|
.calledWith({...existingPackageContents, ...vcsDetails, scripts: liftedScripts})
|
|
54
55
|
.thenReturn(config);
|
|
55
56
|
|
|
56
|
-
await liftPackage(
|
|
57
|
+
await liftPackage(
|
|
58
|
+
{dependencies, devDependencies, projectRoot, packageManager, vcs, pathWithinParent, scripts},
|
|
59
|
+
{logger}
|
|
60
|
+
);
|
|
57
61
|
|
|
58
62
|
expect(writePackageJson).toHaveBeenCalledWith({projectRoot, config});
|
|
59
63
|
expect(processDependencies).toHaveBeenCalledWith({
|
|
@@ -61,7 +65,7 @@ describe('package.json lifter', () => {
|
|
|
61
65
|
devDependencies,
|
|
62
66
|
projectRoot,
|
|
63
67
|
packageManager
|
|
64
|
-
});
|
|
68
|
+
}, {logger});
|
|
65
69
|
});
|
|
66
70
|
|
|
67
71
|
it('should update keywords if tags are provided', async () => {
|
|
@@ -73,7 +77,7 @@ describe('package.json lifter', () => {
|
|
|
73
77
|
.calledWith({...existingPackageContents, ...vcsDetails, scripts: liftedScripts, keywords: tags})
|
|
74
78
|
.thenReturn(config);
|
|
75
79
|
|
|
76
|
-
await liftPackage({dependencies, projectRoot, packageManager, vcs, pathWithinParent, scripts, tags});
|
|
80
|
+
await liftPackage({dependencies, projectRoot, packageManager, vcs, pathWithinParent, scripts, tags}, {logger});
|
|
77
81
|
|
|
78
82
|
expect(writePackageJson).toHaveBeenCalledWith({projectRoot, config});
|
|
79
83
|
});
|
|
@@ -93,7 +97,7 @@ describe('package.json lifter', () => {
|
|
|
93
97
|
})
|
|
94
98
|
.thenReturn(config);
|
|
95
99
|
|
|
96
|
-
await liftPackage({dependencies, projectRoot, packageManager, vcs, pathWithinParent, scripts, tags});
|
|
100
|
+
await liftPackage({dependencies, projectRoot, packageManager, vcs, pathWithinParent, scripts, tags}, {logger});
|
|
97
101
|
|
|
98
102
|
expect(writePackageJson).toHaveBeenCalledWith({projectRoot, config});
|
|
99
103
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {info} from '@travi/cli-messages';
|
|
2
1
|
import {writePackageJson} from '@form8ion/javascript-core';
|
|
3
2
|
|
|
4
3
|
import buildPackageName from './package-name.js';
|
|
@@ -12,8 +11,8 @@ export default async function scaffoldPackage({
|
|
|
12
11
|
license,
|
|
13
12
|
author,
|
|
14
13
|
description
|
|
15
|
-
}) {
|
|
16
|
-
info('Configuring package.json');
|
|
14
|
+
}, {logger}) {
|
|
15
|
+
logger.info('Configuring package.json');
|
|
17
16
|
|
|
18
17
|
const packageName = buildPackageName(projectName, scope);
|
|
19
18
|
|
|
@@ -13,6 +13,8 @@ vi.mock('./package-name.js');
|
|
|
13
13
|
vi.mock('./details.js');
|
|
14
14
|
|
|
15
15
|
describe('package scaffolder', () => {
|
|
16
|
+
const logger = {info: () => undefined};
|
|
17
|
+
|
|
16
18
|
it('should create the package file', async () => {
|
|
17
19
|
const projectName = any.string();
|
|
18
20
|
const packageName = any.string();
|
|
@@ -40,7 +42,7 @@ describe('package scaffolder', () => {
|
|
|
40
42
|
license,
|
|
41
43
|
author,
|
|
42
44
|
description
|
|
43
|
-
})).toEqual({packageName});
|
|
45
|
+
}, {logger})).toEqual({packageName});
|
|
44
46
|
expect(writePackageJson).toHaveBeenCalledWith({projectRoot, config: packageDetails});
|
|
45
47
|
});
|
|
46
48
|
});
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import {mergeIntoExistingPackageJson} from '@form8ion/javascript-core';
|
|
2
|
-
import {info} from '@travi/cli-messages';
|
|
3
2
|
|
|
4
3
|
const defaultBuildDirectory = 'public';
|
|
5
4
|
|
|
6
|
-
export default async function scaffoldApplication({projectRoot}) {
|
|
7
|
-
info('Scaffolding Application Details');
|
|
5
|
+
export default async function scaffoldApplication({projectRoot}, {logger}) {
|
|
6
|
+
logger.info('Scaffolding Application Details');
|
|
8
7
|
|
|
9
8
|
await mergeIntoExistingPackageJson({projectRoot, config: {private: true}});
|
|
10
9
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {mergeIntoExistingPackageJson} from '@form8ion/javascript-core';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {describe, expect, it, vi} from 'vitest';
|
|
4
4
|
import any from '@travi/any';
|
|
5
5
|
|
|
6
6
|
import scaffoldApplication from './scaffolder.js';
|
|
@@ -8,15 +8,13 @@ import scaffoldApplication from './scaffolder.js';
|
|
|
8
8
|
vi.mock('@form8ion/javascript-core');
|
|
9
9
|
|
|
10
10
|
describe('application project-type scaffolder', () => {
|
|
11
|
-
|
|
12
|
-
vi.clearAllMocks();
|
|
13
|
-
});
|
|
11
|
+
const logger = {info: () => undefined};
|
|
14
12
|
|
|
15
13
|
it('should scaffold the details specific to an application project-type', async () => {
|
|
16
14
|
const projectRoot = any.string();
|
|
17
15
|
const buildDirectory = 'public';
|
|
18
16
|
|
|
19
|
-
expect(await scaffoldApplication({projectRoot})).toEqual({
|
|
17
|
+
expect(await scaffoldApplication({projectRoot}, {logger})).toEqual({
|
|
20
18
|
scripts: {
|
|
21
19
|
clean: `rimraf ./${buildDirectory}`,
|
|
22
20
|
start: `node ./${buildDirectory}/index.js`,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import {mergeIntoExistingPackageJson} from '@form8ion/javascript-core';
|
|
2
|
-
import {info} from '@travi/cli-messages';
|
|
3
2
|
|
|
4
|
-
export default async function scaffoldMonorepo({projectRoot}) {
|
|
5
|
-
info('Scaffolding Monorepo Details');
|
|
3
|
+
export default async function scaffoldMonorepo({projectRoot}, {logger}) {
|
|
4
|
+
logger.info('Scaffolding Monorepo Details');
|
|
6
5
|
|
|
7
6
|
await mergeIntoExistingPackageJson({projectRoot, config: {private: true}});
|
|
8
7
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {mergeIntoExistingPackageJson} from '@form8ion/javascript-core';
|
|
2
2
|
|
|
3
|
-
import {describe,
|
|
3
|
+
import {describe, expect, it, vi} from 'vitest';
|
|
4
4
|
import any from '@travi/any';
|
|
5
5
|
|
|
6
6
|
import scaffoldMonorepo from './scaffolder.js';
|
|
@@ -9,13 +9,10 @@ vi.mock('@form8ion/javascript-core');
|
|
|
9
9
|
|
|
10
10
|
describe('monorepo project-type scaffolder', () => {
|
|
11
11
|
const projectRoot = any.string();
|
|
12
|
-
|
|
13
|
-
afterEach(() => {
|
|
14
|
-
vi.clearAllMocks();
|
|
15
|
-
});
|
|
12
|
+
const logger = {info: () => undefined};
|
|
16
13
|
|
|
17
14
|
it('should scaffold the monorepo specific project details', async () => {
|
|
18
|
-
expect(await scaffoldMonorepo({projectRoot})).toEqual({
|
|
15
|
+
expect(await scaffoldMonorepo({projectRoot}, {logger})).toEqual({
|
|
19
16
|
nextSteps: [{
|
|
20
17
|
summary: 'Add packages to your new monorepo',
|
|
21
18
|
description: 'Leverage [@form8ion/add-package-to-monorepo](https://npm.im/@form8ion/add-package-to-monorepo)'
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import deepmerge from 'deepmerge';
|
|
2
|
-
import {info} from '@travi/cli-messages';
|
|
3
2
|
import {dialects, mergeIntoExistingPackageJson} from '@form8ion/javascript-core';
|
|
4
3
|
|
|
5
4
|
import determinePackageAccessLevelFromProjectVisibility from '../publishable/access-level.js';
|
|
@@ -19,8 +18,8 @@ export default async function scaffoldPackageProjectType({
|
|
|
19
18
|
dialect,
|
|
20
19
|
provideExample,
|
|
21
20
|
publishRegistry
|
|
22
|
-
}) {
|
|
23
|
-
info('Scaffolding Package Details');
|
|
21
|
+
}, {logger}) {
|
|
22
|
+
logger.info('Scaffolding Package Details');
|
|
24
23
|
|
|
25
24
|
const packageAccessLevel = determinePackageAccessLevelFromProjectVisibility({projectVisibility: visibility});
|
|
26
25
|
const [detailsForBuild, publishableResults] = await Promise.all([
|
|
@@ -35,6 +35,7 @@ describe('package project-type scaffolder', () => {
|
|
|
35
35
|
const documentation = any.simpleObject();
|
|
36
36
|
const decisions = any.simpleObject();
|
|
37
37
|
const buildDetailsResults = any.simpleObject();
|
|
38
|
+
const logger = {info: () => undefined};
|
|
38
39
|
|
|
39
40
|
beforeEach(() => {
|
|
40
41
|
when(documentationScaffolder.default)
|
|
@@ -68,7 +69,7 @@ describe('package project-type scaffolder', () => {
|
|
|
68
69
|
decisions,
|
|
69
70
|
dialect,
|
|
70
71
|
provideExample
|
|
71
|
-
})).toEqual({
|
|
72
|
+
}, {logger})).toEqual({
|
|
72
73
|
...publishableResults,
|
|
73
74
|
...buildDetailsResults,
|
|
74
75
|
documentation,
|
|
@@ -113,7 +114,7 @@ describe('package project-type scaffolder', () => {
|
|
|
113
114
|
packageBundlers,
|
|
114
115
|
decisions,
|
|
115
116
|
provideExample
|
|
116
|
-
})).toEqual({
|
|
117
|
+
}, {logger})).toEqual({
|
|
117
118
|
...publishableResults,
|
|
118
119
|
...buildDetailsResults,
|
|
119
120
|
documentation,
|
|
@@ -153,7 +154,7 @@ describe('package project-type scaffolder', () => {
|
|
|
153
154
|
decisions,
|
|
154
155
|
dialect,
|
|
155
156
|
provideExample
|
|
156
|
-
})).toEqual({
|
|
157
|
+
}, {logger})).toEqual({
|
|
157
158
|
...publishableResults,
|
|
158
159
|
...buildDetailsResults,
|
|
159
160
|
documentation,
|
|
@@ -199,7 +200,7 @@ describe('package project-type scaffolder', () => {
|
|
|
199
200
|
packageBundlers,
|
|
200
201
|
dialect,
|
|
201
202
|
provideExample
|
|
202
|
-
})).toEqual({
|
|
203
|
+
}, {logger})).toEqual({
|
|
203
204
|
...publishableResults,
|
|
204
205
|
...buildDetailsResults,
|
|
205
206
|
documentation,
|
|
@@ -239,7 +240,7 @@ describe('package project-type scaffolder', () => {
|
|
|
239
240
|
dialect,
|
|
240
241
|
provideExample,
|
|
241
242
|
packageBundlers
|
|
242
|
-
});
|
|
243
|
+
}, {logger});
|
|
243
244
|
|
|
244
245
|
expect(mergeIntoExistingPackageJson).toHaveBeenCalledWith({
|
|
245
246
|
projectRoot,
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {describe, expect, it} from 'vitest';
|
|
2
|
+
import any from '@travi/any';
|
|
2
3
|
|
|
3
4
|
import determinePackageAccessLevelFromProjectVisibility from './access-level.js';
|
|
4
5
|
|
|
5
6
|
describe('package access level', () => {
|
|
6
|
-
it('should return `public` when project visibility is `
|
|
7
|
-
expect(determinePackageAccessLevelFromProjectVisibility({projectVisibility: '
|
|
7
|
+
it('should return `public` when project visibility is `OSS`', () => {
|
|
8
|
+
expect(determinePackageAccessLevelFromProjectVisibility({projectVisibility: 'OSS'})).toEqual('public');
|
|
8
9
|
});
|
|
9
10
|
|
|
10
|
-
it('should return `restricted` when the project visibility is `
|
|
11
|
-
expect(determinePackageAccessLevelFromProjectVisibility({projectVisibility: '
|
|
11
|
+
it('should return `restricted` when the project visibility is `ISS` or `CS`', () => {
|
|
12
|
+
expect(determinePackageAccessLevelFromProjectVisibility({projectVisibility: any.fromList(['ISS', 'CS'])}))
|
|
13
|
+
.toEqual('restricted');
|
|
12
14
|
});
|
|
13
15
|
});
|
|
@@ -18,7 +18,7 @@ export default async function scaffoldProjectType({
|
|
|
18
18
|
dialect,
|
|
19
19
|
provideExample,
|
|
20
20
|
publishRegistry
|
|
21
|
-
}) {
|
|
21
|
+
}, {logger}) {
|
|
22
22
|
switch (projectType) {
|
|
23
23
|
case projectTypes.PACKAGE:
|
|
24
24
|
return scaffoldPackageType({
|
|
@@ -33,9 +33,9 @@ export default async function scaffoldProjectType({
|
|
|
33
33
|
dialect,
|
|
34
34
|
provideExample,
|
|
35
35
|
publishRegistry
|
|
36
|
-
});
|
|
36
|
+
}, {logger});
|
|
37
37
|
case projectTypes.APPLICATION:
|
|
38
|
-
return scaffoldApplicationType({projectRoot});
|
|
38
|
+
return scaffoldApplicationType({projectRoot}, {logger});
|
|
39
39
|
case projectTypes.CLI:
|
|
40
40
|
return scaffoldCliType({
|
|
41
41
|
visibility,
|
|
@@ -46,7 +46,7 @@ export default async function scaffoldProjectType({
|
|
|
46
46
|
packageBundlers
|
|
47
47
|
});
|
|
48
48
|
case projectTypes.MONOREPO:
|
|
49
|
-
return scaffoldMonorepoType({projectRoot});
|
|
49
|
+
return scaffoldMonorepoType({projectRoot}, {logger});
|
|
50
50
|
case 'Other':
|
|
51
51
|
return {};
|
|
52
52
|
default:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {projectTypes} from '@form8ion/javascript-core';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {describe, expect, it, vi} from 'vitest';
|
|
4
4
|
import any from '@travi/any';
|
|
5
5
|
import {when} from 'vitest-when';
|
|
6
6
|
|
|
@@ -27,10 +27,7 @@ describe('project-type scaffolder', () => {
|
|
|
27
27
|
const dialect = any.word();
|
|
28
28
|
const provideExample = any.boolean();
|
|
29
29
|
const packageBundlers = any.simpleObject();
|
|
30
|
-
|
|
31
|
-
afterEach(() => {
|
|
32
|
-
vi.clearAllMocks();
|
|
33
|
-
});
|
|
30
|
+
const logger = {info: () => undefined};
|
|
34
31
|
|
|
35
32
|
it('should apply the package-type scaffolder when the project-type is `Package`', async () => {
|
|
36
33
|
const scope = any.word();
|
|
@@ -46,7 +43,7 @@ describe('project-type scaffolder', () => {
|
|
|
46
43
|
dialect,
|
|
47
44
|
provideExample,
|
|
48
45
|
publishRegistry
|
|
49
|
-
}).thenResolve(results);
|
|
46
|
+
}, {logger}).thenResolve(results);
|
|
50
47
|
|
|
51
48
|
expect(await projectTypeScaffolder({
|
|
52
49
|
projectType: projectTypes.PACKAGE,
|
|
@@ -61,11 +58,11 @@ describe('project-type scaffolder', () => {
|
|
|
61
58
|
dialect,
|
|
62
59
|
provideExample,
|
|
63
60
|
publishRegistry
|
|
64
|
-
})).toEqual(results);
|
|
61
|
+
}, {logger})).toEqual(results);
|
|
65
62
|
});
|
|
66
63
|
|
|
67
64
|
it('should apply the application-type scaffolder when the project-type is `Application`', async () => {
|
|
68
|
-
when(scaffoldApplicationType).calledWith({projectRoot}).thenResolve(results);
|
|
65
|
+
when(scaffoldApplicationType).calledWith({projectRoot}, {logger}).thenResolve(results);
|
|
69
66
|
|
|
70
67
|
expect(await projectTypeScaffolder({
|
|
71
68
|
projectType: projectTypes.APPLICATION,
|
|
@@ -75,7 +72,7 @@ describe('project-type scaffolder', () => {
|
|
|
75
72
|
packageManager,
|
|
76
73
|
decisions,
|
|
77
74
|
visibility
|
|
78
|
-
})).toEqual(results);
|
|
75
|
+
}, {logger})).toEqual(results);
|
|
79
76
|
});
|
|
80
77
|
|
|
81
78
|
it('should apply the cli-type scaffolder when the project-type is `CLI`', async () => {
|
|
@@ -91,24 +88,26 @@ describe('project-type scaffolder', () => {
|
|
|
91
88
|
publishRegistry,
|
|
92
89
|
decisions,
|
|
93
90
|
packageBundlers
|
|
94
|
-
})).toEqual(results);
|
|
91
|
+
}, {logger})).toEqual(results);
|
|
95
92
|
});
|
|
96
93
|
|
|
97
94
|
it('should apply the monorepo-type scaffolder when the project-type is `Monorepo`', async () => {
|
|
98
|
-
when(scaffoldMonorepoType).calledWith({projectRoot}).thenResolve(results);
|
|
95
|
+
when(scaffoldMonorepoType).calledWith({projectRoot}, {logger}).thenResolve(results);
|
|
99
96
|
|
|
100
|
-
expect(await projectTypeScaffolder(
|
|
101
|
-
.
|
|
97
|
+
expect(await projectTypeScaffolder(
|
|
98
|
+
{projectRoot, projectType: projectTypes.MONOREPO, packageManager, decisions},
|
|
99
|
+
{logger}
|
|
100
|
+
)).toEqual(results);
|
|
102
101
|
});
|
|
103
102
|
|
|
104
103
|
it('should not throw an error when the project-type is `Other`', async () => {
|
|
105
|
-
expect(await projectTypeScaffolder({projectType: 'Other'})).toEqual({});
|
|
104
|
+
expect(await projectTypeScaffolder({projectType: 'Other'}, {logger})).toEqual({});
|
|
106
105
|
});
|
|
107
106
|
|
|
108
107
|
it('should throw an error for an unknown project-type', async () => {
|
|
109
108
|
const projectType = any.word();
|
|
110
109
|
|
|
111
|
-
await expect(() => projectTypeScaffolder({projectType}))
|
|
112
|
-
.rejects.
|
|
110
|
+
await expect(() => projectTypeScaffolder({projectType}, {logger}))
|
|
111
|
+
.rejects.toThrow(`The project-type of ${projectType} is invalid`);
|
|
113
112
|
});
|
|
114
113
|
});
|
|
@@ -16,7 +16,7 @@ export function projectIsApplication(answers) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function packageShouldBeScoped(visibility, answers) {
|
|
19
|
-
return '
|
|
19
|
+
return ['ISS', 'CS'].includes(visibility) || answers[questionNames.SHOULD_BE_SCOPED];
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function willBePublishedToNpm(answers) {
|
|
@@ -33,8 +33,15 @@ describe('javascript prompt conditionals', () => {
|
|
|
33
33
|
})).toBe(true);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
it('should present a scope prompt when a package is
|
|
37
|
-
expect(scopePromptShouldBePresentedFactory('
|
|
36
|
+
it('should present a scope prompt when a package is inner source, because they must be scoped', () => {
|
|
37
|
+
expect(scopePromptShouldBePresentedFactory('ISS')({
|
|
38
|
+
[questionNames.SHOULD_BE_SCOPED]: false,
|
|
39
|
+
[questionNames.PROJECT_TYPE]: projectTypes.PACKAGE
|
|
40
|
+
})).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should present a scope prompt when a package is closed source, because they must be scoped', () => {
|
|
44
|
+
expect(scopePromptShouldBePresentedFactory('CS')({
|
|
38
45
|
[questionNames.SHOULD_BE_SCOPED]: false,
|
|
39
46
|
[questionNames.PROJECT_TYPE]: projectTypes.PACKAGE
|
|
40
47
|
})).toBe(true);
|
|
@@ -47,15 +54,29 @@ describe('javascript prompt conditionals', () => {
|
|
|
47
54
|
})).toBe(true);
|
|
48
55
|
});
|
|
49
56
|
|
|
50
|
-
it('should present a scope prompt when a CLI is
|
|
51
|
-
expect(scopePromptShouldBePresentedFactory('
|
|
57
|
+
it('should present a scope prompt when a CLI is closed source, because they must be scoped', () => {
|
|
58
|
+
expect(scopePromptShouldBePresentedFactory('CS')({
|
|
52
59
|
[questionNames.SHOULD_BE_SCOPED]: false,
|
|
53
60
|
[questionNames.PROJECT_TYPE]: projectTypes.CLI
|
|
54
61
|
})).toBe(true);
|
|
55
62
|
});
|
|
56
63
|
|
|
57
|
-
it('should
|
|
58
|
-
expect(scopePromptShouldBePresentedFactory('
|
|
64
|
+
it('should present a scope prompt when a CLI is inner source, because they must be scoped', () => {
|
|
65
|
+
expect(scopePromptShouldBePresentedFactory('ISS')({
|
|
66
|
+
[questionNames.SHOULD_BE_SCOPED]: false,
|
|
67
|
+
[questionNames.PROJECT_TYPE]: projectTypes.CLI
|
|
68
|
+
})).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should not present a scope prompt when an application is closed source', () => {
|
|
72
|
+
expect(scopePromptShouldBePresentedFactory('CS')({
|
|
73
|
+
[questionNames.SHOULD_BE_SCOPED]: false,
|
|
74
|
+
[questionNames.PROJECT_TYPE]: projectTypes.APPLICATION
|
|
75
|
+
})).toBe(false);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should not present a scope prompt when an application is inner source', () => {
|
|
79
|
+
expect(scopePromptShouldBePresentedFactory('ISS')({
|
|
59
80
|
[questionNames.SHOULD_BE_SCOPED]: false,
|
|
60
81
|
[questionNames.PROJECT_TYPE]: projectTypes.APPLICATION
|
|
61
82
|
})).toBe(false);
|
package/src/prompts/questions.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {packageManagers, projectTypes} from '@form8ion/javascript-core';
|
|
2
2
|
import {prompt as promptWithInquirer} from '@form8ion/overridable-prompts';
|
|
3
3
|
import {questionNames as commonQuestionNames, questions as commonQuestions} from '@travi/language-scaffolder-prompts';
|
|
4
|
-
import {warn} from '@travi/cli-messages';
|
|
5
4
|
|
|
6
5
|
import {execa} from 'execa';
|
|
7
6
|
import npmConfFactory from '../../thirdparty-wrappers/npm-conf.js';
|
|
@@ -43,7 +42,8 @@ export async function prompt(
|
|
|
43
42
|
vcs,
|
|
44
43
|
decisions,
|
|
45
44
|
configs,
|
|
46
|
-
pathWithinParent
|
|
45
|
+
pathWithinParent,
|
|
46
|
+
{logger}
|
|
47
47
|
) {
|
|
48
48
|
const npmConf = npmConfFactory();
|
|
49
49
|
|
|
@@ -52,7 +52,7 @@ export async function prompt(
|
|
|
52
52
|
maybeLoggedInNpmUsername = (await execa('npm', ['whoami'])).stdout;
|
|
53
53
|
} catch (failedExecutionResult) {
|
|
54
54
|
if (!decisions[questionNames.SCOPE]) {
|
|
55
|
-
warn('No logged in user found with `npm whoami`. Login with `npm login` '
|
|
55
|
+
logger.warn('No logged in user found with `npm whoami`. Login with `npm login` '
|
|
56
56
|
+ 'to use your npm account name as the package scope default.');
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -101,7 +101,7 @@ export async function prompt(
|
|
|
101
101
|
choices: [...Object.values(projectTypes), 'Other'],
|
|
102
102
|
default: projectTypes.PACKAGE
|
|
103
103
|
},
|
|
104
|
-
...'
|
|
104
|
+
...['ISS', 'CS'].includes(visibility) ? [] : [{
|
|
105
105
|
name: questionNames.SHOULD_BE_SCOPED,
|
|
106
106
|
message: 'Should this package be scoped?',
|
|
107
107
|
type: 'confirm',
|
|
@@ -59,6 +59,7 @@ describe('prompts', () => {
|
|
|
59
59
|
[questionNames.DIALECT]: dialect,
|
|
60
60
|
[questionNames.PROVIDE_EXAMPLE]: provideExample
|
|
61
61
|
};
|
|
62
|
+
const logger = {info: () => undefined, warn: () => undefined};
|
|
62
63
|
|
|
63
64
|
beforeEach(() => {
|
|
64
65
|
when(commonPrompts.questions)
|
|
@@ -166,7 +167,7 @@ describe('prompts', () => {
|
|
|
166
167
|
], decisions)
|
|
167
168
|
.thenResolve({...answers, [questionNames.CONFIGURE_LINTING]: any.word()});
|
|
168
169
|
|
|
169
|
-
expect(await prompt(ciServices, hosts, visibility, vcs, decisions, configs)).toEqual({
|
|
170
|
+
expect(await prompt(ciServices, hosts, visibility, vcs, decisions, configs, undefined, {logger})).toEqual({
|
|
170
171
|
tests,
|
|
171
172
|
projectType,
|
|
172
173
|
ci,
|
|
@@ -188,7 +189,7 @@ describe('prompts', () => {
|
|
|
188
189
|
when(execa).calledWith('npm', ['whoami']).thenResolve({stdout: npmUser});
|
|
189
190
|
prompts.prompt.mockResolvedValue({...answers, [questionNames.CONFIGURE_LINTING]: false});
|
|
190
191
|
|
|
191
|
-
expect(await prompt(ciServices, {}, visibility, vcs, decisions)).toEqual({
|
|
192
|
+
expect(await prompt(ciServices, {}, visibility, vcs, decisions, undefined, undefined, {logger})).toEqual({
|
|
192
193
|
tests,
|
|
193
194
|
projectType,
|
|
194
195
|
ci,
|
|
@@ -211,13 +212,13 @@ describe('prompts', () => {
|
|
|
211
212
|
.thenReturn(commonQuestions);
|
|
212
213
|
prompts.prompt.mockResolvedValue(answers);
|
|
213
214
|
|
|
214
|
-
await prompt(ciServices, {}, '
|
|
215
|
+
await prompt(ciServices, {}, 'CS', vcs, null, null, pathWithinParent, {logger});
|
|
215
216
|
|
|
216
217
|
const [questions] = prompts.prompt.mock.lastCall;
|
|
217
218
|
expect(questions.filter(question => questionNames.NODE_VERSION_CATEGORY === question.name).length).toEqual(0);
|
|
218
219
|
});
|
|
219
220
|
|
|
220
|
-
it('should not ask whether
|
|
221
|
+
it('should not ask whether closed source packages should be scoped', async () => {
|
|
221
222
|
when(execa).calledWith('npm', ['whoami']).thenResolve({stdout: any.word()});
|
|
222
223
|
npmConfFactory.mockReturnValue({get: () => undefined});
|
|
223
224
|
when(commonPrompts.questions)
|
|
@@ -225,7 +226,21 @@ describe('prompts', () => {
|
|
|
225
226
|
.thenReturn(commonQuestions);
|
|
226
227
|
prompts.prompt.mockResolvedValue(answers);
|
|
227
228
|
|
|
228
|
-
await prompt(ciServices, {}, '
|
|
229
|
+
await prompt(ciServices, {}, 'CS', vcs, null, null, pathWithinParent, {logger});
|
|
230
|
+
|
|
231
|
+
const [questions] = prompts.prompt.mock.lastCall;
|
|
232
|
+
expect(questions.filter(question => questionNames.SHOULD_BE_SCOPED === question.name).length).toEqual(0);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('should not ask whether inner source packages should be scoped', async () => {
|
|
236
|
+
when(execa).calledWith('npm', ['whoami']).thenResolve({stdout: any.word()});
|
|
237
|
+
npmConfFactory.mockReturnValue({get: () => undefined});
|
|
238
|
+
when(commonPrompts.questions)
|
|
239
|
+
.calledWith({vcs, ciServices, pathWithinParent})
|
|
240
|
+
.thenReturn(commonQuestions);
|
|
241
|
+
prompts.prompt.mockResolvedValue(answers);
|
|
242
|
+
|
|
243
|
+
await prompt(ciServices, {}, 'ISS', vcs, null, null, pathWithinParent, {logger});
|
|
229
244
|
|
|
230
245
|
const [questions] = prompts.prompt.mock.lastCall;
|
|
231
246
|
expect(questions.filter(question => questionNames.SHOULD_BE_SCOPED === question.name).length).toEqual(0);
|
|
@@ -239,7 +254,7 @@ describe('prompts', () => {
|
|
|
239
254
|
.thenReturn(commonQuestions);
|
|
240
255
|
prompts.prompt.mockResolvedValue(answers);
|
|
241
256
|
|
|
242
|
-
await prompt(ciServices, {}, '
|
|
257
|
+
await prompt(ciServices, {}, 'OSS', vcs, {}, null, pathWithinParent, {logger});
|
|
243
258
|
|
|
244
259
|
const [questions] = prompts.prompt.mock.lastCall;
|
|
245
260
|
expect(questions.filter(question => questionNames.SHOULD_BE_SCOPED === question.name).length).toEqual(1);
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export function scope(visibility) {
|
|
2
2
|
return input => {
|
|
3
|
-
if (!input
|
|
4
|
-
|
|
3
|
+
if (!input) {
|
|
4
|
+
if ('CS' === visibility) {
|
|
5
|
+
return 'Closed source packages must be scoped';
|
|
6
|
+
}
|
|
7
|
+
if ('ISS' === visibility) {
|
|
8
|
+
return 'Inner source packages must be scoped';
|
|
9
|
+
}
|
|
5
10
|
}
|
|
6
11
|
|
|
7
12
|
return true;
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import {expect, it, describe} from 'vitest';
|
|
2
|
+
import any from '@travi/any';
|
|
2
3
|
|
|
3
4
|
import {scope} from './validators.js';
|
|
4
5
|
|
|
5
6
|
describe('question validators', () => {
|
|
6
|
-
it('should require a scope for
|
|
7
|
-
expect(scope('
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
it('should require a scope for a closed-source project', () => {
|
|
8
|
+
expect(scope('CS')()).toEqual('Closed source packages must be scoped');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('should require a scope for an inner-source project', () => {
|
|
12
|
+
expect(scope('ISS')()).toEqual('Inner source packages must be scoped');
|
|
10
13
|
});
|
|
11
14
|
|
|
12
15
|
it('it should consider a provided value to be a valid answer to private projects', () => {
|
|
13
|
-
expect(scope('
|
|
16
|
+
expect(scope('OSS')(any.word())).toBe(true);
|
|
14
17
|
});
|
|
15
18
|
|
|
16
19
|
it('it should consider an empty value to be a valid answer to public projects', () => {
|
|
17
|
-
expect(scope('
|
|
20
|
+
expect(scope('OSS')()).toBe(true);
|
|
18
21
|
});
|
|
19
22
|
});
|