Mago 1.0.0-beta.30
This release introduces mago guard
, a powerful new tool for enforcing architectural rules in your PHP projects. We've also added a new list-files
utility command and landed several key correctness fixes for the analyzer and formatter as we get closer to our first release candidate.
A huge thank you to our community contributors for this release: @dotdash and @bendavies!
🛡️ New Feature: mago guard
We are thrilled to introduce mago guard
, a high-performance tool for defining and enforcing architectural boundaries directly within your project. It combines the power of dependency validation (like deptrac
) and structural rule-checking (like arkitect
) into a single, cohesive command.
The goal of guard
is to provide instant feedback on architectural violations, helping you maintain a clean and scalable codebase. Its concepts are designed to be intuitive, using a "Fortress" metaphor:
- 🏰 The Fortress is your entire codebase.
- 🧱 Perimeter Rules define your defensive layers. They control which namespaces can communicate, preventing illegal dependencies (e.g., ensuring your Domain layer never depends on your UI layer). A violation is a
BoundaryBreach
. - 🏛️ Structural Rules define the building codes inside the fortress. They ensure code within a namespace is built correctly (e.g., all Controllers are
final
, all Repositories implement an interface). A violation is aStructuralFlaw
.
All rules are defined declaratively in your mago.toml
file.
Read the full documentation for mago guard
here.
✨ Other New Features
- New
list-files
Command (#552): A newmago list-files
command has been added. This utility prints a list of all files that would be processed by thelint
,format
,analyze
, orguard
commands, based on your configuration. It's an excellent tool for debugging your[source]
paths and exclusion rules. (Thanks, @dotdash!)
🚀 Analyzer & Formatter Correctness
- Analyzer: Fixed a critical soundness bug where accessing an explicitly optional array shape key (e.g.,
email
inarray{email?: string}
) would not produce a nullable type. Accessing such a key now correctly results in aT|null
type. (#557) - Analyzer: Fixed a bug where a negated
isset()
check on a possibly undefined array key was not correctly narrowing the type tonull
. (Thanks, @bendavies!) - Analyzer: The analyzer now correctly allows assigning a value to a string-keyed index on a
list
, which correctly converts the type to a keyed array. (#559) - Formatter: Fixed a bug where
catch
blocks with multiple exception types that exceeded the print width were not being correctly broken onto multiple lines. (#556) - Linter: The
prefer-arrow-function
rule will no longer suggest converting a closure to an arrow function if the closure imports variables by reference, which is unsafe. (#554)
Closed Issues
Full Changelog: 1.0.0-beta.28...1.0.0-beta.30