linesman 0.3.3+1
linesman: ^0.3.3+1 copied to clipboard
Enforce boundaries between different parts of your codebase.
Linesman #
Linesman helps you enforce boundaries between different parts of your codebase by providing a way to define and validate imports between modules, components, or any other logical units in your Dart application.
Requirements #
Dart 3.10 or later.
Install #
Add linesman as a dev dependency:
# pubspec.yaml
dev_dependencies:
linesman: ^0.3.0
Enable the plugin in analysis_options.yaml:
# analysis_options.yaml
plugins:
linesman: ^0.3.0
Configuration #
Rules are defined in a linesman.yaml file in your package root:
# linesman.yaml
allowByDefault: false
rules:
- type: allow
source: test.dart
target: some_file.dart
- type: deny
source: test.dart
target: some_other_file.dart
message: Use some_file.dart instead
- type: deny
source: test.dart
target: package:some_package/some_other_file.dart
Usage #
The allowed imports in your code are defined by the list of rules in linesman.yaml.
There are two types of rules:
allow: Allows imports of files that match the target glob into files that match the source glob.deny: Denies imports of files that match the target glob into files that match the source glob. Supports an optionalmessagefield shown in the diagnostic output.
source and target accept either a single glob pattern or a list of patterns:
rules:
- type: deny
source:
- feature_a/**
- feature_b/**
target: package:my_app/src/internal/**
Matching is performed using the glob package, which means you can use wildcards and other glob patterns to specify your source and target files.
Globs can be specified with a package:<package_name>/ prefix to match files in a specific package.
If no such prefix is present, the glob will only match files in the current package.
The ordering of rules matters. Subsequent rules will override previous ones that match the same source and target.
If no rules are defined, or if a particular source is not matched by any rule, the default behavior
is defined by the allowByDefault setting, which itself defaults to true.
Groups #
You can define named groups of patterns under the groups key and reference them in rules with a
$ prefix. Groups and inline patterns can be mixed in the same list:
groups:
internal:
- src/internal/**
- src/private/**
features:
- feature_a/**
- feature_b/**
rules:
- type: deny
source: $features
target: $internal
- type: deny
source:
- $features
- utils/**
target: $internal
Layers #
The layers key enforces a layered architecture. Each entry is a group reference or glob pattern, or a list of the
same. Imports can only go downward — lower layers cannot import from higher layers:
groups:
ui:
- ui/**
domain:
- domain/**
data:
- data/**
layers:
- $application
- [$domain, util/**]
- [$http_client, $db, $messaging]
By default, imports are restricted to only the immediately adjacent layer below. Set
allowTransitiveLayerAccess: true to allow upper layers to import from any lower layer:
allowTransitiveLayerAccess: true
layers:
- $ui
- $domain
- $data
With this setting, ui can import from both domain and data.
Using layers will trigger automatic generation of an initial rule set that is applied before explicit rules. This
makes it easy to create overrides where exceptions are needed.
Pub Workspaces #
In a pub workspace, you can place a linesman.yaml
at the workspace root to define rules that apply across all packages. Linesman detects the workspace
root by walking up from the package root and looking for a pubspec.yaml with a workspace key.
If both a workspace-level and a package-level linesman.yaml exist, they are merged: workspace
rules are evaluated first, then package rules. This means package-level rules can override workspace
rules. Groups are also merged, with package-level groups taking precedence on name collisions.
Contributing #
PRs accepted.
License #
Apache 2.0 © Thomas Järvstrand