aberlaas-lint 2.19.0 → 2.20.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/configs/eslint.js +59 -12
- package/lib/circleci.js +67 -51
- package/lib/css.js +67 -56
- package/lib/helpers/{prettier.js → prettierFix.js} +18 -24
- package/lib/js.js +68 -63
- package/lib/json.js +55 -44
- package/lib/main.js +42 -34
- package/lib/yml.js +57 -46
- package/package.json +32 -34
package/configs/eslint.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import globals from 'globals';
|
|
2
1
|
import js from '@eslint/js';
|
|
2
|
+
// @vitest/plugins requires @typescript-eslint/utils and typescripts as deps
|
|
3
|
+
// See: https://github.com/vitest-dev/eslint-plugin-vitest/issues/543
|
|
4
|
+
import pluginVitest from '@vitest/eslint-plugin';
|
|
5
|
+
import { nodeVersion } from 'aberlaas-versions';
|
|
3
6
|
import pluginImport from 'eslint-plugin-import';
|
|
4
7
|
import pluginJsdoc from 'eslint-plugin-jsdoc';
|
|
5
8
|
import pluginN from 'eslint-plugin-n';
|
|
6
9
|
import pluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
|
7
10
|
import pluginReact from 'eslint-plugin-react';
|
|
8
|
-
|
|
9
|
-
// It is currently required to manually add typescript and
|
|
10
|
-
// @typescript-eslint/utils to aberlaas for the plugin to work
|
|
11
|
-
// See: https://github.com/vitest-dev/eslint-plugin-vitest/issues/543
|
|
12
|
-
import pluginVitest from '@vitest/eslint-plugin';
|
|
13
|
-
import { nodeVersion } from 'aberlaas-versions';
|
|
11
|
+
import globals from 'globals';
|
|
14
12
|
|
|
15
13
|
export default [
|
|
16
14
|
{
|
|
@@ -70,6 +68,16 @@ export default [
|
|
|
70
68
|
property: 'contains',
|
|
71
69
|
message: 'Typo: Use _.includes instead',
|
|
72
70
|
},
|
|
71
|
+
{
|
|
72
|
+
object: '_',
|
|
73
|
+
property: 'contain',
|
|
74
|
+
message: 'Typo: Use _.includes instead',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
object: '_',
|
|
78
|
+
property: 'include',
|
|
79
|
+
message: 'Typo: Use _.includes instead',
|
|
80
|
+
},
|
|
73
81
|
{
|
|
74
82
|
object: '_',
|
|
75
83
|
property: 'padLeft',
|
|
@@ -108,12 +116,51 @@ export default [
|
|
|
108
116
|
// Import
|
|
109
117
|
'import/first': ['error'],
|
|
110
118
|
'import/no-cycle': ['error', { ignoreExternal: true, disableScc: true }],
|
|
111
|
-
|
|
119
|
+
// Put most common modules (firost, golgoth, etc) first
|
|
120
|
+
// Then other third parties
|
|
121
|
+
// Then internal files
|
|
122
|
+
'import/order': [
|
|
123
|
+
'error',
|
|
124
|
+
{
|
|
125
|
+
groups: [
|
|
126
|
+
'builtin',
|
|
127
|
+
'external',
|
|
128
|
+
'internal',
|
|
129
|
+
'parent',
|
|
130
|
+
'sibling',
|
|
131
|
+
'index',
|
|
132
|
+
],
|
|
133
|
+
pathGroups: [
|
|
134
|
+
{
|
|
135
|
+
pattern: 'golgoth',
|
|
136
|
+
group: 'external',
|
|
137
|
+
position: 'before',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
pattern: 'firost',
|
|
141
|
+
group: 'external',
|
|
142
|
+
position: 'before',
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
pathGroupsExcludedImportTypes: [],
|
|
146
|
+
'newlines-between': 'never',
|
|
147
|
+
alphabetize: {
|
|
148
|
+
order: 'asc',
|
|
149
|
+
caseInsensitive: true,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
],
|
|
112
153
|
'import/newline-after-import': ['error'],
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
|
|
154
|
+
// import/no-unresolved can only check for .main fields, not the more
|
|
155
|
+
// modern .exports fields.
|
|
156
|
+
// We keep here a list of exceptions for packages we use that don't have a .main field.
|
|
157
|
+
// See: https://github.com/import-js/eslint-plugin-import/issues/2132
|
|
158
|
+
'import/no-unresolved': [
|
|
159
|
+
'error',
|
|
160
|
+
{
|
|
161
|
+
ignore: ['changelogen', 'lint-staged', '@octokit/rest', 'stylelint'],
|
|
162
|
+
},
|
|
163
|
+
],
|
|
117
164
|
|
|
118
165
|
// JSDoc
|
|
119
166
|
'jsdoc/check-param-names': ['warn'],
|
package/lib/circleci.js
CHANGED
|
@@ -1,17 +1,70 @@
|
|
|
1
|
+
import { exists, firostError, run as firostRun, which } from 'firost';
|
|
2
|
+
import { hostGitPath } from 'aberlaas-helper';
|
|
1
3
|
import ciInfo from 'ci-info';
|
|
2
|
-
import {
|
|
3
|
-
import helper from 'aberlaas-helper';
|
|
4
|
-
import lintYml from './yml.js';
|
|
4
|
+
import { fix as fixYml, run as runYml } from './yml.js';
|
|
5
5
|
|
|
6
|
-
export
|
|
6
|
+
export let __;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Lint the file, both for yml issues and if possible circleci specifics
|
|
10
|
+
* @returns {boolean} True on success
|
|
11
|
+
*/
|
|
12
|
+
export async function run() {
|
|
13
|
+
const absoluteConfigPath = await __.getInputFile();
|
|
14
|
+
const isRunningOnCircleCi = __.isRunningOnCircleCi();
|
|
15
|
+
|
|
16
|
+
// Stop early if no config file, or if running on CircleCI
|
|
17
|
+
if (!absoluteConfigPath || isRunningOnCircleCi) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Lint as yml first
|
|
22
|
+
await runYml([absoluteConfigPath]);
|
|
23
|
+
|
|
24
|
+
// Stop early if no circleci bin available
|
|
25
|
+
if (!(await __.hasCircleCiBin())) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Validate the config
|
|
30
|
+
try {
|
|
31
|
+
await __.validateConfig();
|
|
32
|
+
} catch (error) {
|
|
33
|
+
const errorMessage = `CircleCI config error on ${__.configPath}\n${error.message}`;
|
|
34
|
+
throw firostError('ABERLAAS_LINT_CIRCLECI', errorMessage);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Autofix yml issues in file
|
|
42
|
+
* @returns {boolean} True on success
|
|
43
|
+
*/
|
|
44
|
+
export async function fix() {
|
|
45
|
+
const absoluteConfigPath = hostGitPath(__.configPath);
|
|
46
|
+
// Fix yml issues
|
|
47
|
+
await fixYml([absoluteConfigPath]);
|
|
48
|
+
|
|
49
|
+
// Check for file errors so it still fails if file is invalid
|
|
50
|
+
await run();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
__ = {
|
|
7
54
|
configPath: '.circleci/config.yml',
|
|
55
|
+
|
|
8
56
|
/**
|
|
9
|
-
* Find
|
|
57
|
+
* Find the CircleCI config file
|
|
10
58
|
* @returns {Array} Array of files
|
|
11
59
|
*/
|
|
12
|
-
async
|
|
13
|
-
|
|
60
|
+
async getInputFile() {
|
|
61
|
+
const configFile = await hostGitPath(__.configPath);
|
|
62
|
+
if (!(await exists(configFile))) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return configFile;
|
|
14
66
|
},
|
|
67
|
+
|
|
15
68
|
/**
|
|
16
69
|
* Check if the code is currently running on CircleCI
|
|
17
70
|
* @returns {boolean} True if running on CircleCI, false otherwise
|
|
@@ -19,6 +72,7 @@ export default {
|
|
|
19
72
|
isRunningOnCircleCi() {
|
|
20
73
|
return ciInfo.CIRCLE;
|
|
21
74
|
},
|
|
75
|
+
|
|
22
76
|
/**
|
|
23
77
|
* Check if the circleci binary is available in the $PATH
|
|
24
78
|
* @returns {boolean} True if available, false otherwise
|
|
@@ -27,55 +81,17 @@ export default {
|
|
|
27
81
|
const binary = await which('circleci');
|
|
28
82
|
return !!binary;
|
|
29
83
|
},
|
|
84
|
+
|
|
30
85
|
/**
|
|
31
86
|
* Validate the CircleCI config file.
|
|
32
87
|
* @returns {boolean} True if valid, throws an error if not
|
|
33
88
|
*/
|
|
34
89
|
async validateConfig() {
|
|
35
|
-
await
|
|
90
|
+
await firostRun('circleci config validate', { stdout: false });
|
|
36
91
|
},
|
|
37
|
-
|
|
38
|
-
* Lint the file, both for yml issues and if possible circleci specifics
|
|
39
|
-
* @returns {boolean} True on success
|
|
40
|
-
*/
|
|
41
|
-
async run() {
|
|
42
|
-
const absoluteConfigPath = helper.hostPath(this.configPath);
|
|
43
|
-
const hasConfigFile = await exists(absoluteConfigPath);
|
|
44
|
-
const isRunningOnCircleCi = this.isRunningOnCircleCi();
|
|
45
|
-
|
|
46
|
-
// Stop early if no config file, or if running on CircleCI
|
|
47
|
-
if (!hasConfigFile || isRunningOnCircleCi) {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Lint as yml first
|
|
52
|
-
await lintYml.run([absoluteConfigPath]);
|
|
53
|
-
|
|
54
|
-
// Stop early if no circleci bin available
|
|
55
|
-
if (!(await this.hasCircleCiBin())) {
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Validate the config
|
|
60
|
-
try {
|
|
61
|
-
await this.validateConfig();
|
|
62
|
-
} catch (error) {
|
|
63
|
-
const errorMessage = `CircleCI config error on ${this.configPath}\n${error.message}`;
|
|
64
|
-
throw firostError('CircleCiLintError', errorMessage);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return true;
|
|
68
|
-
},
|
|
69
|
-
/**
|
|
70
|
-
* Autofix yml issues in file
|
|
71
|
-
* @returns {boolean} True on success
|
|
72
|
-
*/
|
|
73
|
-
async fix() {
|
|
74
|
-
const absoluteConfigPath = helper.hostPath(this.configPath);
|
|
75
|
-
// Fix yml issues
|
|
76
|
-
await lintYml.fix([absoluteConfigPath]);
|
|
92
|
+
};
|
|
77
93
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
94
|
+
export default {
|
|
95
|
+
run,
|
|
96
|
+
fix,
|
|
81
97
|
};
|
package/lib/css.js
CHANGED
|
@@ -1,11 +1,68 @@
|
|
|
1
|
-
import stylelint from 'stylelint';
|
|
2
1
|
import { _ } from 'golgoth';
|
|
3
2
|
import { firostError } from 'firost';
|
|
4
|
-
import
|
|
3
|
+
import { findHostPackageFiles, getConfig } from 'aberlaas-helper';
|
|
4
|
+
import stylelint from 'stylelint';
|
|
5
5
|
import stylelintConfig from '../configs/stylelint.js';
|
|
6
|
-
import {
|
|
6
|
+
import { prettierFix } from './helpers/prettierFix.js';
|
|
7
7
|
|
|
8
|
-
export
|
|
8
|
+
export let __;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Lint all files and display results.
|
|
12
|
+
* @param {Array} userPatterns Patterns to narrow the search down
|
|
13
|
+
* @param {string} userConfigFile Custom config file to use
|
|
14
|
+
* @param {object} userOptions Options to pass to ESLint, including fix
|
|
15
|
+
* @returns {boolean} True on success
|
|
16
|
+
*/
|
|
17
|
+
export async function run(userPatterns, userConfigFile, userOptions = {}) {
|
|
18
|
+
// Options
|
|
19
|
+
const options = { fix: false, ...userOptions };
|
|
20
|
+
|
|
21
|
+
// Files
|
|
22
|
+
const files = await __.getInputFiles(userPatterns);
|
|
23
|
+
if (_.isEmpty(files)) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Config
|
|
28
|
+
const config = await getConfig(
|
|
29
|
+
userConfigFile,
|
|
30
|
+
'stylelint.config.js',
|
|
31
|
+
stylelintConfig,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const result = await stylelint.lint({
|
|
35
|
+
config,
|
|
36
|
+
files,
|
|
37
|
+
formatter: 'string',
|
|
38
|
+
...options,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (result.errored) {
|
|
42
|
+
throw firostError('ABERLAAS_LINT_CSS', result.report);
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Autofix files in place
|
|
49
|
+
* @param {Array} userPatterns Patterns to narrow the search down
|
|
50
|
+
* @param {string} userConfigFile Custom config file to use
|
|
51
|
+
* @returns {boolean} True on success
|
|
52
|
+
*/
|
|
53
|
+
export async function fix(userPatterns, userConfigFile) {
|
|
54
|
+
const files = await __.getInputFiles(userPatterns);
|
|
55
|
+
if (_.isEmpty(files)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
// Try to pretiffy as much as we can
|
|
59
|
+
await __.prettierFix(files);
|
|
60
|
+
// Still run a lint on it so it can fail if not everything is fixed
|
|
61
|
+
await run(userPatterns, userConfigFile, { fix: true });
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
__ = {
|
|
9
66
|
/**
|
|
10
67
|
* Find all relevant files
|
|
11
68
|
* @param {Array} userPatterns Patterns to narrow the search down
|
|
@@ -15,59 +72,13 @@ export default {
|
|
|
15
72
|
const filePatterns = _.isEmpty(userPatterns)
|
|
16
73
|
? ['./**/*.css']
|
|
17
74
|
: userPatterns;
|
|
18
|
-
return await
|
|
75
|
+
return await findHostPackageFiles(filePatterns, ['.css']);
|
|
19
76
|
},
|
|
20
|
-
/**
|
|
21
|
-
* Lint all files and display results.
|
|
22
|
-
* @param {Array} userPatterns Patterns to narrow the search down
|
|
23
|
-
* @param {string} userConfigFile Custom config file to use
|
|
24
|
-
* @param {object} userOptions Options to pass to ESLint, including fix
|
|
25
|
-
* @returns {boolean} True on success
|
|
26
|
-
*/
|
|
27
|
-
async run(userPatterns, userConfigFile, userOptions = {}) {
|
|
28
|
-
// Options
|
|
29
|
-
const options = { fix: false, ...userOptions };
|
|
30
|
-
|
|
31
|
-
// Files
|
|
32
|
-
const files = await this.getInputFiles(userPatterns);
|
|
33
|
-
if (_.isEmpty(files)) {
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Config
|
|
38
|
-
const config = await helper.getConfig(
|
|
39
|
-
userConfigFile,
|
|
40
|
-
'stylelint.config.js',
|
|
41
|
-
stylelintConfig,
|
|
42
|
-
);
|
|
43
77
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
files,
|
|
47
|
-
formatter: 'string',
|
|
48
|
-
...options,
|
|
49
|
-
});
|
|
78
|
+
prettierFix,
|
|
79
|
+
};
|
|
50
80
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return true;
|
|
55
|
-
},
|
|
56
|
-
/**
|
|
57
|
-
* Autofix files in place
|
|
58
|
-
* @param {Array} userPatterns Patterns to narrow the search down
|
|
59
|
-
* @param {string} userConfigFile Custom config file to use
|
|
60
|
-
* @returns {boolean} True on success
|
|
61
|
-
*/
|
|
62
|
-
async fix(userPatterns, userConfigFile) {
|
|
63
|
-
const files = await this.getInputFiles(userPatterns);
|
|
64
|
-
if (_.isEmpty(files)) {
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
// Try to pretiffy as much as we can
|
|
68
|
-
await prettierFix(files);
|
|
69
|
-
// Still run a lint on it so it can fail if not everything is fixed
|
|
70
|
-
await this.run(userPatterns, userConfigFile, { fix: true });
|
|
71
|
-
return true;
|
|
72
|
-
},
|
|
81
|
+
export default {
|
|
82
|
+
run,
|
|
83
|
+
fix,
|
|
73
84
|
};
|
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import { format as prettierFormat } from 'prettier';
|
|
2
|
-
import { firostError, read, write } from 'firost';
|
|
3
1
|
import { _, pMap } from 'golgoth';
|
|
4
|
-
import
|
|
2
|
+
import { firostError, read, write } from 'firost';
|
|
3
|
+
import { getConfig } from 'aberlaas-helper';
|
|
4
|
+
import { format as prettierFormat } from 'prettier';
|
|
5
5
|
import prettierConfig from '../../configs/prettier.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Fix
|
|
8
|
+
* Fix files using prettier
|
|
9
9
|
* @param {Array} inputFiles Files to auto-fix
|
|
10
10
|
*/
|
|
11
|
-
export async function
|
|
11
|
+
export async function prettierFix(inputFiles) {
|
|
12
12
|
// Config file
|
|
13
|
-
const config = await
|
|
14
|
-
null,
|
|
15
|
-
'prettier.config.js',
|
|
16
|
-
prettierConfig,
|
|
17
|
-
);
|
|
13
|
+
const config = await getConfig(null, 'prettier.config.js', prettierConfig);
|
|
18
14
|
|
|
19
15
|
const errors = [];
|
|
20
16
|
|
|
@@ -36,19 +32,17 @@ export async function fix(inputFiles) {
|
|
|
36
32
|
{ concurrency: 10 },
|
|
37
33
|
);
|
|
38
34
|
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
_.each(errors, (error) => {
|
|
42
|
-
formattedErrors = `${formattedErrors}${error.filepath}\n\n${error.message}\n\n`;
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
throw firostError(
|
|
46
|
-
'LINT_ERROR_FIX_PRETTIER',
|
|
47
|
-
`Some files could not be automatically fixed:\n\n${formattedErrors}`,
|
|
48
|
-
);
|
|
35
|
+
if (_.isEmpty(errors)) {
|
|
36
|
+
return;
|
|
49
37
|
}
|
|
50
|
-
}
|
|
51
38
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
39
|
+
let formattedErrors = '';
|
|
40
|
+
_.each(errors, (error) => {
|
|
41
|
+
formattedErrors = `${formattedErrors}${error.filepath}\n\n${error.message}\n\n`;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
throw firostError(
|
|
45
|
+
'ABERLAAS_LINT_PRETTIER_FIX',
|
|
46
|
+
`Some files could not be automatically fixed:\n\n${formattedErrors}`,
|
|
47
|
+
);
|
|
48
|
+
}
|
package/lib/js.js
CHANGED
|
@@ -1,80 +1,85 @@
|
|
|
1
1
|
import { _ } from 'golgoth';
|
|
2
2
|
import { firostError } from 'firost';
|
|
3
|
+
import { findHostPackageFiles, getConfig } from 'aberlaas-helper';
|
|
3
4
|
import { ESLint } from 'eslint';
|
|
4
|
-
import helper from 'aberlaas-helper';
|
|
5
5
|
import eslintConfig from '../configs/eslint.js';
|
|
6
6
|
|
|
7
|
-
export
|
|
8
|
-
/**
|
|
9
|
-
* Find all relevant files
|
|
10
|
-
* @param {Array} userPatterns Patterns to narrow the search down
|
|
11
|
-
* @returns {Array} Array of files
|
|
12
|
-
*/
|
|
13
|
-
async getInputFiles(userPatterns) {
|
|
14
|
-
const filePatterns = _.isEmpty(userPatterns) ? ['./**/*.js'] : userPatterns;
|
|
7
|
+
export let __;
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* @param {string} userConfigFile Custom config file to use
|
|
27
|
-
* @param {object} userOptions Options to pass to ESLint, including fix
|
|
28
|
-
* @returns {boolean} True on success
|
|
29
|
-
*/
|
|
30
|
-
async run(userPatterns, userConfigFile, userOptions = {}) {
|
|
31
|
-
// Options
|
|
32
|
-
const options = { fix: false, warnIgnored: false, ...userOptions };
|
|
9
|
+
/**
|
|
10
|
+
* Lint all files and display results.
|
|
11
|
+
* @param {Array} userPatterns Patterns to narrow the search down
|
|
12
|
+
* @param {string} userConfigFile Custom config file to use
|
|
13
|
+
* @param {object} userOptions Options to pass to ESLint, including fix
|
|
14
|
+
* @returns {boolean} True on success
|
|
15
|
+
*/
|
|
16
|
+
export async function run(userPatterns, userConfigFile, userOptions = {}) {
|
|
17
|
+
// Options
|
|
18
|
+
const options = { fix: false, warnIgnored: false, ...userOptions };
|
|
33
19
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
20
|
+
// Files to lint
|
|
21
|
+
const files = await __.getInputFiles(userPatterns);
|
|
22
|
+
if (_.isEmpty(files)) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
39
25
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
26
|
+
// Config file
|
|
27
|
+
const config = await getConfig(
|
|
28
|
+
userConfigFile,
|
|
29
|
+
'eslint.config.js',
|
|
30
|
+
eslintConfig,
|
|
31
|
+
);
|
|
46
32
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
33
|
+
// Run the actual lint
|
|
34
|
+
const eslint = new ESLint({
|
|
35
|
+
...options,
|
|
36
|
+
overrideConfigFile: true,
|
|
37
|
+
overrideConfig: config,
|
|
38
|
+
});
|
|
39
|
+
const results = await eslint.lintFiles(files);
|
|
54
40
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
41
|
+
// Fix
|
|
42
|
+
if (options.fix) {
|
|
43
|
+
await ESLint.outputFixes(results);
|
|
44
|
+
}
|
|
59
45
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
46
|
+
// All good, we can stop
|
|
47
|
+
const errorCount = _.chain(results).map('errorCount').sum().value();
|
|
48
|
+
if (errorCount == 0) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
65
51
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
52
|
+
// Format errors
|
|
53
|
+
const formatter = await eslint.loadFormatter('stylish');
|
|
54
|
+
const errorText = formatter.format(results);
|
|
55
|
+
throw firostError('ABERLAAS_LINT_JS', errorText);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Autofix files in place
|
|
60
|
+
* @param {Array} userPatterns Patterns to narrow the search down
|
|
61
|
+
* @param {string} userConfigFile Custom config file to use
|
|
62
|
+
* @returns {boolean} True on success
|
|
63
|
+
*/
|
|
64
|
+
export async function fix(userPatterns, userConfigFile) {
|
|
65
|
+
return await run(userPatterns, userConfigFile, { fix: true });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
__ = {
|
|
71
69
|
/**
|
|
72
|
-
*
|
|
70
|
+
* Find all relevant files
|
|
73
71
|
* @param {Array} userPatterns Patterns to narrow the search down
|
|
74
|
-
* @
|
|
75
|
-
* @returns {boolean} True on success
|
|
72
|
+
* @returns {Array} Array of files
|
|
76
73
|
*/
|
|
77
|
-
async
|
|
78
|
-
|
|
74
|
+
async getInputFiles(userPatterns) {
|
|
75
|
+
const filePatterns = _.isEmpty(userPatterns) ? ['./**/*.js'] : userPatterns;
|
|
76
|
+
const allowedExtensions = ['.js', '.jsx', '.ts', '.tsx'];
|
|
77
|
+
|
|
78
|
+
return await findHostPackageFiles(filePatterns, allowedExtensions);
|
|
79
79
|
},
|
|
80
80
|
};
|
|
81
|
+
|
|
82
|
+
export default {
|
|
83
|
+
run,
|
|
84
|
+
fix,
|
|
85
|
+
};
|
package/lib/json.js
CHANGED
|
@@ -1,10 +1,55 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { _, pMap } from 'golgoth';
|
|
3
3
|
import { firostError, read } from 'firost';
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
4
|
+
import { findHostPackageFiles, hostGitRoot } from 'aberlaas-helper';
|
|
5
|
+
import { prettierFix } from './helpers/prettierFix.js';
|
|
6
6
|
|
|
7
|
-
export
|
|
7
|
+
export let __;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Lint all files and display results.
|
|
11
|
+
* @param {Array} userPatterns Patterns to narrow the search down
|
|
12
|
+
* @returns {boolean} True on success
|
|
13
|
+
*/
|
|
14
|
+
export async function run(userPatterns) {
|
|
15
|
+
const files = await __.getInputFiles(userPatterns);
|
|
16
|
+
if (_.isEmpty(files)) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let hasErrors = false;
|
|
21
|
+
const errorMessages = [];
|
|
22
|
+
await pMap(files, async (filepath) => {
|
|
23
|
+
try {
|
|
24
|
+
JSON.parse(await read(filepath));
|
|
25
|
+
} catch (error) {
|
|
26
|
+
hasErrors = true;
|
|
27
|
+
const relativePath = path.relative(hostGitRoot(), filepath);
|
|
28
|
+
errorMessages.push(`Invalid JSON: ${relativePath}`);
|
|
29
|
+
errorMessages.push(error.message);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
if (hasErrors) {
|
|
34
|
+
throw firostError('ABERLAAS_LINT_JSON', errorMessages.join('\n'));
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Autofix files in place
|
|
41
|
+
* @param {Array} userPatterns Patterns to narrow the search down
|
|
42
|
+
* @returns {boolean} True on success
|
|
43
|
+
*/
|
|
44
|
+
export async function fix(userPatterns) {
|
|
45
|
+
const files = await __.getInputFiles(userPatterns);
|
|
46
|
+
if (_.isEmpty(files)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
await __.prettierFix(files);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
__ = {
|
|
8
53
|
/**
|
|
9
54
|
* Find all relevant files
|
|
10
55
|
* @param {Array} userPatterns Patterns to narrow the search down
|
|
@@ -14,47 +59,13 @@ export default {
|
|
|
14
59
|
const filePatterns = _.isEmpty(userPatterns)
|
|
15
60
|
? ['./**/*.json']
|
|
16
61
|
: userPatterns;
|
|
17
|
-
return await
|
|
62
|
+
return await findHostPackageFiles(filePatterns, ['.json']);
|
|
18
63
|
},
|
|
19
|
-
/**
|
|
20
|
-
* Lint all files and display results.
|
|
21
|
-
* @param {Array} userPatterns Patterns to narrow the search down
|
|
22
|
-
* @returns {boolean} True on success
|
|
23
|
-
*/
|
|
24
|
-
async run(userPatterns) {
|
|
25
|
-
const files = await this.getInputFiles(userPatterns);
|
|
26
|
-
if (_.isEmpty(files)) {
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
64
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
hasErrors = true;
|
|
37
|
-
const relativePath = path.relative(helper.hostRoot(), filepath);
|
|
38
|
-
errorMessages.push(`Invalid JSON: ${relativePath}`);
|
|
39
|
-
errorMessages.push(error.message);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
if (hasErrors) {
|
|
44
|
-
throw firostError('JsonLintError', errorMessages.join('\n'));
|
|
45
|
-
}
|
|
46
|
-
return true;
|
|
47
|
-
},
|
|
48
|
-
/**
|
|
49
|
-
* Autofix files in place
|
|
50
|
-
* @param {Array} userPatterns Patterns to narrow the search down
|
|
51
|
-
* @returns {boolean} True on success
|
|
52
|
-
*/
|
|
53
|
-
async fix(userPatterns) {
|
|
54
|
-
const files = await this.getInputFiles(userPatterns);
|
|
55
|
-
if (_.isEmpty(files)) {
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
await prettierFix(files);
|
|
59
|
-
},
|
|
65
|
+
prettierFix,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default {
|
|
69
|
+
run,
|
|
70
|
+
fix,
|
|
60
71
|
};
|
package/lib/main.js
CHANGED
|
@@ -1,7 +1,42 @@
|
|
|
1
1
|
import { _, pMap } from 'golgoth';
|
|
2
2
|
import { consoleError, firostError, firostImport } from 'firost';
|
|
3
3
|
|
|
4
|
-
export
|
|
4
|
+
export let __;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Wrapper to lint all supported formats
|
|
8
|
+
* @param {object} cliArgs CLI Argument object, as created by minimist
|
|
9
|
+
* @returns {boolean} True on success
|
|
10
|
+
*/
|
|
11
|
+
export async function run(cliArgs = {}) {
|
|
12
|
+
const allTypesKeys = _.keys(__.linters);
|
|
13
|
+
const userTypes = _.intersection(_.keys(cliArgs), allTypesKeys);
|
|
14
|
+
const typesToLint = _.isEmpty(userTypes) ? allTypesKeys : userTypes;
|
|
15
|
+
|
|
16
|
+
let hasErrors = false;
|
|
17
|
+
await pMap(typesToLint, async (type) => {
|
|
18
|
+
const methodName = cliArgs.fix ? 'fix' : 'run';
|
|
19
|
+
try {
|
|
20
|
+
const linter = await __.getLinter(type);
|
|
21
|
+
|
|
22
|
+
const configFile = _.get(cliArgs, `config.${type}`);
|
|
23
|
+
const userPatterns = _.get(cliArgs, '_');
|
|
24
|
+
|
|
25
|
+
await linter[methodName](userPatterns, configFile);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
__.consoleError(error.message);
|
|
28
|
+
hasErrors = true;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (hasErrors) {
|
|
33
|
+
throw firostError('ABERLAAS_LINT_FAIL', 'Fail to lint files');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
__ = {
|
|
5
40
|
/**
|
|
6
41
|
* List of all available linters, along with the --flag name
|
|
7
42
|
**/
|
|
@@ -19,44 +54,17 @@ export default {
|
|
|
19
54
|
* @returns {object} Linter
|
|
20
55
|
**/
|
|
21
56
|
async getLinter(linterType) {
|
|
22
|
-
const linterPath =
|
|
57
|
+
const linterPath = __.linters[linterType];
|
|
23
58
|
if (!linterPath) {
|
|
24
59
|
return false;
|
|
25
60
|
}
|
|
26
61
|
|
|
27
62
|
return await firostImport(linterPath);
|
|
28
63
|
},
|
|
29
|
-
/**
|
|
30
|
-
* Wrapper to lint all supported formats
|
|
31
|
-
* @param {object} cliArgs CLI Argument object, as created by minimist
|
|
32
|
-
* @returns {boolean} True on success
|
|
33
|
-
*/
|
|
34
|
-
async run(cliArgs = {}) {
|
|
35
|
-
const allTypesKeys = _.keys(this.linters);
|
|
36
|
-
const userTypes = _.intersection(_.keys(cliArgs), allTypesKeys);
|
|
37
|
-
const typesToLint = _.isEmpty(userTypes) ? allTypesKeys : userTypes;
|
|
38
|
-
|
|
39
|
-
let hasErrors = false;
|
|
40
|
-
await pMap(typesToLint, async (type) => {
|
|
41
|
-
const methodName = cliArgs.fix ? 'fix' : 'run';
|
|
42
|
-
try {
|
|
43
|
-
const linter = await this.getLinter(type);
|
|
44
|
-
|
|
45
|
-
const configFile = _.get(cliArgs, `config.${type}`);
|
|
46
|
-
const userPatterns = _.get(cliArgs, '_');
|
|
47
|
-
|
|
48
|
-
await linter[methodName](userPatterns, configFile);
|
|
49
|
-
} catch (error) {
|
|
50
|
-
this.__consoleError(error.message);
|
|
51
|
-
hasErrors = true;
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
if (hasErrors) {
|
|
56
|
-
throw firostError('ERROR_LINT', 'Error while linting files');
|
|
57
|
-
}
|
|
58
64
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
consoleError,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default {
|
|
69
|
+
run,
|
|
62
70
|
};
|
package/lib/yml.js
CHANGED
|
@@ -1,11 +1,57 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { firostError, read } from 'firost';
|
|
3
2
|
import { _, pMap } from 'golgoth';
|
|
3
|
+
import { firostError, read } from 'firost';
|
|
4
|
+
import { findHostPackageFiles, hostGitRoot } from 'aberlaas-helper';
|
|
4
5
|
import yamlLint from 'yaml-lint';
|
|
5
|
-
import
|
|
6
|
-
import { fix as prettierFix } from './helpers/prettier.js';
|
|
6
|
+
import { prettierFix } from './helpers/prettierFix.js';
|
|
7
7
|
|
|
8
|
-
export
|
|
8
|
+
export let __;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Lint all files and display results.
|
|
12
|
+
* @param {Array} userPatterns Patterns to narrow the search down
|
|
13
|
+
* @returns {boolean} True on success
|
|
14
|
+
*/
|
|
15
|
+
export async function run(userPatterns) {
|
|
16
|
+
const files = await __.getInputFiles(userPatterns);
|
|
17
|
+
if (_.isEmpty(files)) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let hasErrors = false;
|
|
22
|
+
const errorMessages = [];
|
|
23
|
+
await pMap(files, async (filepath) => {
|
|
24
|
+
const input = await read(filepath);
|
|
25
|
+
try {
|
|
26
|
+
await yamlLint.lint(input);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
hasErrors = true;
|
|
29
|
+
const relativePath = path.relative(hostGitRoot(), filepath);
|
|
30
|
+
errorMessages.push(`Invalid YAML: ${relativePath}`);
|
|
31
|
+
errorMessages.push(error.message);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (hasErrors) {
|
|
36
|
+
throw firostError('ABERLAAS_LINT_YML', errorMessages.join('\n'));
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Autofix files in place
|
|
43
|
+
* @param {Array} userPatterns Patterns to narrow the search down
|
|
44
|
+
* @returns {boolean} True on success
|
|
45
|
+
*/
|
|
46
|
+
export async function fix(userPatterns) {
|
|
47
|
+
const files = await __.getInputFiles(userPatterns);
|
|
48
|
+
if (_.isEmpty(files)) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
await __.prettierFix(files);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
__ = {
|
|
9
55
|
/**
|
|
10
56
|
* Find all relevant files
|
|
11
57
|
* @param {Array} userPatterns Patterns to narrow the search down
|
|
@@ -15,48 +61,13 @@ export default {
|
|
|
15
61
|
const filePatterns = _.isEmpty(userPatterns)
|
|
16
62
|
? ['./**/*.yml', './**/*.yaml']
|
|
17
63
|
: userPatterns;
|
|
18
|
-
return await
|
|
64
|
+
return await findHostPackageFiles(filePatterns, ['.yml', '.yaml']);
|
|
19
65
|
},
|
|
20
|
-
/**
|
|
21
|
-
* Lint all files and display results.
|
|
22
|
-
* @param {Array} userPatterns Patterns to narrow the search down
|
|
23
|
-
* @returns {boolean} True on success
|
|
24
|
-
*/
|
|
25
|
-
async run(userPatterns) {
|
|
26
|
-
const files = await this.getInputFiles(userPatterns);
|
|
27
|
-
if (_.isEmpty(files)) {
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
66
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
} catch (error) {
|
|
38
|
-
hasErrors = true;
|
|
39
|
-
const relativePath = path.relative(helper.hostRoot(), filepath);
|
|
40
|
-
errorMessages.push(`Invalid YAML: ${relativePath}`);
|
|
41
|
-
errorMessages.push(error.message);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
if (hasErrors) {
|
|
46
|
-
throw firostError('YamlLintError', errorMessages.join('\n'));
|
|
47
|
-
}
|
|
48
|
-
return true;
|
|
49
|
-
},
|
|
50
|
-
/**
|
|
51
|
-
* Autofix files in place
|
|
52
|
-
* @param {Array} userPatterns Patterns to narrow the search down
|
|
53
|
-
* @returns {boolean} True on success
|
|
54
|
-
*/
|
|
55
|
-
async fix(userPatterns) {
|
|
56
|
-
const files = await this.getInputFiles(userPatterns);
|
|
57
|
-
if (_.isEmpty(files)) {
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
await prettierFix(files);
|
|
61
|
-
},
|
|
67
|
+
prettierFix,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export default {
|
|
71
|
+
run,
|
|
72
|
+
fix,
|
|
62
73
|
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aberlaas-lint",
|
|
3
3
|
"type": "module",
|
|
4
|
+
"sideEffects": false,
|
|
4
5
|
"description": "aberlaas lint command: Lint files",
|
|
5
|
-
"version": "2.
|
|
6
|
+
"version": "2.20.1",
|
|
6
7
|
"repository": "pixelastic/aberlaas",
|
|
7
8
|
"homepage": "https://projects.pixelastic.com/aberlaas/",
|
|
8
9
|
"author": "Tim Carry (@pixelastic)",
|
|
@@ -22,42 +23,39 @@
|
|
|
22
23
|
"engines": {
|
|
23
24
|
"node": ">=18.18.0"
|
|
24
25
|
},
|
|
25
|
-
"scripts": {
|
|
26
|
-
"build": "../../scripts/local/build",
|
|
27
|
-
"build:prod": "../../scripts/local/build-prod",
|
|
28
|
-
"cms": "../../scripts/local/cms",
|
|
29
|
-
"serve": "../../scripts/local/serve",
|
|
30
|
-
"ci": "../../scripts/local/ci",
|
|
31
|
-
"release": "../../scripts/local/release",
|
|
32
|
-
"update-dependencies": "node ../../scripts/meta/update-dependencies.js",
|
|
33
|
-
"test:meta": "../../scripts/local/test-meta",
|
|
34
|
-
"test": "../../scripts/local/test",
|
|
35
|
-
"test:watch": "../../scripts/local/test-watch",
|
|
36
|
-
"compress": "../../scripts/local/compress",
|
|
37
|
-
"lint": "../../scripts/local/lint",
|
|
38
|
-
"lint:fix": "../../scripts/local/lint-fix"
|
|
39
|
-
},
|
|
40
26
|
"dependencies": {
|
|
41
|
-
"@eslint/js": "9.
|
|
42
|
-
"@typescript-eslint/utils": "8.
|
|
43
|
-
"@vitest/eslint-plugin": "1.
|
|
44
|
-
"aberlaas-helper": "
|
|
45
|
-
"aberlaas-versions": "
|
|
46
|
-
"ci-info": "4.1
|
|
47
|
-
"eslint": "9.
|
|
48
|
-
"eslint-config-prettier": "
|
|
49
|
-
"eslint-plugin-import": "2.
|
|
50
|
-
"eslint-plugin-jsdoc": "
|
|
51
|
-
"eslint-plugin-n": "17.
|
|
52
|
-
"eslint-plugin-prettier": "5.
|
|
27
|
+
"@eslint/js": "9.39.2",
|
|
28
|
+
"@typescript-eslint/utils": "8.54.0",
|
|
29
|
+
"@vitest/eslint-plugin": "1.6.6",
|
|
30
|
+
"aberlaas-helper": "workspace:*",
|
|
31
|
+
"aberlaas-versions": "workspace:*",
|
|
32
|
+
"ci-info": "4.3.1",
|
|
33
|
+
"eslint": "9.39.2",
|
|
34
|
+
"eslint-config-prettier": "10.1.8",
|
|
35
|
+
"eslint-plugin-import": "2.32.0",
|
|
36
|
+
"eslint-plugin-jsdoc": "62.4.1",
|
|
37
|
+
"eslint-plugin-n": "17.23.2",
|
|
38
|
+
"eslint-plugin-prettier": "5.5.5",
|
|
53
39
|
"eslint-plugin-react": "7.37.5",
|
|
54
|
-
"firost": "5.
|
|
55
|
-
"globals": "
|
|
40
|
+
"firost": "5.5.1",
|
|
41
|
+
"globals": "17.2.0",
|
|
56
42
|
"golgoth": "3.0.0",
|
|
57
|
-
"prettier": "3.
|
|
58
|
-
"stylelint": "
|
|
59
|
-
"typescript": "5.
|
|
43
|
+
"prettier": "3.8.1",
|
|
44
|
+
"stylelint": "17.0.0",
|
|
45
|
+
"typescript": "5.9.3",
|
|
60
46
|
"yaml-lint": "1.7.0"
|
|
61
47
|
},
|
|
62
|
-
"
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "cd ../docs && yarn run build",
|
|
50
|
+
"build:prod": "cd ../docs && yarn run build:prod",
|
|
51
|
+
"cms": "cd ../docs && yarn run cms",
|
|
52
|
+
"serve": "cd ../docs && yarn run serve",
|
|
53
|
+
"release": "cd ../.. && ./scripts/release",
|
|
54
|
+
"test:meta": "cd ../.. && ./scripts/test-meta",
|
|
55
|
+
"test": "cd ../.. && ./scripts/test",
|
|
56
|
+
"test:watch": "cd ../.. && ./scripts/test-watch",
|
|
57
|
+
"compress": "cd ../.. && ./scripts/compress",
|
|
58
|
+
"lint": "cd ../.. && ./scripts/lint",
|
|
59
|
+
"lint:fix": "cd ../.. && ./scripts/lint-fix"
|
|
60
|
+
}
|
|
63
61
|
}
|