From 03bdda233cd0cf44d8ad55775aaa651b68844896 Mon Sep 17 00:00:00 2001 From: Sander Verweij Date: Sat, 9 Dec 2023 11:43:44 +0100 Subject: [PATCH] fix(resolve)!: makes alias type derivation more correct and precise BREAKING (#867) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description - takes 'workspaces' field into account when merging package manifests - same for the 'imports' field - when determining what kind of an alias a thing is use the _parsed_ tsconfig to determine it - adds `alias-tsconfig-base-url` and `alias-tsconfig-paths` dependency types to distinguish between the two types of aliases one can use within tsconfigs. B.t.w. for both dependency-cruiser will keep emitting the `alias` and `alias-tsconfig` dependency types as well - both for convenience and backwards compatibility. This PR is theoretically 🚨 BREAKING as rules previously defined on aliases, that didn't fire now _will_ because they're now detected correctly. ## Motivation and Context Now we're doing explicit things with `workspaces` and `imports` fields we need to have them in merged package manifests as well, so in monorepos we still take them into account. The rewrite of the tsconfig alias detection logic is necessary to ensure we detect tsconfig aliases correctly and more precisely. Also see #863. ## How Has This Been Tested? - [x] green ci - [x] additional unit tests - [x] additional integration test(s) ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] Documentation only change - [ ] Refactor (non-breaking change which fixes an issue without changing functionality) - [x] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would cause existing functionality to change) --- doc/rules-reference.md | 44 ++-- src/cli/index.mjs | 2 +- src/extract/get-dependencies.mjs | 11 +- .../resolve/determine-dependency-types.mjs | 3 + src/extract/resolve/index.mjs | 6 +- src/extract/resolve/merge-manifests.mjs | 14 +- src/extract/resolve/module-classifiers.mjs | 128 +++++++--- src/schema/configuration.schema.json | 2 + src/schema/configuration.schema.mjs | 2 +- src/schema/cruise-result.schema.json | 2 + src/schema/cruise-result.schema.mjs | 2 +- src/utl/get-extension.mjs | 2 +- src/validate/matchers.mjs | 5 + .../typescript-path-resolution.json | 14 +- .../.dependency-cruiser.js | 16 ++ .../apps/admin/direct-relative-import.ts | 3 + .../apps/admin/from-subpath-import.ts | 3 + .../apps/admin/from-tsconfig-base-url.ts | 3 + .../apps/admin/from-tsconfig-path-star.ts | 3 + .../apps/admin/from-tsconfig-path.ts | 3 + .../apps/admin/from-workspace.ts | 3 + .../expected.json | 222 ++++++++++++++++ .../libs/aap/index.js | 1 + .../libs/aap/package.json | 8 + .../libs/mies/index.js | 1 + .../libs/mies/package.json | 13 + .../libs/noot/index.js | 1 + .../libs/noot/package.json | 9 + .../libs/wim/index.js | 1 + .../libs/wim/package.json | 9 + .../libs/zus/index.js | 1 + .../libs/zus/package.json | 9 + .../node_modules/.package-lock.json | 49 ++++ .../node_modules/aap | 1 + .../node_modules/mies | 1 + .../node_modules/noot | 1 + .../node_modules/wim | 1 + .../node_modules/zus | 1 + .../workspaces-mono-repo-aliases/package.json | 17 ++ .../tsconfig.json | 13 + test/cli/index.spec.mjs | 23 +- .../ts-config-with-path/tsconfig.json | 2 +- .../determine-dependency-types.spec.mjs | 45 ++-- test/extract/resolve/index.tsconfig.spec.mjs | 236 ++++++++++++------ ...odule-classifiers.get-alias-types.spec.mjs | 85 ++++++- tools/schema/dependency-type.mjs | 2 + types/shared-types.d.mts | 2 + 47 files changed, 853 insertions(+), 172 deletions(-) create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/.dependency-cruiser.js create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/direct-relative-import.ts create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-subpath-import.ts create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-base-url.ts create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-path-star.ts create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-path.ts create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-workspace.ts create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/expected.json create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/aap/index.js create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/aap/package.json create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/mies/index.js create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/mies/package.json create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/noot/index.js create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/noot/package.json create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/wim/index.js create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/wim/package.json create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/zus/index.js create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/zus/package.json create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/.package-lock.json create mode 120000 test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/aap create mode 120000 test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/mies create mode 120000 test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/noot create mode 120000 test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/wim create mode 120000 test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/zus create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/package.json create mode 100644 test/cli/__fixtures__/workspaces-mono-repo-aliases/tsconfig.json diff --git a/doc/rules-reference.md b/doc/rules-reference.md index 39a26dec4..c1bc35900 100644 --- a/doc/rules-reference.md +++ b/doc/rules-reference.md @@ -918,27 +918,29 @@ will ignore them in the evaluation of that rule. This is a list of dependency types dependency-cruiser currently detects. -| dependency type | meaning | example | -| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -| local | a module in your own ('local') package | "./klont" | -| localmodule | a module in your own ('local') package, but which was in the `resolve.modules` attribute of the webpack config you passed | "shared/stuff.ts" | -| npm | it's a module in package.json's `dependencies` | "lodash" | -| npm-dev | it's a module in package.json's `devDependencies` | "chai" | -| npm-optional | it's a module in package.json's `optionalDependencies` | "livescript" | -| npm-peer | it's a module in package.json's `peerDependencies` - note: deprecated in npm 3 | "thing-i-am-a-plugin-for" | -| npm-bundled | it's a module that occurs in package.json's `bundle(d)Dependencies` array | "iwillgetbundled" | -| npm-no-pkg | it's an npm module - but it's nowhere in your package.json | "forgetmenot" | -| npm-unknown | it's an npm module - but there is no (parseable/ valid) package.json in your package | | -| deprecated | it's an npm module, but the version you're using or the module itself is officially deprecated | "some-deprecated-package" | -| core | it's a core module | "fs" | -| aliased | the module was imported via an alias - always occurs alongside one of 'aliased-\*' dependency types below _and_ alongside the dependency type of the dependency it's aliased to (so: local, npm, core ,...) | "~/hello.ts" | -| aliased-subpath-import | the module was imported via a [subpath import](https://nodejs.org/api/packages.html#subpath-imports) | "#thing/hello.mjs" | -| aliased-tsconfig | the module was imported via a typescript [compilerOptions.paths setting in tsconfig](https://www.typescriptlang.org/tsconfig#paths) | "@thing/hello" | -| aliased-webpack | the module was imported via a [webpack resolve alias](https://webpack.js.org/configuration/resolve/#resolvealias) | "Utilities" | -| aliased-workspace | the module was imported via a [workspace](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#workspaces) | "local-workspace-package" | -| unknown | it's unknown what kind of dependency type this is - probably because the module could not be resolved in the first place | "loodash" | -| undetermined | the dependency fell through all detection holes. This could happen with amd dependencies - which have a whole Jurassic park of ways to define where to resolve modules to | "veloci!./raptor" | -| type-only | the module was imported as 'type only' (e.g. `import type { IThing } from "./things";`) - only available for TypeScript sources, and only when tsPreCompilationDeps !== false | | +| dependency type | meaning | example | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------- | +| local | a module in your own ('local') package | "./klont" | +| localmodule | a module in your own ('local') package, but which was in the `resolve.modules` attribute of the webpack config you passed | "shared/stuff.ts" | +| npm | it's a module in package.json's `dependencies` | "lodash" | +| npm-dev | it's a module in package.json's `devDependencies` | "chai" | +| npm-optional | it's a module in package.json's `optionalDependencies` | "livescript" | +| npm-peer | it's a module in package.json's `peerDependencies` - note: deprecated in npm 3, but later on revived. | "thing-i-am-a-plugin-for" | +| npm-bundled | it's a module that occurs in package.json's `bundle(d)Dependencies` array | "iwillgetbundled" | +| npm-no-pkg | it's an npm module - but it's nowhere in your package.json | "forgetmenot" | +| npm-unknown | it's an npm module - but there is no (parseable/ valid) package.json in your package | | +| deprecated | it's an npm module, but the version you're using or the module itself is officially deprecated | "some-deprecated-package" | +| core | it's a (nodejs) core module. B.t.w. you can [influence](./options-reference.md#builtinmodules-influencing-what-to-consider-built-in--core-modules) what to consider a core module if | "fs", "node:test" | +| aliased | the module was imported via an alias - always occurs alongside one of 'aliased-\*' dependency types below _and_ alongside the dependency type of the dependency it's aliased to (so: local, npm, core ,...) | "~/hello.ts" | +| aliased-subpath-import | the module was imported via a [subpath import](https://nodejs.org/api/packages.html#subpath-imports) | "#thing/hello.mjs" | +| aliased-tsconfig | the module was imported via a typescript compilerOptions.paths or compilerOptions.baseUrl setting in tsconfig. Always occurs alongside one of the 'aliased-tsconfig-\*' types below | "@thing/hello" | +| aliased-tsconfig-base-url | the module was imported via a typescript [compilerOptions.baseUrl setting in tsconfig](https://www.typescriptlang.org/tsconfig#baseUrl) | "libs/utensils/src/hello.js" | +| aliased-tsconfig-paths | the module was imported via a typescript [compilerOptions.paths setting in tsconfig](https://www.typescriptlang.org/tsconfig#paths) | "@thing/hello" | +| aliased-webpack | the module was imported via a [webpack resolve alias](https://webpack.js.org/configuration/resolve/#resolvealias) | "Utilities" | +| aliased-workspace | the module was imported via a [workspace](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#workspaces) | "local-workspace-package" | +| unknown | it's unknown what kind of dependency type this is - probably because the module could not be resolved in the first place | "loodash" | +| undetermined | the dependency fell through all detection holes. This could happen with amd dependencies - which have a whole Jurassic park of ways to define where to resolve modules to | "veloci!./raptor" | +| type-only | the module was imported as 'type only' (e.g. `import type { IThing } from "./things";`) - only available for TypeScript sources, only for tsPreCompilationDeps !== false. Will appear alongside other types. | | ### `dynamic` diff --git a/src/cli/index.mjs b/src/cli/index.mjs index 0efa3da6a..a8dd58bf8 100644 --- a/src/cli/index.mjs +++ b/src/cli/index.mjs @@ -137,7 +137,7 @@ async function runCruise(pFileDirectoryArray, pCruiseOptions) { /** * * @param {string[]} pFileDirectoryArray - * @param {import("../../types/options").ICruiseOptions} lCruiseOptions + * @param {import("../../types/options.mjs").ICruiseOptions} lCruiseOptions * @returns {number} */ export default async function executeCli(pFileDirectoryArray, pCruiseOptions) { diff --git a/src/extract/get-dependencies.mjs b/src/extract/get-dependencies.mjs index 03ab8455b..b9312501d 100644 --- a/src/extract/get-dependencies.mjs +++ b/src/extract/get-dependencies.mjs @@ -160,6 +160,7 @@ function addResolutionAttributes( { baseDir, doNotFollow }, pFileName, pResolveOptions, + pTranspileOptions, ) { return function addAttributes(pDependency) { const lResolved = resolve( @@ -167,6 +168,7 @@ function addResolutionAttributes( baseDir, join(baseDir, dirname(pFileName)), pResolveOptions, + pTranspileOptions, ); const lMatchesDoNotFollow = matchesDoNotFollow(lResolved, doNotFollow); @@ -231,7 +233,14 @@ export default function getDependencies( getDependencyUniqueKey, ) .sort(compareDeps) - .map(addResolutionAttributes(pCruiseOptions, pFileName, pResolveOptions)) + .map( + addResolutionAttributes( + pCruiseOptions, + pFileName, + pResolveOptions, + pTranspileOptions, + ), + ) .filter( ({ resolved }) => (!pCruiseOptions?.exclude?.path || diff --git a/src/extract/resolve/determine-dependency-types.mjs b/src/extract/resolve/determine-dependency-types.mjs index 46bfe0163..3dd05a0e9 100644 --- a/src/extract/resolve/determine-dependency-types.mjs +++ b/src/extract/resolve/determine-dependency-types.mjs @@ -171,6 +171,7 @@ function determineExternalModuleDependencyTypes( * @param {string} pFileDirectory the directory relative to which to resolve (only used for npm deps here) * @param {import("../../../types/resolve-options.mjs").IResolveOptions} pResolveOptions an enhanced resolve 'resolve' key * @param {string} pBaseDirectory the base directory dependency cruise is run on + * @param {import("../../../types/dependency-cruiser.mjs").ITranspileOptions} pTranspileOptions * * @return {import("../../../types/shared-types.js").DependencyType[]} an array of dependency types for the dependency */ @@ -182,6 +183,7 @@ export default function determineDependencyTypes( pFileDirectory, pResolveOptions, pBaseDirectory, + pTranspileOptions, ) { /** @type {import("../../../types/shared-types.js").DependencyType[]}*/ let lReturnValue = []; @@ -196,6 +198,7 @@ export default function determineDependencyTypes( pDependency.resolved, lResolveOptions, pManifest, + pTranspileOptions, ); if (lAliases.length > 0) { lReturnValue = lAliases; diff --git a/src/extract/resolve/index.mjs b/src/extract/resolve/index.mjs index 355fa68a6..6e0e83901 100644 --- a/src/extract/resolve/index.mjs +++ b/src/extract/resolve/index.mjs @@ -160,15 +160,18 @@ function resolveWithRetry( * @param {string} pFileDirectory the directory of the file the dependency was * detected in * @param {import("../../../types/resolve-options.mjs").IResolveOptions} pResolveOptions + * @param {any} pTranspileOptions * @return {Partial } * + * */ -// eslint-disable-next-line max-lines-per-function +// eslint-disable-next-line max-lines-per-function, max-params export default function resolve( pDependency, pBaseDirectory, pFileDirectory, pResolveOptions, + pTranspileOptions, ) { let lResolvedDependency = resolveWithRetry( pDependency, @@ -197,6 +200,7 @@ export default function resolve( pFileDirectory, pResolveOptions, pBaseDirectory, + pTranspileOptions, ), }; diff --git a/src/extract/resolve/merge-manifests.mjs b/src/extract/resolve/merge-manifests.mjs index 5b5e4db53..799e182cf 100644 --- a/src/extract/resolve/merge-manifests.mjs +++ b/src/extract/resolve/merge-manifests.mjs @@ -24,12 +24,14 @@ function mergeDependencyArray(pClosestDependencyKey, pFurtherDependencyKey) { return uniq(pClosestDependencyKey.concat(pFurtherDependencyKey)); } -function isDependencyKey(pKey) { - return pKey.endsWith("ependencies"); +function isInterestingKey(pKey) { + return ( + pKey.endsWith("ependencies") || pKey === "workspaces" || pKey === "imports" + ); } function getDependencyKeys(pPackage) { - return Object.keys(pPackage).filter(isDependencyKey); + return Object.keys(pPackage).filter(isInterestingKey); } function getJointUniqueDependencyKeys(pClosestPackage, pFurtherPackage) { @@ -40,6 +42,10 @@ function getJointUniqueDependencyKeys(pClosestPackage, pFurtherPackage) { ); } +function isAnArrayKey(pKey) { + return pKey.startsWith("bundle") || pKey === "workspaces"; +} + /** * returns an object with * - the *dependencies keys from both passed packages @@ -63,7 +69,7 @@ export default function mergeManifests(pClosestManifest, pFurtherManifest) { ) .map((pKey) => ({ key: pKey, - value: pKey.startsWith("bundle") + value: isAnArrayKey(pKey) ? mergeDependencyArray( pClosestManifest?.[pKey] ?? [], pFurtherManifest?.[pKey] ?? [], diff --git a/src/extract/resolve/module-classifiers.mjs b/src/extract/resolve/module-classifiers.mjs index 6a0206f6d..c2aee3803 100644 --- a/src/extract/resolve/module-classifiers.mjs +++ b/src/extract/resolve/module-classifiers.mjs @@ -1,4 +1,5 @@ import { isAbsolute, resolve as path_resolve } from "node:path"; +import { join as posix_join } from "node:path/posix"; import { isMatch } from "picomatch"; import getExtension from "#utl/get-extension.mjs"; @@ -31,8 +32,7 @@ export function isExternalModule( // WebPack treats these differently: // - absolute paths only match that exact path // - relative paths get a node lookup treatment so "turtle" matches - // "turtle", "../turtle", "../../turtle", "../../../turtle" (.. => - // turtles all the way down) + // "turtle", "../turtle", "../../turtle", "../../../turtle" // hence we'll have to test for them in different fashion as well. // reference: https://webpack.js.org/configuration/resolve/#resolve-modules (pModuleFolderName) => { @@ -50,15 +50,13 @@ export function isExternalModule( function determineFollowableExtensions(pResolveOptions) { let lReturnValue = new Set(pResolveOptions.extensions); - // we could include things like pictures, movies, html, xml - // etc in lKnownUnfollowables as well. Typically in - // javascript-like sources you don't import non-javascript - // stuff without mentioning the extension (`import 'styles.scss` - // is more clear than`import 'styles'` as you'd expect that - // to resolve to something javascript-like. - // Defensively added the stylesheetlanguages here explicitly - // nonetheless - they can contain import statements and the - // fallback javascript parser will happily parse them, which + // we could include things like pictures, movies, html, xml etc in + // lKnownUnfollowables as well. Typically in javascript-like sources you don't + // import non-javascript stuff without mentioning the extension + // (`import 'styles.scss` is more clear than`import 'styles'` as you'd expect + // that to resolve to something javascript-like. Defensively added the + // stylesheetlanguages here explicitly nonetheless - they can contain import + // statements and the fallback javascript parser will happily parse them, which // will result in false positives. const lKnownUnfollowables = [ ".json", @@ -154,7 +152,7 @@ function isWorkspaceAliased(pModuleName, pResolvedModuleName, pManifest) { // // oh and: ```picomatch.isMatch('asdf', 'asdf/**') === true``` so // in case it's only 'asdf' that's in the resolved module name for some reason - // we're good as well. + // we're good as well. const lModuleFriendlyWorkspaceGlobs = pManifest.workspaces.map( (pWorkspace) => pWorkspace.endsWith("/") ? `${pWorkspace}**` : `${pWorkspace}/**`, @@ -166,7 +164,7 @@ function isWorkspaceAliased(pModuleName, pResolvedModuleName, pManifest) { // the symlinked workspace folders are not resolved to their realpath. // So we need to check both the thing in node_modules _and_ the resolved // thing. Annoyingly, the symlink in node_modules is the `name` attribute - // of the workspace, not the path of the workspace itself. So if it's + // of the workspace, not the path of the workspace itself. So if it's // in node_modules we need to check against the unresolved modulename. // // Other then the detection for when symlinks are resolved to their realpath @@ -183,57 +181,117 @@ function isWorkspaceAliased(pModuleName, pResolvedModuleName, pManifest) { } /** + * * @param {string} pModuleName - * @param {string} pResolvedModuleName - * @param {import("../../../types/resolve-options").IResolveOptions} pResolveOptions - * @param {string} pBaseDirectory + * @param {Record} pPaths * @returns {boolean} */ -function isLikelyTSAliased( +function matchesTSConfigPaths(pModuleName, pPaths) { + // "paths patterns can contain a single * wildcard, which matches any string. + // The * token can then be used in the file path values to substitute the + // matched string." + // https://www.typescriptlang.org/docs/handbook/modules/reference.html#wildcard-substitutions + // + // So, just like with subpath imports, the LHS of a path pattern is not a glob + // and the '*' functions as a string replacement only. + // + // TODO: 'any string' - does this include the empty string as well? Checks seem + // to indicate it doesn't, so we use `.+` instead of `.*` + return Object.keys(pPaths).some((pPathLHS) => { + // eslint-disable-next-line security/detect-non-literal-regexp + const lMatchRE = new RegExp(`^${pPathLHS.replace(/\*/g, ".+")}$`); + return Boolean(pModuleName.match(lMatchRE)); + }); +} + +function stripExtension(pModulePath) { + const lExtension = getExtension(pModulePath); + return lExtension ? pModulePath.slice(0, -lExtension.length) : pModulePath; +} + +function stripIndex(pModulePath) { + return pModulePath.endsWith("/index") + ? pModulePath.slice(0, -"/index".length) + : pModulePath; +} + +/** + * + * https://www.typescriptlang.org/docs/handbook/modules/reference.html#baseurl + * + * @param {string} pModuleName + * @param {string} pResolvedModuleName + * @param {string} pTSConfigBaseURL + */ +function matchesTSConfigBaseURL( pModuleName, pResolvedModuleName, - pResolveOptions, - pBaseDirectory, + pTSConfigBaseURL, ) { - return ( - pResolveOptions.tsConfig && - !isRelativeModuleName(pModuleName) && - pResolvedModuleName && - !isExternalModule(pResolvedModuleName, ["node_modules"], pBaseDirectory) + if (!pTSConfigBaseURL) { + return false; + } + // "If baseUrl is set, TypeScript will resolve non-relative module names + // relative to the baseUrl." + // https://www.typescriptlang.org/docs/handbook/modules.html#base-url + const strippedModuleNameJoinedToBaseURL = stripIndex( + stripExtension(posix_join(pTSConfigBaseURL, pModuleName)), ); + const strippedResolvedModuleName = stripIndex( + stripExtension(pResolvedModuleName), + ); + return strippedModuleNameJoinedToBaseURL.endsWith(strippedResolvedModuleName); } /** * @param {string} pModuleName * @param {string} pResolvedModuleName - * @param {import("../../../types/resolve-options").IResolveOptions} pResolveOptions - * @param {object} pManifest + * @param {import("../../../types/resolve-options.mjs").IResolveOptions} pResolveOptions + * @param {any} pManifest + * @param {import("../../../types/dependency-cruiser.mjs").ITranspileOptions} pTranspileOptions * @returns {string[]} */ +// eslint-disable-next-line max-params, complexity export function getAliasTypes( pModuleName, pResolvedModuleName, pResolveOptions, pManifest, + pTranspileOptions, ) { - if (isSubpathImport(pModuleName, pManifest)) { - return ["aliased", "aliased-subpath-import"]; + if (isRelativeModuleName(pModuleName)) { + return []; } + // the order of these ifs is deliberate. First stuff bolted on by bundlers & transpilers. if (isWebPackAliased(pModuleName, pResolveOptions.alias)) { return ["aliased", "aliased-webpack"]; } - if (isWorkspaceAliased(pModuleName, pResolvedModuleName, pManifest)) { - return ["aliased", "aliased-workspace"]; - } if ( - isLikelyTSAliased( + matchesTSConfigBaseURL( pModuleName, pResolvedModuleName, - pResolveOptions, - pResolveOptions.baseDirectory, + pTranspileOptions?.tsConfig?.options?.baseUrl, + ) + ) { + return ["aliased", "aliased-tsconfig", "aliased-tsconfig-base-url"]; + } + if ( + matchesTSConfigPaths( + pModuleName, + pTranspileOptions?.tsConfig?.options?.paths ?? {}, ) ) { - return ["aliased", "aliased-tsconfig"]; + return ["aliased", "aliased-tsconfig", "aliased-tsconfig-paths"]; + } + // The order of subpath imports and workspaces isn't _that_ important, as they + // can't be confused + // - subpath imports _must_ start with a # + // - workspaces (or, more precise: package names) are forbidden to even _contain_ a # + if (isSubpathImport(pModuleName, pManifest)) { + return ["aliased", "aliased-subpath-import"]; + } + if (isWorkspaceAliased(pModuleName, pResolvedModuleName, pManifest)) { + return ["aliased", "aliased-workspace"]; } return []; } diff --git a/src/schema/configuration.schema.json b/src/schema/configuration.schema.json index 8f509db9a..0184795d1 100644 --- a/src/schema/configuration.schema.json +++ b/src/schema/configuration.schema.json @@ -389,6 +389,8 @@ "aliased", "aliased-subpath-import", "aliased-tsconfig", + "aliased-tsconfig-base-url", + "aliased-tsconfig-paths", "aliased-webpack", "aliased-workspace", "core", diff --git a/src/schema/configuration.schema.mjs b/src/schema/configuration.schema.mjs index a8d2ef47e..db2dcc871 100644 --- a/src/schema/configuration.schema.mjs +++ b/src/schema/configuration.schema.mjs @@ -1 +1 @@ -/* generated - don't edit */export default {"title":"dependency-cruiser configuration","$schema":"http://json-schema.org/draft-07/schema#","$id":"https://dependency-cruiser.js.org/schema/configuration.schema.json","type":"object","additionalProperties":false,"properties":{"$schema":{"type":"string"},"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}},"options":{"$ref":"#/definitions/OptionsType"},"extends":{"$ref":"#/definitions/ExtendsType"}},"definitions":{"RuleSetType":{"type":"object","additionalProperties":false,"properties":{"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}}}},"AllowedRuleType":{"oneOf":[{"$ref":"#/definitions/RegularAllowedRuleType"},{"$ref":"#/definitions/ReachabilityAllowedRuleType"}]},"RegularAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"ReachabilityAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"ForbiddenRuleType":{"oneOf":[{"$ref":"#/definitions/RegularForbiddenRuleType"},{"$ref":"#/definitions/ReachabilityForbiddenRuleType"},{"$ref":"#/definitions/DependentsForbiddenRuleType"}]},"RegularForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"DependentsForbiddenRuleType":{"type":"object","required":["module","from"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/DependentsModuleRestrictionType"},"from":{"$ref":"#/definitions/DependentsFromRestrictionType"}}},"ReachabilityForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"RequiredRuleType":{"type":"object","required":["module","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/RequiredModuleRestrictionType"},"to":{"$ref":"#/definitions/RequiredToRestrictionType"}}},"FromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"orphan":{"type":"boolean"}}},"ReachabilityFromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ToRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"couldNotResolve":{"type":"boolean"},"circular":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"$ref":"#/definitions/REAsStringsType"},"exoticRequireNot":{"$ref":"#/definitions/REAsStringsType"},"preCompilationOnly":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"dependencyTypesNot":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"moreThanOneDependencyType":{"type":"boolean"},"license":{"$ref":"#/definitions/REAsStringsType"},"licenseNot":{"$ref":"#/definitions/REAsStringsType"},"via":{"$ref":"#/definitions/REAsStringsType"},"viaOnly":{"$ref":"#/definitions/REAsStringsType"},"viaNot":{"$ref":"#/definitions/REAsStringsType"},"viaSomeNot":{"$ref":"#/definitions/REAsStringsType"},"moreUnstable":{"type":"boolean"}}},"DependentsModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"numberOfDependentsLessThan":{"type":"integer","minimum":0,"maximum":100},"numberOfDependentsMoreThan":{"type":"integer","minimum":0,"maximum":100}}},"DependentsFromRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ReachabilityToRestrictionType":{"required":["reachable"],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"reachable":{"type":"boolean"}}},"RequiredModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"RequiredToRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"DependencyTypeType":{"type":"string","enum":["aliased","aliased-subpath-import","aliased-tsconfig","aliased-webpack","aliased-workspace","core","deprecated","local","localmodule","npm","npm-bundled","npm-dev","npm-no-pkg","npm-optional","npm-peer","npm-unknown","undetermined","unknown","type-only"]},"REAsStringsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"SeverityType":{"type":"string","enum":["error","warn","info","ignore"]},"OptionsType":{"type":"object","additionalProperties":false,"properties":{"doNotFollow":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundDoNotFollowType"}]},"exclude":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundExcludeType"}]},"includeOnly":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundIncludeOnlyType"}]},"focus":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundFocusType"}]},"reaches":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundReachesType"}]},"highlight":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundHighlightType"}]},"knownViolations":{"$ref":"#/definitions/ViolationsType"},"collapse":{"oneOf":[{"type":"string"},{"type":"integer","minimum":1,"maximum":9}]},"maxDepth":{"type":"integer","minimum":0,"maximum":99},"moduleSystems":{"$ref":"#/definitions/ModuleSystemsType"},"prefix":{"type":"string"},"preserveSymlinks":{"type":"boolean"},"combinedDependencies":{"type":"boolean"},"tsConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"tsPreCompilationDeps":{"oneOf":[{"type":"boolean"},{"type":"string","enum":["specify"]}]},"extraExtensionsToScan":{"type":"array","items":{"type":"string"}},"externalModuleResolutionStrategy":{"type":"string","enum":["node_modules","yarn-pnp"]},"builtInModules":{"type":"object","additionalProperties":false,"properties":{"override":{"type":"array","items":{"type":"string"}},"add":{"type":"array","items":{"type":"string"}}}},"forceDeriveDependents":{"type":"boolean"},"webpackConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"},"env":{"oneOf":[{"type":"object"},{"type":"string"}]},"arguments":{"type":"object"}}},"enhancedResolveOptions":{"type":"object","additionalProperties":false,"properties":{"exportsFields":{"type":"array","items":{"type":"string"}},"conditionNames":{"type":"array","items":{"type":"string"}},"extensions":{"type":"array","items":{"type":"string"}},"mainFields":{"type":"array","items":{"type":"string"}},"mainFiles":{"type":"array"},"aliasFields":{"type":"array","items":{"type":"string"}},"cachedInputFileSystem":{"type":"object","additionalProperties":false,"properties":{"cacheDuration":{"type":"integer","minimum":0,"maximum":1800000}}}}},"babelConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"parser":{"type":"string","enum":["acorn","swc","tsc"]},"exoticRequireStrings":{"type":"array","items":{"type":"string"}},"reporterOptions":{"$ref":"#/definitions/ReporterOptionsType"},"progress":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["cli-feedback","performance-log","ndjson","none"]},"maximumLevel":{"type":"number","enum":[-1,40,50,60,70,80,99]}}},"metrics":{"type":"boolean"},"baseDir":{"type":"string"},"cache":{"oneOf":[{"type":"boolean"},{"type":"string"},{"$ref":"#/definitions/CacheOptionsType"}]}}},"ModuleSystemType":{"type":"string","enum":["cjs","es6","amd","tsd"]},"ModuleSystemsType":{"type":"array","items":{"$ref":"#/definitions/ModuleSystemType"}},"CompoundExcludeType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dynamic":{"type":"boolean"}}},"CompoundDoNotFollowType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"CompoundIncludeOnlyType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundFocusType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"depth":{"type":"number","minimum":1,"maximum":4}}},"CompoundReachesType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundHighlightType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"ReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"anon":{"$ref":"#/definitions/AnonReporterOptionsType"},"archi":{"$ref":"#/definitions/DotReporterOptionsType"},"dot":{"$ref":"#/definitions/DotReporterOptionsType"},"ddot":{"$ref":"#/definitions/DotReporterOptionsType"},"flat":{"$ref":"#/definitions/DotReporterOptionsType"},"markdown":{"$ref":"#/definitions/MarkdownReporterOptionsType"},"metrics":{"$ref":"#/definitions/MetricsReporterOptionsType"},"mermaid":{"$ref":"#/definitions/MermaidReporterOptionsType"},"text":{"$ref":"#/definitions/TextReporterOptionsType"}}},"AnonReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"wordlist":{"type":"array","items":{"type":"string"}}}},"MetricsReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"orderBy":{"type":"string","enum":["instability","moduleCount","afferentCouplings","efferentCouplings","name"]},"hideModules":{"type":"boolean"},"hideFolders":{"type":"boolean"}}},"MarkdownReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"showTitle":{"type":"boolean"},"title":{"type":"string"},"showSummary":{"type":"boolean"},"showSummaryHeader":{"type":"boolean"},"summaryHeader":{"type":"string"},"showStatsSummary":{"type":"boolean"},"showRulesSummary":{"type":"boolean"},"includeIgnoredInSummary":{"type":"boolean"},"showDetails":{"type":"boolean"},"includeIgnoredInDetails":{"type":"boolean"},"showDetailsHeader":{"type":"boolean"},"detailsHeader":{"type":"string"},"collapseDetails":{"type":"boolean"},"collapsedMessage":{"type":"string"},"noViolationsMessage":{"type":"string"},"showFooter":{"type":"boolean"}}},"MermaidReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"minify":{"type":"boolean"}}},"TextReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"highlightFocused":{"type":"boolean"}}},"DotReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"collapsePattern":{"$ref":"#/definitions/REAsStringsType"},"filters":{"$ref":"#/definitions/ReporterFiltersType"},"showMetrics":{"type":"boolean"},"theme":{"$ref":"#/definitions/DotThemeType"}}},"DotThemeType":{"type":"object","additionalProperties":false,"properties":{"replace":{"type":"boolean"},"graph":{"type":"object"},"node":{"type":"object"},"edge":{"type":"object"},"modules":{"$ref":"#/definitions/DotThemeArrayType"},"dependencies":{"$ref":"#/definitions/DotThemeArrayType"}}},"DotThemeArrayType":{"type":"array","items":{"$ref":"#/definitions/DotThemeEntryType"}},"DotThemeEntryType":{"type":"object","additionalProperties":false,"properties":{"criteria":{"type":"object"},"attributes":{"type":"object"}}},"ReporterFiltersType":{"type":"object","additionalProperties":false,"properties":{"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"$ref":"#/definitions/CompoundIncludeOnlyType"},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"}}},"ViolationsType":{"type":"array","items":{"$ref":"#/definitions/ViolationType"}},"ViolationType":{"type":"object","required":["from","to","rule"],"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"},"type":{"$ref":"#/definitions/ViolationTypeType"},"rule":{"$ref":"#/definitions/RuleSummaryType"},"cycle":{"type":"array","items":{"type":"string"}},"via":{"type":"array","items":{"type":"string"}},"metrics":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}},"to":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}}}},"comment":{"type":"string"}}},"RuleSummaryType":{"type":"object","required":["name","severity"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"}}},"ViolationTypeType":{"type":"string","enum":["dependency","module","reachability","cycle","instability","folder"]},"CacheOptionsType":{"type":"object","additionalProperties":false,"properties":{"folder":{"type":"string"},"strategy":{"$ref":"#/definitions/CacheStrategyType"},"compress":{"type":"boolean","default":false}}},"CacheStrategyType":{"type":"string","enum":["metadata","content"]},"ExtendsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}}} \ No newline at end of file +/* generated - don't edit */export default {"title":"dependency-cruiser configuration","$schema":"http://json-schema.org/draft-07/schema#","$id":"https://dependency-cruiser.js.org/schema/configuration.schema.json","type":"object","additionalProperties":false,"properties":{"$schema":{"type":"string"},"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}},"options":{"$ref":"#/definitions/OptionsType"},"extends":{"$ref":"#/definitions/ExtendsType"}},"definitions":{"RuleSetType":{"type":"object","additionalProperties":false,"properties":{"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}}}},"AllowedRuleType":{"oneOf":[{"$ref":"#/definitions/RegularAllowedRuleType"},{"$ref":"#/definitions/ReachabilityAllowedRuleType"}]},"RegularAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"ReachabilityAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"ForbiddenRuleType":{"oneOf":[{"$ref":"#/definitions/RegularForbiddenRuleType"},{"$ref":"#/definitions/ReachabilityForbiddenRuleType"},{"$ref":"#/definitions/DependentsForbiddenRuleType"}]},"RegularForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"DependentsForbiddenRuleType":{"type":"object","required":["module","from"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/DependentsModuleRestrictionType"},"from":{"$ref":"#/definitions/DependentsFromRestrictionType"}}},"ReachabilityForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"RequiredRuleType":{"type":"object","required":["module","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/RequiredModuleRestrictionType"},"to":{"$ref":"#/definitions/RequiredToRestrictionType"}}},"FromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"orphan":{"type":"boolean"}}},"ReachabilityFromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ToRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"couldNotResolve":{"type":"boolean"},"circular":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"$ref":"#/definitions/REAsStringsType"},"exoticRequireNot":{"$ref":"#/definitions/REAsStringsType"},"preCompilationOnly":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"dependencyTypesNot":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"moreThanOneDependencyType":{"type":"boolean"},"license":{"$ref":"#/definitions/REAsStringsType"},"licenseNot":{"$ref":"#/definitions/REAsStringsType"},"via":{"$ref":"#/definitions/REAsStringsType"},"viaOnly":{"$ref":"#/definitions/REAsStringsType"},"viaNot":{"$ref":"#/definitions/REAsStringsType"},"viaSomeNot":{"$ref":"#/definitions/REAsStringsType"},"moreUnstable":{"type":"boolean"}}},"DependentsModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"numberOfDependentsLessThan":{"type":"integer","minimum":0,"maximum":100},"numberOfDependentsMoreThan":{"type":"integer","minimum":0,"maximum":100}}},"DependentsFromRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ReachabilityToRestrictionType":{"required":["reachable"],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"reachable":{"type":"boolean"}}},"RequiredModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"RequiredToRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"DependencyTypeType":{"type":"string","enum":["aliased","aliased-subpath-import","aliased-tsconfig","aliased-tsconfig-base-url","aliased-tsconfig-paths","aliased-webpack","aliased-workspace","core","deprecated","local","localmodule","npm","npm-bundled","npm-dev","npm-no-pkg","npm-optional","npm-peer","npm-unknown","undetermined","unknown","type-only"]},"REAsStringsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"SeverityType":{"type":"string","enum":["error","warn","info","ignore"]},"OptionsType":{"type":"object","additionalProperties":false,"properties":{"doNotFollow":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundDoNotFollowType"}]},"exclude":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundExcludeType"}]},"includeOnly":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundIncludeOnlyType"}]},"focus":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundFocusType"}]},"reaches":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundReachesType"}]},"highlight":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundHighlightType"}]},"knownViolations":{"$ref":"#/definitions/ViolationsType"},"collapse":{"oneOf":[{"type":"string"},{"type":"integer","minimum":1,"maximum":9}]},"maxDepth":{"type":"integer","minimum":0,"maximum":99},"moduleSystems":{"$ref":"#/definitions/ModuleSystemsType"},"prefix":{"type":"string"},"preserveSymlinks":{"type":"boolean"},"combinedDependencies":{"type":"boolean"},"tsConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"tsPreCompilationDeps":{"oneOf":[{"type":"boolean"},{"type":"string","enum":["specify"]}]},"extraExtensionsToScan":{"type":"array","items":{"type":"string"}},"externalModuleResolutionStrategy":{"type":"string","enum":["node_modules","yarn-pnp"]},"builtInModules":{"type":"object","additionalProperties":false,"properties":{"override":{"type":"array","items":{"type":"string"}},"add":{"type":"array","items":{"type":"string"}}}},"forceDeriveDependents":{"type":"boolean"},"webpackConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"},"env":{"oneOf":[{"type":"object"},{"type":"string"}]},"arguments":{"type":"object"}}},"enhancedResolveOptions":{"type":"object","additionalProperties":false,"properties":{"exportsFields":{"type":"array","items":{"type":"string"}},"conditionNames":{"type":"array","items":{"type":"string"}},"extensions":{"type":"array","items":{"type":"string"}},"mainFields":{"type":"array","items":{"type":"string"}},"mainFiles":{"type":"array"},"aliasFields":{"type":"array","items":{"type":"string"}},"cachedInputFileSystem":{"type":"object","additionalProperties":false,"properties":{"cacheDuration":{"type":"integer","minimum":0,"maximum":1800000}}}}},"babelConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"parser":{"type":"string","enum":["acorn","swc","tsc"]},"exoticRequireStrings":{"type":"array","items":{"type":"string"}},"reporterOptions":{"$ref":"#/definitions/ReporterOptionsType"},"progress":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["cli-feedback","performance-log","ndjson","none"]},"maximumLevel":{"type":"number","enum":[-1,40,50,60,70,80,99]}}},"metrics":{"type":"boolean"},"baseDir":{"type":"string"},"cache":{"oneOf":[{"type":"boolean"},{"type":"string"},{"$ref":"#/definitions/CacheOptionsType"}]}}},"ModuleSystemType":{"type":"string","enum":["cjs","es6","amd","tsd"]},"ModuleSystemsType":{"type":"array","items":{"$ref":"#/definitions/ModuleSystemType"}},"CompoundExcludeType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dynamic":{"type":"boolean"}}},"CompoundDoNotFollowType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"CompoundIncludeOnlyType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundFocusType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"depth":{"type":"number","minimum":1,"maximum":4}}},"CompoundReachesType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundHighlightType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"ReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"anon":{"$ref":"#/definitions/AnonReporterOptionsType"},"archi":{"$ref":"#/definitions/DotReporterOptionsType"},"dot":{"$ref":"#/definitions/DotReporterOptionsType"},"ddot":{"$ref":"#/definitions/DotReporterOptionsType"},"flat":{"$ref":"#/definitions/DotReporterOptionsType"},"markdown":{"$ref":"#/definitions/MarkdownReporterOptionsType"},"metrics":{"$ref":"#/definitions/MetricsReporterOptionsType"},"mermaid":{"$ref":"#/definitions/MermaidReporterOptionsType"},"text":{"$ref":"#/definitions/TextReporterOptionsType"}}},"AnonReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"wordlist":{"type":"array","items":{"type":"string"}}}},"MetricsReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"orderBy":{"type":"string","enum":["instability","moduleCount","afferentCouplings","efferentCouplings","name"]},"hideModules":{"type":"boolean"},"hideFolders":{"type":"boolean"}}},"MarkdownReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"showTitle":{"type":"boolean"},"title":{"type":"string"},"showSummary":{"type":"boolean"},"showSummaryHeader":{"type":"boolean"},"summaryHeader":{"type":"string"},"showStatsSummary":{"type":"boolean"},"showRulesSummary":{"type":"boolean"},"includeIgnoredInSummary":{"type":"boolean"},"showDetails":{"type":"boolean"},"includeIgnoredInDetails":{"type":"boolean"},"showDetailsHeader":{"type":"boolean"},"detailsHeader":{"type":"string"},"collapseDetails":{"type":"boolean"},"collapsedMessage":{"type":"string"},"noViolationsMessage":{"type":"string"},"showFooter":{"type":"boolean"}}},"MermaidReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"minify":{"type":"boolean"}}},"TextReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"highlightFocused":{"type":"boolean"}}},"DotReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"collapsePattern":{"$ref":"#/definitions/REAsStringsType"},"filters":{"$ref":"#/definitions/ReporterFiltersType"},"showMetrics":{"type":"boolean"},"theme":{"$ref":"#/definitions/DotThemeType"}}},"DotThemeType":{"type":"object","additionalProperties":false,"properties":{"replace":{"type":"boolean"},"graph":{"type":"object"},"node":{"type":"object"},"edge":{"type":"object"},"modules":{"$ref":"#/definitions/DotThemeArrayType"},"dependencies":{"$ref":"#/definitions/DotThemeArrayType"}}},"DotThemeArrayType":{"type":"array","items":{"$ref":"#/definitions/DotThemeEntryType"}},"DotThemeEntryType":{"type":"object","additionalProperties":false,"properties":{"criteria":{"type":"object"},"attributes":{"type":"object"}}},"ReporterFiltersType":{"type":"object","additionalProperties":false,"properties":{"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"$ref":"#/definitions/CompoundIncludeOnlyType"},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"}}},"ViolationsType":{"type":"array","items":{"$ref":"#/definitions/ViolationType"}},"ViolationType":{"type":"object","required":["from","to","rule"],"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"},"type":{"$ref":"#/definitions/ViolationTypeType"},"rule":{"$ref":"#/definitions/RuleSummaryType"},"cycle":{"type":"array","items":{"type":"string"}},"via":{"type":"array","items":{"type":"string"}},"metrics":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}},"to":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}}}},"comment":{"type":"string"}}},"RuleSummaryType":{"type":"object","required":["name","severity"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"}}},"ViolationTypeType":{"type":"string","enum":["dependency","module","reachability","cycle","instability","folder"]},"CacheOptionsType":{"type":"object","additionalProperties":false,"properties":{"folder":{"type":"string"},"strategy":{"$ref":"#/definitions/CacheStrategyType"},"compress":{"type":"boolean","default":false}}},"CacheStrategyType":{"type":"string","enum":["metadata","content"]},"ExtendsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}}} \ No newline at end of file diff --git a/src/schema/cruise-result.schema.json b/src/schema/cruise-result.schema.json index 8a86a687d..9bd31ccb6 100644 --- a/src/schema/cruise-result.schema.json +++ b/src/schema/cruise-result.schema.json @@ -270,6 +270,8 @@ "aliased", "aliased-subpath-import", "aliased-tsconfig", + "aliased-tsconfig-base-url", + "aliased-tsconfig-paths", "aliased-webpack", "aliased-workspace", "core", diff --git a/src/schema/cruise-result.schema.mjs b/src/schema/cruise-result.schema.mjs index b5ad6e04f..8b08f68ba 100644 --- a/src/schema/cruise-result.schema.mjs +++ b/src/schema/cruise-result.schema.mjs @@ -1 +1 @@ -/* generated - don't edit */export default {"title":"dependency-cruiser output format","$schema":"http://json-schema.org/draft-07/schema#","$id":"https://dependency-cruiser.js.org/schema/cruise-result.schema.json","type":"object","required":["summary","modules"],"additionalProperties":false,"properties":{"modules":{"$ref":"#/definitions/ModulesType"},"folders":{"$ref":"#/definitions/FoldersType"},"summary":{"$ref":"#/definitions/SummaryType"},"revisionData":{"$ref":"#/definitions/RevisionDataType"}},"definitions":{"ModulesType":{"type":"array","items":{"$ref":"#/definitions/ModuleType"}},"ModuleType":{"type":"object","required":["source","dependencies","valid"],"additionalProperties":false,"properties":{"source":{"type":"string"},"valid":{"type":"boolean"},"dependencies":{"$ref":"#/definitions/DependenciesType"},"dependents":{"type":"array","items":{"type":"string"}},"followable":{"type":"boolean"},"matchesDoNotFollow":{"type":"boolean"},"matchesFocus":{"type":"boolean"},"matchesReaches":{"type":"boolean"},"matchesHighlight":{"type":"boolean"},"coreModule":{"type":"boolean"},"couldNotResolve":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"license":{"type":"string"},"orphan":{"type":"boolean"},"reachable":{"type":"array","items":{"$ref":"#/definitions/ReachableType"}},"reaches":{"type":"array","items":{"$ref":"#/definitions/ReachesType"}},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}},"consolidated":{"type":"boolean"},"instability":{"type":"number"},"checksum":{"type":"string"}}},"ReachableType":{"type":"object","required":["value","asDefinedInRule","matchedFrom"],"additionalProperties":false,"properties":{"value":{"type":"boolean"},"asDefinedInRule":{"type":"string"},"matchedFrom":{"type":"string"}}},"ReachesType":{"type":"object","required":["modules","asDefinedInRule"],"additionalProperties":false,"properties":{"modules":{"type":"array","items":{"type":"object","required":["source","via"],"additionalProperties":false,"properties":{"source":{"type":"string"},"via":{"type":"array","items":{"type":"string"}}}}},"asDefinedInRule":{"type":"string"}}},"DependenciesType":{"type":"array","items":{"$ref":"#/definitions/DependencyType"}},"DependencyType":{"type":"object","required":["circular","coreModule","couldNotResolve","dependencyTypes","exoticallyRequired","dynamic","followable","module","moduleSystem","resolved","valid"],"additionalProperties":false,"properties":{"module":{"type":"string"},"protocol":{"type":"string","enum":["data:","file:","node:"]},"mimeType":{"type":"string"},"resolved":{"type":"string"},"coreModule":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"license":{"type":"string"},"followable":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"type":"string"},"matchesDoNotFollow":{"type":"boolean"},"couldNotResolve":{"type":"boolean"},"preCompilationOnly":{"type":"boolean"},"typeOnly":{"type":"boolean"},"circular":{"type":"boolean"},"cycle":{"type":"array","items":{"type":"string"}},"moduleSystem":{"$ref":"#/definitions/ModuleSystemType"},"valid":{"type":"boolean"},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}},"instability":{"type":"number"}}},"DependencyTypeType":{"type":"string","enum":["aliased","aliased-subpath-import","aliased-tsconfig","aliased-webpack","aliased-workspace","core","deprecated","local","localmodule","npm","npm-bundled","npm-dev","npm-no-pkg","npm-optional","npm-peer","npm-unknown","undetermined","unknown","type-only"]},"ModuleSystemType":{"type":"string","enum":["cjs","es6","amd","tsd"]},"RuleSummaryType":{"type":"object","required":["name","severity"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"}}},"SeverityType":{"type":"string","enum":["error","warn","info","ignore"]},"FoldersType":{"type":"array","items":{"$ref":"#/definitions/FolderType"}},"FolderType":{"type":"object","required":["name","moduleCount"],"additionalProperties":false,"properties":{"name":{"type":"string"},"dependents":{"type":"array","items":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string"}}}},"dependencies":{"type":"array","items":{"type":"object","required":["name","valid","circular"],"additionalProperties":false,"properties":{"name":{"type":"string"},"instability":{"type":"number"},"valid":{"type":"boolean"},"circular":{"type":"boolean"},"cycle":{"type":"array","items":{"type":"string"}},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}}}}},"moduleCount":{"type":"number"},"afferentCouplings":{"type":"number"},"efferentCouplings":{"type":"number"},"instability":{"type":"number"}}},"SummaryType":{"type":"object","required":["violations","error","warn","info","totalCruised","optionsUsed"],"additionalProperties":false,"properties":{"violations":{"$ref":"#/definitions/ViolationsType"},"error":{"type":"number"},"warn":{"type":"number"},"info":{"type":"number"},"ignore":{"type":"number"},"totalCruised":{"type":"number"},"totalDependenciesCruised":{"type":"number"},"ruleSetUsed":{"$ref":"#/definitions/RuleSetType"},"optionsUsed":{"$ref":"#/definitions/OptionsUsedType"}}},"ViolationsType":{"type":"array","items":{"$ref":"#/definitions/ViolationType"}},"ViolationType":{"type":"object","required":["from","to","rule"],"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"},"type":{"$ref":"#/definitions/ViolationTypeType"},"rule":{"$ref":"#/definitions/RuleSummaryType"},"cycle":{"type":"array","items":{"type":"string"}},"via":{"type":"array","items":{"type":"string"}},"metrics":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}},"to":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}}}},"comment":{"type":"string"}}},"ViolationTypeType":{"type":"string","enum":["dependency","module","reachability","cycle","instability","folder"]},"RuleSetType":{"type":"object","additionalProperties":false,"properties":{"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}}}},"AllowedRuleType":{"oneOf":[{"$ref":"#/definitions/RegularAllowedRuleType"},{"$ref":"#/definitions/ReachabilityAllowedRuleType"}]},"RegularAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"ReachabilityAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"ForbiddenRuleType":{"oneOf":[{"$ref":"#/definitions/RegularForbiddenRuleType"},{"$ref":"#/definitions/ReachabilityForbiddenRuleType"},{"$ref":"#/definitions/DependentsForbiddenRuleType"}]},"RegularForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"DependentsForbiddenRuleType":{"type":"object","required":["module","from"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/DependentsModuleRestrictionType"},"from":{"$ref":"#/definitions/DependentsFromRestrictionType"}}},"ReachabilityForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"RequiredRuleType":{"type":"object","required":["module","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/RequiredModuleRestrictionType"},"to":{"$ref":"#/definitions/RequiredToRestrictionType"}}},"FromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"orphan":{"type":"boolean"}}},"ReachabilityFromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ToRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"couldNotResolve":{"type":"boolean"},"circular":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"$ref":"#/definitions/REAsStringsType"},"exoticRequireNot":{"$ref":"#/definitions/REAsStringsType"},"preCompilationOnly":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"dependencyTypesNot":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"moreThanOneDependencyType":{"type":"boolean"},"license":{"$ref":"#/definitions/REAsStringsType"},"licenseNot":{"$ref":"#/definitions/REAsStringsType"},"via":{"$ref":"#/definitions/REAsStringsType"},"viaOnly":{"$ref":"#/definitions/REAsStringsType"},"viaNot":{"$ref":"#/definitions/REAsStringsType"},"viaSomeNot":{"$ref":"#/definitions/REAsStringsType"},"moreUnstable":{"type":"boolean"}}},"DependentsModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"numberOfDependentsLessThan":{"type":"integer","minimum":0,"maximum":100},"numberOfDependentsMoreThan":{"type":"integer","minimum":0,"maximum":100}}},"DependentsFromRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ReachabilityToRestrictionType":{"required":["reachable"],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"reachable":{"type":"boolean"}}},"RequiredModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"RequiredToRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"REAsStringsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"OptionsUsedType":{"type":"object","additionalProperties":false,"properties":{"doNotFollow":{"$ref":"#/definitions/CompoundDoNotFollowType"},"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundIncludeOnlyType"}]},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"},"highlight":{"$ref":"#/definitions/CompoundHighlightType"},"knownViolations":{"$ref":"#/definitions/ViolationsType"},"collapse":{"type":"string"},"maxDepth":{"type":"integer","minimum":0,"maximum":99},"moduleSystems":{"$ref":"#/definitions/ModuleSystemsType"},"prefix":{"type":"string"},"preserveSymlinks":{"type":"boolean"},"combinedDependencies":{"type":"boolean"},"tsConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"tsPreCompilationDeps":{"oneOf":[{"type":"boolean"},{"type":"string","enum":["specify"]}]},"extraExtensionsToScan":{"type":"array","items":{"type":"string"}},"externalModuleResolutionStrategy":{"type":"string","enum":["node_modules","yarn-pnp"]},"builtInModules":{"type":"object","additionalProperties":false,"properties":{"override":{"type":"array","items":{"type":"string"}},"add":{"type":"array","items":{"type":"string"}}}},"forceDeriveDependents":{"type":"boolean"},"webpackConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"},"env":{"oneOf":[{"type":"object"},{"type":"string"}]},"arguments":{"type":"object"}}},"enhancedResolveOptions":{"type":"object","additionalProperties":false,"properties":{"exportsFields":{"type":"array","items":{"type":"string"}},"conditionNames":{"type":"array","items":{"type":"string"}},"extensions":{"type":"array","items":{"type":"string"}},"mainFields":{"type":"array","items":{"type":"string"}},"mainFiles":{"type":"array"},"aliasFields":{"type":"array","items":{"type":"string"}},"cachedInputFileSystem":{"type":"object","additionalProperties":false,"properties":{"cacheDuration":{"type":"integer","minimum":0,"maximum":1800000}}}}},"babelConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"parser":{"type":"string","enum":["acorn","swc","tsc"]},"exoticRequireStrings":{"type":"array","items":{"type":"string"}},"reporterOptions":{"$ref":"#/definitions/ReporterOptionsType"},"progress":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["cli-feedback","performance-log","ndjson","none"]},"maximumLevel":{"type":"number","enum":[-1,40,50,60,70,80,99]}}},"metrics":{"type":"boolean"},"baseDir":{"type":"string"},"cache":{"oneOf":[{"type":"boolean","enum":[false]},{"$ref":"#/definitions/CacheOptionsType"}]},"args":{"type":"string"},"rulesFile":{"type":"string"},"outputTo":{"type":"string"},"outputType":{"$ref":"#/definitions/OutputType"}}},"ModuleSystemsType":{"type":"array","items":{"$ref":"#/definitions/ModuleSystemType"}},"OutputType":{"oneOf":[{"type":"string","enum":["json","html","dot","ddot","cdot","archi","fdot","flat","csv","err","err-long","err-html","teamcity","anon","text","metrics","markdown","mermaid","d2","null"]},{"type":"string","pattern":"^plugin:[^:]+$"}]},"CompoundExcludeType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dynamic":{"type":"boolean"}}},"CompoundDoNotFollowType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"CompoundIncludeOnlyType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundFocusType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"depth":{"type":"number","minimum":1,"maximum":4}}},"CompoundReachesType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundHighlightType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"ReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"anon":{"$ref":"#/definitions/AnonReporterOptionsType"},"archi":{"$ref":"#/definitions/DotReporterOptionsType"},"dot":{"$ref":"#/definitions/DotReporterOptionsType"},"ddot":{"$ref":"#/definitions/DotReporterOptionsType"},"flat":{"$ref":"#/definitions/DotReporterOptionsType"},"markdown":{"$ref":"#/definitions/MarkdownReporterOptionsType"},"metrics":{"$ref":"#/definitions/MetricsReporterOptionsType"},"mermaid":{"$ref":"#/definitions/MermaidReporterOptionsType"},"text":{"$ref":"#/definitions/TextReporterOptionsType"}}},"AnonReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"wordlist":{"type":"array","items":{"type":"string"}}}},"MetricsReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"orderBy":{"type":"string","enum":["instability","moduleCount","afferentCouplings","efferentCouplings","name"]},"hideModules":{"type":"boolean"},"hideFolders":{"type":"boolean"}}},"MarkdownReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"showTitle":{"type":"boolean"},"title":{"type":"string"},"showSummary":{"type":"boolean"},"showSummaryHeader":{"type":"boolean"},"summaryHeader":{"type":"string"},"showStatsSummary":{"type":"boolean"},"showRulesSummary":{"type":"boolean"},"includeIgnoredInSummary":{"type":"boolean"},"showDetails":{"type":"boolean"},"includeIgnoredInDetails":{"type":"boolean"},"showDetailsHeader":{"type":"boolean"},"detailsHeader":{"type":"string"},"collapseDetails":{"type":"boolean"},"collapsedMessage":{"type":"string"},"noViolationsMessage":{"type":"string"},"showFooter":{"type":"boolean"}}},"MermaidReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"minify":{"type":"boolean"}}},"TextReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"highlightFocused":{"type":"boolean"}}},"DotReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"collapsePattern":{"$ref":"#/definitions/REAsStringsType"},"filters":{"$ref":"#/definitions/ReporterFiltersType"},"showMetrics":{"type":"boolean"},"theme":{"$ref":"#/definitions/DotThemeType"}}},"DotThemeType":{"type":"object","additionalProperties":false,"properties":{"replace":{"type":"boolean"},"graph":{"type":"object"},"node":{"type":"object"},"edge":{"type":"object"},"modules":{"$ref":"#/definitions/DotThemeArrayType"},"dependencies":{"$ref":"#/definitions/DotThemeArrayType"}}},"DotThemeArrayType":{"type":"array","items":{"$ref":"#/definitions/DotThemeEntryType"}},"DotThemeEntryType":{"type":"object","additionalProperties":false,"properties":{"criteria":{"type":"object"},"attributes":{"type":"object"}}},"ReporterFiltersType":{"type":"object","additionalProperties":false,"properties":{"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"$ref":"#/definitions/CompoundIncludeOnlyType"},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"}}},"CacheOptionsType":{"type":"object","additionalProperties":false,"properties":{"folder":{"type":"string"},"strategy":{"$ref":"#/definitions/CacheStrategyType"},"compress":{"type":"boolean","default":false}}},"CacheStrategyType":{"type":"string","enum":["metadata","content"]},"RevisionDataType":{"type":"object","required":["SHA1","changes"],"properties":{"SHA1":{"type":"string"},"changes":{"type":"array","items":{"type":"object","required":["name","changeType"],"properties":{"name":{"type":"string"},"changeType":{"type":"string","enum":["added","copied","deleted","modified","renamed","type changed","unmerged","pairing broken","unknown","unmodified","untracked","ignored"]},"oldName":{"type":"string"},"checksum":{"type":"string"},"args":{"type":"array","items":{"type":"string"}},"rulesFile":{"type":"string"}}}}}}}} \ No newline at end of file +/* generated - don't edit */export default {"title":"dependency-cruiser output format","$schema":"http://json-schema.org/draft-07/schema#","$id":"https://dependency-cruiser.js.org/schema/cruise-result.schema.json","type":"object","required":["summary","modules"],"additionalProperties":false,"properties":{"modules":{"$ref":"#/definitions/ModulesType"},"folders":{"$ref":"#/definitions/FoldersType"},"summary":{"$ref":"#/definitions/SummaryType"},"revisionData":{"$ref":"#/definitions/RevisionDataType"}},"definitions":{"ModulesType":{"type":"array","items":{"$ref":"#/definitions/ModuleType"}},"ModuleType":{"type":"object","required":["source","dependencies","valid"],"additionalProperties":false,"properties":{"source":{"type":"string"},"valid":{"type":"boolean"},"dependencies":{"$ref":"#/definitions/DependenciesType"},"dependents":{"type":"array","items":{"type":"string"}},"followable":{"type":"boolean"},"matchesDoNotFollow":{"type":"boolean"},"matchesFocus":{"type":"boolean"},"matchesReaches":{"type":"boolean"},"matchesHighlight":{"type":"boolean"},"coreModule":{"type":"boolean"},"couldNotResolve":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"license":{"type":"string"},"orphan":{"type":"boolean"},"reachable":{"type":"array","items":{"$ref":"#/definitions/ReachableType"}},"reaches":{"type":"array","items":{"$ref":"#/definitions/ReachesType"}},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}},"consolidated":{"type":"boolean"},"instability":{"type":"number"},"checksum":{"type":"string"}}},"ReachableType":{"type":"object","required":["value","asDefinedInRule","matchedFrom"],"additionalProperties":false,"properties":{"value":{"type":"boolean"},"asDefinedInRule":{"type":"string"},"matchedFrom":{"type":"string"}}},"ReachesType":{"type":"object","required":["modules","asDefinedInRule"],"additionalProperties":false,"properties":{"modules":{"type":"array","items":{"type":"object","required":["source","via"],"additionalProperties":false,"properties":{"source":{"type":"string"},"via":{"type":"array","items":{"type":"string"}}}}},"asDefinedInRule":{"type":"string"}}},"DependenciesType":{"type":"array","items":{"$ref":"#/definitions/DependencyType"}},"DependencyType":{"type":"object","required":["circular","coreModule","couldNotResolve","dependencyTypes","exoticallyRequired","dynamic","followable","module","moduleSystem","resolved","valid"],"additionalProperties":false,"properties":{"module":{"type":"string"},"protocol":{"type":"string","enum":["data:","file:","node:"]},"mimeType":{"type":"string"},"resolved":{"type":"string"},"coreModule":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"license":{"type":"string"},"followable":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"type":"string"},"matchesDoNotFollow":{"type":"boolean"},"couldNotResolve":{"type":"boolean"},"preCompilationOnly":{"type":"boolean"},"typeOnly":{"type":"boolean"},"circular":{"type":"boolean"},"cycle":{"type":"array","items":{"type":"string"}},"moduleSystem":{"$ref":"#/definitions/ModuleSystemType"},"valid":{"type":"boolean"},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}},"instability":{"type":"number"}}},"DependencyTypeType":{"type":"string","enum":["aliased","aliased-subpath-import","aliased-tsconfig","aliased-tsconfig-base-url","aliased-tsconfig-paths","aliased-webpack","aliased-workspace","core","deprecated","local","localmodule","npm","npm-bundled","npm-dev","npm-no-pkg","npm-optional","npm-peer","npm-unknown","undetermined","unknown","type-only"]},"ModuleSystemType":{"type":"string","enum":["cjs","es6","amd","tsd"]},"RuleSummaryType":{"type":"object","required":["name","severity"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"}}},"SeverityType":{"type":"string","enum":["error","warn","info","ignore"]},"FoldersType":{"type":"array","items":{"$ref":"#/definitions/FolderType"}},"FolderType":{"type":"object","required":["name","moduleCount"],"additionalProperties":false,"properties":{"name":{"type":"string"},"dependents":{"type":"array","items":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string"}}}},"dependencies":{"type":"array","items":{"type":"object","required":["name","valid","circular"],"additionalProperties":false,"properties":{"name":{"type":"string"},"instability":{"type":"number"},"valid":{"type":"boolean"},"circular":{"type":"boolean"},"cycle":{"type":"array","items":{"type":"string"}},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}}}}},"moduleCount":{"type":"number"},"afferentCouplings":{"type":"number"},"efferentCouplings":{"type":"number"},"instability":{"type":"number"}}},"SummaryType":{"type":"object","required":["violations","error","warn","info","totalCruised","optionsUsed"],"additionalProperties":false,"properties":{"violations":{"$ref":"#/definitions/ViolationsType"},"error":{"type":"number"},"warn":{"type":"number"},"info":{"type":"number"},"ignore":{"type":"number"},"totalCruised":{"type":"number"},"totalDependenciesCruised":{"type":"number"},"ruleSetUsed":{"$ref":"#/definitions/RuleSetType"},"optionsUsed":{"$ref":"#/definitions/OptionsUsedType"}}},"ViolationsType":{"type":"array","items":{"$ref":"#/definitions/ViolationType"}},"ViolationType":{"type":"object","required":["from","to","rule"],"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"},"type":{"$ref":"#/definitions/ViolationTypeType"},"rule":{"$ref":"#/definitions/RuleSummaryType"},"cycle":{"type":"array","items":{"type":"string"}},"via":{"type":"array","items":{"type":"string"}},"metrics":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}},"to":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}}}},"comment":{"type":"string"}}},"ViolationTypeType":{"type":"string","enum":["dependency","module","reachability","cycle","instability","folder"]},"RuleSetType":{"type":"object","additionalProperties":false,"properties":{"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}}}},"AllowedRuleType":{"oneOf":[{"$ref":"#/definitions/RegularAllowedRuleType"},{"$ref":"#/definitions/ReachabilityAllowedRuleType"}]},"RegularAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"ReachabilityAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"ForbiddenRuleType":{"oneOf":[{"$ref":"#/definitions/RegularForbiddenRuleType"},{"$ref":"#/definitions/ReachabilityForbiddenRuleType"},{"$ref":"#/definitions/DependentsForbiddenRuleType"}]},"RegularForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"DependentsForbiddenRuleType":{"type":"object","required":["module","from"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/DependentsModuleRestrictionType"},"from":{"$ref":"#/definitions/DependentsFromRestrictionType"}}},"ReachabilityForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"RequiredRuleType":{"type":"object","required":["module","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/RequiredModuleRestrictionType"},"to":{"$ref":"#/definitions/RequiredToRestrictionType"}}},"FromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"orphan":{"type":"boolean"}}},"ReachabilityFromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ToRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"couldNotResolve":{"type":"boolean"},"circular":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"$ref":"#/definitions/REAsStringsType"},"exoticRequireNot":{"$ref":"#/definitions/REAsStringsType"},"preCompilationOnly":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"dependencyTypesNot":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"moreThanOneDependencyType":{"type":"boolean"},"license":{"$ref":"#/definitions/REAsStringsType"},"licenseNot":{"$ref":"#/definitions/REAsStringsType"},"via":{"$ref":"#/definitions/REAsStringsType"},"viaOnly":{"$ref":"#/definitions/REAsStringsType"},"viaNot":{"$ref":"#/definitions/REAsStringsType"},"viaSomeNot":{"$ref":"#/definitions/REAsStringsType"},"moreUnstable":{"type":"boolean"}}},"DependentsModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"numberOfDependentsLessThan":{"type":"integer","minimum":0,"maximum":100},"numberOfDependentsMoreThan":{"type":"integer","minimum":0,"maximum":100}}},"DependentsFromRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ReachabilityToRestrictionType":{"required":["reachable"],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"reachable":{"type":"boolean"}}},"RequiredModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"RequiredToRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"REAsStringsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"OptionsUsedType":{"type":"object","additionalProperties":false,"properties":{"doNotFollow":{"$ref":"#/definitions/CompoundDoNotFollowType"},"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundIncludeOnlyType"}]},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"},"highlight":{"$ref":"#/definitions/CompoundHighlightType"},"knownViolations":{"$ref":"#/definitions/ViolationsType"},"collapse":{"type":"string"},"maxDepth":{"type":"integer","minimum":0,"maximum":99},"moduleSystems":{"$ref":"#/definitions/ModuleSystemsType"},"prefix":{"type":"string"},"preserveSymlinks":{"type":"boolean"},"combinedDependencies":{"type":"boolean"},"tsConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"tsPreCompilationDeps":{"oneOf":[{"type":"boolean"},{"type":"string","enum":["specify"]}]},"extraExtensionsToScan":{"type":"array","items":{"type":"string"}},"externalModuleResolutionStrategy":{"type":"string","enum":["node_modules","yarn-pnp"]},"builtInModules":{"type":"object","additionalProperties":false,"properties":{"override":{"type":"array","items":{"type":"string"}},"add":{"type":"array","items":{"type":"string"}}}},"forceDeriveDependents":{"type":"boolean"},"webpackConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"},"env":{"oneOf":[{"type":"object"},{"type":"string"}]},"arguments":{"type":"object"}}},"enhancedResolveOptions":{"type":"object","additionalProperties":false,"properties":{"exportsFields":{"type":"array","items":{"type":"string"}},"conditionNames":{"type":"array","items":{"type":"string"}},"extensions":{"type":"array","items":{"type":"string"}},"mainFields":{"type":"array","items":{"type":"string"}},"mainFiles":{"type":"array"},"aliasFields":{"type":"array","items":{"type":"string"}},"cachedInputFileSystem":{"type":"object","additionalProperties":false,"properties":{"cacheDuration":{"type":"integer","minimum":0,"maximum":1800000}}}}},"babelConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"parser":{"type":"string","enum":["acorn","swc","tsc"]},"exoticRequireStrings":{"type":"array","items":{"type":"string"}},"reporterOptions":{"$ref":"#/definitions/ReporterOptionsType"},"progress":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["cli-feedback","performance-log","ndjson","none"]},"maximumLevel":{"type":"number","enum":[-1,40,50,60,70,80,99]}}},"metrics":{"type":"boolean"},"baseDir":{"type":"string"},"cache":{"oneOf":[{"type":"boolean","enum":[false]},{"$ref":"#/definitions/CacheOptionsType"}]},"args":{"type":"string"},"rulesFile":{"type":"string"},"outputTo":{"type":"string"},"outputType":{"$ref":"#/definitions/OutputType"}}},"ModuleSystemsType":{"type":"array","items":{"$ref":"#/definitions/ModuleSystemType"}},"OutputType":{"oneOf":[{"type":"string","enum":["json","html","dot","ddot","cdot","archi","fdot","flat","csv","err","err-long","err-html","teamcity","anon","text","metrics","markdown","mermaid","d2","null"]},{"type":"string","pattern":"^plugin:[^:]+$"}]},"CompoundExcludeType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dynamic":{"type":"boolean"}}},"CompoundDoNotFollowType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"CompoundIncludeOnlyType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundFocusType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"depth":{"type":"number","minimum":1,"maximum":4}}},"CompoundReachesType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundHighlightType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"ReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"anon":{"$ref":"#/definitions/AnonReporterOptionsType"},"archi":{"$ref":"#/definitions/DotReporterOptionsType"},"dot":{"$ref":"#/definitions/DotReporterOptionsType"},"ddot":{"$ref":"#/definitions/DotReporterOptionsType"},"flat":{"$ref":"#/definitions/DotReporterOptionsType"},"markdown":{"$ref":"#/definitions/MarkdownReporterOptionsType"},"metrics":{"$ref":"#/definitions/MetricsReporterOptionsType"},"mermaid":{"$ref":"#/definitions/MermaidReporterOptionsType"},"text":{"$ref":"#/definitions/TextReporterOptionsType"}}},"AnonReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"wordlist":{"type":"array","items":{"type":"string"}}}},"MetricsReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"orderBy":{"type":"string","enum":["instability","moduleCount","afferentCouplings","efferentCouplings","name"]},"hideModules":{"type":"boolean"},"hideFolders":{"type":"boolean"}}},"MarkdownReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"showTitle":{"type":"boolean"},"title":{"type":"string"},"showSummary":{"type":"boolean"},"showSummaryHeader":{"type":"boolean"},"summaryHeader":{"type":"string"},"showStatsSummary":{"type":"boolean"},"showRulesSummary":{"type":"boolean"},"includeIgnoredInSummary":{"type":"boolean"},"showDetails":{"type":"boolean"},"includeIgnoredInDetails":{"type":"boolean"},"showDetailsHeader":{"type":"boolean"},"detailsHeader":{"type":"string"},"collapseDetails":{"type":"boolean"},"collapsedMessage":{"type":"string"},"noViolationsMessage":{"type":"string"},"showFooter":{"type":"boolean"}}},"MermaidReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"minify":{"type":"boolean"}}},"TextReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"highlightFocused":{"type":"boolean"}}},"DotReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"collapsePattern":{"$ref":"#/definitions/REAsStringsType"},"filters":{"$ref":"#/definitions/ReporterFiltersType"},"showMetrics":{"type":"boolean"},"theme":{"$ref":"#/definitions/DotThemeType"}}},"DotThemeType":{"type":"object","additionalProperties":false,"properties":{"replace":{"type":"boolean"},"graph":{"type":"object"},"node":{"type":"object"},"edge":{"type":"object"},"modules":{"$ref":"#/definitions/DotThemeArrayType"},"dependencies":{"$ref":"#/definitions/DotThemeArrayType"}}},"DotThemeArrayType":{"type":"array","items":{"$ref":"#/definitions/DotThemeEntryType"}},"DotThemeEntryType":{"type":"object","additionalProperties":false,"properties":{"criteria":{"type":"object"},"attributes":{"type":"object"}}},"ReporterFiltersType":{"type":"object","additionalProperties":false,"properties":{"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"$ref":"#/definitions/CompoundIncludeOnlyType"},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"}}},"CacheOptionsType":{"type":"object","additionalProperties":false,"properties":{"folder":{"type":"string"},"strategy":{"$ref":"#/definitions/CacheStrategyType"},"compress":{"type":"boolean","default":false}}},"CacheStrategyType":{"type":"string","enum":["metadata","content"]},"RevisionDataType":{"type":"object","required":["SHA1","changes"],"properties":{"SHA1":{"type":"string"},"changes":{"type":"array","items":{"type":"object","required":["name","changeType"],"properties":{"name":{"type":"string"},"changeType":{"type":"string","enum":["added","copied","deleted","modified","renamed","type changed","unmerged","pairing broken","unknown","unmodified","untracked","ignored"]},"oldName":{"type":"string"},"checksum":{"type":"string"},"args":{"type":"array","items":{"type":"string"}},"rulesFile":{"type":"string"}}}}}}}} \ No newline at end of file diff --git a/src/utl/get-extension.mjs b/src/utl/get-extension.mjs index 89b1c135a..ea7958d83 100644 --- a/src/utl/get-extension.mjs +++ b/src/utl/get-extension.mjs @@ -15,7 +15,7 @@ const EXTENSION_RE = /(?((\.d\.(c|m)?ts)|\.coffee\.md)$)/; * @param {string} pFileName path to the file to be parsed * @return {string} extension */ -export default function getExtensions(pFileName) { +export default function getExtension(pFileName) { const lMatchResult = pFileName.match(EXTENSION_RE); return lMatchResult?.groups?.extension ?? extname(pFileName); diff --git a/src/validate/matchers.mjs b/src/validate/matchers.mjs index 53ea890f2..13eddc208 100644 --- a/src/validate/matchers.mjs +++ b/src/validate/matchers.mjs @@ -3,10 +3,15 @@ import has from "lodash/has.js"; import { replaceGroupPlaceholders } from "#utl/regex-util.mjs"; import { intersects } from "#utl/array-util.mjs"; +// by their nature these dependency types always occur alongside other +// dependency types, like 'local' or 'npm'. Hence we exclude them from +// the 'duplicate dependency types' matcher. const NOT_REALLY_DUPLICATES = new Set([ "aliased", "aliased-subpath-import", "aliased-tsconfig", + "aliased-tsconfig-base-url", + "aliased-tsconfig-paths", "aliased-webpack", "aliased-workspace", "type-only", diff --git a/test/cli/__fixtures__/typescript-path-resolution.json b/test/cli/__fixtures__/typescript-path-resolution.json index 0c8c0d759..ba215fc31 100644 --- a/test/cli/__fixtures__/typescript-path-resolution.json +++ b/test/cli/__fixtures__/typescript-path-resolution.json @@ -12,7 +12,12 @@ "coreModule": false, "followable": true, "couldNotResolve": false, - "dependencyTypes": ["aliased", "aliased-tsconfig", "local"], + "dependencyTypes": [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-base-url", + "local" + ], "matchesDoNotFollow": false, "circular": false, "valid": true @@ -44,7 +49,12 @@ "coreModule": false, "followable": true, "couldNotResolve": false, - "dependencyTypes": ["aliased", "aliased-tsconfig", "local"], + "dependencyTypes": [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-base-url", + "local" + ], "matchesDoNotFollow": false, "circular": false, "valid": true diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/.dependency-cruiser.js b/test/cli/__fixtures__/workspaces-mono-repo-aliases/.dependency-cruiser.js new file mode 100644 index 000000000..d362a9868 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/.dependency-cruiser.js @@ -0,0 +1,16 @@ +/** @type {import('dependency-cruiser').IConfiguration} */ +module.exports = { + options: { + doNotFollow: { + path: "node_modules", + }, + moduleSystems: ["es6", "cjs"], + tsPreCompilationDeps: true, + combinedDependencies: true, + preserveSymlinks: false, + tsConfig: { + fileName: "tsconfig.json", + }, + cache: false, + }, +}; diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/direct-relative-import.ts b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/direct-relative-import.ts new file mode 100644 index 000000000..0582f3405 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/direct-relative-import.ts @@ -0,0 +1,3 @@ +import aap from "../../libs/aap"; + +console.log(aap); diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-subpath-import.ts b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-subpath-import.ts new file mode 100644 index 000000000..a7af4a2e4 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-subpath-import.ts @@ -0,0 +1,3 @@ +import subPathImport from "#mies/index.js"; + +console.log(subPathImport); diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-base-url.ts b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-base-url.ts new file mode 100644 index 000000000..0228d168f --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-base-url.ts @@ -0,0 +1,3 @@ +import tsConfigBasePath from "libs/wim"; + +console.log(tsConfigBasePath); diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-path-star.ts b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-path-star.ts new file mode 100644 index 000000000..0cd8e870e --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-path-star.ts @@ -0,0 +1,3 @@ +import tsConfigPathStar from "@modules/zus/index.js"; + +console.log(tsConfigPathStar); diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-path.ts b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-path.ts new file mode 100644 index 000000000..4c7ad5c15 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-tsconfig-path.ts @@ -0,0 +1,3 @@ +import tsConfigPath from "@sister"; + +console.log(tsConfigPath); diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-workspace.ts b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-workspace.ts new file mode 100644 index 000000000..f917d9e26 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/apps/admin/from-workspace.ts @@ -0,0 +1,3 @@ +import workspace from "noot/index.js"; + +console.log(workspace); diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/expected.json b/test/cli/__fixtures__/workspaces-mono-repo-aliases/expected.json new file mode 100644 index 000000000..e735cd285 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/expected.json @@ -0,0 +1,222 @@ +{ + "modules": [ + { + "source": "apps/admin/direct-relative-import.ts", + "dependencies": [ + { + "dynamic": false, + "module": "../../libs/aap", + "moduleSystem": "es6", + "exoticallyRequired": false, + "resolved": "libs/aap/index.js", + "coreModule": false, + "followable": true, + "couldNotResolve": false, + "dependencyTypes": ["local"], + "matchesDoNotFollow": false, + "circular": false, + "valid": true + } + ], + "dependents": [], + "orphan": false, + "valid": true + }, + { + "source": "libs/aap/index.js", + "dependencies": [], + "dependents": ["apps/admin/direct-relative-import.ts"], + "orphan": false, + "valid": true + }, + { + "source": "apps/admin/from-subpath-import.ts", + "dependencies": [ + { + "dynamic": false, + "module": "#mies/index.js", + "moduleSystem": "es6", + "exoticallyRequired": false, + "resolved": "libs/mies/index.js", + "coreModule": false, + "followable": true, + "couldNotResolve": false, + "dependencyTypes": ["aliased", "aliased-subpath-import", "local"], + "matchesDoNotFollow": false, + "circular": false, + "valid": true + } + ], + "dependents": [], + "orphan": false, + "valid": true + }, + { + "source": "libs/mies/index.js", + "dependencies": [], + "dependents": ["apps/admin/from-subpath-import.ts"], + "orphan": false, + "valid": true + }, + { + "source": "apps/admin/from-tsconfig-base-url.ts", + "dependencies": [ + { + "dynamic": false, + "module": "libs/wim", + "moduleSystem": "es6", + "exoticallyRequired": false, + "resolved": "libs/wim/index.js", + "coreModule": false, + "followable": true, + "couldNotResolve": false, + "dependencyTypes": [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-base-url", + "local" + ], + "matchesDoNotFollow": false, + "circular": false, + "valid": true + } + ], + "dependents": [], + "orphan": false, + "valid": true + }, + { + "source": "libs/wim/index.js", + "dependencies": [], + "dependents": ["apps/admin/from-tsconfig-base-url.ts"], + "orphan": false, + "valid": true + }, + { + "source": "apps/admin/from-tsconfig-path-star.ts", + "dependencies": [ + { + "dynamic": false, + "module": "@modules/zus/index.js", + "moduleSystem": "es6", + "exoticallyRequired": false, + "resolved": "libs/zus/index.js", + "coreModule": false, + "followable": true, + "couldNotResolve": false, + "dependencyTypes": [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-paths", + "local" + ], + "matchesDoNotFollow": false, + "circular": false, + "valid": true + } + ], + "dependents": [], + "orphan": false, + "valid": true + }, + { + "source": "libs/zus/index.js", + "dependencies": [], + "dependents": [ + "apps/admin/from-tsconfig-path-star.ts", + "apps/admin/from-tsconfig-path.ts" + ], + "orphan": false, + "valid": true + }, + { + "source": "apps/admin/from-tsconfig-path.ts", + "dependencies": [ + { + "dynamic": false, + "module": "@sister", + "moduleSystem": "es6", + "exoticallyRequired": false, + "resolved": "libs/zus/index.js", + "coreModule": false, + "followable": true, + "couldNotResolve": false, + "dependencyTypes": [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-paths", + "local" + ], + "matchesDoNotFollow": false, + "circular": false, + "valid": true + } + ], + "dependents": [], + "orphan": false, + "valid": true + }, + { + "source": "apps/admin/from-workspace.ts", + "dependencies": [ + { + "dynamic": false, + "module": "noot/index.js", + "moduleSystem": "es6", + "exoticallyRequired": false, + "resolved": "libs/noot/index.js", + "coreModule": false, + "followable": true, + "couldNotResolve": false, + "dependencyTypes": ["aliased", "aliased-workspace", "local"], + "matchesDoNotFollow": false, + "circular": false, + "valid": true + } + ], + "dependents": [], + "orphan": false, + "valid": true + }, + { + "source": "libs/noot/index.js", + "dependencies": [], + "dependents": ["apps/admin/from-workspace.ts"], + "orphan": false, + "valid": true + } + ], + "summary": { + "violations": [], + "error": 0, + "warn": 0, + "info": 0, + "ignore": 0, + "totalCruised": 11, + "totalDependenciesCruised": 6, + "optionsUsed": { + "baseDir": ".", + "cache": false, + "combinedDependencies": true, + "doNotFollow": { + "path": "node_modules" + }, + "exoticRequireStrings": [], + "externalModuleResolutionStrategy": "node_modules", + "metrics": false, + "moduleSystems": ["es6", "cjs"], + "outputTo": "../../__output__/workspaces-mono-repo-aliases.json", + "outputType": "json", + "preserveSymlinks": false, + "rulesFile": ".dependency-cruiser.js", + "tsConfig": { + "fileName": "tsconfig.json" + }, + "tsPreCompilationDeps": true, + "args": "apps/admin/" + }, + "ruleSetUsed": { + "forbidden": [] + } + } +} diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/aap/index.js b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/aap/index.js new file mode 100644 index 000000000..5a48a1ee1 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/aap/index.js @@ -0,0 +1 @@ +module.exports = "aap"; diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/aap/package.json b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/aap/package.json new file mode 100644 index 000000000..1f2b03a17 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/aap/package.json @@ -0,0 +1,8 @@ +{ + "name": "aap", + "version": "1.0.0", + "description": "", + "main": "index.js", + "author": "Sander Verweij (https://sverweij.github.io/)", + "license": "MIT" +} diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/mies/index.js b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/mies/index.js new file mode 100644 index 000000000..7e4cf664c --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/mies/index.js @@ -0,0 +1 @@ +module.exports = "mies"; diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/mies/package.json b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/mies/package.json new file mode 100644 index 000000000..a14206ba4 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/mies/package.json @@ -0,0 +1,13 @@ +{ + "name": "mies", + "version": "1.0.0", + "description": "", + "main": "index.js", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "Sander Verweij (https://sverweij.github.io/)", + "license": "MIT" +} diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/noot/index.js b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/noot/index.js new file mode 100644 index 000000000..2b0a0aa8d --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/noot/index.js @@ -0,0 +1 @@ +module.exports = "noot"; diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/noot/package.json b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/noot/package.json new file mode 100644 index 000000000..775efff59 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/noot/package.json @@ -0,0 +1,9 @@ +{ + "name": "noot", + "version": "1.0.0", + "description": "", + "main": "index.js", + "keywords": [], + "author": "Sander Verweij (https://sverweij.github.io/)", + "license": "MIT" +} diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/wim/index.js b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/wim/index.js new file mode 100644 index 000000000..ff6b08124 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/wim/index.js @@ -0,0 +1 @@ +module.exports = "wim"; diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/wim/package.json b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/wim/package.json new file mode 100644 index 000000000..01bf0ba00 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/wim/package.json @@ -0,0 +1,9 @@ +{ + "name": "wim", + "version": "1.0.0", + "description": "", + "main": "index.js", + "devDependencies": {}, + "author": "Sander Verweij (https://sverweij.github.io/)", + "license": "MIT" +} diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/zus/index.js b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/zus/index.js new file mode 100644 index 000000000..5a01e0c5a --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/zus/index.js @@ -0,0 +1 @@ +module.exports = "zus"; diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/zus/package.json b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/zus/package.json new file mode 100644 index 000000000..5a7fa2ff1 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/libs/zus/package.json @@ -0,0 +1,9 @@ +{ + "name": "zus", + "version": "1.0.0", + "description": "", + "main": "index.js", + "devDependencies": {}, + "author": "Sander Verweij (https://sverweij.github.io/)", + "license": "MIT" +} diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/.package-lock.json b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/.package-lock.json new file mode 100644 index 000000000..34d6c1b4a --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/.package-lock.json @@ -0,0 +1,49 @@ +{ + "lockfileVersion": 3, + "requires": true, + "packages": { + "libs/aap": { + "version": "1.0.0", + "license": "MIT" + }, + "libs/mies": { + "version": "1.0.0", + "license": "MIT", + "devDependencies": {} + }, + "libs/noot": { + "version": "1.0.0", + "license": "MIT" + }, + "libs/wim": { + "version": "1.0.0", + "license": "MIT", + "devDependencies": {} + }, + "libs/zus": { + "version": "1.0.0", + "license": "MIT", + "devDependencies": {} + }, + "node_modules/aap": { + "resolved": "libs/aap", + "link": true + }, + "node_modules/mies": { + "resolved": "libs/mies", + "link": true + }, + "node_modules/noot": { + "resolved": "libs/noot", + "link": true + }, + "node_modules/wim": { + "resolved": "libs/wim", + "link": true + }, + "node_modules/zus": { + "resolved": "libs/zus", + "link": true + } + } +} diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/aap b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/aap new file mode 120000 index 000000000..de3b4619b --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/aap @@ -0,0 +1 @@ +../libs/aap \ No newline at end of file diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/mies b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/mies new file mode 120000 index 000000000..28857f91a --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/mies @@ -0,0 +1 @@ +../libs/mies \ No newline at end of file diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/noot b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/noot new file mode 120000 index 000000000..4d6b208d8 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/noot @@ -0,0 +1 @@ +../libs/noot \ No newline at end of file diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/wim b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/wim new file mode 120000 index 000000000..174a9fddd --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/wim @@ -0,0 +1 @@ +../libs/wim \ No newline at end of file diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/zus b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/zus new file mode 120000 index 000000000..fa3c20403 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/node_modules/zus @@ -0,0 +1 @@ +../libs/zus \ No newline at end of file diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/package.json b/test/cli/__fixtures__/workspaces-mono-repo-aliases/package.json new file mode 100644 index 000000000..abdcaa56f --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/package.json @@ -0,0 +1,17 @@ +{ + "name": "workspaces-example", + "license": "MIT", + "version": "1.0.0", + "description": "", + "main": "index.js", + "workspaces": [ + "libs/aap", + "libs/noot", + "libs/mies", + "libs/wim", + "libs/zus" + ], + "imports": { + "#*": "./libs/*" + } +} diff --git a/test/cli/__fixtures__/workspaces-mono-repo-aliases/tsconfig.json b/test/cli/__fixtures__/workspaces-mono-repo-aliases/tsconfig.json new file mode 100644 index 000000000..bca5cd9c9 --- /dev/null +++ b/test/cli/__fixtures__/workspaces-mono-repo-aliases/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es2016", + "module": "commonjs", + "baseUrl": "./", + "paths": { + "@modules/*": ["./libs/*"], + "@sister": ["./libs/zus/*"] + }, + "noEmit": true, + "skipLibCheck": true + } +} diff --git a/test/cli/index.spec.mjs b/test/cli/index.spec.mjs index 6263ddb39..22d66e981 100644 --- a/test/cli/index.spec.mjs +++ b/test/cli/index.spec.mjs @@ -1,7 +1,7 @@ import { readFileSync, unlinkSync } from "node:fs"; +import { doesNotThrow, equal, throws } from "node:assert/strict"; // path.posix instead of path because otherwise on win32 the resulting // outputTo would contain \\ instead of / which for this unit test doesn't matter -import { doesNotThrow, equal, throws } from "node:assert/strict"; import { join, posix as path } from "node:path"; import chalk from "chalk"; import intercept from "intercept-stdout"; @@ -169,6 +169,7 @@ function resetOutputDirectory() { deleteDammit(path.join(OUT_DIR, "known-errors-not-known.txt")); deleteDammit(path.join(OUT_DIR, "known-errors-known.txt")); deleteDammit(path.join(OUT_DIR, "this-thing-likely-wont-exist.txt")); + deleteDammit(path.join(OUT_DIR, "workspaces-mono-repo-aliases.json")); } function setModuleType(pTestPairs, pModuleType) { @@ -220,6 +221,7 @@ function runFileBasedTests(pModuleType) { } /* eslint mocha/no-hooks-for-single-case: off */ describe("[E] cli/index", () => { + const lCurrentWorkingDirectory = process.cwd(); before("set up", () => { resetOutputDirectory(); }); @@ -228,6 +230,10 @@ describe("[E] cli/index", () => { resetOutputDirectory(); }); + afterEach("reset cwd", () => { + process.chdir(lCurrentWorkingDirectory); + }); + describe("[E] specials", () => { let lChalkLevel = chalk.level; @@ -495,6 +501,21 @@ describe("[E] cli/index", () => { assertJSONFileEqual(lOutputTo, path.join(FIX_DIR, lOutputFileName)); }); + it("dependency-cruise on a mono repo with tsconfig aliases will resolve the correct alias types", async () => { + const lOutputFileName = "workspaces-mono-repo-aliases.json"; + const lOutputTo = path.join("../../__output__", lOutputFileName); + process.chdir("./test/cli/__fixtures__/workspaces-mono-repo-aliases"); + + const lExitCode = await cli(["apps/admin/"], { + config: ".dependency-cruiser.js", + outputType: "json", + outputTo: lOutputTo, + }); + + equal(lExitCode, 0); + assertJSONFileEqual(lOutputTo, "expected.json"); + }); + it("dependency-cruise with a babelConfig will use that (es6 edition)", async () => { const lOutputFileName = "babel-es6-result.json"; const lOutputTo = path.join(OUT_DIR, lOutputFileName); diff --git a/test/extract/resolve/__mocks__/ts-config-with-path/tsconfig.json b/test/extract/resolve/__mocks__/ts-config-with-path/tsconfig.json index 142b03fec..5c023d09b 100644 --- a/test/extract/resolve/__mocks__/ts-config-with-path/tsconfig.json +++ b/test/extract/resolve/__mocks__/ts-config-with-path/tsconfig.json @@ -13,7 +13,7 @@ "paths": { "*": ["./typos/*"], "gewoon/*": ["./common/*"], - "shared": ["./shared"] + "@shared": ["./shared"] }, "esModuleInterop": true } diff --git a/test/extract/resolve/determine-dependency-types.spec.mjs b/test/extract/resolve/determine-dependency-types.spec.mjs index 98bcb411d..603c6d547 100644 --- a/test/extract/resolve/determine-dependency-types.spec.mjs +++ b/test/extract/resolve/determine-dependency-types.spec.mjs @@ -371,26 +371,37 @@ describe("[U] extract/resolve/determineDependencyTypes - determine dependencyTyp }); it("classifies likely TS aliased modules as aliased & aliased-tsconfig", () => { + const lDependency = { + couldNotResolve: false, + resolved: "src/wappie.js", + }; + const lModuleName = "@wappie"; + const lManifest = {}; + const lFileDirectory = "."; + const lResolveOptions = { + tsConfig: "tsconfig.json", + }; + const lBaseDirectory = null; + const lTranspileOptions = { + tsConfig: { + options: { + paths: { + "@wappie": ["src"], + }, + }, + }, + }; deepEqual( determineDependencyTypes( - // dependency - { - couldNotResolve: false, - resolved: "src/wappie.js", - }, - // pModuleName - "@wappie", - // pManifest - {}, - // pFileDirectory - ".", - // pResolveOptions - { - tsConfig: "tsconfig.json", - }, - // pBaseDirectory + lDependency, + lModuleName, + lManifest, + lFileDirectory, + lResolveOptions, + lBaseDirectory, + lTranspileOptions, ), - ["aliased", "aliased-tsconfig", "local"], + ["aliased", "aliased-tsconfig", "aliased-tsconfig-paths", "local"], ); }); diff --git a/test/extract/resolve/index.tsconfig.spec.mjs b/test/extract/resolve/index.tsconfig.spec.mjs index 0722947ff..deed4dd00 100644 --- a/test/extract/resolve/index.tsconfig.spec.mjs +++ b/test/extract/resolve/index.tsconfig.spec.mjs @@ -24,27 +24,40 @@ const PARSED_TSCONFIG_RESOLUTIONS = extractTSConfig(TSCONFIG); describe("[I] extract/resolve/index - typescript tsconfig processing", () => { it("considers a typescript config - non-* alias", async () => { + const lDependency = { + module: "@shared", + moduleSystem: "es6", + }; + const lBaseDirectory = join(__dirname, "__mocks__"); + const lFileDirectory = join(__dirname, "__mocks__", "ts-config-with-path"); + const lResolveOptions = await normalizeResolveOptions( + { + tsConfig: TSCONFIG, + bustTheCache: true, + }, + {}, + PARSED_TSCONFIG, + ); + const lTranspileOptions = { + tsConfig: PARSED_TSCONFIG, + }; deepEqual( resolve( - { - module: "shared", - moduleSystem: "es6", - }, - join(__dirname, "__mocks__"), - join(__dirname, "__mocks__", "ts-config-with-path"), - await normalizeResolveOptions( - { - tsConfig: TSCONFIG, - bustTheCache: true, - }, - {}, - PARSED_TSCONFIG, - ), + lDependency, + lBaseDirectory, + lFileDirectory, + lResolveOptions, + lTranspileOptions, ), { coreModule: false, couldNotResolve: false, - dependencyTypes: ["aliased", "aliased-tsconfig", "local"], + dependencyTypes: [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-paths", + "local", + ], followable: true, resolved: "ts-config-with-path/src/shared/index.ts", }, @@ -52,27 +65,40 @@ describe("[I] extract/resolve/index - typescript tsconfig processing", () => { }); it("considers a typescript config - combined/* alias", async () => { + const lDependency = { + module: "gewoon/wood/tree", + moduleSystem: "es6", + }; + const lBaseDirectory = join(__dirname, "__mocks__"); + const lFileDirectory = join(__dirname, "__mocks__", "ts-config-with-path"); + const lResolveOptions = await normalizeResolveOptions( + { + tsConfig: TSCONFIG, + bustTheCache: true, + }, + {}, + PARSED_TSCONFIG, + ); + const lTranspileOptions = { + tsConfig: PARSED_TSCONFIG, + }; deepEqual( resolve( - { - module: "gewoon/wood/tree", - moduleSystem: "es6", - }, - join(__dirname, "__mocks__"), - join(__dirname, "__mocks__", "ts-config-with-path"), - await normalizeResolveOptions( - { - tsConfig: TSCONFIG, - bustTheCache: true, - }, - {}, - PARSED_TSCONFIG, - ), + lDependency, + lBaseDirectory, + lFileDirectory, + lResolveOptions, + lTranspileOptions, ), { coreModule: false, couldNotResolve: false, - dependencyTypes: ["aliased", "aliased-tsconfig", "local"], + dependencyTypes: [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-paths", + "local", + ], followable: true, resolved: "ts-config-with-path/src/common/wood/tree.ts", }, @@ -80,27 +106,40 @@ describe("[I] extract/resolve/index - typescript tsconfig processing", () => { }); it("considers a typescript config - * alias", async () => { + const lDependency = { + module: "daddayaddaya", + moduleSystem: "es6", + }; + const lBaseDirectory = join(__dirname, "__mocks__"); + const lFileDirectory = join(__dirname, "__mocks__", "ts-config-with-path"); + const lResolveOptions = await normalizeResolveOptions( + { + tsConfig: TSCONFIG, + bustTheCache: true, + }, + {}, + PARSED_TSCONFIG, + ); + const lTranspileOptions = { + tsConfig: PARSED_TSCONFIG, + }; deepEqual( resolve( - { - module: "daddayaddaya", - moduleSystem: "es6", - }, - join(__dirname, "__mocks__"), - join(__dirname, "__mocks__", "ts-config-with-path"), - await normalizeResolveOptions( - { - tsConfig: TSCONFIG, - bustTheCache: true, - }, - {}, - PARSED_TSCONFIG, - ), + lDependency, + lBaseDirectory, + lFileDirectory, + lResolveOptions, + lTranspileOptions, ), { coreModule: false, couldNotResolve: false, - dependencyTypes: ["aliased", "aliased-tsconfig", "local"], + dependencyTypes: [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-paths", + "local", + ], followable: true, resolved: "ts-config-with-path/src/typos/daddayaddaya.ts", }, @@ -115,27 +154,45 @@ describe("[I] extract/resolve/index - typescript tsconfig processing", () => { "tsconfig-no-paths.json", ); const PARSED_TSCONFIG_NO_PATHS = extractTSConfig(TSCONFIG_NO_PATHS); + const lDependency = { + module: "common/wood/tree", + moduleSystem: "es6", + }; + const lBaseDirectory = join(__dirname, "__mocks__"); + const lFileDirectory = join( + __dirname, + "__mocks__", + "ts-config-with-path", + "src", + "typos", + ); + const lResolveOptions = await normalizeResolveOptions( + { + tsConfig: TSCONFIG_NO_PATHS, + bustTheCache: true, + }, + {}, + PARSED_TSCONFIG_NO_PATHS, + ); + const lTranspileOptions = { tsConfig: PARSED_TSCONFIG_NO_PATHS }; + deepEqual( resolve( - { - module: "common/wood/tree", - moduleSystem: "es6", - }, - join(__dirname, "__mocks__"), - join(__dirname, "__mocks__", "ts-config-with-path", "src", "typos"), - await normalizeResolveOptions( - { - tsConfig: TSCONFIG_NO_PATHS, - bustTheCache: true, - }, - {}, - PARSED_TSCONFIG_NO_PATHS, - ), + lDependency, + lBaseDirectory, + lFileDirectory, + lResolveOptions, + lTranspileOptions, ), { coreModule: false, couldNotResolve: false, - dependencyTypes: ["aliased", "aliased-tsconfig", "local"], + dependencyTypes: [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-base-url", + "local", + ], followable: true, resolved: "ts-config-with-path/src/common/wood/tree.ts", }, @@ -143,31 +200,42 @@ describe("[I] extract/resolve/index - typescript tsconfig processing", () => { }); it("for aliases resolves in the same fashion as the typescript compiler - dts-vs-ts", async () => { + const lDependency = { + module: "things/dts-before-ts", + moduleSystem: "es6", + }; + const lBaseDirectory = join(__dirname, "__mocks__"); + const lFileDirectory = join( + __dirname, + "__mocks__", + "ts-config-with-path-correct-resolution-prio", + ); + const lResolveOptions = await normalizeResolveOptions( + { + tsConfig: TSCONFIG_RESOLUTIONS, + bustTheCache: true, + }, + {}, + PARSED_TSCONFIG_RESOLUTIONS, + ); + const lTranspileOptions = { tsConfig: PARSED_TSCONFIG_RESOLUTIONS }; deepEqual( resolve( - { - module: "things/dts-before-ts", - moduleSystem: "es6", - }, - join(__dirname, "__mocks__"), - join( - __dirname, - "__mocks__", - "ts-config-with-path-correct-resolution-prio", - ), - await normalizeResolveOptions( - { - tsConfig: TSCONFIG_RESOLUTIONS, - bustTheCache: true, - }, - {}, - PARSED_TSCONFIG_RESOLUTIONS, - ), + lDependency, + lBaseDirectory, + lFileDirectory, + lResolveOptions, + lTranspileOptions, ), { coreModule: false, couldNotResolve: false, - dependencyTypes: ["aliased", "aliased-tsconfig", "local"], + dependencyTypes: [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-paths", + "local", + ], followable: true, resolved: "ts-config-with-path-correct-resolution-prio/src/aliassed/dts-before-ts.ts", @@ -196,11 +264,19 @@ describe("[I] extract/resolve/index - typescript tsconfig processing", () => { {}, PARSED_TSCONFIG_RESOLUTIONS, ), + { + tsConfig: PARSED_TSCONFIG_RESOLUTIONS, + }, ), { coreModule: false, couldNotResolve: false, - dependencyTypes: ["aliased", "aliased-tsconfig", "local"], + dependencyTypes: [ + "aliased", + "aliased-tsconfig", + "aliased-tsconfig-paths", + "local", + ], followable: true, resolved: "ts-config-with-path-correct-resolution-prio/src/aliassed/js-before-ts.js", diff --git a/test/extract/resolve/module-classifiers.get-alias-types.spec.mjs b/test/extract/resolve/module-classifiers.get-alias-types.spec.mjs index 2114ae111..449f577fb 100644 --- a/test/extract/resolve/module-classifiers.get-alias-types.spec.mjs +++ b/test/extract/resolve/module-classifiers.get-alias-types.spec.mjs @@ -68,6 +68,7 @@ describe("[I] extract/resolve/module-classifiers - getAliasTypes", () => { [], ); }); + it("doesn't run aliased and aliased-subpath-import when a thing starts with #, but there are no imports", () => { const lManifest = { name: "test", @@ -218,23 +219,97 @@ describe("[I] extract/resolve/module-classifiers - getAliasTypes", () => { ); }); - it("should return aliased and aliased-tsconfig for tsconfig alias", () => { + it("doesn't run aliased and aliased-workspace for when resolved matches a workspace, but module requested is relative", () => { const lManifest = { name: "test", version: "1.0.0", dependencies: {}, + workspaces: ["*/?-package"], + }; + const lResolveOptions = {}; + deepEqual( + getAliasTypes( + "../a-package/some-workspaced-local-package", + "packages/a-package/index.js", + lResolveOptions, + lManifest, + ), + [], + ); + }); + + it("classifies as a webpack alias if it could be both a webpack alias _and_ a workspace alias", () => { + const lManifest = { + name: "test", + version: "1.0.0", + dependencies: {}, + workspaces: ["*/?-package"], }; const lResolveOptions = { - tsConfig: "tsconfig.json", + alias: { + "@": "./src", + }, }; deepEqual( getAliasTypes( - "@tsconfig/package", - "aap/noot/mies.js", + "@some/thing.js", + "packages/a-package/index.js", + lResolveOptions, + lManifest, + ), + ["aliased", "aliased-webpack"], + ); + }); + + it("classifies as a webpack alias if it could be both a webpack alias _and_ a subpath import", () => { + const lManifest = { + name: "test", + version: "1.0.0", + dependencies: {}, + imports: { + "#*": "./src/*", + }, + }; + const lResolveOptions = { + alias: { + "#": "./src", + }, + }; + deepEqual( + getAliasTypes( + "#some/thing.js", + "src/some/thing.js", lResolveOptions, lManifest, ), - ["aliased", "aliased-tsconfig"], + ["aliased", "aliased-webpack"], + ); + }); + + it("should return aliased and aliased-tsconfig for tsconfig alias", () => { + const lManifest = { + name: "test", + version: "1.0.0", + dependencies: {}, + }; + const lTranspileOptions = { + tsConfig: { + options: { + paths: { + "@tsconfig/*": ["./src/*"], + }, + }, + }, + }; + deepEqual( + getAliasTypes( + "@tsconfig/package", + "src/package/index.js", + {}, + lManifest, + lTranspileOptions, + ), + ["aliased", "aliased-tsconfig", "aliased-tsconfig-paths"], ); }); }); diff --git a/tools/schema/dependency-type.mjs b/tools/schema/dependency-type.mjs index fe4c22e06..9cff31da9 100644 --- a/tools/schema/dependency-type.mjs +++ b/tools/schema/dependency-type.mjs @@ -6,6 +6,8 @@ export default { "aliased", "aliased-subpath-import", "aliased-tsconfig", + "aliased-tsconfig-base-url", + "aliased-tsconfig-paths", "aliased-webpack", "aliased-workspace", "core", diff --git a/types/shared-types.d.mts b/types/shared-types.d.mts index 01785fb56..1de1e29a4 100644 --- a/types/shared-types.d.mts +++ b/types/shared-types.d.mts @@ -38,6 +38,8 @@ export type DependencyType = | "aliased" | "aliased-subpath-import" | "aliased-tsconfig" + | "aliased-tsconfig-base-url" + | "aliased-tsconfig-paths" | "aliased-webpack" | "aliased-workspace" | "core"