@form8ion/javascript 15.8.3 → 16.0.0-beta.1
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 +2 -2
- package/lib/index.js +66 -58
- package/lib/index.js.map +1 -1
- package/package.json +17 -17
- 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 +11 -5
- 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 +5 -3
- package/src/project-type/scaffolder.js +4 -4
- package/src/project-type/scaffolder.test.js +15 -16
- package/src/prompts/questions.js +3 -3
- package/src/prompts/questions.test.js +6 -5
- 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
package/package.json
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
"name": "@form8ion/javascript",
|
|
3
3
|
"description": "JavaScript language plugin for the @form8ion toolset",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "16.0.0-beta.1",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
8
|
-
"node": "^
|
|
8
|
+
"node": "^22.21.0 || >=24.12"
|
|
9
9
|
},
|
|
10
10
|
"author": "Matt Travi <npm@travi.org> (https://matt.travi.org)",
|
|
11
11
|
"repository": "form8ion/javascript",
|
|
12
12
|
"bugs": "https://github.com/form8ion/javascript/issues",
|
|
13
|
-
"homepage": "https://
|
|
13
|
+
"homepage": "https://www.npmjs.com/package/@form8ion/javascript",
|
|
14
14
|
"runkitExampleFilename": "./example.js",
|
|
15
15
|
"exports": {
|
|
16
16
|
"module": "./lib/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"pretest": "run-s build",
|
|
23
23
|
"test": "npm-run-all --print-label --parallel lint:* --parallel test:*",
|
|
24
24
|
"lint:engines": "ls-engines",
|
|
25
|
-
"lint:gherkin": "
|
|
25
|
+
"lint:gherkin": "gplint --config .gplintrc.json",
|
|
26
26
|
"lint:js": "eslint . --cache",
|
|
27
27
|
"lint:js:fix": "run-s 'lint:js -- --fix'",
|
|
28
28
|
"lint:lockfile": "lockfile-lint",
|
|
@@ -59,26 +59,25 @@
|
|
|
59
59
|
"access": "public",
|
|
60
60
|
"provenance": true
|
|
61
61
|
},
|
|
62
|
-
"packageManager": "npm@11.
|
|
62
|
+
"packageManager": "npm@11.15.0+sha512.fa4d2d93b9519e93143e70bb913b94ff2ad5fe69c5a0f84943be557cbb59e9fc1bcce55768fb1313f225f4f9f50c78b8f366f2332aa41effd7b10efa98d8d72f",
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@form8ion/c8": "^1.0.0-beta.2",
|
|
65
65
|
"@form8ion/codecov": "^7.0.0-beta.1",
|
|
66
66
|
"@form8ion/commit-convention": "^8.0.0-beta.6",
|
|
67
67
|
"@form8ion/config-file": "^1.1.1",
|
|
68
|
-
"@form8ion/core": "^
|
|
68
|
+
"@form8ion/core": "^5.0.0-beta.9",
|
|
69
69
|
"@form8ion/eslint": "^7.0.0-beta.1",
|
|
70
70
|
"@form8ion/husky": "^7.0.0-beta.1",
|
|
71
71
|
"@form8ion/javascript-core": "^12.0.0-beta.1",
|
|
72
72
|
"@form8ion/overridable-prompts": "^1.2.0",
|
|
73
73
|
"@form8ion/prettier": "^3.0.0",
|
|
74
74
|
"@hapi/hoek": "^11.0.0",
|
|
75
|
-
"@travi/cli-messages": "^1.1.0",
|
|
76
75
|
"@travi/language-scaffolder-prompts": "^2.0.0-beta.1",
|
|
77
76
|
"camelcase": "^9.0.0",
|
|
78
77
|
"deepmerge": "^4.2.2",
|
|
79
78
|
"execa": "^9.5.1",
|
|
80
79
|
"ini": "^6.0.0",
|
|
81
|
-
"joi": "^
|
|
80
|
+
"joi": "^18.2.1",
|
|
82
81
|
"mustache": "^4.2.0",
|
|
83
82
|
"npm-conf": "^1.1.3",
|
|
84
83
|
"sort-object-keys": "^2.0.0",
|
|
@@ -86,34 +85,35 @@
|
|
|
86
85
|
"validate-npm-package-name": "^7.0.0"
|
|
87
86
|
},
|
|
88
87
|
"devDependencies": {
|
|
89
|
-
"@cucumber/cucumber": "12.
|
|
90
|
-
"@form8ion/commitlint-config": "2.0.
|
|
88
|
+
"@cucumber/cucumber": "12.9.0",
|
|
89
|
+
"@form8ion/commitlint-config": "2.0.15",
|
|
91
90
|
"@form8ion/eslint-config": "7.1.0-beta.1",
|
|
92
91
|
"@form8ion/eslint-config-cucumber": "1.4.1",
|
|
93
92
|
"@form8ion/eslint-config-vitest": "1.1.0",
|
|
94
93
|
"@form8ion/remark-lint-preset": "6.0.7",
|
|
95
94
|
"@rollup/plugin-node-resolve": "16.0.3",
|
|
96
|
-
"@travi/any": "3.
|
|
97
|
-
"@vitest/coverage-v8": "4.1.
|
|
95
|
+
"@travi/any": "3.3.0",
|
|
96
|
+
"@vitest/coverage-v8": "4.1.7",
|
|
98
97
|
"ban-sensitive-files": "1.10.11",
|
|
99
98
|
"chai": "6.2.2",
|
|
100
99
|
"cz-conventional-changelog": "3.3.0",
|
|
101
|
-
"
|
|
100
|
+
"debug": "4.4.3",
|
|
101
|
+
"gplint": "2.5.2",
|
|
102
102
|
"husky": "9.1.7",
|
|
103
103
|
"js-yaml": "4.1.1",
|
|
104
104
|
"lockfile-lint": "5.0.0",
|
|
105
105
|
"ls-engines": "0.9.4",
|
|
106
106
|
"mock-fs": "5.5.0",
|
|
107
|
-
"npm-run-all2": "
|
|
108
|
-
"publint": "0.3.
|
|
107
|
+
"npm-run-all2": "9.0.1",
|
|
108
|
+
"publint": "0.3.21",
|
|
109
109
|
"remark-cli": "12.0.1",
|
|
110
110
|
"remark-toc": "9.0.0",
|
|
111
111
|
"remark-usage": "11.0.1",
|
|
112
112
|
"rimraf": "6.1.3",
|
|
113
|
-
"rollup": "4.60.
|
|
113
|
+
"rollup": "4.60.4",
|
|
114
114
|
"rollup-plugin-auto-external": "2.0.0",
|
|
115
115
|
"testdouble": "3.20.2",
|
|
116
|
-
"vitest": "4.1.
|
|
116
|
+
"vitest": "4.1.7",
|
|
117
117
|
"vitest-when": "0.10.0"
|
|
118
118
|
}
|
|
119
119
|
}
|
package/src/code-style/lifter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {applyEnhancers} from '@form8ion/core';
|
|
2
2
|
import * as eslintPlugin from '@form8ion/eslint';
|
|
3
3
|
|
|
4
|
-
export default function liftCodeStyle(options) {
|
|
5
|
-
return applyEnhancers({options, enhancers: [eslintPlugin]});
|
|
4
|
+
export default function liftCodeStyle(options, dependencies) {
|
|
5
|
+
return applyEnhancers({options, enhancers: [eslintPlugin], dependencies});
|
|
6
6
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {DEV_DEPENDENCY_TYPE, packageManagers} from '@form8ion/javascript-core';
|
|
1
|
+
import {DEV_DEPENDENCY_TYPE} from '@form8ion/javascript-core';
|
|
3
2
|
|
|
4
3
|
import {execa} from 'execa';
|
|
5
4
|
import {getDependencyTypeFlag, getExactFlag, getInstallationCommandFor} from './package-managers.js';
|
|
@@ -8,10 +7,11 @@ export default async function installDependencies(
|
|
|
8
7
|
dependencies,
|
|
9
8
|
dependenciesType,
|
|
10
9
|
projectRoot,
|
|
11
|
-
packageManager
|
|
10
|
+
packageManager,
|
|
11
|
+
{logger}
|
|
12
12
|
) {
|
|
13
13
|
if (dependencies.length) {
|
|
14
|
-
info(`Installing ${dependenciesType} dependencies`, {level: 'secondary'});
|
|
14
|
+
logger.info(`Installing ${dependenciesType} dependencies`, {level: 'secondary'});
|
|
15
15
|
|
|
16
16
|
await execa(
|
|
17
17
|
`. ~/.nvm/nvm.sh && nvm use && ${packageManager} ${
|
|
@@ -21,5 +21,5 @@ export default async function installDependencies(
|
|
|
21
21
|
}`,
|
|
22
22
|
{shell: true, cwd: projectRoot}
|
|
23
23
|
);
|
|
24
|
-
} else warn(`No ${dependenciesType} dependencies to install`);
|
|
24
|
+
} else logger.warn(`No ${dependenciesType} dependencies to install`);
|
|
25
25
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {execa} from 'execa';
|
|
2
|
-
import {DEV_DEPENDENCY_TYPE
|
|
2
|
+
import {DEV_DEPENDENCY_TYPE} from '@form8ion/javascript-core';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {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 {getDependencyTypeFlag,
|
|
8
|
+
import {getDependencyTypeFlag, getExactFlag, getInstallationCommandFor} from './package-managers.js';
|
|
9
9
|
import install from './installer.js';
|
|
10
10
|
|
|
11
11
|
vi.mock('execa');
|
|
@@ -20,13 +20,14 @@ describe('dependencies installer', () => {
|
|
|
20
20
|
const uniqueDependencies = any.listOf(any.word);
|
|
21
21
|
const dependencies = [duplicateDependency, ...uniqueDependencies, duplicateDependency];
|
|
22
22
|
const exactFlag = any.word();
|
|
23
|
+
const logger = {info: () => undefined, warn: () => undefined};
|
|
23
24
|
|
|
24
25
|
beforeEach(() => {
|
|
25
26
|
when(getInstallationCommandFor).calledWith(packageManager).thenReturn(installationCommand);
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
it('should avoid execution when there are no dependencies to install', async () => {
|
|
29
|
-
await install([]);
|
|
30
|
+
await install([], undefined, undefined, undefined, {logger});
|
|
30
31
|
|
|
31
32
|
expect(execa).not.toHaveBeenCalled();
|
|
32
33
|
});
|
|
@@ -35,7 +36,7 @@ describe('dependencies installer', () => {
|
|
|
35
36
|
const dependenciesType = any.word();
|
|
36
37
|
when(getDependencyTypeFlag).calledWith(packageManager, dependenciesType).thenReturn(typeFlag);
|
|
37
38
|
|
|
38
|
-
await install(dependencies, dependenciesType, projectRoot, packageManager);
|
|
39
|
+
await install(dependencies, dependenciesType, projectRoot, packageManager, {logger});
|
|
39
40
|
|
|
40
41
|
expect(execa).toHaveBeenCalledWith(
|
|
41
42
|
`. ~/.nvm/nvm.sh && nvm use && ${packageManager} ${installationCommand} ${
|
|
@@ -46,11 +47,11 @@ describe('dependencies installer', () => {
|
|
|
46
47
|
});
|
|
47
48
|
|
|
48
49
|
it('should pin versions when installing dev-dependencies', async () => {
|
|
49
|
-
await install(dependencies, DEV_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
50
|
+
await install(dependencies, DEV_DEPENDENCY_TYPE, projectRoot, packageManager, {logger});
|
|
50
51
|
when(getDependencyTypeFlag).calledWith(packageManager, DEV_DEPENDENCY_TYPE).thenReturn(typeFlag);
|
|
51
52
|
when(getExactFlag).calledWith(packageManager).thenReturn(exactFlag);
|
|
52
53
|
|
|
53
|
-
await install(dependencies, DEV_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
54
|
+
await install(dependencies, DEV_DEPENDENCY_TYPE, projectRoot, packageManager, {logger});
|
|
54
55
|
|
|
55
56
|
expect(execa).toHaveBeenCalledWith(
|
|
56
57
|
`. ~/.nvm/nvm.sh && nvm use && ${packageManager} ${installationCommand} ${
|
|
@@ -59,19 +60,4 @@ describe('dependencies installer', () => {
|
|
|
59
60
|
{shell: true, cwd: projectRoot}
|
|
60
61
|
);
|
|
61
62
|
});
|
|
62
|
-
|
|
63
|
-
it('should default to `npm` when the package-manager is not specified', async () => {
|
|
64
|
-
when(getDependencyTypeFlag).calledWith(packageManagers.NPM, DEV_DEPENDENCY_TYPE).thenReturn(typeFlag);
|
|
65
|
-
when(getExactFlag).calledWith(packageManagers.NPM).thenReturn(exactFlag);
|
|
66
|
-
when(getInstallationCommandFor).calledWith(packageManagers.NPM).thenReturn(installationCommand);
|
|
67
|
-
|
|
68
|
-
await install(dependencies, DEV_DEPENDENCY_TYPE, projectRoot);
|
|
69
|
-
|
|
70
|
-
expect(execa).toHaveBeenCalledWith(
|
|
71
|
-
`. ~/.nvm/nvm.sh && nvm use && ${packageManagers.NPM} ${installationCommand} ${
|
|
72
|
-
[duplicateDependency, ...uniqueDependencies].join(' ')
|
|
73
|
-
} --${typeFlag} --${exactFlag}`,
|
|
74
|
-
{shell: true, cwd: projectRoot}
|
|
75
|
-
);
|
|
76
|
-
});
|
|
77
63
|
});
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {error, info} from '@travi/cli-messages';
|
|
2
1
|
import {DEV_DEPENDENCY_TYPE, PROD_DEPENDENCY_TYPE} from '@form8ion/javascript-core';
|
|
3
2
|
|
|
4
3
|
import install from './installer.js';
|
|
5
4
|
import remove from './remover.js';
|
|
6
5
|
|
|
7
|
-
export default async function processDependencies(
|
|
8
|
-
|
|
6
|
+
export default async function processDependencies(
|
|
7
|
+
{dependencies = {}, devDependencies, projectRoot, packageManager},
|
|
8
|
+
{logger}
|
|
9
|
+
) {
|
|
10
|
+
logger.info('Processing dependencies');
|
|
9
11
|
|
|
10
12
|
if (Array.isArray(devDependencies)) {
|
|
11
13
|
throw new Error(
|
|
@@ -20,11 +22,11 @@ export default async function processDependencies({dependencies = {}, devDepende
|
|
|
20
22
|
const {javascript: {production = [], development = [], remove: dependenciesToRemove = []} = {}} = dependencies;
|
|
21
23
|
|
|
22
24
|
try {
|
|
23
|
-
await install(production, PROD_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
24
|
-
await install(development, DEV_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
25
|
-
await remove({packageManager, dependencies: dependenciesToRemove});
|
|
25
|
+
await install(production, PROD_DEPENDENCY_TYPE, projectRoot, packageManager, {logger});
|
|
26
|
+
await install(development, DEV_DEPENDENCY_TYPE, projectRoot, packageManager, {logger});
|
|
27
|
+
await remove({packageManager, dependencies: dependenciesToRemove}, {logger});
|
|
26
28
|
} catch (e) {
|
|
27
|
-
error('Failed to update dependencies');
|
|
28
|
-
error(e, {level: 'secondary'});
|
|
29
|
+
logger.error('Failed to update dependencies');
|
|
30
|
+
logger.error(e, {level: 'secondary'});
|
|
29
31
|
}
|
|
30
32
|
}
|
|
@@ -13,6 +13,7 @@ vi.mock('./remover.js');
|
|
|
13
13
|
describe('dependencies processor', () => {
|
|
14
14
|
const projectRoot = any.string();
|
|
15
15
|
const packageManager = any.word();
|
|
16
|
+
const logger = {info: () => undefined, error: () => undefined};
|
|
16
17
|
|
|
17
18
|
it('should process the provided dependency lists', async () => {
|
|
18
19
|
const production = any.listOf(any.word);
|
|
@@ -23,52 +24,64 @@ describe('dependencies processor', () => {
|
|
|
23
24
|
dependencies: {javascript: {production, development, remove}},
|
|
24
25
|
projectRoot,
|
|
25
26
|
packageManager
|
|
26
|
-
});
|
|
27
|
+
}, {logger});
|
|
27
28
|
|
|
28
|
-
expect(installDependencies).toHaveBeenCalledWith(
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
expect(installDependencies).toHaveBeenCalledWith(
|
|
30
|
+
production,
|
|
31
|
+
PROD_DEPENDENCY_TYPE,
|
|
32
|
+
projectRoot,
|
|
33
|
+
packageManager,
|
|
34
|
+
{logger}
|
|
35
|
+
);
|
|
36
|
+
expect(installDependencies).toHaveBeenCalledWith(
|
|
37
|
+
development,
|
|
38
|
+
DEV_DEPENDENCY_TYPE,
|
|
39
|
+
projectRoot,
|
|
40
|
+
packageManager,
|
|
41
|
+
{logger}
|
|
42
|
+
);
|
|
43
|
+
expect(removeDependencies).toHaveBeenCalledWith({packageManager, dependencies: remove}, {logger});
|
|
31
44
|
});
|
|
32
45
|
|
|
33
46
|
it('should process as empty lists when dependencies are not provided', async () => {
|
|
34
|
-
await processDependencies({projectRoot, packageManager});
|
|
47
|
+
await processDependencies({projectRoot, packageManager}, {logger});
|
|
35
48
|
|
|
36
|
-
expect(installDependencies).toHaveBeenCalledWith([], PROD_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
37
|
-
expect(installDependencies).toHaveBeenCalledWith([], DEV_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
49
|
+
expect(installDependencies).toHaveBeenCalledWith([], PROD_DEPENDENCY_TYPE, projectRoot, packageManager, {logger});
|
|
50
|
+
expect(installDependencies).toHaveBeenCalledWith([], DEV_DEPENDENCY_TYPE, projectRoot, packageManager, {logger});
|
|
38
51
|
});
|
|
39
52
|
|
|
40
53
|
it('should process as empty lists when javascript dependencies are not provided', async () => {
|
|
41
|
-
await processDependencies({projectRoot, packageManager, dependencies: {}});
|
|
54
|
+
await processDependencies({projectRoot, packageManager, dependencies: {}}, {logger});
|
|
42
55
|
|
|
43
|
-
expect(installDependencies).toHaveBeenCalledWith([], PROD_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
44
|
-
expect(installDependencies).toHaveBeenCalledWith([], DEV_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
56
|
+
expect(installDependencies).toHaveBeenCalledWith([], PROD_DEPENDENCY_TYPE, projectRoot, packageManager, {logger});
|
|
57
|
+
expect(installDependencies).toHaveBeenCalledWith([], DEV_DEPENDENCY_TYPE, projectRoot, packageManager, {logger});
|
|
45
58
|
});
|
|
46
59
|
|
|
47
60
|
it('should process as empty lists when dependency types are not provided', async () => {
|
|
48
|
-
await processDependencies({projectRoot, packageManager, dependencies: {javascript: {}}});
|
|
61
|
+
await processDependencies({projectRoot, packageManager, dependencies: {javascript: {}}}, {logger});
|
|
49
62
|
|
|
50
|
-
expect(installDependencies).toHaveBeenCalledWith([], PROD_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
51
|
-
expect(installDependencies).toHaveBeenCalledWith([], DEV_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
52
|
-
expect(removeDependencies).toHaveBeenCalledWith({packageManager, dependencies: []});
|
|
63
|
+
expect(installDependencies).toHaveBeenCalledWith([], PROD_DEPENDENCY_TYPE, projectRoot, packageManager, {logger});
|
|
64
|
+
expect(installDependencies).toHaveBeenCalledWith([], DEV_DEPENDENCY_TYPE, projectRoot, packageManager, {logger});
|
|
65
|
+
expect(removeDependencies).toHaveBeenCalledWith({packageManager, dependencies: []}, {logger});
|
|
53
66
|
});
|
|
54
67
|
|
|
55
68
|
it('should prevent an installation error from bubbling', async () => {
|
|
56
69
|
installDependencies.mockRejectedValue(new Error());
|
|
57
70
|
|
|
58
|
-
|
|
71
|
+
expect(() => processDependencies({dependencies: {javascript: {}}}, {logger})).not.toThrow();
|
|
59
72
|
});
|
|
60
73
|
|
|
61
74
|
it('should throw an error if dependencies is defined as an array rather than an object', async () => {
|
|
62
75
|
const dependencies = any.listOf(any.word);
|
|
63
76
|
|
|
64
|
-
await expect(() => processDependencies({dependencies}))
|
|
65
|
-
.rejects.
|
|
77
|
+
await expect(() => processDependencies({dependencies}, {logger}))
|
|
78
|
+
.rejects.toThrow(`Expected dependencies to be an object. Instead received: ${dependencies}`);
|
|
66
79
|
});
|
|
67
80
|
|
|
68
81
|
it('should throw an error if devDependencies is defined as an array', async () => {
|
|
69
82
|
const devDependencies = any.listOf(any.word);
|
|
70
83
|
|
|
71
|
-
await expect(() => processDependencies({devDependencies})).rejects.toThrowError(
|
|
84
|
+
await expect(() => processDependencies({devDependencies}, {logger})).rejects.toThrowError(
|
|
72
85
|
`devDependencies provided as: ${devDependencies}. Instead, provide under dependencies.javascript.development`
|
|
73
86
|
);
|
|
74
87
|
});
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import {execa} from 'execa';
|
|
2
|
-
import {info} from '@travi/cli-messages';
|
|
3
2
|
|
|
4
|
-
export default async function removeDependencies({packageManager, dependencies}) {
|
|
3
|
+
export default async function removeDependencies({packageManager, dependencies}, {logger}) {
|
|
5
4
|
if (dependencies.length) {
|
|
6
|
-
info('Removing dependencies dependencies', {level: 'secondary'});
|
|
5
|
+
logger.info('Removing dependencies dependencies', {level: 'secondary'});
|
|
7
6
|
|
|
8
7
|
await execa(packageManager, ['remove', ...dependencies]);
|
|
9
8
|
}
|
|
@@ -8,11 +8,13 @@ import removeDependencies from './remover.js';
|
|
|
8
8
|
vi.mock('execa');
|
|
9
9
|
|
|
10
10
|
describe('dependency remover', () => {
|
|
11
|
+
const logger = {info: () => undefined};
|
|
12
|
+
|
|
11
13
|
it('should remove the dependencies using the named package manager', async () => {
|
|
12
14
|
const packageManager = any.word();
|
|
13
15
|
const dependencies = any.listOf(any.word);
|
|
14
16
|
|
|
15
|
-
await removeDependencies({packageManager, dependencies});
|
|
17
|
+
await removeDependencies({packageManager, dependencies}, {logger});
|
|
16
18
|
|
|
17
19
|
expect(execa).toHaveBeenCalledWith(packageManager, ['remove', ...dependencies]);
|
|
18
20
|
});
|
|
@@ -21,7 +23,7 @@ describe('dependency remover', () => {
|
|
|
21
23
|
const packageManager = any.word();
|
|
22
24
|
const dependencies = [];
|
|
23
25
|
|
|
24
|
-
await removeDependencies({packageManager, dependencies});
|
|
26
|
+
await removeDependencies({packageManager, dependencies}, {logger});
|
|
25
27
|
|
|
26
28
|
expect(execa).not.toHaveBeenCalled();
|
|
27
29
|
});
|
package/src/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 {applyEnhancers} from '@form8ion/core';
|
|
5
4
|
import * as huskyPlugin from '@form8ion/husky';
|
|
6
5
|
import * as commitConventionPlugin from '@form8ion/commit-convention';
|
|
@@ -23,8 +22,8 @@ export default async function liftJavaScript({
|
|
|
23
22
|
pathWithinParent,
|
|
24
23
|
enhancers = {},
|
|
25
24
|
configs = {}
|
|
26
|
-
}) {
|
|
27
|
-
info('Lifting JavaScript-specific details');
|
|
25
|
+
}, dependencies) {
|
|
26
|
+
dependencies.logger.info('Lifting JavaScript-specific details');
|
|
28
27
|
|
|
29
28
|
const [packageManager, packageContents] = await Promise.all([
|
|
30
29
|
resolvePackageManager({projectRoot, packageManager: results.packageManager}),
|
|
@@ -46,10 +45,14 @@ export default async function liftJavaScript({
|
|
|
46
45
|
packageManagers,
|
|
47
46
|
registriesPlugin
|
|
48
47
|
},
|
|
49
|
-
options: {packageManager, projectRoot, vcs, packageDetails: JSON.parse(packageContents), configs}
|
|
48
|
+
options: {packageManager, projectRoot, vcs, packageDetails: JSON.parse(packageContents), configs},
|
|
49
|
+
dependencies
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
await liftPackage(
|
|
52
|
+
await liftPackage(
|
|
53
|
+
deepmerge.all([{projectRoot, packageManager, vcs, pathWithinParent}, enhancerResults]),
|
|
54
|
+
dependencies
|
|
55
|
+
);
|
|
53
56
|
|
|
54
57
|
return enhancerResults;
|
|
55
58
|
}
|
package/src/lifter.test.js
CHANGED
|
@@ -29,13 +29,12 @@ describe('lift', () => {
|
|
|
29
29
|
const projectRoot = any.string();
|
|
30
30
|
const scripts = any.simpleObject();
|
|
31
31
|
const tags = any.listOf(any.word);
|
|
32
|
-
const dependencies = any.simpleObject();
|
|
33
|
-
const devDependencies = any.simpleObject();
|
|
32
|
+
const dependencies = {...any.simpleObject(), logger: {info: () => undefined}};
|
|
34
33
|
const packageManager = any.word();
|
|
35
34
|
const manager = any.word();
|
|
36
35
|
const enhancerResults = any.simpleObject();
|
|
37
36
|
const vcsDetails = any.simpleObject();
|
|
38
|
-
const results = {...any.simpleObject(), scripts, tags,
|
|
37
|
+
const results = {...any.simpleObject(), scripts, tags, packageManager: manager};
|
|
39
38
|
const pathWithinParent = any.string();
|
|
40
39
|
const packageDetails = any.simpleObject();
|
|
41
40
|
const internalEnhancers = {
|
|
@@ -66,17 +65,18 @@ describe('lift', () => {
|
|
|
66
65
|
.calledWith({
|
|
67
66
|
results,
|
|
68
67
|
enhancers: internalEnhancers,
|
|
69
|
-
options: {projectRoot, packageManager, vcs: vcsDetails, packageDetails, configs}
|
|
68
|
+
options: {projectRoot, packageManager, vcs: vcsDetails, packageDetails, configs},
|
|
69
|
+
dependencies
|
|
70
70
|
})
|
|
71
71
|
.thenResolve(enhancerResults);
|
|
72
72
|
|
|
73
|
-
const liftResults = await lift({projectRoot, vcs: vcsDetails, results, pathWithinParent, configs});
|
|
73
|
+
const liftResults = await lift({projectRoot, vcs: vcsDetails, results, pathWithinParent, configs}, dependencies);
|
|
74
74
|
|
|
75
75
|
expect(liftResults).toEqual(enhancerResults);
|
|
76
|
-
expect(liftPackage).toHaveBeenCalledWith(
|
|
77
|
-
{projectRoot, packageManager, vcs: vcsDetails, pathWithinParent},
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
expect(liftPackage).toHaveBeenCalledWith(
|
|
77
|
+
deepmerge.all([{projectRoot, packageManager, vcs: vcsDetails, pathWithinParent}, enhancerResults]),
|
|
78
|
+
dependencies
|
|
79
|
+
);
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
it('should apply provided enhancers', async () => {
|
|
@@ -85,11 +85,12 @@ describe('lift', () => {
|
|
|
85
85
|
.calledWith({
|
|
86
86
|
results,
|
|
87
87
|
enhancers: {...enhancers, ...internalEnhancers},
|
|
88
|
-
options: {projectRoot, packageManager, vcs: vcsDetails, packageDetails, configs: {}}
|
|
88
|
+
options: {projectRoot, packageManager, vcs: vcsDetails, packageDetails, configs: {}},
|
|
89
|
+
dependencies
|
|
89
90
|
})
|
|
90
91
|
.thenResolve(enhancerResults);
|
|
91
92
|
|
|
92
|
-
const liftResults = await lift({projectRoot, vcs: vcsDetails, results, pathWithinParent, enhancers});
|
|
93
|
+
const liftResults = await lift({projectRoot, vcs: vcsDetails, results, pathWithinParent, enhancers}, dependencies);
|
|
93
94
|
|
|
94
95
|
expect(liftResults).toEqual(enhancerResults);
|
|
95
96
|
});
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import {promises as fs} from 'node:fs';
|
|
2
|
-
import {info} from '@travi/cli-messages';
|
|
3
2
|
|
|
4
3
|
import {determineLatestVersionOf, install as installNodeVersion} from './tasks.js';
|
|
5
4
|
|
|
6
|
-
export default async function scaffoldNodeVersion({projectRoot, nodeVersionCategory}) {
|
|
5
|
+
export default async function scaffoldNodeVersion({projectRoot, nodeVersionCategory}, {logger}) {
|
|
7
6
|
if (!nodeVersionCategory) return undefined;
|
|
8
7
|
|
|
9
8
|
const lowerCaseCategory = nodeVersionCategory.toLowerCase();
|
|
10
|
-
info(`Configuring ${lowerCaseCategory} version of node`);
|
|
9
|
+
logger.info(`Configuring ${lowerCaseCategory} version of node`);
|
|
11
10
|
|
|
12
|
-
const version = await determineLatestVersionOf(nodeVersionCategory);
|
|
11
|
+
const version = await determineLatestVersionOf(nodeVersionCategory, {logger});
|
|
13
12
|
|
|
14
13
|
await fs.writeFile(`${projectRoot}/.nvmrc`, version);
|
|
15
14
|
|
|
16
|
-
await installNodeVersion(nodeVersionCategory);
|
|
15
|
+
await installNodeVersion(nodeVersionCategory, {logger});
|
|
17
16
|
|
|
18
17
|
return version;
|
|
19
18
|
}
|
|
@@ -12,6 +12,7 @@ vi.mock('./tasks.js');
|
|
|
12
12
|
|
|
13
13
|
describe('node-version scaffolder', () => {
|
|
14
14
|
const projectRoot = any.string();
|
|
15
|
+
const logger = {info: () => undefined};
|
|
15
16
|
|
|
16
17
|
afterEach(() => {
|
|
17
18
|
vi.clearAllMocks();
|
|
@@ -20,14 +21,14 @@ describe('node-version scaffolder', () => {
|
|
|
20
21
|
it('should configure nvm with the desired version', async () => {
|
|
21
22
|
const nodeVersionCategory = any.word();
|
|
22
23
|
const version = any.word();
|
|
23
|
-
when(determineLatestVersionOf).calledWith(nodeVersionCategory).thenResolve(version);
|
|
24
|
+
when(determineLatestVersionOf).calledWith(nodeVersionCategory, {logger}).thenResolve(version);
|
|
24
25
|
|
|
25
|
-
expect(await scaffoldNodeVersion({projectRoot, nodeVersionCategory})).toEqual(version);
|
|
26
|
-
expect(installNodeVersion).toHaveBeenCalledWith(nodeVersionCategory);
|
|
26
|
+
expect(await scaffoldNodeVersion({projectRoot, nodeVersionCategory}, {logger})).toEqual(version);
|
|
27
|
+
expect(installNodeVersion).toHaveBeenCalledWith(nodeVersionCategory, {logger});
|
|
27
28
|
expect(fs.writeFile).toHaveBeenCalledWith(`${projectRoot}/.nvmrc`, version);
|
|
28
29
|
});
|
|
29
30
|
|
|
30
31
|
it('should return `undefined` when a category is not defined', async () => {
|
|
31
|
-
expect(await scaffoldNodeVersion({projectRoot})).toBe(undefined);
|
|
32
|
+
expect(await scaffoldNodeVersion({projectRoot}, {logger})).toBe(undefined);
|
|
32
33
|
});
|
|
33
34
|
});
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {info} from '@travi/cli-messages';
|
|
2
|
-
|
|
3
1
|
import {execa} from 'execa';
|
|
4
2
|
|
|
5
|
-
export async function determineLatestVersionOf(nodeVersionCategory) {
|
|
6
|
-
info('Determining version of node', {level: 'secondary'});
|
|
3
|
+
export async function determineLatestVersionOf(nodeVersionCategory, {logger}) {
|
|
4
|
+
logger.info('Determining version of node', {level: 'secondary'});
|
|
7
5
|
|
|
8
6
|
const {stdout: nvmLsOutput} = await execa(
|
|
9
7
|
`. ~/.nvm/nvm.sh && nvm ls-remote${('LTS' === nodeVersionCategory) ? ' --lts' : ''}`,
|
|
@@ -16,8 +14,8 @@ export async function determineLatestVersionOf(nodeVersionCategory) {
|
|
|
16
14
|
return lsLine.match(/(v[0-9]+)\.[0-9]+\.[0-9]+/)[1];
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
export function install(nodeVersionCategory) {
|
|
20
|
-
info(`Installing ${nodeVersionCategory} version of node using nvm`, {level: 'secondary'});
|
|
17
|
+
export function install(nodeVersionCategory, {logger}) {
|
|
18
|
+
logger.info(`Installing ${nodeVersionCategory} version of node using nvm`, {level: 'secondary'});
|
|
21
19
|
|
|
22
20
|
const subprocess = execa('. ~/.nvm/nvm.sh && nvm install', {shell: true});
|
|
23
21
|
subprocess.stdout.pipe(process.stdout);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {execa} from 'execa';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {describe, expect, it, vi} from 'vitest';
|
|
4
4
|
import {when} from 'vitest-when';
|
|
5
5
|
import any from '@travi/any';
|
|
6
6
|
|
|
@@ -11,17 +11,14 @@ vi.mock('execa');
|
|
|
11
11
|
describe('node-version tasks', () => {
|
|
12
12
|
const majorVersion = any.integer();
|
|
13
13
|
const version = `v${majorVersion}.${any.integer()}.${any.integer()}`;
|
|
14
|
-
|
|
15
|
-
afterEach(() => {
|
|
16
|
-
vi.clearAllMocks();
|
|
17
|
-
});
|
|
14
|
+
const logger = {info: () => undefined};
|
|
18
15
|
|
|
19
16
|
it('should return the latest node version when latest is requested', async () => {
|
|
20
17
|
when(execa)
|
|
21
18
|
.calledWith('. ~/.nvm/nvm.sh && nvm ls-remote', {shell: true})
|
|
22
19
|
.thenResolve({stdout: [...any.listOf(any.word), version, ''].join('\n')});
|
|
23
20
|
|
|
24
|
-
expect(await determineLatestVersionOf(any.word())).toEqual(`v${majorVersion}`);
|
|
21
|
+
expect(await determineLatestVersionOf(any.word(), {logger})).toEqual(`v${majorVersion}`);
|
|
25
22
|
});
|
|
26
23
|
|
|
27
24
|
it('should return the latest LTS node version when LTS is requested', async () => {
|
|
@@ -29,14 +26,14 @@ describe('node-version tasks', () => {
|
|
|
29
26
|
.calledWith('. ~/.nvm/nvm.sh && nvm ls-remote --lts', {shell: true})
|
|
30
27
|
.thenResolve({stdout: [...any.listOf(any.word), version, ''].join('\n')});
|
|
31
28
|
|
|
32
|
-
expect(await determineLatestVersionOf('LTS')).toEqual(`v${majorVersion}`);
|
|
29
|
+
expect(await determineLatestVersionOf('LTS', {logger})).toEqual(`v${majorVersion}`);
|
|
33
30
|
});
|
|
34
31
|
|
|
35
32
|
it('should install the node version', async () => {
|
|
36
33
|
const pipe = vi.fn();
|
|
37
34
|
when(execa).calledWith('. ~/.nvm/nvm.sh && nvm install', {shell: true}).thenReturn({stdout: {pipe}});
|
|
38
35
|
|
|
39
|
-
await install();
|
|
36
|
+
await install(undefined, {logger});
|
|
40
37
|
|
|
41
38
|
expect(pipe).toHaveBeenCalledWith(process.stdout);
|
|
42
39
|
});
|
package/src/options/schemas.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import joi from 'joi';
|
|
2
|
+
import {visibilityOptions} from '@form8ion/core';
|
|
2
3
|
|
|
3
4
|
export const scopeBasedConfigSchema = joi.object({scope: joi.string().regex(/^@[a-z0-9-]+$/i, 'scope').required()});
|
|
4
5
|
|
|
@@ -9,6 +10,6 @@ export const nameBasedConfigSchema = joi.object({
|
|
|
9
10
|
|
|
10
11
|
export const registriesSchema = joi.object().pattern(joi.string(), joi.string().uri()).default({});
|
|
11
12
|
|
|
12
|
-
export const visibilitySchema = joi.string().valid(
|
|
13
|
+
export const visibilitySchema = joi.string().valid(...Object.keys(visibilityOptions)).required();
|
|
13
14
|
|
|
14
15
|
export const projectNameSchema = joi.string().regex(/^@\w*\//, {invert: true}).required();
|
|
@@ -104,21 +104,27 @@ describe('options schemas', () => {
|
|
|
104
104
|
expect(() => validateOptions(visibilitySchema)).toThrowError('"value" is required');
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
it('should allow
|
|
108
|
-
const visibility = '
|
|
107
|
+
it('should allow "Open Source" as a valid value', () => {
|
|
108
|
+
const visibility = 'OSS';
|
|
109
109
|
|
|
110
110
|
expect(validateOptions(visibilitySchema, visibility)).toEqual(visibility);
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
it('should allow
|
|
114
|
-
const visibility = '
|
|
113
|
+
it('should allow "Inner Source" as a valid value', () => {
|
|
114
|
+
const visibility = 'ISS';
|
|
115
|
+
|
|
116
|
+
expect(validateOptions(visibilitySchema, visibility)).toEqual(visibility);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should allow "Closed Source" as a valid value', () => {
|
|
120
|
+
const visibility = 'CS';
|
|
115
121
|
|
|
116
122
|
expect(validateOptions(visibilitySchema, visibility)).toEqual(visibility);
|
|
117
123
|
});
|
|
118
124
|
|
|
119
125
|
it('should consider values other than `Public` and `Private` as invalid', () => {
|
|
120
126
|
expect(() => validateOptions(visibilitySchema, any.word()))
|
|
121
|
-
.toThrowError('"value" must be one of [
|
|
127
|
+
.toThrowError('"value" must be one of [OSS, ISS, CS]');
|
|
122
128
|
});
|
|
123
129
|
});
|
|
124
130
|
|