aberlaas 2.1.0 → 2.2.0
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 +124 -1
- package/commands/compress/dummy.js +11 -0
- package/commands/compress/index.js +5 -14
- package/commands/compress/png.js +18 -9
- package/commands/init/index.js +4 -0
- package/commands/lint/css.js +25 -19
- package/commands/lint/helpers/prettier.js +40 -12
- package/commands/lint/js.js +2 -3
- package/commands/lint/json.js +6 -5
- package/commands/lint/yml.js +6 -5
- package/commands/test/index.js +1 -2
- package/configs/eslint.cjs +18 -3
- package/configs/lintstaged.cjs +6 -0
- package/helper.js +13 -0
- package/package.json +4 -9
- package/templates/_yarnrc.yml +9 -0
- package/templates/scripts/compress +4 -0
- package/configs/jest/index.cjs +0 -52
- package/configs/jest/jest-extended.cjs +0 -3
- package/configs/jest/setupFileAfterEnv.cjs +0 -13
- package/configs/jest/sharedState.cjs +0 -14
- package/configs/jest/testEnvironment.cjs +0 -46
- package/configs/jest.cjs +0 -1
- package/templates/jest.config.cjs +0 -4
package/README.md
CHANGED
|
@@ -192,6 +192,129 @@ userland allows user to change the files if they want to change the behavior.
|
|
|
192
192
|
configuration files for `aberlaas` itself. They eat their own dog food by
|
|
193
193
|
referencing the same configs as above.
|
|
194
194
|
|
|
195
|
+
## Tools used and their future
|
|
196
|
+
|
|
197
|
+
### ESLint
|
|
198
|
+
|
|
199
|
+
ESLint doesn't yet support ESM config files. We'll upgrade to the latest ESLint
|
|
200
|
+
when it does. This should also help fix the issue with Yarn PnP (see below).
|
|
201
|
+
|
|
202
|
+
### Yarn
|
|
203
|
+
|
|
204
|
+
**tl;dr; We'll move to Yarn PnP once ESLint has support for Flat Configs, and
|
|
205
|
+
default `yarn run` doesn't add a ~1s delay overhead**
|
|
206
|
+
|
|
207
|
+
#### PnP
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
Aberlaas is using Yarn Berry (v2+) as its main package management tool.
|
|
211
|
+
|
|
212
|
+
Yarn Berry comes with a Plug And Play (PnP) feature that replaces the usage of
|
|
213
|
+
`node_modules` in favor of a `.pnp.cjs` file. Instead of having a very large
|
|
214
|
+
`node_modules` folder, a unique copy of each dependency is stored in the user
|
|
215
|
+
home folder and the `.pnp.cjs` file only keeps references to those folder. This
|
|
216
|
+
makes installing dependencies faster as it needs way less I/O.
|
|
217
|
+
|
|
218
|
+
By ditching the whole `node_modules` principle, it also removes concepts like
|
|
219
|
+
hoisting of dependencies in a monorepo. This, unfortunately, breaks ESLint.
|
|
220
|
+
|
|
221
|
+
ESLint expect all its plugins to be defined as `peerDependencies` at the root of
|
|
222
|
+
a mono-repo, as it will always try to include them from there. It works more or
|
|
223
|
+
less correctly at the best of times, and `aberlaas` already has some hacks
|
|
224
|
+
(including `resolvePluginsRelativeTo`) to work around that.
|
|
225
|
+
|
|
226
|
+
But with PnP, there is no way to make it work correctly, so I will need to wait
|
|
227
|
+
for a better compatibility between ESLint and Yarn 2 before using it.
|
|
228
|
+
|
|
229
|
+
Sources:
|
|
230
|
+
- [#8](https://github.com/yarnpkg/berry/issues/8), the initial case study of Yarn + ESLint
|
|
231
|
+
- [GitHub issue that explicitly explain the problem](https://github.com/yarnpkg/berry/discussions/3909)
|
|
232
|
+
- [`eslint-patch`, an ESLint plugin that hacks around this issue](https://yarnpkg.com/package?name=@rushstack/eslint-patch)
|
|
233
|
+
- [The `resolvePluginsRelativeTo` bandaid from ESLint](https://eslint.org/docs/latest/use/command-line-interface#--resolve-plugins-relative-to)
|
|
234
|
+
- [A nice postmortem of moving to Yarn 2](https://www.dolthub.com/blog/2022-03-18-migrating-to-yarn-2/)
|
|
235
|
+
- [The Flat Config feature in ESLint that should solve the problem](https://eslint.org/docs/latest/use/configure/configuration-files-new)
|
|
236
|
+
|
|
237
|
+
#### Calling binaries from the host
|
|
238
|
+
|
|
239
|
+
In yarn v1, if you install `aberlaas` in your project, all of `aberlaas`
|
|
240
|
+
dependencies (including binaries) were hoisted to the root. This was a design
|
|
241
|
+
flaw, as if several dependencies defined binaries by the same name, they would
|
|
242
|
+
fight in a race condition to take the slot in `node_modules/.bin`.
|
|
243
|
+
|
|
244
|
+
This has been fixed in Yarn Berry, but it also means it's no longer possible to
|
|
245
|
+
call `yarn run eslint` from a repository that includes `aberlaas`, because
|
|
246
|
+
`eslint` is not a direct dependency of the repo.
|
|
247
|
+
|
|
248
|
+
It might be possible to define proxy binaries inside of `aberlaas`, but those
|
|
249
|
+
will incur performance issues as they will need to spawn one more yarn context
|
|
250
|
+
(see below).
|
|
251
|
+
|
|
252
|
+
#### Calling binaries from aberlaas
|
|
253
|
+
|
|
254
|
+
In Yarn V1, I was calling binaries that `aberlaas` depends on (`eslint`, `vitest`,
|
|
255
|
+
etc) by calling `yarn run`. This was adding some overhead but was acceptable.
|
|
256
|
+
Yarn Berry adds even more overhead and it is becoming noticeable.
|
|
257
|
+
|
|
258
|
+
Now, my prefered way it to use the NodeJS API of the dependencies instead of
|
|
259
|
+
their CLI, to limit the overhead. I managed to move most tools to this new
|
|
260
|
+
approach, but sometimes I still need to use the CLI (`vitest` for example has
|
|
261
|
+
awesome live watching and display reloading that I don't think I can easily
|
|
262
|
+
replicate through code).
|
|
263
|
+
|
|
264
|
+
I ran some performance tests to see what would be the fastest way to call
|
|
265
|
+
`vitest` from `aberlaas`
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
hyperfine \
|
|
269
|
+
"zsh -i -c 'yarn bin vitest && /home/tim/local/www/projects/aberlaas/node_modules/vitest/vitest.mjs --version'" \
|
|
270
|
+
"zsh -i -c 'yarn run vitest --version'" \
|
|
271
|
+
"/home/tim/local/www/projects/aberlaas/node_modules/vitest/vitest.mjs --version" \
|
|
272
|
+
"/home/tim/local/www/projects/aberlaas/node_modules/.bin/vitest --version"
|
|
273
|
+
Benchmark 1: zsh -i -c 'yarn run vitest --version'
|
|
274
|
+
Time (mean ± σ): 1.945 s ± 0.051 s [User: 1.986 s, System: 0.850 s]
|
|
275
|
+
Range (min … max): 1.859 s … 2.018 s 10 runs
|
|
276
|
+
|
|
277
|
+
Benchmark 2: zsh -i -c 'yarn bin vitest && /home/tim/local/www/projects/aberlaas/node_modules/vitest/vitest.mjs --version'
|
|
278
|
+
Time (mean ± σ): 2.108 s ± 0.150 s [User: 2.108 s, System: 0.843 s]
|
|
279
|
+
Range (min … max): 1.930 s … 2.289 s 10 runs
|
|
280
|
+
|
|
281
|
+
Benchmark 3: /home/tim/local/www/projects/aberlaas/node_modules/vitest/vitest.m
|
|
282
|
+
js --version
|
|
283
|
+
Time (mean ± σ): 482.5 ms ± 40.9 ms [User: 448.4 ms, System: 327.2 ms]
|
|
284
|
+
Range (min … max): 442.1 ms … 553.3 ms 10 runs
|
|
285
|
+
|
|
286
|
+
Benchmark 4: /home/tim/local/www/projects/aberlaas/node_modules/.bin/vitest --version
|
|
287
|
+
Time (mean ± σ): 491.9 ms ± 29.6 ms [User: 454.1 ms, System: 331.2 ms]
|
|
288
|
+
Range (min … max): 453.8 ms … 535.4 ms 10 runs
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Finding the binary through `yarn bin` then calling it is the slowest, but `yarn
|
|
292
|
+
run` isn't much faster. Directly calling the binary is the fastest, but it's
|
|
293
|
+
path can't be easily guessed (apart from reading and parsing a `package.json`).
|
|
294
|
+
But using the symlinks in `node_modules/.bin` is consistent, barely slower than
|
|
295
|
+
calling the binary directly and much faster than using yarn.
|
|
296
|
+
|
|
297
|
+
This is what I'll be using. Of course, this will break when I'll move to PnP as
|
|
298
|
+
the `node_modules` folder won't be there, but hopefully Yarn will be faster by
|
|
299
|
+
then and I can use `yarn run` reliably.
|
|
300
|
+
|
|
301
|
+
#### Speed
|
|
302
|
+
|
|
303
|
+
With Yarn 2+, calling `yarn run` seem to add ~1s of overhead each time. This is
|
|
304
|
+
a known issue (due to the fact Yarn 2 needs to spawn yarn 1, node and a few
|
|
305
|
+
other layers).
|
|
306
|
+
|
|
307
|
+
1s is not much in itself, but grows quickly when you have nested `yarn run
|
|
308
|
+
aberlaas` calls that call `yarn run eslint`, and even more when you need to deal
|
|
309
|
+
with monorepos and multiple packages that each have their own yarn scope.
|
|
310
|
+
|
|
311
|
+
There are open issues on the topic, but nothing merged yet:
|
|
312
|
+
|
|
313
|
+
- [#3732](https://github.com/yarnpkg/berry/issues/3732), where it is discussed to make yarn run aware that it's running yarn run
|
|
314
|
+
and keep the same state without spawning new yarns
|
|
315
|
+
- [#2575](https://github.com/yarnpkg/berry/issues/2575), which is the main issue about Yarn performance, with benchmarks against
|
|
316
|
+
npm/npx/yarn v1.
|
|
317
|
+
|
|
195
318
|
## Where does the name Aberlaas come from?
|
|
196
319
|
|
|
197
320
|
Aberlaas is the base camp from which all great expedition start in the _La Horde
|
|
@@ -205,4 +328,4 @@ For your convenience, `aberlass` and `aberlas` are added as aliases by default.
|
|
|
205
328
|
|
|
206
329
|
## Documentation
|
|
207
330
|
|
|
208
|
-
The complete documentation can be found on https://projects.pixelastic.com/aberlaas/
|
|
331
|
+
The complete documentation can be found on https://projects.pixelastic.com/aberlaas/
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is a temporary, dummy file to be able to test the top-level
|
|
3
|
+
* compress.run() function. I assume I'll add more compression types in addition
|
|
4
|
+
* to png, so this dummy compress is just to test that all compress are
|
|
5
|
+
* correctly called, but it doesn't do anything
|
|
6
|
+
**/
|
|
7
|
+
export default {
|
|
8
|
+
async run() {
|
|
9
|
+
return true;
|
|
10
|
+
},
|
|
11
|
+
};
|
|
@@ -2,11 +2,13 @@ import _ from 'golgoth/lodash.js';
|
|
|
2
2
|
import pMap from 'golgoth/pMap.js';
|
|
3
3
|
import consoleError from 'firost/consoleError.js';
|
|
4
4
|
import firostError from 'firost/error.js';
|
|
5
|
-
import
|
|
5
|
+
import compressPng from './png.js';
|
|
6
|
+
import compressDummy from './dummy.js';
|
|
6
7
|
|
|
7
8
|
export default {
|
|
8
9
|
types: {
|
|
9
|
-
png:
|
|
10
|
+
png: compressPng,
|
|
11
|
+
dummy: compressDummy,
|
|
10
12
|
},
|
|
11
13
|
/**
|
|
12
14
|
* Wrapper to compress all supported formats
|
|
@@ -22,7 +24,7 @@ export default {
|
|
|
22
24
|
await pMap(typesToCompress, async (type) => {
|
|
23
25
|
try {
|
|
24
26
|
const userPatterns = _.get(cliArgs, '_');
|
|
25
|
-
const compresser =
|
|
27
|
+
const compresser = this.types[type];
|
|
26
28
|
|
|
27
29
|
await compresser.run(userPatterns);
|
|
28
30
|
} catch (error) {
|
|
@@ -37,16 +39,5 @@ export default {
|
|
|
37
39
|
|
|
38
40
|
return true;
|
|
39
41
|
},
|
|
40
|
-
/**
|
|
41
|
-
* Find all relevant files of the specified extension in the host
|
|
42
|
-
* Note: Should be used by child classes
|
|
43
|
-
* @param {Array} safeListExtension List of allowed extensions to keep
|
|
44
|
-
* @param {Array} userPatterns Patterns to narrow the search down
|
|
45
|
-
* @returns {Array} Array of files
|
|
46
|
-
**/
|
|
47
|
-
async getInputFiles(safeListExtension, userPatterns = []) {
|
|
48
|
-
const inputPatterns = _.isEmpty(userPatterns) ? '.' : userPatterns;
|
|
49
|
-
return await helper.findHostFiles(inputPatterns, safeListExtension);
|
|
50
|
-
},
|
|
51
42
|
__consoleError: consoleError,
|
|
52
43
|
};
|
package/commands/compress/png.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import helper from '../../helper.js';
|
|
2
|
+
import _ from 'golgoth/lodash.js';
|
|
2
3
|
import run from 'firost/run.js';
|
|
3
4
|
import which from 'firost/which.js';
|
|
4
5
|
import firostError from 'firost/error.js';
|
|
@@ -10,15 +11,19 @@ export default {
|
|
|
10
11
|
* @returns {Array} Array of files
|
|
11
12
|
**/
|
|
12
13
|
async getInputFiles(userPatterns) {
|
|
13
|
-
|
|
14
|
+
const filePatterns = _.isEmpty(userPatterns)
|
|
15
|
+
? ['./**/*.png']
|
|
16
|
+
: userPatterns;
|
|
17
|
+
return await helper.findHostFiles(filePatterns, ['.png']);
|
|
14
18
|
},
|
|
19
|
+
|
|
15
20
|
/**
|
|
16
|
-
|
|
17
|
-
*
|
|
21
|
+
|
|
22
|
+
* Returns path to the binary to execute
|
|
23
|
+
* @returns {string|boolean} Path to the binary, or false if not found
|
|
18
24
|
**/
|
|
19
|
-
async
|
|
20
|
-
|
|
21
|
-
return !!binary;
|
|
25
|
+
async getBinaryPath() {
|
|
26
|
+
return await this.__which('pngmin');
|
|
22
27
|
},
|
|
23
28
|
/**
|
|
24
29
|
* Compress files
|
|
@@ -27,16 +32,20 @@ export default {
|
|
|
27
32
|
**/
|
|
28
33
|
async run(userPatterns) {
|
|
29
34
|
// Stop early if no bin
|
|
30
|
-
|
|
35
|
+
const binaryPath = await this.getBinaryPath();
|
|
36
|
+
if (!binaryPath) {
|
|
31
37
|
return true;
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
try {
|
|
35
41
|
const files = await this.getInputFiles(userPatterns);
|
|
36
|
-
const command =
|
|
42
|
+
const command = `${binaryPath} ${files.join(' ')}`;
|
|
37
43
|
await run(command, { stdout: false });
|
|
38
44
|
} catch (error) {
|
|
39
45
|
throw firostError('PngCompressError', error.message);
|
|
40
46
|
}
|
|
47
|
+
|
|
48
|
+
return true;
|
|
41
49
|
},
|
|
50
|
+
__which: which,
|
|
42
51
|
};
|
package/commands/init/index.js
CHANGED
|
@@ -45,6 +45,9 @@ export default {
|
|
|
45
45
|
* default rules and overwrite them as they see fit
|
|
46
46
|
**/
|
|
47
47
|
async addConfigFiles() {
|
|
48
|
+
// Yarn
|
|
49
|
+
await this.copyToHost('templates/_yarnrc.yml', '.yarnrc.yml');
|
|
50
|
+
|
|
48
51
|
// ESLint
|
|
49
52
|
await this.copyToHost('templates/_eslintrc.cjs', '.eslintrc.cjs');
|
|
50
53
|
await this.copyToHost('templates/_eslintignore.conf', '.eslintignore');
|
|
@@ -106,6 +109,7 @@ export default {
|
|
|
106
109
|
async addScripts() {
|
|
107
110
|
const defaultScripts = [
|
|
108
111
|
{ key: 'ci', value: 'scripts/ci' },
|
|
112
|
+
{ key: 'compress', value: 'scripts/compress' },
|
|
109
113
|
{ key: 'lint', value: 'scripts/lint' },
|
|
110
114
|
{ key: 'lint:fix', value: 'scripts/lint-fix' },
|
|
111
115
|
{ key: 'release', value: 'scripts/release' },
|
package/commands/lint/css.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import helper from '../../helper.js';
|
|
2
2
|
import { fix as prettierFix } from './helpers/prettier.js';
|
|
3
|
+
import stylelint from 'stylelint';
|
|
3
4
|
import _ from 'golgoth/lodash.js';
|
|
4
5
|
import firostError from 'firost/error.js';
|
|
5
|
-
import run from 'firost/run.js';
|
|
6
6
|
|
|
7
7
|
export default {
|
|
8
8
|
/**
|
|
@@ -11,37 +11,45 @@ export default {
|
|
|
11
11
|
* @returns {Array} Array of files
|
|
12
12
|
**/
|
|
13
13
|
async getInputFiles(userPatterns) {
|
|
14
|
-
|
|
14
|
+
const filePatterns = _.isEmpty(userPatterns)
|
|
15
|
+
? ['./**/*.css']
|
|
16
|
+
: userPatterns;
|
|
17
|
+
return await helper.findHostFiles(filePatterns, ['.css']);
|
|
15
18
|
},
|
|
16
19
|
/**
|
|
17
20
|
* Lint all files and display results.
|
|
18
21
|
* @param {Array} userPatterns Patterns to narrow the search down
|
|
19
22
|
* @param {string} userConfigFile Custom config file to use
|
|
23
|
+
* @param {object} userOptions Options to pass to ESLint, including fix
|
|
20
24
|
* @returns {boolean} True on success
|
|
21
25
|
**/
|
|
22
|
-
async run(userPatterns, userConfigFile) {
|
|
26
|
+
async run(userPatterns, userConfigFile, userOptions = {}) {
|
|
27
|
+
// Options
|
|
28
|
+
const options = { fix: false, ...userOptions };
|
|
29
|
+
|
|
30
|
+
// Files
|
|
23
31
|
const files = await this.getInputFiles(userPatterns);
|
|
24
32
|
if (_.isEmpty(files)) {
|
|
25
33
|
return true;
|
|
26
34
|
}
|
|
27
35
|
|
|
36
|
+
// Config
|
|
28
37
|
const configFile = await helper.configFile(
|
|
29
38
|
userConfigFile,
|
|
30
39
|
'.stylelintrc.cjs',
|
|
31
40
|
'configs/stylelint.cjs',
|
|
32
41
|
);
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
throw firostError('ERROR_CSS_LINT', error.stdout);
|
|
42
|
+
const config = await helper.import(configFile);
|
|
43
|
+
|
|
44
|
+
const result = await stylelint.lint({
|
|
45
|
+
config,
|
|
46
|
+
files,
|
|
47
|
+
formatter: 'string',
|
|
48
|
+
...options,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (result.errored) {
|
|
52
|
+
throw firostError('ERROR_CSS_LINT', result.output);
|
|
45
53
|
}
|
|
46
54
|
return true;
|
|
47
55
|
},
|
|
@@ -57,11 +65,9 @@ export default {
|
|
|
57
65
|
return true;
|
|
58
66
|
}
|
|
59
67
|
// Try to pretiffy as much as we can
|
|
60
|
-
await
|
|
68
|
+
await prettierFix(files);
|
|
61
69
|
// Still run a lint on it so it can fail if not everything is fixed
|
|
62
|
-
await this.run(userPatterns, userConfigFile);
|
|
70
|
+
await this.run(userPatterns, userConfigFile, { fix: true });
|
|
63
71
|
return true;
|
|
64
72
|
},
|
|
65
|
-
__prettierFix: prettierFix,
|
|
66
|
-
__run: run,
|
|
67
73
|
};
|
|
@@ -1,25 +1,53 @@
|
|
|
1
|
+
import * as prettier from 'prettier';
|
|
1
2
|
import helper from '../../../helper.js';
|
|
2
|
-
import run from 'firost/run.js';
|
|
3
3
|
import firostError from 'firost/error.js';
|
|
4
|
+
import write from 'firost/write.js';
|
|
5
|
+
import read from 'firost/read.js';
|
|
6
|
+
import pMap from 'golgoth/pMap.js';
|
|
7
|
+
import _ from 'golgoth/lodash.js';
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
10
|
* Fix all files using prettier
|
|
7
|
-
* Note: Will be called by child classes
|
|
8
|
-
* Note: Prettier does not output any information as to why it failed, so
|
|
9
|
-
* we'll manually run the command on each file individually so we can catch
|
|
10
|
-
* the file that errors and display it
|
|
11
11
|
* @param {Array} inputFiles Files to auto-fix
|
|
12
12
|
**/
|
|
13
13
|
export async function fix(inputFiles) {
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
// Config file
|
|
15
|
+
const configFile = await helper.configFile(
|
|
16
|
+
null,
|
|
17
|
+
'.prettierrc.cjs',
|
|
18
|
+
'lib/configs/prettier.cjs',
|
|
19
|
+
);
|
|
20
|
+
const config = await prettier.resolveConfig(configFile);
|
|
21
|
+
|
|
22
|
+
const errors = [];
|
|
23
|
+
|
|
24
|
+
// Read all files, run them through the formatter and save them back to disk
|
|
25
|
+
// If any emits error, store the errors and display them all in one output
|
|
26
|
+
await pMap(
|
|
27
|
+
inputFiles,
|
|
28
|
+
async (filepath) => {
|
|
29
|
+
try {
|
|
30
|
+
const content = await read(filepath);
|
|
31
|
+
const options = { ...config, filepath };
|
|
32
|
+
const result = await prettier.format(content, options);
|
|
33
|
+
await write(result, filepath);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
const message = error.toString();
|
|
36
|
+
errors.push({ filepath, message });
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{ concurrency: 10 },
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (!_.isEmpty(errors)) {
|
|
43
|
+
let formattedErrors = '';
|
|
44
|
+
_.each(errors, (error) => {
|
|
45
|
+
formattedErrors = `${formattedErrors}${error.filepath}\n\n${error.message}\n\n`;
|
|
46
|
+
});
|
|
47
|
+
|
|
20
48
|
throw firostError(
|
|
21
49
|
'LINT_ERROR_FIX_PRETTIER',
|
|
22
|
-
|
|
50
|
+
`Some files could not be automatically fixed:\n\n${formattedErrors}`,
|
|
23
51
|
);
|
|
24
52
|
}
|
|
25
53
|
}
|
package/commands/lint/js.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import helper from '../../helper.js';
|
|
2
2
|
import _ from 'golgoth/lodash.js';
|
|
3
3
|
import firostError from 'firost/error.js';
|
|
4
|
-
import run from 'firost/run.js';
|
|
5
4
|
import { ESLint } from 'eslint';
|
|
6
5
|
|
|
7
6
|
export default {
|
|
@@ -11,7 +10,8 @@ export default {
|
|
|
11
10
|
* @returns {Array} Array of files
|
|
12
11
|
**/
|
|
13
12
|
async getInputFiles(userPatterns) {
|
|
14
|
-
|
|
13
|
+
const filePatterns = _.isEmpty(userPatterns) ? ['./**/*.js'] : userPatterns;
|
|
14
|
+
return await helper.findHostFiles(filePatterns, ['.js']);
|
|
15
15
|
},
|
|
16
16
|
/**
|
|
17
17
|
* Lint all files and display results.
|
|
@@ -70,5 +70,4 @@ export default {
|
|
|
70
70
|
async fix(userPatterns, userConfigFile) {
|
|
71
71
|
return await this.run(userPatterns, userConfigFile, { fix: true });
|
|
72
72
|
},
|
|
73
|
-
__run: run,
|
|
74
73
|
};
|
package/commands/lint/json.js
CHANGED
|
@@ -13,7 +13,10 @@ export default {
|
|
|
13
13
|
* @returns {Array} Array of files
|
|
14
14
|
**/
|
|
15
15
|
async getInputFiles(userPatterns) {
|
|
16
|
-
|
|
16
|
+
const filePatterns = _.isEmpty(userPatterns)
|
|
17
|
+
? ['./**/*.json']
|
|
18
|
+
: userPatterns;
|
|
19
|
+
return await helper.findHostFiles(filePatterns, ['.json']);
|
|
17
20
|
},
|
|
18
21
|
/**
|
|
19
22
|
* Lint all files and display results.
|
|
@@ -30,7 +33,7 @@ export default {
|
|
|
30
33
|
const errorMessages = [];
|
|
31
34
|
await pMap(files, async (filepath) => {
|
|
32
35
|
try {
|
|
33
|
-
|
|
36
|
+
JSON.parse(await read(filepath));
|
|
34
37
|
} catch (error) {
|
|
35
38
|
hasErrors = true;
|
|
36
39
|
const relativePath = path.relative(helper.hostRoot(), filepath);
|
|
@@ -54,8 +57,6 @@ export default {
|
|
|
54
57
|
if (_.isEmpty(files)) {
|
|
55
58
|
return true;
|
|
56
59
|
}
|
|
57
|
-
await
|
|
60
|
+
await prettierFix(files);
|
|
58
61
|
},
|
|
59
|
-
__prettierFix: prettierFix,
|
|
60
|
-
__parse: JSON.parse,
|
|
61
62
|
};
|
package/commands/lint/yml.js
CHANGED
|
@@ -14,7 +14,10 @@ export default {
|
|
|
14
14
|
* @returns {Array} Array of files
|
|
15
15
|
**/
|
|
16
16
|
async getInputFiles(userPatterns) {
|
|
17
|
-
|
|
17
|
+
const filePatterns = _.isEmpty(userPatterns)
|
|
18
|
+
? ['./**/*.yml', './**/*.yaml']
|
|
19
|
+
: userPatterns;
|
|
20
|
+
return await helper.findHostFiles(filePatterns, ['.yml', '.yaml']);
|
|
18
21
|
},
|
|
19
22
|
/**
|
|
20
23
|
* Lint all files and display results.
|
|
@@ -32,7 +35,7 @@ export default {
|
|
|
32
35
|
await pMap(files, async (filepath) => {
|
|
33
36
|
const input = await read(filepath);
|
|
34
37
|
try {
|
|
35
|
-
await
|
|
38
|
+
await yamlLint.lint(input);
|
|
36
39
|
} catch (error) {
|
|
37
40
|
hasErrors = true;
|
|
38
41
|
const relativePath = path.relative(helper.hostRoot(), filepath);
|
|
@@ -56,8 +59,6 @@ export default {
|
|
|
56
59
|
if (_.isEmpty(files)) {
|
|
57
60
|
return true;
|
|
58
61
|
}
|
|
59
|
-
await
|
|
62
|
+
await prettierFix(files);
|
|
60
63
|
},
|
|
61
|
-
__prettierFix: prettierFix,
|
|
62
|
-
__lint: yamlLint.lint,
|
|
63
64
|
};
|
package/commands/test/index.js
CHANGED
|
@@ -17,9 +17,8 @@ export default {
|
|
|
17
17
|
**/
|
|
18
18
|
async run(cliArgs) {
|
|
19
19
|
const options = await this.vitestCliOptions(cliArgs);
|
|
20
|
-
const binary = await helper.which('vitest');
|
|
21
20
|
|
|
22
|
-
await run(
|
|
21
|
+
await run(`yarn run vitest ${options.join(' ')}`, { stdin: true });
|
|
23
22
|
return true;
|
|
24
23
|
},
|
|
25
24
|
|
package/configs/eslint.cjs
CHANGED
|
@@ -15,6 +15,23 @@ module.exports = {
|
|
|
15
15
|
'plugin:import/recommended',
|
|
16
16
|
'plugin:prettier/recommended',
|
|
17
17
|
],
|
|
18
|
+
settings: {
|
|
19
|
+
// eslint-plugin-import doesn't currently support the "exports" syntax in
|
|
20
|
+
// package.json. This allow mapping between custom entrypoints and
|
|
21
|
+
// files on disk.
|
|
22
|
+
// For example, it doesn't understand "import * from 'vitest/config';" as
|
|
23
|
+
// "vitest/config/" isn't really an existing filepath, but a mapping defined
|
|
24
|
+
// in vitest package.json
|
|
25
|
+
//
|
|
26
|
+
// Until this is fixed (see
|
|
27
|
+
// https://github.com/import-js/eslint-plugin-import/issues/2430)
|
|
28
|
+
// we manually define the most common extensions
|
|
29
|
+
'import/resolver': {
|
|
30
|
+
node: {
|
|
31
|
+
extensions: ['.js', '.cjs', '.mjs', '.d.ts'],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
18
35
|
plugins: ['jsdoc', 'prettier'],
|
|
19
36
|
rules: {
|
|
20
37
|
'dot-notation': ['error'],
|
|
@@ -98,10 +115,8 @@ module.exports = {
|
|
|
98
115
|
testName: false,
|
|
99
116
|
// Shorter method names
|
|
100
117
|
fit: false,
|
|
101
|
-
ftest: false,
|
|
102
118
|
fdescribe: false,
|
|
103
119
|
xit: false,
|
|
104
|
-
xtest: false,
|
|
105
120
|
xdescribe: false,
|
|
106
121
|
|
|
107
122
|
captureOutput: false,
|
|
@@ -113,7 +128,7 @@ module.exports = {
|
|
|
113
128
|
],
|
|
114
129
|
rules: {
|
|
115
130
|
'no-restricted-globals': [
|
|
116
|
-
'
|
|
131
|
+
'error',
|
|
117
132
|
{
|
|
118
133
|
name: 'fit',
|
|
119
134
|
message: 'No focused test',
|
package/configs/lintstaged.cjs
CHANGED
|
@@ -18,6 +18,12 @@ if (pkg.scripts && pkg.scripts.lint) {
|
|
|
18
18
|
result['*.json'] = ['yarn run lint:fix --json'];
|
|
19
19
|
result['*.js'] = ['yarn run lint:fix --js'];
|
|
20
20
|
}
|
|
21
|
+
|
|
22
|
+
// Compressing images
|
|
23
|
+
if (pkg.scripts && pkg.scripts.compress) {
|
|
24
|
+
result['*.png'] = ['yarn run compress --png'];
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
// Testing changed js files
|
|
22
28
|
if (pkg.scripts && pkg.scripts.test) {
|
|
23
29
|
result['./lib/**/*.js'] = ['yarn run test --failFast --related'];
|
package/helper.js
CHANGED
|
@@ -159,4 +159,17 @@ export default {
|
|
|
159
159
|
async yarnRun(scriptName) {
|
|
160
160
|
return await run(`yarn run ${scriptName}`, { cwd: this.hostRoot() });
|
|
161
161
|
},
|
|
162
|
+
/**
|
|
163
|
+
* Dynamically import a file
|
|
164
|
+
* This is a wrapper around the default import, but bypasses the cache
|
|
165
|
+
* It makes sure importing a file several times always loads the last version
|
|
166
|
+
* TODO: This should probably be moved in firost once firost is moved to ESM
|
|
167
|
+
* @param {string} filepath Path to the file to load
|
|
168
|
+
* @returns {object} Content of the loaded file
|
|
169
|
+
**/
|
|
170
|
+
async import(filepath) {
|
|
171
|
+
const content = await import(`${filepath}?cacheBusting=${Date.now()}`);
|
|
172
|
+
|
|
173
|
+
return content.default || content;
|
|
174
|
+
},
|
|
162
175
|
};
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "aberlaas",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "Scaffold your JavaScript projects with tests, lint and release scripts",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.2.0",
|
|
6
6
|
"repository": "pixelastic/aberlaas",
|
|
7
7
|
"homepage": "https://projects.pixelastic.com/aberlaas/",
|
|
8
8
|
"author": "Tim Carry (@pixelastic)",
|
|
@@ -33,15 +33,14 @@
|
|
|
33
33
|
"configs/",
|
|
34
34
|
"templates/"
|
|
35
35
|
],
|
|
36
|
-
"bin":
|
|
37
|
-
"aberlaas": "bin/aberlaas.js"
|
|
38
|
-
},
|
|
36
|
+
"bin": "bin/aberlaas.js",
|
|
39
37
|
"dependencies": {
|
|
40
38
|
"@octokit/rest": "18.12.0",
|
|
41
39
|
"ci-info": "3.9.0",
|
|
42
40
|
"dedent": "1.5.1",
|
|
43
41
|
"eslint": "8.54.0",
|
|
44
42
|
"eslint-config-prettier": "9.0.0",
|
|
43
|
+
"eslint-plugin-import": "2.29.0",
|
|
45
44
|
"eslint-plugin-jsdoc": "46.9.0",
|
|
46
45
|
"eslint-plugin-n": "16.3.1",
|
|
47
46
|
"eslint-plugin-prettier": "5.0.1",
|
|
@@ -77,9 +76,5 @@
|
|
|
77
76
|
"test:watch": "../scripts/lib/test-watch",
|
|
78
77
|
"postinstall": "./scripts/postinstall"
|
|
79
78
|
},
|
|
80
|
-
"
|
|
81
|
-
"eslint-plugin-import": "2.29.0",
|
|
82
|
-
"eslint-plugin-vitest": "0.3.10"
|
|
83
|
-
},
|
|
84
|
-
"gitHead": "5d021891b8ba9c030747a3bc7bf20d86c85422db"
|
|
79
|
+
"gitHead": "bbf9f5024d007deca00abf451ddf879c876d80aa"
|
|
85
80
|
}
|
package/configs/jest/index.cjs
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const jestExtendedPath = path.resolve(__dirname, './jest-extended.cjs');
|
|
3
|
-
const setupFileAfterEnv = path.resolve(__dirname, './setupFileAfterEnv.cjs');
|
|
4
|
-
const testEnvironment = path.resolve(__dirname, './testEnvironment.cjs');
|
|
5
|
-
module.exports = {
|
|
6
|
-
// Custom environment that automatically set testName and allow for --failFast
|
|
7
|
-
testEnvironment,
|
|
8
|
-
|
|
9
|
-
// Use additional Jest plugins
|
|
10
|
-
setupFilesAfterEnv: [jestExtendedPath, setupFileAfterEnv],
|
|
11
|
-
|
|
12
|
-
// We need to set rootDir to the host directory, otherwise Jest will assume
|
|
13
|
-
// test are to be looked for in the directory that contains the config (ie.
|
|
14
|
-
// aberlaas).
|
|
15
|
-
rootDir: process.cwd(),
|
|
16
|
-
|
|
17
|
-
// Tests should be in a __tests__ folder
|
|
18
|
-
testMatch: ['**/__tests__/**/*.js?(x)'],
|
|
19
|
-
|
|
20
|
-
// By default watch mode watches for changes in all directories, and whenever
|
|
21
|
-
// a test file or associated code file changes, it re-runs tests.
|
|
22
|
-
// This can cause useless re-render of tests when it catches changes in
|
|
23
|
-
// directories like ./tmp, etc, so we exclude such directories
|
|
24
|
-
// watchPathIgnorePatterns only accept RegExp and not globs, so we have to
|
|
25
|
-
// deal with ((.*)/)? to express any depth of folders
|
|
26
|
-
watchPathIgnorePatterns: [
|
|
27
|
-
'<rootDir>/((.*)/)?node_modules/',
|
|
28
|
-
'<rootDir>/((.*)/)?tmp/',
|
|
29
|
-
'<rootDir>/((.*)/)?templates/',
|
|
30
|
-
],
|
|
31
|
-
testPathIgnorePatterns: [
|
|
32
|
-
'<rootDir>/((.*)/)?fixtures/',
|
|
33
|
-
'<rootDir>/((.*)/)?tmp/',
|
|
34
|
-
'<rootDir>/((.*)/)?templates/',
|
|
35
|
-
],
|
|
36
|
-
|
|
37
|
-
// moduleNameMapper: {
|
|
38
|
-
// // When using lodash-es (which is treeshakeable, thus preferable in front-end
|
|
39
|
-
// // envs), it will fail in tests as it isn't compiled to ES5.
|
|
40
|
-
// // So, we make jest load the full lodash instead. Note that the lib still
|
|
41
|
-
// // needs to be added as a devDependency
|
|
42
|
-
// '^lodash-es$': 'lodash',
|
|
43
|
-
// },
|
|
44
|
-
|
|
45
|
-
// Make sure we don't transform source code and use the default ESM code
|
|
46
|
-
transform: {},
|
|
47
|
-
|
|
48
|
-
bail: true,
|
|
49
|
-
|
|
50
|
-
resetMocks: true,
|
|
51
|
-
restoreMocks: true,
|
|
52
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/* eslint-disable jest/no-jasmine-globals,no-global-assign */
|
|
2
|
-
const captureOutput = require('firost/captureOutput');
|
|
3
|
-
const dedent = require('dedent');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Add new globals to each test file:
|
|
7
|
-
* - captureOutput accepts a callback that will be executed with all output
|
|
8
|
-
* silenced and returned instead
|
|
9
|
-
* - dedent (https://github.com/dmnd/dedent) to enter multiline strings without
|
|
10
|
-
* the indentation
|
|
11
|
-
**/
|
|
12
|
-
global.captureOutput = captureOutput;
|
|
13
|
-
global.dedent = dedent;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Jest environments are sandboxed by test suite. To be able to fail fast and
|
|
3
|
-
* stop all tests as soon as one of them failed, we are using this file as an
|
|
4
|
-
* external singleton.
|
|
5
|
-
**/
|
|
6
|
-
module.exports = {
|
|
7
|
-
__skipAllTests: false,
|
|
8
|
-
skipAllTests() {
|
|
9
|
-
this.__skipAllTests = true;
|
|
10
|
-
},
|
|
11
|
-
shouldSkipAllTests() {
|
|
12
|
-
return this.__skipAllTests;
|
|
13
|
-
},
|
|
14
|
-
};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
const NodeEnvironment = require('jest-environment-node');
|
|
2
|
-
const shouldFailFast = process.env.ABERLAAS_TEST_FAIL_FAST;
|
|
3
|
-
const sharedState = require('./sharedState.cjs');
|
|
4
|
-
|
|
5
|
-
class AberlaasEnvironment extends NodeEnvironment {
|
|
6
|
-
async handleTestEvent(event, _state) {
|
|
7
|
-
this.failFast(event);
|
|
8
|
-
this.setTestName(event);
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* If one test fails, we skip all other tests
|
|
12
|
-
* @param {object} event As fired by handleTestEvent
|
|
13
|
-
*/
|
|
14
|
-
failFast(event) {
|
|
15
|
-
// Do nothing if --failFast is not passed
|
|
16
|
-
if (!shouldFailFast) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Whenever a test is failing, we update the shared state to skip all other
|
|
21
|
-
// tests
|
|
22
|
-
const eventName = event.name;
|
|
23
|
-
const isTestFailing = eventName == 'test_fn_failure';
|
|
24
|
-
const isTestStarting = eventName === 'test_start';
|
|
25
|
-
|
|
26
|
-
if (isTestFailing) {
|
|
27
|
-
sharedState.skipAllTests();
|
|
28
|
-
}
|
|
29
|
-
if (isTestStarting && sharedState.shouldSkipAllTests()) {
|
|
30
|
-
event.test.mode = 'skip';
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* When a test starts, we set the global variable testName to the name of the
|
|
35
|
-
* test
|
|
36
|
-
* @param {object} event As fired by handleTestEvent
|
|
37
|
-
**/
|
|
38
|
-
setTestName(event) {
|
|
39
|
-
const eventName = event.name;
|
|
40
|
-
if (eventName === 'test_start') {
|
|
41
|
-
this.global.testName = event.test.name;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
module.exports = AberlaasEnvironment;
|
package/configs/jest.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = require('./jest/index.cjs');
|