limits
Each modules unit may be imported by at most max_fan_in files outside
it, and import at most max_fan_out files and packages of the project
outside it. A module that everything imports, or that imports everything, is
hard to change without touching much else.
Example
[contracts.small-surface]
type = "limits"
modules = ["web/src/*"]
max_fan_in = 20
max_fan_out = 12
max_fan_in = 2, a third file importing web/src/lib breaks the contract. app/main.ts counts once, though it imports two of its files.Each directory of web/src is checked on its own:
- Fan-in is the number of files outside the unit that import it. A file
counts once, however many of the unit's files it imports. A unit may be an
external package:
modules = ["npm:*"]limits how many files import each. - Fan-out is the number of files outside the unit that it imports, and of packages that it imports as a whole, such as a Go package. Each counts once, however many of the unit's files import it.
- Not counted: imports between the unit's own files, imports of external
packages such as
npm:reactand of builtins such asnode:fs, and the imports that the contract leaves out: those of itsexclude_kinds, itsignore_imports, suppressed ones, and those in the baseline. Only direct imports count. To restrict who may import an external package, use aprotectedcontract.
A unit over a limit is a violation that names the count and the limit, and lists the imports that make up the count. A unit over both limits is two violations.
Options
| Option | Default | |
|---|---|---|
modules | required | Selectors of the limited units. |
max_fan_in | none | The most files outside each unit that may import it. |
max_fan_out | none | The most files and packages of the project outside each unit that it may import. |
At least one of max_fan_in and max_fan_out is required.
Common options
Like every contract type, limits also takes:
| Option | Default | |
|---|---|---|
type | required | The contract type, such as "layers". |
name | the id | The title shown in the output. |
severity | "error" | "warn" reports a broken contract without failing the check, for rolling a contract out gradually. |
exclude_kinds | [analysis] exclude_kinds | The import kinds to leave out, e.g. ["type"]. |
reexports | [analysis] reexports | "transparent" sees an import of names from a [pass-through module](../concepts.md#pass-through modules) as imports of the modules that define them, as bundlers load them; "opaque" as an import of the pass-through module. Not for encapsulation. |
ignore_imports | [] | "<selector> -> <selector>" entries: the direct imports between them are left out of the contract. |
unmatched_ignore_imports | "error" | Whether an ignore_imports entry that matches no import breaks the contract ("error"), is a warning ("warn") or is fine ("none"). |
guidance | none | Text shown under each violation, such as how to fix it. |