dependency-cruiser 13.1.5 → 14.1.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.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { program } from "commander";
3
- import validateNodeEnvironment from "../src/cli/validate-node-environment.mjs";
3
+ import assertNodeEnvironmentSuitable from "../src/cli/assert-node-environment-suitable.mjs";
4
4
  import meta from "../src/meta.js";
5
5
  import cli from "../src/cli/index.mjs";
6
6
 
@@ -10,7 +10,7 @@ function formatError(pError) {
10
10
  }
11
11
 
12
12
  try {
13
- validateNodeEnvironment();
13
+ assertNodeEnvironmentSuitable();
14
14
 
15
15
  program
16
16
  .description(
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { program } from "commander";
4
- import validateNodeEnvironment from "../src/cli/validate-node-environment.mjs";
4
+ import assertNodeEnvironmentSuitable from "../src/cli/assert-node-environment-suitable.mjs";
5
5
  import meta from "../src/meta.js";
6
6
  import format from "../src/cli/format.mjs";
7
7
 
@@ -11,7 +11,7 @@ function formatError(pError) {
11
11
  }
12
12
 
13
13
  try {
14
- validateNodeEnvironment();
14
+ assertNodeEnvironmentSuitable();
15
15
 
16
16
  program
17
17
  .description(
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { EOL } from "node:os";
3
3
  import { program } from "commander";
4
- import validateNodeEnvironment from "../src/cli/validate-node-environment.mjs";
4
+ import assertNodeEnvironmentSuitable from "../src/cli/assert-node-environment-suitable.mjs";
5
5
  import meta from "../src/meta.js";
6
6
  import cli from "../src/cli/index.mjs";
7
7
 
8
8
  try {
9
- validateNodeEnvironment();
9
+ assertNodeEnvironmentSuitable();
10
10
 
11
11
  program
12
12
  .description(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dependency-cruiser",
3
- "version": "13.1.5",
3
+ "version": "14.1.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",
@@ -176,25 +176,25 @@
176
176
  "wrap-ansi": "8.1.0"
177
177
  },
178
178
  "devDependencies": {
179
- "@babel/core": "7.22.11",
180
- "@babel/plugin-transform-modules-commonjs": "7.22.11",
181
- "@babel/preset-typescript": "7.22.11",
182
- "@swc/core": "1.3.80",
183
- "@types/lodash": "4.14.197",
184
- "@types/node": "20.5.6",
185
- "@types/prompts": "2.4.4",
186
- "@typescript-eslint/eslint-plugin": "6.4.1",
187
- "@typescript-eslint/parser": "6.4.1",
179
+ "@babel/core": "7.23.0",
180
+ "@babel/plugin-transform-modules-commonjs": "7.23.0",
181
+ "@babel/preset-typescript": "7.23.0",
182
+ "@swc/core": "1.3.90",
183
+ "@types/lodash": "4.14.199",
184
+ "@types/node": "20.8.0",
185
+ "@types/prompts": "2.4.5",
186
+ "@typescript-eslint/eslint-plugin": "6.7.3",
187
+ "@typescript-eslint/parser": "6.7.3",
188
188
  "@vue/compiler-sfc": "3.3.4",
189
189
  "c8": "8.0.1",
190
190
  "coffeescript": "2.7.0",
191
- "eslint": "8.48.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",
195
195
  "eslint-plugin-eslint-comments": "3.2.0",
196
196
  "eslint-plugin-import": "2.28.1",
197
- "eslint-plugin-mocha": "10.1.0",
197
+ "eslint-plugin-mocha": "10.2.0",
198
198
  "eslint-plugin-node": "11.1.0",
199
199
  "eslint-plugin-security": "1.7.1",
200
200
  "eslint-plugin-unicorn": "^48.0.1",
@@ -204,11 +204,11 @@
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",
211
+ "symlink-dir": "5.2.0",
212
212
  "typescript": "5.2.2",
213
213
  "upem": "8.0.0",
214
214
  "vue-template-compiler": "2.7.14",
@@ -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,7 +1,7 @@
1
1
  import satisfies from "semver/functions/satisfies.js";
2
2
  import meta from "../meta.js";
3
3
 
4
- export default function validateNodeEnvironment(pNodeVersion) {
4
+ export default function assertNodeEnvironmentSuitable(pNodeVersion) {
5
5
  // not using default parameter here because the check should run
6
6
  // run on node 4 as well
7
7
  const lNodeVersion = pNodeVersion || process.versions.node;
@@ -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 */
@@ -135,9 +135,10 @@ function buildExtensionsAttribute(pInitOptions) {
135
135
  * @returns {string}
136
136
  */
137
137
  function buildMainFieldsAttribute(pInitOptions) {
138
- return pInitOptions.usesTypeScript
139
- ? `mainFields: ["main", "types", "typings"],`
140
- : `// mainFields: ["main", "types", "typings"],`;
138
+ if (pInitOptions.isTypeModule) {
139
+ return `mainFields: ["module", "main", "types", "typings"],`;
140
+ }
141
+ return `mainFields: ["main", "types", "typings"],`;
141
142
  }
142
143
 
143
144
  /**
@@ -2,6 +2,7 @@
2
2
  import prompts from "prompts";
3
3
  import {
4
4
  isLikelyMonoRepo,
5
+ isTypeModule,
5
6
  getMonoRepoPackagesCandidates,
6
7
  getSourceFolderCandidates,
7
8
  getTestFolderCandidates,
@@ -33,6 +34,12 @@ const QUESTIONS = [
33
34
  message: "This looks like mono repo. Is that correct?",
34
35
  initial: isLikelyMonoRepo(),
35
36
  },
37
+ {
38
+ name: "isTypeModule",
39
+ type: () => (isTypeModule() ? "confirm" : false),
40
+ message: "It looks like this is an ESM package. Is that correct?",
41
+ initial: isTypeModule(),
42
+ },
36
43
  {
37
44
  name: "sourceLocation",
38
45
  type: (_, pAnswers) => (pAnswers.isMonoRepo ? "list" : false),
@@ -61,7 +68,7 @@ const QUESTIONS = [
61
68
  initial: (_, pAnswers) => {
62
69
  return !hasTestsWithinSource(
63
70
  getTestFolderCandidates(),
64
- toSourceLocationArray(pAnswers.sourceLocation)
71
+ toSourceLocationArray(pAnswers.sourceLocation),
65
72
  );
66
73
  },
67
74
  },
@@ -16,6 +16,7 @@ import {
16
16
  getDefaultConfigFileName,
17
17
  hasJSConfigCandidates,
18
18
  getJSConfigCandidates,
19
+ isTypeModule,
19
20
  } from "./environment-helpers.mjs";
20
21
  import { writeRunScriptsToManifest } from "./write-run-scripts-to-manifest.mjs";
21
22
 
@@ -32,6 +33,7 @@ function getOneShotConfig(pOneShotConfigId) {
32
33
  /** @type {import("./types").IPartialInitConfig} */
33
34
  const lBaseConfig = {
34
35
  isMonoRepo: isLikelyMonoRepo(),
36
+ isTypeModule: isTypeModule(),
35
37
  combinedDependencies: false,
36
38
  useJsConfig: hasJSConfigCandidates() && !hasTSConfigCandidates(),
37
39
  jsConfig: getJSConfigCandidates().shift(),
@@ -5,6 +5,12 @@ export interface IInitConfig {
5
5
  * Whether or not the current folder houses a mono repo
6
6
  */
7
7
  isMonoRepo: boolean;
8
+ /**
9
+ * Whether or not the current folder is a package is an ESM package
10
+ * by default (and resolutions of external dependencies should be
11
+ * treated as such)
12
+ */
13
+ isTypeModule: boolean;
8
14
  /**
9
15
  * Whether or not you allow usage of external dependencies declared in
10
16
  * package.jsons of parent folders
@@ -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
  }
@@ -10,7 +10,7 @@ function extendNamedRule(pExtendedRule, pForbiddenArrayBase) {
10
10
  ...pBaseRule,
11
11
  ...pAll,
12
12
  }),
13
- pExtendedRule
13
+ pExtendedRule,
14
14
  );
15
15
  }
16
16
 
@@ -23,7 +23,7 @@ function extendNamedRule(pExtendedRule, pForbiddenArrayBase) {
23
23
  * rules get merged, where individual attributes of the named rules
24
24
  * in pForbiddenArrayExtended win)
25
25
  *
26
- * @param {*} pRuleArrayExtended - array of 'fobidden' rules that extend the ...
26
+ * @param {*} pRuleArrayExtended - array of 'forbidden' rules that extend the ...
27
27
  * @param {*} pRuleArrayBase - array of 'forbidden' rules to extend
28
28
  *
29
29
  * @return {Array} - the merged array
@@ -32,7 +32,7 @@ function mergeRules(pRuleArrayExtended, pRuleArrayBase) {
32
32
  // merge anonymous on 100% equality
33
33
  let lAnonymousRules = uniqWith(
34
34
  pRuleArrayExtended.concat(pRuleArrayBase).filter(({ name }) => !name),
35
- isDeepStrictEqual
35
+ isDeepStrictEqual,
36
36
  );
37
37
 
38
38
  let lNamedRules = pRuleArrayExtended
@@ -48,7 +48,7 @@ function mergeRules(pRuleArrayExtended, pRuleArrayBase) {
48
48
  // the other concats (anonymous, allowed) don't need it
49
49
  // but have it to be consistent with this
50
50
  lNamedRules.concat(pRuleArrayBase).filter(({ name }) => name),
51
- ({ name }) => name
51
+ ({ name }) => name,
52
52
  );
53
53
 
54
54
  return lNamedRules.concat(lAnonymousRules);
@@ -67,7 +67,7 @@ function mergeRules(pRuleArrayExtended, pRuleArrayBase) {
67
67
  function mergeAllowedRules(pAllowedArrayExtended, pAllowedArrayBase) {
68
68
  return uniqWith(
69
69
  pAllowedArrayExtended.concat(pAllowedArrayBase),
70
- isDeepStrictEqual
70
+ isDeepStrictEqual,
71
71
  );
72
72
  }
73
73
 
@@ -109,15 +109,15 @@ function mergeAllowedSeverities(pConfigExtended, pConfigBase) {
109
109
  export default (pConfigExtended, pConfigBase) => {
110
110
  const lForbidden = mergeRules(
111
111
  pConfigExtended?.forbidden ?? [],
112
- pConfigBase?.forbidden ?? []
112
+ pConfigBase?.forbidden ?? [],
113
113
  );
114
114
  const lRequired = mergeRules(
115
115
  pConfigExtended?.required ?? [],
116
- pConfigBase?.required ?? []
116
+ pConfigBase?.required ?? [],
117
117
  );
118
118
  const lAllowed = mergeAllowedRules(
119
119
  pConfigExtended?.allowed ?? [],
120
- pConfigBase?.allowed ?? []
120
+ pConfigBase?.allowed ?? [],
121
121
  );
122
122
 
123
123
  return {
@@ -131,7 +131,7 @@ export default (pConfigExtended, pConfigBase) => {
131
131
  : {}),
132
132
  options: mergeOptions(
133
133
  pConfigExtended?.options ?? {},
134
- pConfigBase?.options ?? {}
134
+ pConfigBase?.options ?? {},
135
135
  ),
136
136
  };
137
137
  };
@@ -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,29 +45,36 @@ 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
- .reduce((pSum, pFullPathToFile) => {
50
+ .flatMap((pFullPathToFile) => {
51
51
  let lStat = statSync(join(pOptions.baseDir, pFullPathToFile), {
52
52
  throwIfNoEntry: false,
53
53
  });
54
54
 
55
55
  if (lStat) {
56
56
  if (lStat.isDirectory()) {
57
- return pSum.concat(
58
- gatherScannableFilesFromDirectory(pFullPathToFile, pOptions)
59
- );
57
+ return gatherScannableFilesFromDirectory(pFullPathToFile, pOptions);
60
58
  }
61
59
  if (fileIsScannable(pOptions, pFullPathToFile)) {
62
- return pSum.concat(pFullPathToFile);
60
+ return pFullPathToFile;
63
61
  }
64
62
  }
65
- return pSum;
66
- }, [])
63
+ return [];
64
+ })
67
65
  .map((pFullPathToFile) => pathToPosix(pFullPathToFile))
68
66
  .filter((pFullPathToFile) => shouldBeIncluded(pFullPathToFile, pOptions));
69
67
  }
70
68
 
69
+ function expandGlob(pBaseDirectory, pScannedGlob) {
70
+ const isMatch = picomatch(pathToPosix(pScannedGlob.glob));
71
+ return readdirSync(join(pBaseDirectory, pScannedGlob.base), {
72
+ recursive: true,
73
+ })
74
+ .filter((pFile) => isMatch(pFile))
75
+ .map((pFile) => pathToPosix(join(pScannedGlob.base, pFile)));
76
+ }
77
+
71
78
  /**
72
79
  * Returns an array of strings, representing paths to files to be gathered
73
80
  *
@@ -78,7 +85,7 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
78
85
  * Files and directories are assumed to be either absolute, or relative to the
79
86
  * current working directory.
80
87
  *
81
- * @param {string[]} pFileAndDirectoryArray globs and/ or paths to files or
88
+ * @param {string[]} pFileDirectoryAndGlobArray globs and/ or paths to files or
82
89
  * directories to be gathered
83
90
  * @param {import('../../types/dependency-cruiser.js').IStrictCruiseOptions} pOptions options that
84
91
  * influence what needs to be gathered/ scanned
@@ -87,31 +94,26 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
87
94
  * - includeOnly - regexp what to include
88
95
  * @return {string[]} paths to files to be gathered.
89
96
  */
90
- export default function gatherInitialSources(pFileAndDirectoryArray, pOptions) {
97
+ export default function gatherInitialSources(
98
+ pFileDirectoryAndGlobArray,
99
+ pOptions,
100
+ ) {
91
101
  const lOptions = { baseDir: process.cwd(), ...pOptions };
92
102
 
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) => {
103
+ return pFileDirectoryAndGlobArray
104
+ .flatMap((pFileDirectoryOrGlob) => {
105
+ const lScannedGlob = picomatch.scan(pFileDirectoryOrGlob);
106
+ if (lScannedGlob.isGlob) {
107
+ return expandGlob(lOptions.baseDir, lScannedGlob);
108
+ }
109
+ return normalize(pFileDirectoryOrGlob);
110
+ })
111
+ .flatMap((pFileOrDirectory) => {
108
112
  if (statSync(join(lOptions.baseDir, pFileOrDirectory)).isDirectory()) {
109
- return pAll.concat(
110
- gatherScannableFilesFromDirectory(pFileOrDirectory, lOptions)
111
- );
112
- } else {
113
- return pAll.concat(pathToPosix(pFileOrDirectory));
113
+ return gatherScannableFilesFromDirectory(pFileOrDirectory, lOptions);
114
114
  }
115
- }, [])
115
+ // Not a glob anymore, and not a directory => it's a file
116
+ return pathToPosix(pFileOrDirectory);
117
+ })
116
118
  .sort();
117
119
  }
@@ -21,7 +21,7 @@ function resolveModule(
21
21
  pModule,
22
22
  pBaseDirectory,
23
23
  pFileDirectory,
24
- pResolveOptions
24
+ pResolveOptions,
25
25
  ) {
26
26
  let lReturnValue = null;
27
27
 
@@ -34,13 +34,14 @@ function resolveModule(
34
34
  lStrippedModuleName,
35
35
  pBaseDirectory,
36
36
  pFileDirectory,
37
- pResolveOptions
37
+ pResolveOptions,
38
38
  );
39
39
  } else {
40
40
  lReturnValue = resolveAMD(
41
41
  lStrippedModuleName,
42
42
  pBaseDirectory,
43
- pFileDirectory
43
+ pFileDirectory,
44
+ pResolveOptions,
44
45
  );
45
46
  }
46
47
  return lReturnValue;
@@ -89,13 +90,13 @@ function resolveWithRetry(
89
90
  pModule,
90
91
  pBaseDirectory,
91
92
  pFileDirectory,
92
- pResolveOptions
93
+ pResolveOptions,
93
94
  ) {
94
95
  let lReturnValue = resolveModule(
95
96
  pModule,
96
97
  pBaseDirectory,
97
98
  pFileDirectory,
98
- pResolveOptions
99
+ pResolveOptions,
99
100
  );
100
101
  const lStrippedModuleName = stripToModuleName(pModule.module);
101
102
 
@@ -123,17 +124,17 @@ function resolveWithRetry(
123
124
  ) {
124
125
  const lModuleWithoutExtension = lStrippedModuleName.replace(
125
126
  /\.(js|jsx|cjs|mjs)$/g,
126
- ""
127
+ "",
127
128
  );
128
129
  const lExtensionsToTry = getTypeScriptExtensionsToTry(
129
- extname(lStrippedModuleName)
130
+ extname(lStrippedModuleName),
130
131
  );
131
132
 
132
133
  const lReturnValueCandidate = resolveModule(
133
134
  { ...pModule, module: lModuleWithoutExtension },
134
135
  pBaseDirectory,
135
136
  pFileDirectory,
136
- { ...pResolveOptions, extensions: lExtensionsToTry }
137
+ { ...pResolveOptions, extensions: lExtensionsToTry },
137
138
  );
138
139
 
139
140
  if (isTypeScriptIshExtension(lReturnValueCandidate.resolved)) {
@@ -160,13 +161,13 @@ export default function resolve(
160
161
  pDependency,
161
162
  pBaseDirectory,
162
163
  pFileDirectory,
163
- pResolveOptions
164
+ pResolveOptions,
164
165
  ) {
165
166
  let lResolvedDependency = resolveWithRetry(
166
167
  pDependency,
167
168
  pBaseDirectory,
168
169
  pFileDirectory,
169
- pResolveOptions
170
+ pResolveOptions,
170
171
  );
171
172
  const lStrippedModuleName = stripToModuleName(pDependency.module);
172
173
 
@@ -176,7 +177,7 @@ export default function resolve(
176
177
  lStrippedModuleName,
177
178
  lResolvedDependency.resolved,
178
179
  { baseDirectory: pBaseDirectory, fileDirectory: pFileDirectory },
179
- pResolveOptions
180
+ pResolveOptions,
180
181
  ),
181
182
  dependencyTypes: determineDependencyTypes(
182
183
  { ...pDependency, ...lResolvedDependency },
@@ -184,11 +185,11 @@ export default function resolve(
184
185
  getManifest(
185
186
  pFileDirectory,
186
187
  pBaseDirectory,
187
- pResolveOptions.combinedDependencies
188
+ pResolveOptions.combinedDependencies,
188
189
  ),
189
190
  pFileDirectory,
190
191
  pResolveOptions,
191
- pBaseDirectory
192
+ pBaseDirectory,
192
193
  ),
193
194
  };
194
195
 
@@ -210,11 +211,11 @@ export default function resolve(
210
211
  again corresponds with a real file on disk
211
212
  */
212
213
  // eslint-disable-next-line no-control-regex
213
- lResolvedDependency.resolved.replace(/\u0000#/g, "#")
214
- )
215
- )
216
- )
217
- )
214
+ lResolvedDependency.resolved.replace(/\u0000#/g, "#"),
215
+ ),
216
+ ),
217
+ ),
218
+ ),
218
219
  );
219
220
  } catch (pError) {
220
221
  lResolvedDependency.couldNotResolve = true;