dependency-cruiser 16.2.4-beta-2 → 16.2.4

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 (41) hide show
  1. package/package.json +4 -3
  2. package/src/cache/helpers.mjs +1 -1
  3. package/src/cli/init-config/environment-helpers.mjs +9 -10
  4. package/src/cli/init-config/normalize-init-options.mjs +1 -2
  5. package/src/cli/normalize-cli-options.mjs +12 -11
  6. package/src/config-utl/extract-depcruise-config/index.mjs +1 -2
  7. package/src/enrich/derive/reachable.mjs +4 -3
  8. package/src/enrich/summarize/summarize-folders.mjs +2 -3
  9. package/src/enrich/summarize/summarize-modules.mjs +8 -5
  10. package/src/enrich/summarize/summarize-options.mjs +5 -6
  11. package/src/extract/index.mjs +1 -2
  12. package/src/extract/parse/to-javascript-ast.mjs +8 -6
  13. package/src/extract/parse/to-swc-ast.mjs +2 -2
  14. package/src/extract/parse/to-typescript-ast.mjs +2 -2
  15. package/src/extract/resolve/determine-dependency-types.mjs +1 -2
  16. package/src/extract/resolve/external-module-helpers.mjs +12 -13
  17. package/src/extract/resolve/get-manifest.mjs +12 -12
  18. package/src/extract/resolve/merge-manifests.mjs +8 -6
  19. package/src/extract/resolve/resolve-amd.mjs +2 -2
  20. package/src/graph-utl/add-focus.mjs +5 -6
  21. package/src/graph-utl/consolidate-module-dependencies.mjs +16 -5
  22. package/src/graph-utl/rule-set.mjs +12 -11
  23. package/src/main/cruise.mjs +2 -1
  24. package/src/main/helpers.mjs +3 -0
  25. package/src/main/options/assert-validity.mjs +1 -2
  26. package/src/main/options/normalize.mjs +6 -6
  27. package/src/main/report-wrap.mjs +2 -3
  28. package/src/main/rule-set/assert-validity.mjs +3 -1
  29. package/src/main/rule-set/normalize.mjs +10 -11
  30. package/src/meta.cjs +1 -1
  31. package/src/report/anon/anonymize-path-element.mjs +4 -4
  32. package/src/report/anon/index.mjs +1 -2
  33. package/src/report/anon/random-string.mjs +4 -4
  34. package/src/report/dot/index.mjs +19 -24
  35. package/src/report/dot/module-utl.mjs +6 -3
  36. package/src/report/error-html/utl.mjs +3 -2
  37. package/src/report/plugins.mjs +3 -5
  38. package/src/validate/index.mjs +4 -5
  39. package/src/validate/match-module-rule.mjs +11 -8
  40. package/src/validate/matchers.mjs +3 -4
  41. package/src/validate/rule-classifiers.mjs +3 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dependency-cruiser",
3
- "version": "16.2.4-beta-2",
3
+ "version": "16.2.4",
4
4
  "description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
5
5
  "keywords": [
6
6
  "static analysis",
@@ -139,7 +139,7 @@
139
139
  "ajv": "8.12.0",
140
140
  "chalk": "5.3.0",
141
141
  "commander": "12.0.0",
142
- "enhanced-resolve": "5.15.1",
142
+ "enhanced-resolve": "5.16.0",
143
143
  "figures": "6.1.0",
144
144
  "ignore": "5.3.1",
145
145
  "indent-string": "5.0.0",
@@ -147,6 +147,7 @@
147
147
  "is-installed-globally": "1.0.0",
148
148
  "json5": "2.2.3",
149
149
  "lodash": "4.17.21",
150
+ "memoize": "10.0.0",
150
151
  "picomatch": "4.0.1",
151
152
  "prompts": "2.4.2",
152
153
  "rechoir": "^0.8.0",
@@ -155,7 +156,7 @@
155
156
  "semver-try-require": "6.2.3",
156
157
  "teamcity-service-messages": "0.1.14",
157
158
  "tsconfig-paths-webpack-plugin": "4.1.0",
158
- "watskeburt": "4.0.0",
159
+ "watskeburt": "4.0.1",
159
160
  "wrap-ansi": "9.0.0"
160
161
  },
