linter-bundle 4.0.2 → 5.0.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.
Files changed (39) hide show
  1. package/.linter-bundle.js +8 -8
  2. package/CHANGELOG.md +23 -1
  3. package/README.md +1 -1
  4. package/eslint/{index.js → index.cjs} +7 -7
  5. package/eslint/{overrides-javascript-lazy.js → overrides-javascript-lazy.cjs} +1 -1
  6. package/eslint/{overrides-javascript.js → overrides-javascript.cjs} +1 -0
  7. package/eslint/{overrides-react.js → overrides-react.cjs} +4 -4
  8. package/eslint/rules/no-unnecessary-typeof.js +12 -1
  9. package/eslint/rules/package.json +8 -0
  10. package/eslint/rules/restricted-filenames.js +4 -4
  11. package/eslint/rules/restricted-filenames.md +1 -1
  12. package/files/index.js +54 -24
  13. package/helper/{ensure-type.js → ensure-type.cjs} +2 -0
  14. package/helper/get-git-files.js +3 -7
  15. package/helper/get-outdated-dependencies.js +48 -0
  16. package/helper/{validate-package-overrides.js → get-outdated-overrides.js} +9 -10
  17. package/helper/get-stylelint-path.js +15 -12
  18. package/helper/is-npm-or-yarn.js +12 -12
  19. package/helper/linter-bundle-config.cjs +70 -0
  20. package/helper/linter-bundle-config.d.ts +46 -0
  21. package/helper/linter-bundle-config.js +36 -0
  22. package/helper/run-process.js +14 -10
  23. package/lint.js +33 -27
  24. package/package.json +8 -7
  25. package/stylelint/index.cjs +1007 -0
  26. package/stylelint/plugins/stylelint-high-performance-animation.js +4 -5
  27. package/stylelint/plugins/stylelint-selector-no-empty.js +2 -2
  28. package/stylelint/plugins/stylelint-selector-tag-no-without-class.js +6 -7
  29. package/stylelint/plugins/stylelint-stylistic.js +7 -6
  30. package/helper/config.js +0 -48
  31. package/helper/find-missing-overrides.js +0 -49
  32. package/stylelint/index.js +0 -1007
  33. package/types.d.ts +0 -43
  34. /package/eslint/{overrides-gatsby.js → overrides-gatsby.cjs} +0 -0
  35. /package/eslint/{overrides-jest.js → overrides-jest.cjs} +0 -0
  36. /package/eslint/{overrides-jsdoc.js → overrides-jsdoc.cjs} +0 -0
  37. /package/eslint/{overrides-storybook.js → overrides-storybook.cjs} +0 -0
  38. /package/eslint/{overrides-type-declarations.js → overrides-type-declarations.cjs} +0 -0
  39. /package/eslint/{overrides-worker.js → overrides-worker.cjs} +0 -0
package/.linter-bundle.js CHANGED
@@ -8,7 +8,7 @@ const snippets = {
8
8
  pascalCase: '[A-Z]*([a-zA-Z0-9])'
9
9
  };
10
10
 
