dependency-cruiser 13.1.4 → 14.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dependency-cruiser",
3
- "version": "13.1.4",
3
+ "version": "14.0.0",
4
4
  "description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
5
5
  "keywords": [
6
6
  "static analysis",
@@ -158,13 +158,13 @@
158
158
  "commander": "11.0.0",
159
159
  "enhanced-resolve": "5.15.0",
160
160
  "figures": "5.0.0",
161
- "glob": "10.3.3",
162
161
  "ignore": "5.2.4",
163
162
  "indent-string": "5.0.0",
164
163
  "interpret": "^3.1.1",
165
164
  "is-installed-globally": "0.4.0",
166
165
  "json5": "2.2.3",
167
166
  "lodash": "4.17.21",
167
+ "picomatch": "2.3.1",
168
168
  "prompts": "2.4.2",
169
169
  "rechoir": "^0.8.0",
170
170
  "safe-regex": "2.1.1",
@@ -172,23 +172,23 @@
172
172
  "semver-try-require": "6.2.3",
173
173
  "teamcity-service-messages": "0.1.14",
174
174
  "tsconfig-paths-webpack-plugin": "4.1.0",
175
- "watskeburt": "0.12.1",
175
+ "watskeburt": "1.0.1",
176
176
  "wrap-ansi": "8.1.0"
177
177
  },
178
178
  "devDependencies": {
179
- "@babel/core": "7.22.10",
180
- "@babel/plugin-transform-modules-commonjs": "7.22.5",
181
- "@babel/preset-typescript": "7.22.5",
182
- "@swc/core": "1.3.78",
183
- "@types/lodash": "4.14.197",
184
- "@types/node": "20.5.1",
179
+ "@babel/core": "7.22.20",
180
+ "@babel/plugin-transform-modules-commonjs": "7.22.15",
181
+ "@babel/preset-typescript": "7.22.15",
182
+ "@swc/core": "1.3.87",
183
+ "@types/lodash": "4.14.199",
184
+ "@types/node": "20.6.3",
185
185
  "@types/prompts": "2.4.4",
186
- "@typescript-eslint/eslint-plugin": "6.4.0",
187
- "@typescript-eslint/parser": "6.4.0",
186
+ "@typescript-eslint/eslint-plugin": "6.7.2",
187
+ "@typescript-eslint/parser": "6.7.2",
188
188
  "@vue/compiler-sfc": "3.3.4",
189
189
  "c8": "8.0.1",
190
190
  "coffeescript": "2.7.0",
191
- "eslint": "8.47.0",
191
+ "eslint": "8.50.0",
192
192
  "eslint-config-moving-meadow": "4.0.2",
193
193
  "eslint-config-prettier": "9.0.0",
194
194
  "eslint-plugin-budapestian": "5.0.1",
@@ -200,16 +200,16 @@
200
200
  "eslint-plugin-unicorn": "^48.0.1",
201
201
  "husky": "8.0.3",
202
202
  "intercept-stdout": "0.1.2",
203
- "lint-staged": "14.0.0",
203
+ "lint-staged": "14.0.1",
204
204
  "mocha": "10.2.0",
205
205
  "normalize-newline": "4.1.0",
206
206
  "npm-run-all": "4.1.5",
207
- "prettier": "3.0.2",
207
+ "prettier": "3.0.3",
208
208
  "proxyquire": "2.1.3",
209
209
  "shx": "0.3.4",
210
210
  "svelte": "3.59.1",
211
- "symlink-dir": "5.1.1",
212
- "typescript": "5.1.6",
211
+ "symlink-dir": "5.2.0",
212
+ "typescript": "5.2.2",
213
213
  "upem": "8.0.0",
214
214
  "vue-template-compiler": "2.7.14",
215
215
  "yarn": "1.22.19"
@@ -240,7 +240,7 @@
240
240
  ]
241
241
  },
242
242
  "engines": {
243
- "node": "^16.14||>=18"
243
+ "node": "^18.17||>=20"
244
244
  },