161
162
  "overrides": {
@@ -2,7 +2,7 @@
2
2
  import { createHash } from "node:crypto";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { extname } from "node:path";
5
- import memoize from "lodash/memoize.js";
5
+ import memoize from "memoize";
6
6
  // @ts-expect-error ts(2307) - the ts compiler is not privy to the existence of #imports in package.json
7
7
  import { filenameMatchesPattern } from "#graph-utl/match-facade.mjs";
8
8
 
@@ -1,7 +1,5 @@
1
- // @ts-check
2
1
  import { readFileSync, readdirSync, accessSync, statSync, R_OK } from "node:fs";
3
2
  import { join } from "node:path";
4
- import has from "lodash/has.js";
5
3
  import { DEFAULT_CONFIG_FILE_NAME } from "../defaults.mjs";
6
4
 
7
5
  const LIKELY_SOURCE_FOLDERS = ["src", "lib", "app", "bin", "sources"];
@@ -47,7 +45,8 @@ function babelIsConfiguredInManifest() {
47
45
  let lReturnValue = false;
48
46
 
49
47
  try {
50
- lReturnValue = has(readManifest(), "babel");
48
+ // @ts-expect-error defaultly tsc doesn't know about newfangled stuff like hasOwn
49
+ lReturnValue = Object.hasOwn(readManifest(), "babel");
51
50
  } catch (pError) {
52
51
  // silently ignore - we'll return false anyway then
53
52
  }
@@ -75,7 +74,7 @@ export function isTypeModule() {
75
74
  */
76
75
  function getFolderNames(pFolderName) {
77
76
  return readdirSync(pFolderName, "utf8").filter((pFileName) =>
78
- statSync(join(pFolderName, pFileName)).isDirectory()
77
+ statSync(join(pFolderName, pFileName)).isDirectory(),
79
78
  );
80
79
  }
81
80
 
@@ -88,7 +87,7 @@ function getMatchingFileNames(pPattern, pFolderName = process.cwd()) {
88
87
  return readdirSync(pFolderName, "utf8").filter(
89
88
  (pFileName) =>
90
89
  statSync(join(pFolderName, pFileName)).isFile() &&
91
- pFileName.match(pPattern)
90
+ pFileName.match(pPattern),
92
91
  );
93
92
  }
94
93
 
@@ -102,14 +101,14 @@ export function isLikelyMonoRepo(pFolderNames = getFolderNames(process.cwd())) {
102
101
 
103
102
  export function hasTestsWithinSource(pTestLocations, pSourceLocations) {
104
103
  return pTestLocations.every((pTestLocation) =>
105
- pSourceLocations.includes(pTestLocation)
104
+ pSourceLocations.includes(pTestLocation),
106
105
  );
107
106
  }
108
107
 
109
108
  export function getFolderCandidates(pCandidateFolderArray) {
110
109
  return (pFolderNames = getFolderNames(process.cwd())) => {
111
110
  return pFolderNames.filter((pFolderName) =>
112
- pCandidateFolderArray.includes(pFolderName)
111
+ pCandidateFolderArray.includes(pFolderName),
113
112
  );
114
113
  };
115
114
  }
@@ -134,7 +133,7 @@ function getManifestFilesWithABabelConfig() {
134
133
 
135
134
  export const getBabelConfigCandidates = () =>
136
135
  getManifestFilesWithABabelConfig().concat(
137
- getMatchingFileNames(BABEL_CONFIG_CANDIDATE_PATTERN)
136
+ getMatchingFileNames(BABEL_CONFIG_CANDIDATE_PATTERN),
138
137
  );
139
138
  export const hasBabelConfigCandidates = () =>
140
139
  getBabelConfigCandidates().length > 0;
@@ -154,12 +153,12 @@ export const hasWebpackConfigCandidates = () =>
154
153
  getWebpackConfigCandidates().length > 0;
155
154
 
156
155
  export const getSourceFolderCandidates = getFolderCandidates(
157
- LIKELY_SOURCE_FOLDERS
156
+ LIKELY_SOURCE_FOLDERS,
158
157
  );
159
158
  export const getTestFolderCandidates = getFolderCandidates(LIKELY_TEST_FOLDERS);
160
159
 
161
160
  export const getMonoRepoPackagesCandidates = getFolderCandidates(
162
- LIKELY_PACKAGES_FOLDERS
161
+ LIKELY_PACKAGES_FOLDERS,
163
162
  );
164
163
 
165
164
  /**
@@ -1,4 +1,3 @@
1
- import has from "lodash/has.js";
2
1
  import {
3
2
  getSourceFolderCandidates,
4
3
  getTestFolderCandidates,
@@ -72,7 +71,7 @@ function populate(pInitOptions) {
72
71
  */
73
72
  export default function normalizeInitOptions(pInitOptions) {
74
73
  let lReturnValue = populate(pInitOptions);
75
- if (!has(lReturnValue, "hasTestsOutsideSource")) {
74
+ if (!Object.hasOwn(lReturnValue, "hasTestsOutsideSource")) {
76
75
  lReturnValue.hasTestsOutsideSource =
77
76
  !pInitOptions.isMonoRepo &&
78
77
  !hasTestsWithinSource(
@@ -1,8 +1,6 @@
1
1
  import { accessSync, R_OK } from "node:fs";
2
2
  import { isAbsolute } from "node:path";
3
3
  import set from "lodash/set.js";
4
- import get from "lodash/get.js";
5
- import has from "lodash/has.js";
6
4
  import {
7
5
  RULES_FILE_NAME_SEARCH_ARRAY,
8
6
  DEFAULT_BASELINE_FILE_NAME,
@@ -22,7 +20,7 @@ function getOptionValue(pDefault) {
22
20
  function normalizeConfigFileName(pCliOptions, pConfigWrapperName, pDefault) {
23
21
  let lOptions = structuredClone(pCliOptions);
24
22
 
25
- if (has(lOptions, pConfigWrapperName)) {
23
+ if (Object.hasOwn(lOptions, pConfigWrapperName)) {
26
24
  set(
27
25
  lOptions,
28
26
  `ruleSet.options.${pConfigWrapperName}.fileName`,
@@ -33,8 +31,8 @@ function normalizeConfigFileName(pCliOptions, pConfigWrapperName, pDefault) {
33
31
  }
34
32
 
35
33
  if (
36
- get(lOptions, `ruleSet.options.${pConfigWrapperName}`, null) &&
37
- !get(lOptions, `ruleSet.options.${pConfigWrapperName}.fileName`, null)
34
+ (lOptions?.ruleSet?.options?.[pConfigWrapperName] ?? null) &&
35
+ !(lOptions?.ruleSet?.options?.[pConfigWrapperName]?.fileName ?? null)
38
36
  ) {
39
37
  set(lOptions, `ruleSet.options.${pConfigWrapperName}.fileName`, pDefault);
40
38
  }
@@ -108,7 +106,10 @@ function validateAndGetKnownViolationsFileName(pKnownViolations) {
108
106
  }
109
107
 
110
108
  function normalizeKnownViolationsOption(pCliOptions) {
111
- if (!has(pCliOptions, "ignoreKnown") || pCliOptions.ignoreKnown === false) {
109
+ if (
110
+ !Object.hasOwn(pCliOptions, "ignoreKnown") ||
111
+ pCliOptions.ignoreKnown === false
112
+ ) {
112
113
  return {};
113
114
  }
114
115
  return {
@@ -135,7 +136,7 @@ async function normalizeValidationOption(pCliOptions) {
135
136
  }
136
137
 
137
138
  function normalizeProgress(pCliOptions) {
138
- if (!has(pCliOptions, "progress")) {
139
+ if (!Object.hasOwn(pCliOptions, "progress")) {
139
140
  return {};
140
141
  }
141
142
 
@@ -147,7 +148,7 @@ function normalizeProgress(pCliOptions) {
147
148
  }
148
149
 
149
150
  function normalizeCacheStrategy(pCliOptions) {
150
- if (!has(pCliOptions, "cacheStrategy")) {
151
+ if (!Object.hasOwn(pCliOptions, "cacheStrategy")) {
151
152
  return {};
152
153
  }
153
154
  const lStrategy =
@@ -169,7 +170,7 @@ function normalizeCacheStrategy(pCliOptions) {
169
170
  }
170
171
 
171
172
  function normalizeCache(pCliOptions) {
172
- if (!has(pCliOptions, "cache")) {
173
+ if (!Object.hasOwn(pCliOptions, "cache")) {
173
174
  return {};
174
175
  }
175
176
 
@@ -203,13 +204,13 @@ export default async function normalizeOptions(pOptionsAsPassedFromCommander) {
203
204
  ...pOptionsAsPassedFromCommander,
204
205
  };
205
206
 
206
- if (has(lOptions, "moduleSystems")) {
207
+ if (Object.hasOwn(lOptions, "moduleSystems")) {
207
208
  lOptions.moduleSystems = lOptions.moduleSystems
208
209
  .split(",")
209
210
  .map((pString) => pString.trim());
210
211
  }
211
212
 
212
- if (has(lOptions, "config")) {
213
+ if (Object.hasOwn(lOptions, "config")) {
213
214
  lOptions.validate = lOptions.config;
214
215
  }
215
216
 
@@ -1,5 +1,4 @@
1
1
  import { dirname } from "node:path";
2
- import has from "lodash/has.js";
3
2
  import readConfig from "./read-config.mjs";
4
3
  import mergeConfigs from "./merge-configs.mjs";
5
4
  import normalizeResolveOptions from "#main/resolve-options/normalize.mjs";
@@ -80,7 +79,7 @@ export default async function extractDepcruiseConfig(
80
79
 
81
80
  let lReturnValue = await readConfig(lResolvedFileName);
82
81
 
83
- if (has(lReturnValue, "extends")) {
82
+ if (lReturnValue?.extends) {
84
83
  lReturnValue = await processExtends(
85
84
  lReturnValue,
86
85
  pAlreadyVisited,
@@ -1,14 +1,15 @@
1
1
  /* eslint-disable security/detect-object-injection, no-inline-comments */
2
- import has from "lodash/has.js";
3
2
  import matchers from "#validate/matchers.mjs";
4
3
  import IndexedModuleGraph from "#graph-utl/indexed-module-graph.mjs";
5
4
  import { extractGroups } from "#utl/regex-util.mjs";
6
5
 
7
6
  function getReachableRules(pRuleSet) {
8
7
  return (pRuleSet?.forbidden ?? [])
9
- .filter((pRule) => has(pRule.to, "reachable"))
8
+ .filter((pRule) => Object.hasOwn(pRule?.to ?? {}, "reachable"))
10
9
  .concat(
11
- (pRuleSet?.allowed ?? []).filter((pRule) => has(pRule.to, "reachable")),
10
+ (pRuleSet?.allowed ?? []).filter((pRule) =>
11
+ Object.hasOwn(pRule?.to ?? {}, "reachable"),
12
+ ),
12
13
  );
13
14
  }
14
15
 
@@ -1,12 +1,11 @@
1
- import has from "lodash/has.js";
2
1
  import { findRuleByName } from "#graph-utl/rule-set.mjs";
3
2
 
4
3
  function classifyViolation(pRule, pRuleSet) {
5
4
  const lRule = findRuleByName(pRuleSet, pRule.name);
6
- if (has(lRule, "to.moreUnstable")) {
5
+ if (Object.hasOwn(lRule?.to ?? {}, "moreUnstable")) {
7
6
  return "instability";
8
7
  }
9
- if (has(lRule, "to.circular")) {
8
+ if (Object.hasOwn(lRule?.to ?? {}, "circular")) {
10
9
  return "cycle";
11
10
  }
12
11
  return "folder";
@@ -1,5 +1,4 @@
1
1
  import flattenDeep from "lodash/flattenDeep.js";
2
- import has from "lodash/has.js";
3
2
  import uniqWith from "lodash/uniqWith.js";
4
3
  import isSameViolation from "./is-same-violation.mjs";
5
4
  import { findRuleByName } from "#graph-utl/rule-set.mjs";
@@ -14,6 +13,7 @@ function cutNonTransgressions(pModule) {
14
13
  };
15
14
  }
16
15
 
16
+ // eslint-disable-next-line complexity
17
17
  function toDependencyViolationSummary(pRule, pModule, pDependency, pRuleSet) {
18
18
  let lReturnValue = {
19
19
  type: "dependency",
@@ -23,7 +23,7 @@ function toDependencyViolationSummary(pRule, pModule, pDependency, pRuleSet) {
23
23
  };
24
24
 
25
25
  if (
26
- has(pDependency, "cycle") &&
26
+ Object.hasOwn(pDependency, "cycle") &&
27
27
  findRuleByName(pRuleSet, pRule.name)?.to?.circular
28
28
  ) {
29
29
  lReturnValue = {
@@ -34,9 +34,12 @@ function toDependencyViolationSummary(pRule, pModule, pDependency, pRuleSet) {
34
34
  }
35
35
 
36
36
  if (
37
- has(pModule, "instability") &&
38
- has(pDependency, "instability") &&
39
- has(findRuleByName(pRuleSet, pRule.name), "to.moreUnstable")
37
+ Object.hasOwn(pModule, "instability") &&
38
+ Object.hasOwn(pDependency, "instability") &&
39
+ Object.hasOwn(
40
+ findRuleByName(pRuleSet, pRule.name)?.to ?? {},
41
+ "moreUnstable",
42
+ )
40
43
  ) {
41
44
  lReturnValue = {
42
45
  ...lReturnValue,
@@ -1,5 +1,3 @@
1
- import has from "lodash/has.js";
2
-
3
1
  const SHAREABLE_OPTIONS = [
4
2
  "babelConfig",
5
3
  "baseDir",
@@ -35,22 +33,23 @@ const SHAREABLE_OPTIONS = [
35
33
  function makeOptionsPresentable(pOptions) {
36
34
  return SHAREABLE_OPTIONS.filter(
37
35
  (pShareableOptionKey) =>
38
- has(pOptions, pShareableOptionKey) && pOptions[pShareableOptionKey] !== 0
36
+ Object.hasOwn(pOptions, pShareableOptionKey) &&
37
+ pOptions?.[pShareableOptionKey] !== 0,
39
38
  )
40
39
  .filter(
41
40
  (pShareableOptionKey) =>
42
41
  pShareableOptionKey !== "doNotFollow" ||
43
- Object.keys(pOptions.doNotFollow).length > 0
42
+ Object.keys(pOptions.doNotFollow).length > 0,
44
43
  )
45
44
  .filter(
46
45
  (pShareableOptionKey) =>
47
46
  pShareableOptionKey !== "exclude" ||
48
- Object.keys(pOptions.exclude).length > 0
47
+ Object.keys(pOptions.exclude).length > 0,
49
48
  )
50
49
  .filter(
51
50
  (pShareableOptionKey) =>
52
51
  pShareableOptionKey !== "knownViolations" ||
53
- pOptions.knownViolations.length > 0
52
+ pOptions.knownViolations.length > 0,
54
53
  )
55
54
  .reduce((pAll, pShareableOptionKey) => {
56
55
  pAll[pShareableOptionKey] = pOptions[pShareableOptionKey];
@@ -1,4 +1,3 @@
1
- import has from "lodash/has.js";
2
1
  import getDependencies from "./get-dependencies.mjs";
3
2
  import gatherInitialSources from "./gather-initial-sources.mjs";
4
3
  import clearCaches from "./clear-caches.mjs";
@@ -123,7 +122,7 @@ function filterExcludedDynamicDependencies(pModule, pExclude) {
123
122
  ...pModule,
124
123
  dependencies: pModule.dependencies.filter(
125
124
  ({ dynamic }) =>
126
- !has(pExclude, "dynamic") || pExclude.dynamic !== dynamic,
125
+ !Object.hasOwn(pExclude, "dynamic") || pExclude.dynamic !== dynamic,
127
126
  ),
128
127
  };
129
128
  }
@@ -2,7 +2,7 @@ import { readFileSync } from "node:fs";
2
2
  import { Parser as acornParser, parse as acornParse } from "acorn";
3
3
  import { parse as acornLooseParse } from "acorn-loose";
4
4
  import acornJsx from "acorn-jsx";
5
- import memoize from "lodash/memoize.js";
5
+ import memoize, { memoizeClear } from "memoize";
6
6
  import transpile from "../transpile/index.mjs";
7
7
  import getExtension from "#utl/get-extension.mjs";
8
8
 
@@ -82,13 +82,15 @@ function getAST(pFileName, pTranspileOptions) {
82
82
  * @param {any} pTranspileOptions - options for the transpiler(s) - typically a tsconfig or a babel config
83
83
  * @return {acorn.Node} - a (javascript) AST
84
84
  */
85
- export const getASTCached = memoize(
86
- getAST,
87
- (pFileName, pTranspileOptions) => `${pFileName}|${pTranspileOptions}`,
88
- );
85
+ // taking the transpile options into account of the memoize cache key seems like
86
+ // a good idea. However, previously we use `${pTranspileOptions}` which always
87
+ // serializes to [object Object], which doesn't help. So for now we're not
88
+ // taking the transpile options into account. If we ever need to, it'll be
89
+ // a JSON.stringify away (which _will_ be significantly slower)
90
+ export const getASTCached = memoize(getAST);
89
91
 
90
92
  export function clearCache() {
91
- getASTCached.cache.clear();
93
+ memoizeClear(getASTCached);
92
94
  }
93
95
 
94
96
  export default {
@@ -1,5 +1,5 @@
1
1
  import tryImport from "semver-try-require";
2
- import memoize from "lodash/memoize.js";
2
+ import memoize, { memoizeClear } from "memoize";
3
3
  import meta from "#meta.cjs";
4
4
 
5
5
  /** @type {import('@swc/core')} */
@@ -29,7 +29,7 @@ function getAST(pFileName) {
29
29
  export const getASTCached = memoize(getAST);
30
30
 
31
31
  export function clearCache() {
32
- getASTCached.cache.clear();
32
+ memoizeClear(getASTCached);
33
33
  }
34
34
 
35
35
  export default {
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import tryImport from "semver-try-require";
3
- import memoize from "lodash/memoize.js";
3
+ import memoize, { memoizeClear } from "memoize";
4
4
  import transpile from "../transpile/index.mjs";
5
5
  import meta from "#meta.cjs";
6
6
  import getExtension from "#utl/get-extension.mjs";
@@ -56,7 +56,7 @@ function getAST(pFileName, pTranspileOptions) {
56
56
  export const getASTCached = memoize(getAST);
57
57
 
58
58
  export function clearCache() {
59
- getASTCached.cache.clear();
59
+ memoizeClear(getASTCached);
60
60
  }
61
61
 
62
62
  export default {
@@ -1,5 +1,4 @@
1
1
  import { join } from "node:path/posix";
2
- import has from "lodash/has.js";
3
2
  import {
4
3
  isRelativeModuleName,
5
4
  isExternalModule,
@@ -17,7 +16,7 @@ function dependencyKeyHasModuleName(
17
16
  ) {
18
17
  return (pKey) =>
19
18
  pKey.includes("ependencies") &&
20
- has(pPackageDependencies[pKey], join(pPrefix, pModuleName));
19
+ Object.hasOwn(pPackageDependencies[pKey], join(pPrefix, pModuleName));
21
20
  }
22
21
 
23
22
  const NPM2DEP_TYPE = new Map([
@@ -1,7 +1,6 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import memoize from "lodash/memoize.js";
4
- import has from "lodash/has.js";
3
+ import memoize, { memoizeClear } from "memoize";
5
4
  import { resolve } from "./resolve.mjs";
6
5
  import { isScoped, isRelativeModuleName } from "./module-classifiers.mjs";
7
6
 
@@ -97,7 +96,7 @@ function bareGetPackageJson(pModuleName, pFileDirectory, pResolveOptions) {
97
96
  // we need a separate caching context so as not to **** up the regular
98
97
  // cruise, which might actually want to utilize the exportsFields
99
98
  // and an array of extensions
100
- "manifest-resolution"
99
+ "manifest-resolution",
101
100
  );
102
101
  lReturnValue = JSON.parse(readFileSync(lPackageJsonFilename, "utf8"));
103
102
  } catch (pError) {
@@ -106,10 +105,9 @@ function bareGetPackageJson(pModuleName, pFileDirectory, pResolveOptions) {
106
105
  return lReturnValue;
107
106
  }
108
107
 
109
- export const getPackageJson = memoize(
110
- bareGetPackageJson,
111
- (pModuleName, pBaseDirectory) => `${pBaseDirectory}|${pModuleName}`
112
- );
108
+ export const getPackageJson = memoize(bareGetPackageJson, {
109
+ cacheKey: (pArguments) => `${pArguments[0]}|${pArguments[1]}`,
110
+ });
113
111
 
114
112
  /**
115
113
  * Tells whether the pModule as resolved to pBaseDirectory is deprecated
@@ -122,17 +120,18 @@ export const getPackageJson = memoize(
122
120
  export function dependencyIsDeprecated(
123
121
  pModuleName,
124
122
  pFileDirectory,
125
- pResolveOptions
123
+ pResolveOptions,
126
124
  ) {
127
125
  let lReturnValue = false;
128
126
  let lPackageJson = getPackageJson(
129
127
  pModuleName,
130
128
  pFileDirectory,
131
- pResolveOptions
129
+ pResolveOptions,
132
130
  );
133
131
 
134
132
  if (Boolean(lPackageJson)) {
135
- lReturnValue = has(lPackageJson, "deprecated") && lPackageJson.deprecated;
133
+ lReturnValue =
134
+ Object.hasOwn(lPackageJson, "deprecated") && lPackageJson.deprecated;
136
135
  }
137
136
  return lReturnValue;
138
137
  }
@@ -151,12 +150,12 @@ export function getLicense(pModuleName, pFileDirectory, pResolveOptions) {
151
150
  let lPackageJson = getPackageJson(
152
151
  pModuleName,
153
152
  pFileDirectory,
154
- pResolveOptions
153
+ pResolveOptions,
155
154
  );
156
155
 
157
156
  if (
158
157
  Boolean(lPackageJson) &&
159
- has(lPackageJson, "license") &&
158
+ Object.hasOwn(lPackageJson, "license") &&
160
159
  typeof lPackageJson.license === "string"
161
160
  ) {
162
161
  lReturnValue = lPackageJson.license;
@@ -165,5 +164,5 @@ export function getLicense(pModuleName, pFileDirectory, pResolveOptions) {
165
164
  }
166
165
 
167
166
  export function clearCache() {
168
- getPackageJson.cache.clear();
167
+ memoizeClear(getPackageJson);
169
168
  }
@@ -1,6 +1,6 @@
1
1
  import { join, dirname, sep } from "node:path";
2
2
  import { readFileSync } from "node:fs";
3
- import memoize from "lodash/memoize.js";
3
+ import memoize, { memoizeClear } from "memoize";
4
4
  import mergePackages from "./merge-manifests.mjs";
5
5
 
6
6
  /**
@@ -23,7 +23,7 @@ const getSingleManifest = memoize((pFileDirectory) => {
23
23
  // find the closest package.json from pFileDirectory
24
24
  const lPackageContent = readFileSync(
25
25
  join(pFileDirectory, "package.json"),
26
- "utf8"
26
+ "utf8",
27
27
  );
28
28
 
29
29
  try {
@@ -48,7 +48,7 @@ function maybeReadPackage(pFileDirectory) {
48
48
  try {
49
49
  const lPackageContent = readFileSync(
50
50
  join(pFileDirectory, "package.json"),
51
- "utf8"
51
+ "utf8",
52
52
  );
53
53
 
54
54
  try {
@@ -81,9 +81,9 @@ function getIntermediatePaths(pFileDirectory, pBaseDirectory) {
81
81
  }
82
82
 
83
83
  // despite the two parameters there's no resolver function provided
84
- // to the _.memoize. This is deliberate - the pBaseDirectory will typically
85
- // be the same for each call in a typical cruise, so the lodash'
86
- // default memoize resolver (the first param) will suffice.
84
+ // to memoize. This is deliberate - the pBaseDirectory will typically
85
+ // be the same for each call in a typical cruise, so the default
86
+ // memoize resolver (the first param) will suffice.
87
87
  const getCombinedManifests = memoize((pFileDirectory, pBaseDirectory) => {
88
88
  // The way this is called, this shouldn't happen. If it is, there's
89
89
  // something gone terribly awry
@@ -94,16 +94,16 @@ const getCombinedManifests = memoize((pFileDirectory, pBaseDirectory) => {
94
94
  throw new Error(
95
95
  `Unexpected Error: Unusual baseDir passed to package reading function: '${pBaseDirectory}'\n` +
96
96
  `Please file a bug: https://github.com/sverweij/dependency-cruiser/issues/new?template=bug-report.md` +
97
- `&title=Unexpected Error: Unusual baseDir passed to package reading function: '${pBaseDirectory}'`
97
+ `&title=Unexpected Error: Unusual baseDir passed to package reading function: '${pBaseDirectory}'`,
98
98
  );
99
99
  }
100
100
 
101
101
  const lReturnValue = getIntermediatePaths(
102
102
  pFileDirectory,
103
- pBaseDirectory
103
+ pBaseDirectory,
104
104
  ).reduce(
105
105
  (pAll, pCurrent) => mergePackages(pAll, maybeReadPackage(pCurrent)),
106
- {}
106
+ {},
107
107
  );
108
108
 
109
109
  return Object.keys(lReturnValue).length > 0 ? lReturnValue : null;
@@ -128,7 +128,7 @@ const getCombinedManifests = memoize((pFileDirectory, pBaseDirectory) => {
128
128
  export function getManifest(
129
129
  pFileDirectory,
130
130
  pBaseDirectory,
131
- pCombinedDependencies = false
131
+ pCombinedDependencies = false,
132
132
  ) {
133
133
  if (pCombinedDependencies) {
134
134
  return getCombinedManifests(pFileDirectory, pBaseDirectory);
@@ -138,6 +138,6 @@ export function getManifest(
138
138
  }
139
139
 
140
140
  export function clearCache() {
141
- getCombinedManifests.cache.clear();
142
- getSingleManifest.cache.clear();
141
+ memoizeClear(getCombinedManifests);
142
+ memoizeClear(getSingleManifest);
143
143
  }
@@ -1,6 +1,4 @@
1
1
  /* eslint-disable security/detect-object-injection */
2
- import uniq from "lodash/uniq.js";
3
-
4
2
  function normalizeManifestKeys(pManifest) {
5
3
  let lReturnValue = pManifest;
6
4
 
@@ -21,7 +19,9 @@ function mergeDependencyKey(pClosestDependencyKey, pFurtherDependencyKey) {
21
19
  }
22
20
 
23
21
  function mergeDependencyArray(pClosestDependencyKey, pFurtherDependencyKey) {
24
- return uniq(pClosestDependencyKey.concat(pFurtherDependencyKey));
22
+ return Array.from(
23
+ new Set(pClosestDependencyKey.concat(pFurtherDependencyKey)),
24
+ );
25
25
  }
26
26
 
27
27
  function isInterestingKey(pKey) {
@@ -35,9 +35,11 @@ function getDependencyKeys(pPackage) {
35
35
  }
36
36
 
37
37
  function getJointUniqueDependencyKeys(pClosestPackage, pFurtherPackage) {
38
- return uniq(
39
- getDependencyKeys(pClosestPackage).concat(
40
- getDependencyKeys(pFurtherPackage),
38
+ return Array.from(
39
+ new Set(
40
+ getDependencyKeys(pClosestPackage).concat(
41
+ getDependencyKeys(pFurtherPackage),
42
+ ),
41
43
  ),
42
44
  );
43
45
  }
@@ -1,6 +1,6 @@
1
1
  import { accessSync, R_OK } from "node:fs";
2
2
  import { relative, join } from "node:path";
3
- import memoize from "lodash/memoize.js";
3
+ import memoize, { memoizeClear } from "memoize";
4
4
  import { isBuiltin } from "./is-built-in.mjs";
5
5
  import pathToPosix from "#utl/path-to-posix.mjs";
6
6
 
@@ -63,5 +63,5 @@ export function resolveAMD(
63
63
  }
64
64
 
65
65
  export function clearCache() {
66
- fileExists.cache.clear();
66
+ memoizeClear(fileExists);
67
67
  }