11
- module.exports = {
11
+ export default {
12
12
  files: {
13
13
  restrictions: [
14
14
  {
@@ -17,16 +17,17 @@ module.exports = {
17
17
  '.git/**',
18
18
  '.github/FUNDING.yml',
19
19
  '.vscode/settings.json',
20
+ `eslint/rules/package.json`,
20
21
  `eslint/rules/${snippets.kebabCase}.{js,md}`,
21
- `eslint/{index.js,overrides-${snippets.kebabCase}.js}`,
22
+ `eslint/{index.cjs,overrides-${snippets.kebabCase}.cjs}`,
22
23
  'files/index.js',
23
- `helper/${snippets.kebabCase}.js`,
24
+ `helper/${snippets.kebabCase}.{js,cjs,d.ts}`,
24
25
  'markdownlint/base.json',
25
26
  'node_modules/**',
26
- 'stylelint/index.js',
27
+ 'stylelint/index.cjs',
27
28
  `stylelint/plugins/stylelint-${snippets.kebabCase}.js`,
28
29
  '.editorconfig',
29
- '.eslintrc.js',
30
+ '.eslintrc.cjs',
30
31
  '.gitattributes',
31
32
  '.gitignore',
32
33
  '.linter-bundle.js',
@@ -37,10 +38,9 @@ module.exports = {
37
38
  'lint.js',
38
39
  'package-lock.json',
39
40
  'package.json',
40
- 'stylelint.config.js',
41
+ 'stylelint.config.cjs',
42
+ 'test-stylelint.js',
41
43
  'tsconfig.json',
42
- 'types.d.ts',
43
- 'validate-stylelint-options.mjs',
44
44
  'vscode-eslint-1.png',
45
45
  'vscode-eslint-2.png'
46
46
  ]
package/CHANGELOG.md CHANGED
@@ -6,7 +6,29 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- [Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v4.0.2...HEAD)
9
+ [Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v5.0.0...HEAD)
10
+
11
+ ## [5.0.0] - 2023-09-03
12
+
13
+ ## Changed
14
+
15
+ - [general] Migrated the code base from CommonJS to ESModules (as far as possible, because ESLint currently does not support ESModules)
16
+ - [general] The linter-bundle configuration can now be a ESModule (`.linter-bundle.mjs` is supported)
17
+ - [files] Report unmatched `allowed` pattern
18
+ - [markdownlint] Updated `markdownlint-cli` from `0.35.0` to `0.36.0`
19
+ - [eslint] Disabled `considerComments` option of [`import/new-after-import`](https://github.com/import-js/eslint-plugin-import/blob/v2.28.1/docs/rules/newline-after-import.md) rule
20
+ as it conflicts with the [`import/order`](https://github.com/import-js/eslint-plugin-import/blob/v2.28.1/docs/rules/order.md) rule
21
+ - [eslint/overrides-javascript] Disable [`import/dynamic-import-chunkname`](https://github.com/import-js/eslint-plugin-import/blob/v2.28.1/docs/rules/dynamic-import-chunkname.md) for JavaScript files
22
+
23
+ [Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v4.0.3...v5.0.0)
24
+
25
+ ## [4.0.3] - 2023-08-31
26
+
27
+ ### Changed
28
+
29
+ - [files] Don't show "No relevant files changed." if the `--git`` option was not used
30
+
31
+ [Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v4.0.2...v4.0.3)
10
32
 
11
33
  ## [4.0.2] - 2023-08-31
12
34
 
package/README.md CHANGED
@@ -622,7 +622,7 @@ This can be done by adding these options to your `.vscode/settings.json`:
622
622
  {
623
623
  "eslint.nodePath": "./node_modules/linter-bundle/node_modules/eslint",
624
624
  "eslint.options": {
625
- "overrideConfigFile": "./.eslintrc.js",
625
+ "overrideConfigFile": "./.eslintrc.js", // or "./.eslintrc.cjs" or "./eslintrc.json"
626
626
  "resolvePluginsRelativeTo": "./node_modules/linter-bundle",
627
627
  "rulePaths": ["./node_modules/linter-bundle/eslint/rules"],
628
628
  "reportUnusedDisableDirectives": "error",
@@ -8,8 +8,8 @@
8
8
  const fs = require('node:fs');
9
9
  const path = require('node:path');
10
10
 
11
- const config = require('../helper/config.js');
12
- const ensureType = require('../helper/ensure-type');
11
+ const ensureType = require('../helper/ensure-type.cjs');
12
+ const { linterBundleConfig } = require('../helper/linter-bundle-config.cjs');
13
13
 
14
14
  module.exports = {
15
15
  ignorePatterns: [
@@ -283,16 +283,16 @@ module.exports = {
283
283
  name: 'isNaN',
284
284
  message: 'Use Number.isNaN() instead, and ensure that the input value is of type number. isNaN(undefined) !== Number.isNaN(undefined)'
285
285
  },
286
- ...ensureType.array(config.ts?.overrides?.general?.['no-restricted-globals']?.additionalRestrictions)
286
+ ...ensureType.array(linterBundleConfig.ts?.overrides?.general?.['no-restricted-globals']?.additionalRestrictions)
287
287
  ],
288
288
  'no-restricted-imports': 'off', // Covered by @typescript-eslint/no-restricted-imports
289
289
  'no-restricted-properties': [
290
290
  'error',
291
- ...ensureType.array(config.ts?.overrides?.general?.['no-restricted-properties']?.additionalRestrictions)
291
+ ...ensureType.array(linterBundleConfig.ts?.overrides?.general?.['no-restricted-properties']?.additionalRestrictions)
292
292
  ],
293
293
  'no-restricted-syntax': [
294
294
  'error',
295
- ...ensureType.array(config.ts?.overrides?.general?.['no-restricted-syntax']?.additionalRestrictions)
295
+ ...ensureType.array(linterBundleConfig.ts?.overrides?.general?.['no-restricted-syntax']?.additionalRestrictions)
296
296
  ],
297
297
  'no-return-assign': 'error',
298
298
  'no-script-url': 'error',
@@ -821,7 +821,7 @@ module.exports = {
821
821
  'import/max-dependencies': ['error', { max: 20, ignoreTypeImports: true }],
822
822
  'import/named': 'error',
823
823
  'import/namespace': ['error', { allowComputed: true }],
824
- 'import/newline-after-import': ['error', { considerComments: true }],
824
+ 'import/newline-after-import': ['error', { considerComments: false }],
825
825
  'import/no-absolute-path': 'error',
826
826
  'import/no-amd': 'error',
827
827
  'import/no-anonymous-default-export': 'error',
@@ -866,7 +866,7 @@ module.exports = {
866
866
  'newlines-between': 'always',
867
867
  'pathGroupsExcludedImportTypes': [],
868
868
  'pathGroups': [
869
- ...ensureType.array(config.ts?.overrides?.general?.['import/order']?.additionalExternalPatterns).map(
869
+ ...ensureType.array(linterBundleConfig.ts?.overrides?.general?.['import/order']?.additionalExternalPatterns).map(
870
870
  /**
871
871
  * Creates an "external" group using the additional external pattern configuration.
872
872
  * @param {string} pattern - A given pattern
@@ -2,7 +2,7 @@
2
2
  * @file Extends `./overrides-javascript` but ignores unsafe types.
3
3
  */
4
4
 
5
- const overridesJavaScript = require('./overrides-javascript');
5
+ const overridesJavaScript = require('./overrides-javascript.cjs');
6
6
 
7
7
  module.exports = {
8
8
  ...overridesJavaScript,
@@ -43,6 +43,7 @@ module.exports = {
43
43
  'import/no-import-module-exports': 'error',
44
44
  'import/no-internal-modules': 'off',
45
45
  'import/no-nodejs-modules': 'off',
46
+ 'import/dynamic-import-chunkname': 'off',
46
47
 
47
48
  /**
48
49
  * eslint-plugin-n
@@ -2,8 +2,8 @@
2
2
  * @file Settings for React code in TypeScript (TSX) files.
3
3
  */
4
4
 
5
- const config = require('../helper/config.js');
6
- const ensureType = require('../helper/ensure-type');
5
+ const ensureType = require('../helper/ensure-type.cjs');
6
+ const { linterBundleConfig } = require('../helper/linter-bundle-config.cjs');
7
7
 
8
8
  module.exports = {
9
9
  overrides: [
@@ -91,11 +91,11 @@ module.exports = {
91
91
  'react/forbid-component-props': ['error', { forbid: [
92
92
  {
93
93
  propName: 'className',
94
- allowedFor: ensureType.array(config.ts?.overrides?.react?.['react/forbid-component-props']?.allowClassNameFor)
94
+ allowedFor: ensureType.array(linterBundleConfig.ts?.overrides?.react?.['react/forbid-component-props']?.allowClassNameFor)
95
95
  },
96
96
  {
97
97
  propName: 'style',
98
- allowedFor: ensureType.array(config.ts?.overrides?.react?.['react/forbid-component-props']?.allowStyleFor)
98
+ allowedFor: ensureType.array(linterBundleConfig.ts?.overrides?.react?.['react/forbid-component-props']?.allowStyleFor)
99
99
  }
100
100
  ] }],
101
101
  'react/forbid-dom-props': 'error',
@@ -6,7 +6,6 @@
6
6
 
7
7
  const ts = require('typescript');
8
8
 
9
- // @ts-expect-error -- TypeScript is not able to resolve the folder since @typescript-eslint v6.0.0
10
9
  const { ESLintUtils } = require('@typescript-eslint/utils');
11
10
 
12
11
  /**
@@ -22,8 +21,20 @@ module.exports = {
22
21
  text: 'Unnecessary `typeof`, because the only possible type of {{ variableName }} is `{{ typeName }}`.'
23
22
  }
24
23
  },
24
+ /**
25
+ * Create a new rule.
26
+ *
27
+ * @param {Readonly<import('@typescript-eslint/utils/ts-eslint').RuleContext<'text', []>>} context - RuleContext of @typescript-eslint instead of ESlint
28
+ * @returns {import('@typescript-eslint/utils/ts-eslint').RuleListener} RuleListener of @typescript-eslint, instead of ESlint
29
+ */
25
30
  create (context) {
26
31
  return {
32
+ /**
33
+ * Rule function to handle unary expressions.
34
+ *
35
+ * @param {import('@typescript-eslint/typescript-estree').TSESTree.UnaryExpression} node - UnaryExpression of @typescript-eslint instead of ESlint
36
+ * @returns {import('@typescript-eslint/utils/ts-eslint').RuleFunction<import('@typescript-eslint/typescript-estree').TSESTree.UnaryExpression> | void} RuleFunction of @typescript-eslint instead of ESlint
37
+ */
27
38
  UnaryExpression (node) {
28
39
  if (node.operator !== 'typeof') {
29
40
  return;
@@ -0,0 +1,8 @@
1
+ {
2
+ "type": "commonjs",
3
+ "peerDependencies": {
4
+ "@typescript-eslint/utils": "*",
5
+ "micromatch": "*",
6
+ "typescript": "*"
7
+ }
8
+ }
@@ -6,7 +6,8 @@ const path = require('node:path');
6
6
 
7
7
  const micromatch = require('micromatch');
8
8
 
9
- const config = require('../../helper/config.js');
9
+ // eslint-disable-next-line n/no-process-env -- Only merge the linter-bundle config, if the linting is not started by the linter-bundle CLI tool (e.g. if ESlint is running separately in VSCode), to get warnings shown there too
10
+ const linterBundleConfig = (!process.env['LINTER_BUNDLE'] ? require('../../helper/linter-bundle-config.cjs').linterBundleConfig : undefined);
10
11
 
11
12
  /**
12
13
  * @type {import('eslint').Rule.RuleModule}
@@ -50,10 +51,9 @@ module.exports = {
50
51
  }
51
52
  },
52
53
  create: (context) => {
53
- const filePath = context.getFilename();
54
+ const filePath = context.filename;
54
55
  /** @type {{ basePath: string, allowed?: string[]; disallowed?: string[]; }[]} */
55
- // eslint-disable-next-line n/no-process-env -- Only merge the linter-bundle config, if the linting is not started by the linter-bundle CLI tool (e.g. if ESlint is running separately in VSCode), to get warnings shown there too
56
- const options = (!process.env['LINTER_BUNDLE'] && config.files?.restrictions ? [...config.files.restrictions, ...context.options] : context.options);
56
+ const options = linterBundleConfig?.files?.restrictions ? [...linterBundleConfig.files.restrictions, ...context.options] : context.options;
57
57
 
58
58
  for (const { basePath, allowed, disallowed } of options) {
59
59
  const normalizedName = path.relative(path.join(process.cwd(), basePath), filePath);
@@ -64,7 +64,7 @@ If both are set, `disallowed` wins over `allowed` and all unspecified files are
64
64
 
65
65
  Instead of defining the same complex patterns over and over again, e.g. for casing, you can write them into a variable and use them within the pattern, for example by using template strings.
66
66
 
67
- Example of `.eslintrc.js`:
67
+ Example of `.eslintrc.cjs`:
68
68
 
69
69
  ```js
70
70
  const snippets = {
package/files/index.js CHANGED
@@ -2,17 +2,18 @@
2
2
  * @file Ensures that only files which match given glob patterns are part of the project.
3
3
  */
4
4
 
5
- const fs = require('node:fs');
6
- const path = require('node:path');
5
+ import * as fs from 'node:fs';
6
+ import * as path from 'node:path';
7
7
 
8
- const micromatch = require('micromatch');
8
+ import micromatch from 'micromatch';
9
9
 
10
- const config = require('../helper/config.js');
10
+ import { linterBundleConfig } from '../helper/linter-bundle-config.js';
11
11
 
12
- const restrictions = config.files?.restrictions;
12
+ const restrictions = linterBundleConfig.files?.restrictions;
13
+ const matcherOptions = { dot: true };
13
14
 
14
15
  if (Array.isArray(restrictions)) {
15
- let noOfErrors = 0;
16
+ let noOfDisallowedFiles = 0;
16
17
 
17
18
  const argFiles = process.argv.splice(2).map((filePath) => path.join(process.cwd(), filePath));
18
19
 
@@ -25,7 +26,24 @@ if (Array.isArray(restrictions)) {
25
26
  const report = (filePath) => {
26
27
  process.stderr.write(`Disallowed filename "${filePath}"\n`);
27
28
 
28
- noOfErrors++;
29
+ noOfDisallowedFiles++;
30
+ };
31
+
32
+ /**
33
+ * Reports the error to the `console` and increase the error counter.
34
+ *
35
+ * @param {[string, (str: string) => boolean][]} matchers - Array of micromatch matchers
36
+ * @param {string} filePath - Path to the file to check
37
+ * @returns {string | undefined} On match returns the matching pattern, otherwise `undefined`
38
+ */
39
+ const isMatch = (matchers, filePath) => {
40
+ for (const [pattern, matcher] of matchers) {
41
+ if (matcher(filePath)) {
42
+ return pattern;
43
+ }
44
+ }
45
+
46
+ return;
29
47
  };
30
48
 
31
49
  for (const { basePath, allowed, disallowed } of restrictions) {
@@ -33,38 +51,50 @@ if (Array.isArray(restrictions)) {
33
51
 
34
52
  const files = (argFiles.length > 0 ? argFiles.filter((filePath) => !path.relative(absoluteBasePath, filePath).startsWith('..')) : getFiles(absoluteBasePath));
35
53
 
54
+ const allowedMatchers = allowed?.map((pattern) => /** @type {[string, (str: string) => boolean]} */([pattern, micromatch.matcher(pattern, matcherOptions)]));
55
+ const disallowedMatchers = disallowed?.map((pattern) => /** @type {[string, (str: string) => boolean]} */([pattern, micromatch.matcher(pattern, matcherOptions)]));
56
+
57
+ const unmatchedAllowedPatterns = new Set(allowed);
58
+
36
59
  for (const filePath of files) {
37
60
  const normalizedFilePath = path.relative(absoluteBasePath, filePath);
38
61
 
39
- if (allowed && !disallowed) {
40
- if (!micromatch.isMatch(normalizedFilePath, allowed, { dot: true })) {
41
- report(normalizedFilePath);
62
+ if (allowedMatchers && !disallowedMatchers) {
63
+ const pattern = isMatch(allowedMatchers, normalizedFilePath);
42
64
 
43
- continue;
65
+ if (pattern) {
66
+ unmatchedAllowedPatterns.delete(pattern);
44
67
  }
45
- }
46
- else if (!allowed && disallowed) {
47
- if (micromatch.isMatch(normalizedFilePath, disallowed, { dot: true })) {
68
+ else {
48
69
  report(normalizedFilePath);
49
-
50
- continue;
51
70
  }
52
71
  }
53
- else if (allowed && disallowed) {
54
- if (
55
- micromatch.isMatch(normalizedFilePath, disallowed, { dot: true }) ||
56
- !micromatch.isMatch(normalizedFilePath, allowed, { dot: true })
57
- ) {
72
+ else if (!allowedMatchers && disallowedMatchers) {
73
+ if (isMatch(disallowedMatchers, normalizedFilePath)) {
58
74
  report(normalizedFilePath);
75
+ }
76
+ }
77
+ else if (allowedMatchers && disallowedMatchers) {
78
+ const pattern = isMatch(allowedMatchers, normalizedFilePath);
59
79
 
60
- continue;
80
+ if (pattern) {
81
+ unmatchedAllowedPatterns.delete(pattern);
61
82
  }
83
+ else if (isMatch(disallowedMatchers, normalizedFilePath)) {
84
+ report(normalizedFilePath);
85
+ }
86
+ }
87
+ }
88
+
89
+ if (unmatchedAllowedPatterns.size > 0) {
90
+ for (const [pattern] of unmatchedAllowedPatterns.entries()) {
91
+ process.stderr.write(`Unmatched "allowed" pattern: "${pattern}"\n`);
62
92
  }
63
93
  }
64
94
  }
65
95
 
66
- if (noOfErrors > 0) {
67
- process.stderr.write(`\nFound ${noOfErrors} disallowed file${(noOfErrors !== 0 ? 's' : '')}\n`);
96
+ if (noOfDisallowedFiles > 0) {
97
+ process.stderr.write(`\nFound ${noOfDisallowedFiles} disallowed file${(noOfDisallowedFiles !== 0 ? 's' : '')}\n`);
68
98
 
69
99
  process.exitCode = -1;
70
100
  }
@@ -1,5 +1,7 @@
1
1
  /**
2
2
  * @file Ensures that a value is of a specific type, if not it converts the value into that type.
3
+ *
4
+ * This module has to be CommonJS as it is only used by `eslint` which does not support ESModules.
3
5
  */
4
6
 
5
7
  /**
@@ -2,9 +2,9 @@
2
2
  * @file Handling of changed files from Git.
3
3
  */
4
4
 
5
- const { runProcess } = require('./run-process.js');
5
+ import { runProcess } from './run-process.js';
6
6
 
7
- /** @typedef {import('./run-process').ProcessResult} ProcessResult */
7
+ /** @typedef {import('./run-process.js').ProcessResult} ProcessResult */
8
8
 
9
9
  /** @type {{ diff: Promise<ProcessResult>; modified: Promise<ProcessResult>; deleted: Promise<ProcessResult>; } | undefined} */
10
10
  let gitFilesProcessPromise;
@@ -17,7 +17,7 @@ let gitFiles;
17
17
  * @public
18
18
  * @returns {Promise<string[]>} The list of changed files.
19
19
  */
20
- async function getGitFiles () {
20
+ export async function getGitFiles () {
21
21
  if (!gitFilesProcessPromise) {
22
22
  gitFilesProcessPromise = {
23
23
  // Returns changed files, also stashed and committed
@@ -46,7 +46,3 @@ async function getGitFiles () {
46
46
 
47
47
  return gitFiles;
48
48
  }
49
-
50
- module.exports = {
51
- getGitFiles
52
- };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @file Ensures that the installed dependencies of the project matches to the versions used by the linter-bundle.
3
+ *
4
+ * @see https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides
5
+ * @see https://classic.yarnpkg.com/en/docs/selective-version-resolutions/
6
+ */
7
+
8
+ import * as fs from 'node:fs/promises';
9
+ import * as path from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+
12
+ const dirname = path.dirname(fileURLToPath(import.meta.url));
13
+
14
+ /** @typedef {{ name: string; configuredVersion: string; expectedVersion: string; }} Dependency */
15
+
16
+ /**
17
+ * Detects if installed versions of dependencies don't match to the required dependencies.
18
+ *
19
+ * @public
20
+ * @returns {Promise<Dependency[]>} An array of missing overrides (=wrong versions).
21
+ */
22
+ export async function getOutdatedDependencies () {
23
+ const linterBundleDependencies = JSON.parse(await fs.readFile(path.resolve(dirname, '../package.json'), 'utf8')).dependencies;
24
+
25
+ const outdatedDependencies = await Promise.all(Object.entries(linterBundleDependencies).map(async ([name, expectedVersion]) => {
26
+ let dependencyPackageJson;
27
+
28
+ try {
29
+ dependencyPackageJson = JSON.parse(await fs.readFile(path.join(process.cwd(), 'node_modules', name, 'package.json'), 'utf8'));
30
+ }
31
+ catch {
32
+ // If the file does not exist, we ignore it, because in this case it's most likely a linter-bundle-only dependency.
33
+ return;
34
+ }
35
+
36
+ if (dependencyPackageJson.version !== expectedVersion) {
37
+ return {
38
+ name,
39
+ configuredVersion: dependencyPackageJson.version,
40
+ expectedVersion
41
+ };
42
+ }
43
+
44
+ return;
45
+ }));
46
+
47
+ return /** @type {Dependency[]} */(outdatedDependencies.filter((dependency) => dependency !== undefined));
48
+ }
@@ -5,8 +5,11 @@
5
5
  * @see https://classic.yarnpkg.com/en/docs/selective-version-resolutions/
6
6
  */
7
7
 
8
- const fs = require('node:fs');
9
- const path = require('node:path');
8
+ import * as fs from 'node:fs/promises';
9
+ import * as path from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+
12
+ const dirname = path.dirname(fileURLToPath(import.meta.url));
10
13
 
11
14
  /** @typedef {{ name: string; configuredVersion: string; expectedVersion: string; }} Dependency */
12
15
 
@@ -14,11 +17,11 @@ const path = require('node:path');
14
17
  * Detects outdated "overrides"/"resolutions" dependencies.
15
18
  *
16
19
  * @public
17
- * @returns {{ overrides: Dependency[]; resolutions: Dependency[]; }} Either the input array, or an empty array, if the input array is not an array.
20
+ * @returns {Promise<{ overrides: Dependency[]; resolutions: Dependency[]; }>} Either the input array, or an empty array, if the input array is not an array.
18
21
  */
19
- function validatePackageOverrides () {
20
- const linterBundleDependencies = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf8')).dependencies;
21
- const projectPackageJson = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'));
22
+ export async function getOutdatedOverrides () {
23
+ const linterBundleDependencies = JSON.parse(await fs.readFile(path.resolve(dirname, '../package.json'), 'utf8')).dependencies;
24
+ const projectPackageJson = JSON.parse(await fs.readFile(path.join(process.cwd(), 'package.json'), 'utf8'));
22
25
 
23
26
  const overrides = [];
24
27
  const resolutions = [];
@@ -57,7 +60,3 @@ function validatePackageOverrides () {
57
60
 
58
61
  return { overrides, resolutions };
59
62
  }
60
-
61
- module.exports = {
62
- validatePackageOverrides
63
- };
@@ -2,31 +2,34 @@
2
2
  * @file Returns the path to the Stylelint CLI script.
3
3
  */
4
4
 
5
- const fs = require('node:fs');
6
- const path = require('node:path');
5
+ import * as fs from 'node:fs/promises';
6
+ import { createRequire } from 'node:module';
7
+ import * as path from 'node:path';
8
+
9
+ const require = createRequire(import.meta.url);
7
10
 
8
11
  /**
9
12
  * Returns if the project is using npm or yarn.
10
13
  *
11
14
  * @public
12
- * @returns {string | null} Return the path to the Stylelint CLI script, or `null` if it can't be found.
15
+ * @returns {Promise<string | null>} Return the path to the Stylelint CLI script, or `null` if it can't be found.
13
16
  */
14
- function getStylelintPath () {
17
+ export async function getStylelintPath () {
15
18
  const stylelintLibPath = path.dirname(require.resolve('stylelint'));
16
19
 
17
- for (const stylelintBinPath of [
20
+ for await (const stylelintBinPath of [
18
21
  path.join(stylelintLibPath, '../bin/stylelint.mjs'),
19
22
  path.join(stylelintLibPath, '../bin/stylelint.js')
20
23
  ]) {
21
- if (fs.existsSync(stylelintBinPath)) {
22
- return stylelintBinPath;
24
+ try {
25
+ const stat = await fs.stat(stylelintBinPath);
26
+
27
+ if (stat.isFile()) {
28
+ return stylelintBinPath;
29
+ }
23
30
  }
31
+ catch { /* Do nothing */ }
24
32
  }
25
33
 
26
34
  return null;
27
35
  }
28
-
29
- module.exports = {
30
- getStylelintPath
31
- };
32
-
@@ -2,30 +2,34 @@
2
2
  * @file Check if the project is using npm or yarn by checking the existence of a `package-lock.json` or a `yarn.lock`.
3
3
  */
4
4
 
5
- const fs = require('node:fs');
6
- const path = require('node:path');
5
+ import * as fs from 'node:fs/promises';
6
+ import * as path from 'node:path';
7
7
 
8
8
  /**
9
9
  * Returns if the project is using npm or yarn.
10
10
  *
11
11
  * @public
12
- * @returns {'none' | 'npm' | 'yarn' | 'both'} Returns which package manager name.
12
+ * @returns {Promise<'none' | 'npm' | 'yarn' | 'both'>} Returns which package manager name.
13
13
  */
14
- function isNpmOrYarn () {
14
+ export async function isNpmOrYarn () {
15
15
  let npm = false;
16
16
  let yarn = false;
17
17
 
18
18
  try {
19
- fs.accessSync(path.join(process.cwd(), 'package-lock.json'), fs.constants.R_OK);
19
+ const stat = await fs.stat(path.join(process.cwd(), 'package-lock.json'));
20
20
 
21
- npm = true;
21
+ if (stat.isFile()) {
22
+ npm = true;
23
+ }
22
24
  }
23
25
  catch { /* `package-lock.json` cannot be accessed. */ }
24
26
 
25
27
  try {
26
- fs.accessSync(path.join(process.cwd(), 'yarn.lock'), fs.constants.R_OK);
28
+ const stat = await fs.stat(path.join(process.cwd(), 'yarn.lock'));
27
29
 
28
- yarn = true;
30
+ if (stat.isFile()) {
31
+ yarn = true;
32
+ }
29
33
  }
30
34
  catch { /* `yarn.lock` cannot be accessed. */ }
31
35
 
@@ -43,7 +47,3 @@ function isNpmOrYarn () {
43
47
 
44
48
  return 'none';
45
49
  }
46
-
47
- module.exports = {
48
- isNpmOrYarn
49
- };