-
-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
albertoodev edited this page Jul 21, 2026
·
8 revisions
SPM follows Clean Architecture with independent feature modules under lib/features/. Each
feature has the same internal layout: data/ → domain/ → presentation/.
lib/
├── core/
│ ├── constants/
│ ├── errors/ # failures.dart: 20 typed Failure subclasses + CompoundFailure
│ ├── injection/ # static service locators (AnalysisDI, IsolationDI, InjectionDI, ValidationDI…)
│ ├── loggor/ # SpmLogger (use instead of print)
│ └── types.dart # shared type aliases (Result<T>, AsyncResult<T>, JsonRecord, …)
│
└── features/
├── analysis/ # static AST analysis → analyze
├── injection/ # code transformation + app execution → inject / run
├── isolation/ # rebuild-scope extraction → isolate
├── profiler/ # runtime-side API imported by the instrumented app
└── validation/ # structural-mutation gate → validate
Each feature follows the same three-layer layout:
<feature>/
├── data/
│ ├── data_sources/
│ ├── models/
│ └── repositories/
├── domain/
│ ├── entities/
│ ├── repositories/
│ └── use_cases/
└── presentation/ # one Command subclass, wiring CLI args → use cases via the feature's DI
| Feature | Command | Responsibility |
|---|---|---|
| analysis | analyze | Walks Dart files, finds every State subclass, extracts build-tree metrics via feature sets → specialized extractors and visitors. Streams AnalysisResultEntity records as JSONL. |
| isolation | isolate | Finds rebuild scopes (State, ConsumerWidget/HookConsumerWidget, builder patterns like BlocBuilder/Consumer/Selector/Obx/GetX/Observer) and transplants each into a self-contained .dart file, grouped by type. DI class: IsolationDI. |
| injection | inject, run | Reads the analysis JSONL and rewrites each target State class to extends SpmState<T> (adding an instanceId getter and the SpmState import); modes inject / remove. run then launches the app and connects to its Dart VM Service over WebSocket to collect ext.spm.profiler events. |
| profiler | (imported by the app) | Runtime-side API. SpmState.setState picks SpmProfiler.monitor() under --profile or SpmProfiler.monitorDataFlow() under --debug, measuring frame timings and rebuild counts and emitting events back to SPM over the VM Service. |
| validation | validate | Static gate deciding whether a mutation is a clean structural variant of a base file. DI class: ValidationDI. See AST Internals. |
-
types.dartholds all shared type aliases. The key ones areResult<T> = Either<Failure, T>,AsyncResult<T>,StreamResult<T>,AsyncVoidResult = AsyncResult<void>,AsyncVoid = Future<void>(data layer, may throw), andJsonRecord = Map<String, dynamic>. Always use these aliases; never spell out the full types inline. -
errors/failures.dartdefines 20 typedFailuresubclasses (e.g.InjectionFailure,RunAppFailure,FlutterAnalyzeFailure);CompoundFailureaggregates multiple failures. -
injection/holds static service locators built on lazy singleton getters (??=), with no external DI framework. Each DI class exposes areset()to clear all singletons; call it insetUp/tearDownwhen testing through the DI layer. -
loggor/logger.dartprovidesSpmLoggerfor stdout/stderr. Use it instead ofprint.
-
bin/spm.dart→lib/runner.dart(SpmRunner, aCommandRunnerwith the featureCommandsubclasses registered). - Each feature's
presentation/contains oneCommandsubclass wiring CLI args to use cases via the feature's DI singleton.
Either<Failure, T> is used throughout the data and domain layers (Left = error, Right =
success). Data sources may throw domain-specific exceptions; repositories translate those into
typed failures. Presentation commands fold results and return a non-zero status on failure, and
bin/spm.dart terminates the process with that returned status.
| Package | Role |
|---|---|
analyzer |
Dart AST parsing and semantic resolution. |
dartz |
Either type for functional error handling. |
vm_service |
Connect to the Dart VM to collect profiler events. |
web_socket_channel |
WebSocket transport to the VM Service. |
args |
CLI argument parsing. |
path |
Cross-platform path utilities. |
Commands
Reference
Internals
Contributing