245
245
  "supportedTranspilers": {
246
246
  "babel": ">=7.0.0 <8.0.0",
@@ -1,5 +1,5 @@
1
1
  import _format from "../main/format.mjs";
2
- import validateFileExistence from "./utl/validate-file-existence.mjs";
2
+ import assertFileExistence from "./utl/assert-file-existence.mjs";
3
3
  import normalizeOptions from "./normalize-cli-options.mjs";
4
4
  import { getInStream, write } from "./utl/io.mjs";
5
5
 
@@ -13,7 +13,7 @@ export default async function format(pResultFile, pOptions) {
13
13
  const lOptions = await normalizeOptions(pOptions);
14
14
 
15
15
  if (pResultFile !== "-") {
16
- validateFileExistence(pResultFile);
16
+ assertFileExistence(pResultFile);
17
17
  }
18
18
 
19
19
  return new Promise((pResolve, pReject) => {
@@ -29,13 +29,13 @@ export default async function format(pResultFile, pOptions) {
29
29
  /* c8 ignore start */
30
30
  (pError) => {
31
31
  pReject(pError);
32
- }
32
+ },
33
33
  /* c8 ignore stop */
34
34
  )
35
35
  .on("end", async () => {
36
36
  const lReportingResult = await _format(
37
37
  JSON.parse(lInputAsString),
38
- lOptions
38
+ lOptions,
39
39
  );
40
40
 
41
41
  write(lOptions.outputTo, lReportingResult.output);
package/src/cli/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { join } from "node:path";
2
- import { glob } from "glob";
2
+ import picomatch from "picomatch";
3
3
  import cloneDeep from "lodash/cloneDeep.js";
4
4
  import set from "lodash/set.js";
5
5
  import isInstalledGlobally from "is-installed-globally";
@@ -8,7 +8,7 @@ import chalk from "chalk";
8
8
  import cruise from "../main/cruise.mjs";
9
9
  import { INFO, bus } from "../utl/bus.mjs";
10
10
 
11
- import validateFileExistence from "./utl/validate-file-existence.mjs";
11
+ import assertFileExistence from "./utl/assert-file-existence.mjs";
12
12
  import normalizeCliOptions from "./normalize-cli-options.mjs";
13
13
  import { write } from "./utl/io.mjs";
14
14
  import setUpCliFeedbackListener from "./listeners/cli-feedback.mjs";
@@ -27,7 +27,7 @@ async function extractResolveOptions(pCruiseOptions) {
27
27
  lResolveOptions = await extractWebpackResolveConfig(
28
28
  lWebPackConfigFileName,
29
29
  pCruiseOptions?.ruleSet?.options?.webpackConfig?.env ?? null,
30
- pCruiseOptions?.ruleSet?.options?.webpackConfig?.arguments ?? null
30
+ pCruiseOptions?.ruleSet?.options?.webpackConfig?.arguments ?? null,
31
31
  );
32
32
  }
33
33
  return lResolveOptions;
@@ -39,7 +39,7 @@ async function addKnownViolations(pCruiseOptions) {
39
39
  "../config-utl/extract-known-violations.mjs"
40
40
  );
41
41
  const lKnownViolations = await extractKnownViolations(
42
- pCruiseOptions.knownViolationsFile
42
+ pCruiseOptions.knownViolationsFile,
43
43
  );
44
44
 
45
45
  // Check against json schema is already done in src/main/options/validate
@@ -95,24 +95,24 @@ function setUpListener(pCruiseOptions) {
95
95
  if (Boolean(lListenerFunction)) {
96
96
  lListenerFunction(
97
97
  bus,
98
- pCruiseOptions?.ruleSet?.options?.progress?.maximumLevel ?? INFO
98
+ pCruiseOptions?.ruleSet?.options?.progress?.maximumLevel ?? INFO,
99
99
  );
100
100
  }
101
101
  }
102
102
 
103
103
  async function runCruise(pFileDirectoryArray, pCruiseOptions) {
104
104
  const lCruiseOptions = await addKnownViolations(
105
- await normalizeCliOptions(pCruiseOptions)
105
+ await normalizeCliOptions(pCruiseOptions),
106
106
  );
107
107
 
108
108
  pFileDirectoryArray
109
- .filter((pFileOrDirectory) => !glob.hasMagic(pFileOrDirectory))
109
+ .filter((pFileOrDirectory) => !picomatch.scan(pFileOrDirectory).isGlob)
110
110
  .map((pFileOrDirectory) =>
111
111
  lCruiseOptions?.ruleSet?.options?.baseDir
112
112
  ? join(lCruiseOptions.ruleSet.options.baseDir, pFileOrDirectory)
113
- : pFileOrDirectory
113
+ : pFileOrDirectory,
114
114
  )
115
- .forEach(validateFileExistence);
115
+ .forEach(assertFileExistence);
116
116
 
117
117
  setUpListener(lCruiseOptions);
118
118
 
@@ -126,7 +126,7 @@ async function runCruise(pFileDirectoryArray, pCruiseOptions) {
126
126
  pFileDirectoryArray,
127
127
  lCruiseOptions,
128
128
  lResolveOptions,
129
- { tsConfig, babelConfig }
129
+ { tsConfig, babelConfig },
130
130
  );
131
131
 
132
132
  bus.progress("cli: writing results", { complete: 1 });
@@ -151,14 +151,14 @@ export default async function executeCli(pFileDirectoryArray, pCruiseOptions) {
151
151
  if (isInstalledGlobally) {
152
152
  process.stderr.write(
153
153
  `\n ${chalk.yellow(
154
- "WARNING"
154
+ "WARNING",
155
155
  )}: You're running a globally installed dependency-cruiser.\n\n` +
156
156
  ` We recommend to ${chalk.bold.italic.underline(
157
- "install and run it as a local devDependency"
157
+ "install and run it as a local devDependency",
158
158
  )} in\n` +
159
159
  ` your project instead. There it has your project's environment and\n` +
160
160
  ` transpilers at its disposal. That will ensure it can find e.g.\n` +
161
- ` TypeScript, Vue or Svelte modules and dependencies.\n\n`
161
+ ` TypeScript, Vue or Svelte modules and dependencies.\n\n`,
162
162
  );
163
163
  }
164
164
  /* c8 ignore stop */
@@ -1,11 +1,11 @@
1
1
  import { accessSync, R_OK } from "node:fs";
2
2
 
3
- export default function validateFileExistence(pDirectoryOrFile) {
3
+ export default function assertFileExistence(pDirectoryOrFile) {
4
4
  try {
5
5
  accessSync(pDirectoryOrFile, R_OK);
6
6
  } catch (pError) {
7
7
  throw new Error(
8
- `Can't open '${pDirectoryOrFile}' for reading. Does it exist?\n`
8
+ `Can't open '${pDirectoryOrFile}' for reading. Does it exist?\n`,
9
9
  );
10
10
  }
11
11
  }
@@ -1,6 +1,6 @@
1
1
  import { readdirSync, statSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { glob } from "glob";
2
+ import { join, normalize } from "node:path";
3
+ import picomatch from "picomatch";
4
4
  import { filenameMatchesPattern } from "../graph-utl/match-facade.mjs";
5
5
  import getExtension from "../utl/get-extension.mjs";
6
6
  import pathToPosix from "../utl/path-to-posix.mjs";
@@ -45,7 +45,7 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
45
45
  return readdirSync(join(pOptions.baseDir, pDirectoryName))
46
46
  .map((pFileName) => join(pDirectoryName, pFileName))
47
47
  .filter((pFullPathToFile) =>
48
- shouldNotBeExcluded(pathToPosix(pFullPathToFile), pOptions)
48
+ shouldNotBeExcluded(pathToPosix(pFullPathToFile), pOptions),
49
49
  )
50
50
  .reduce((pSum, pFullPathToFile) => {
51
51
  let lStat = statSync(join(pOptions.baseDir, pFullPathToFile), {
@@ -55,7 +55,7 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
55
55
  if (lStat) {
56
56
  if (lStat.isDirectory()) {
57
57
  return pSum.concat(
58
- gatherScannableFilesFromDirectory(pFullPathToFile, pOptions)
58
+ gatherScannableFilesFromDirectory(pFullPathToFile, pOptions),
59
59
  );
60
60
  }
61
61
  if (fileIsScannable(pOptions, pFullPathToFile)) {
@@ -68,6 +68,15 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
68
68
  .filter((pFullPathToFile) => shouldBeIncluded(pFullPathToFile, pOptions));
69
69
  }
70
70
 
71
+ function expandGlob(pBaseDirectory, pScannedGlob) {
72
+ const isMatch = picomatch(pathToPosix(pScannedGlob.glob));
73
+ return readdirSync(join(pBaseDirectory, pScannedGlob.base), {
74
+ recursive: true,
75
+ })
76
+ .filter((pFile) => isMatch(pFile))
77
+ .map((pFile) => pathToPosix(join(pScannedGlob.base, pFile)));
78
+ }
79
+
71
80
  /**
72
81
  * Returns an array of strings, representing paths to files to be gathered
73
82
  *
@@ -78,7 +87,7 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
78
87
  * Files and directories are assumed to be either absolute, or relative to the
79
88
  * current working directory.
80
89
  *
81
- * @param {string[]} pFileAndDirectoryArray globs and/ or paths to files or
90
+ * @param {string[]} pFileDirectoryAndGlobArray globs and/ or paths to files or
82
91
  * directories to be gathered
83
92
  * @param {import('../../types/dependency-cruiser.js').IStrictCruiseOptions} pOptions options that
84
93
  * influence what needs to be gathered/ scanned
@@ -87,31 +96,26 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
87
96
  * - includeOnly - regexp what to include
88
97
  * @return {string[]} paths to files to be gathered.
89
98
  */
90
- export default function gatherInitialSources(pFileAndDirectoryArray, pOptions) {
99
+ export default function gatherInitialSources(
100
+ pFileDirectoryAndGlobArray,
101
+ pOptions,
102
+ ) {
91
103
  const lOptions = { baseDir: process.cwd(), ...pOptions };
92
104
 
93
- // these are `.reduce`s and not `.map`s because they typically return larger
94
- // arrays than the pFileAndDirectoryArray:
95
- // - `glob` returns an array of strings
96
- // - so does `gatherScannableFilesFromDirectory`
97
- return pFileAndDirectoryArray
98
- .reduce(
99
- (pAll, pFileOrDirectory) =>
100
- pAll.concat(
101
- glob.sync(pathToPosix(pFileOrDirectory), {
102
- cwd: pathToPosix(lOptions.baseDir),
103
- })
104
- ),
105
- []
106
- )
107
- .reduce((pAll, pFileOrDirectory) => {
105
+ return pFileDirectoryAndGlobArray
106
+ .flatMap((pFileDirectoryOrGlob) => {
107
+ const lScannedGlob = picomatch.scan(pFileDirectoryOrGlob);
108
+ if (lScannedGlob.isGlob) {
109
+ return expandGlob(lOptions.baseDir, lScannedGlob);
110
+ }
111
+ return pathToPosix(normalize(pFileDirectoryOrGlob));
112
+ })
113
+ .flatMap((pFileOrDirectory) => {
108
114
  if (statSync(join(lOptions.baseDir, pFileOrDirectory)).isDirectory()) {
109
- return pAll.concat(
110
- gatherScannableFilesFromDirectory(pFileOrDirectory, lOptions)
111
- );
112
- } else {
113
- return pAll.concat(pathToPosix(pFileOrDirectory));
115
+ return gatherScannableFilesFromDirectory(pFileOrDirectory, lOptions);
114
116
  }
115
- }, [])
117
+ // Not a glob anymore, and not a directory => it's a file
118
+ return pathToPosix(pFileOrDirectory);
119
+ })
116
120
  .sort();
117
121
  }
package/src/meta.js CHANGED
@@ -1,9 +1,9 @@
1
1
  /* generated - don't edit */
2
2
 
3
3
  module.exports = {
4
- version: "13.1.4",
4
+ version: "14.0.0",
5
5
  engines: {
6
- node: "^16.14||>=18",
6
+ node: "^18.17||>=20",
7
7
  },
8
8
  supportedTranspilers: {
9
9
  babel: ">=7.0.0 <8.0.0",