Skip to content

Instantly share code, notes, and snippets.

@bvarberg
Last active December 8, 2023 21:20
Show Gist options
  • Save bvarberg/5a787c389d6af4e77128cb9e7cc6f518 to your computer and use it in GitHub Desktop.
Save bvarberg/5a787c389d6af4e77128cb9e7cc6f518 to your computer and use it in GitHub Desktop.
Example dependency-cruiser configuration
// .depcruise/config.js
/** @type {import('dependency-cruiser').IConfiguration} */
module.exports = {
extends: "dependency-cruiser/configs/recommended-strict",
forbidden: [
// Some example rules
{
name: "not-into-component-implementation",
severity: "error",
comment: `Modules should not depend on the private implementation details of a component.
Consider changing the importer to instead depend only on what is exposed publicly by the top-level component (what is in the index file).
Given more scrutiny, you may also consider extracting the desired functionality to a new top-level component.
`,
from: {
path: "^src/[^/]+/([^/]+)/.+",
},
to: {
path: "^src/components/[^/]+/(?!index.tsx?)",
pathNot: "^src/components/$1/.+",
},
},
{
name: "not-into-views",
comment:
"Code outside of views should not depend on views. Only the top-level App component may depend on a view component.",
severity: "error",
from: { pathNot: ["^src/views", "^src/App.tsx"] },
to: { path: "^src/views" },
},
{
name: "views-not-to-views",
comment:
"One view should not depend on the private implementation details of another view.",
severity: "error",
from: { path: "(^src/views/)([^/]+)/" },
to: { path: "^$1", pathNot: "$1$2" },
},
{
name: "not-into-testing",
comment:
"Only test files and Storybook files may depend on code in the testing module.",
severity: "error",
from: {
pathNot: ["^src/testing", "\\.test\\.tsx?$", "\\.stories\\.tsx?$"],
},
to: { path: "^src/testing" },
},
{
name: "highly-depended-upon",
comment: "More than 3 other modules depend on this module.",
severity: "info",
from: {},
module: {
path: "^src/.*",
numberOfDependentsMoreThan: 3,
},
},
],
options: {
doNotFollow: {
path: ["node_modules"],
dependencyTypes: [
"npm",
"npm-dev",
"npm-optional",
"npm-peer",
"npm-bundled",
"npm-no-pkg",
],
},
includeOnly: "^src",
exclude: ["^src/setupTests.ts"],
prefix: `vscode://file/${process.cwd()}/`, // links in the generated reports will open in VS Code
tsPreCompilationDeps: true,
tsConfig: {
fileName: "tsconfig.json",
},
enhancedResolveOptions: {
exportsFields: ["exports"],
conditionNames: ["import", "require", "node", "default"],
},
reporterOptions: {
dot: {
// Instability value = # dependencies / (# dependencies + # dependents)
// -> Higher value hints at instability
// -> Lower value hints at stablility
showMetrics: true,
// Collapse packages and some folders into a single object in the visualization (instead of showing internal files too)
collapsePattern: [
"node_modules/[^/]+",
"^src/testing",
"^src/packages/[^/]+",
],
// Specifically filter out some files when formatting as a graph
filters: {
focus: {
path: ["^src"],
},
exclude: {
path: ["^src/.*\\.test.tsx?", "^src/.*\\.stories.tsx?"],
},
},
theme: {
graph: {
splines: "ortho", // i.e., straight connector lines
rankdir: "TD", // i.e., top down (vertical)
},
},
},
},
},
};
{
"devDependencies": {
"dependency-cruiser": "^11.4.0",
},
"scripts": {
"deps:json": "depcruise --config .depcruise/config.js --metrics --output-type json src > ./deps/deps.json",
"deps:fmt:check": "depcruise-fmt --output-type err ./deps/deps.json",
"deps:fmt:graph": "depcruise-fmt --output-type dot ./deps/deps.json | dot -T svg | depcruise-wrap-stream-in-html > ./deps/graph.html",
"deps:fmt:graph:folders": "depcruise-fmt --output-type ddot ./deps/deps.json | dot -T svg | depcruise-wrap-stream-in-html > ./deps/folders.html",
"deps:fmt:report": "depcruise-fmt --output-type err-html ./deps/deps.json > ./deps/report.html",
"deps:check": "npm run deps:json && npm run deps:fmt:check",
"deps:graph": "npm run deps:json && npm run deps:fmt:graph",
"deps:graph:folders": "npm run deps:json && npm run deps:fmt:graph:folders",
"deps:report": "npm run deps:json && npm run deps:fmt:report"
}
}
@bvarberg
Copy link
Author

bvarberg commented Mar 10, 2022

You must have the graphviz package installed on your machine for the deps:fmt:graph and deps:fmt:graph:folders to work. Graphviz provides the dot and ddot tools.

@bvarberg
Copy link
Author

Example of the deps:fmt:graph output.
anonymized

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment