archspec 1.0.1 → 1.1.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +12 -6
- data/lib/archspec/analyzer.rb +639 -261
- data/lib/archspec/architectures.rb +7 -3
- data/lib/archspec/component_spec.rb +13 -2
- data/lib/archspec/diagnostic.rb +19 -3
- data/lib/archspec/dsl.rb +69 -38
- data/lib/archspec/formatters/explanation.rb +33 -5
- data/lib/archspec/formatters/json.rb +1 -0
- data/lib/archspec/formatters/text.rb +19 -1
- data/lib/archspec/model.rb +266 -65
- data/lib/archspec/rubydex_index.rb +379 -0
- data/lib/archspec/rules/component_rules.rb +3 -4
- data/lib/archspec/rules/cycle_rule.rb +130 -33
- data/lib/archspec/rules/naming_rules.rb +11 -22
- data/lib/archspec/rules/protocol_rules.rb +117 -22
- data/lib/archspec/rules/reasoned.rb +37 -0
- data/lib/archspec/source_location.rb +1 -3
- data/lib/archspec/version.rb +1 -1
- data/lib/archspec.rb +4 -2
- metadata +21 -6
- data/lib/archspec/value_object.rb +0 -46
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3d1149a18e2ffb69c03d15e95ca539d3c42c1fda406376069313b9e07365a1b1
|
|
4
|
+
data.tar.gz: 290b05eb65ad246ebd1d81a025abe013a3150d5afc7e0bb6cb834dae3f64a429
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2e02c22290a4616b60edb2a5fd97ba991237e6da3b2fe495a5fde7802ac520fa432c821a9eb895c98333ce1acb170aff476ffa016c1de924199a9b47463d3994
|
|
7
|
+
data.tar.gz: 99d07ea4daff657b1823a81beff200f2139a3646c1ef7ad1bb3f041f13a9a03d7bd39a8b5b4b0176bda00ca13506043a691a1c93f65f54eed33a17c129e0f6af
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<strong>Executable architecture specifications for Ruby and Rails</strong>
|
|
6
6
|
|
|
7
|
-
<p>Declare your components and boundaries in one <code>Archspec.rb</code>, and every change gets checked in CI, whether a person or a coding agent wrote it. No AI involved, just
|
|
7
|
+
<p>Declare your components and boundaries in one <code>Archspec.rb</code>, and every change gets checked in CI, whether a person or a coding agent wrote it. No AI involved, just static analysis.</p>
|
|
8
8
|
|
|
9
9
|
Battle tested in [<picture><source media="(prefers-color-scheme: dark)" srcset="https://rubyllm.com/assets/images/logotype_dark.svg"><img src="https://rubyllm.com/assets/images/logotype.svg" alt="RubyLLM" height="30" align="absmiddle"></picture>](https://rubyllm.com) and at [<picture><source media="(prefers-color-scheme: dark)" srcset="https://chatwithwork.com/logotype-dark.svg"><img src="https://chatwithwork.com/logotype.svg" alt="Chat with Work" height="30" align="absmiddle"></picture>](https://chatwithwork.com)
|
|
10
10
|
|
|
@@ -18,7 +18,7 @@ Battle tested in [<picture><source media="(prefers-color-scheme: dark)" srcset="
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
ArchSpec turns your architecture into executable checks: components, layers, constant references, inheritance, mixins, named method calls, method protocols, naming conventions, cycles, and Rails boundaries. It is plain static analysis:
|
|
21
|
+
ArchSpec turns your architecture into executable checks: components, layers, constant references, inheritance, mixins, named method calls, method protocols, naming conventions, cycles, and Rails boundaries. It is plain static analysis: Rubydex builds the semantic index, Prism supplies a small syntax overlay, the app never boots, and no AI is involved in checking your code.
|
|
22
22
|
|
|
23
23
|
## Why ArchSpec?
|
|
24
24
|
|
|
@@ -100,10 +100,13 @@ Write local rules in plain Ruby:
|
|
|
100
100
|
component :controllers, in: "app/controllers/**/*.rb"
|
|
101
101
|
component :models, in: "app/models/**/*.rb"
|
|
102
102
|
component :services, in: "app/services/**/*.rb"
|
|
103
|
+
component :records, descendants_of: "ApplicationRecord"
|
|
103
104
|
|
|
104
105
|
controllers.can_only_use :models, :services
|
|
105
106
|
models.cannot_use :controllers
|
|
106
|
-
services.cannot_call :render, :redirect_to, :params, :session
|
|
107
|
+
services.cannot_call :render, :redirect_to, :params, :session,
|
|
108
|
+
because: "services do not own the HTTP response"
|
|
109
|
+
models.cannot_call :find_by_sql, receiver: "ActiveRecord::Base"
|
|
107
110
|
services.cannot_instantiate_and_invoke
|
|
108
111
|
```
|
|
109
112
|
|
|
@@ -124,7 +127,7 @@ architecture :cqrs,
|
|
|
124
127
|
- **Layers:** dependency direction and cycles
|
|
125
128
|
- **Rails:** controller APIs kept out of models and services
|
|
126
129
|
- **Architectures:** Rails, vanilla Rails, layered, hexagonal, clean, modular monolith, CQRS, event-driven, and Ruby conventions bundles
|
|
127
|
-
- **Protocols:**
|
|
130
|
+
- **Protocols:** instance/class APIs and callable signatures such as `call(amount, actor:)`
|
|
128
131
|
- **Naming:** conventions on a component's public API, such as banning `get_`/`set_` or pairing `with_x` with `without_x`
|
|
129
132
|
- **Objects:** rules against one-shot `Something.new(...).whatever` command objects
|
|
130
133
|
- **Empty components:** directories that must stay empty, like `app/services` in vanilla Rails
|
|
@@ -136,6 +139,8 @@ ArchSpec does not check Zeitwerk constant names. Zeitwerk does that itself. Add
|
|
|
136
139
|
|
|
137
140
|
## Installation
|
|
138
141
|
|
|
142
|
+
ArchSpec requires Ruby 3.2 or newer.
|
|
143
|
+
|
|
139
144
|
Add ArchSpec to your Gemfile:
|
|
140
145
|
|
|
141
146
|
```ruby
|
|
@@ -172,8 +177,9 @@ bundle exec archspec check --update-todo
|
|
|
172
177
|
bundle exec archspec explain app/models/user.rb
|
|
173
178
|
```
|
|
174
179
|
|
|
175
|
-
`explain` shows why a file or constant belongs to a component
|
|
176
|
-
facts
|
|
180
|
+
`explain` shows why a file or constant belongs to a component, its resolved
|
|
181
|
+
ancestry, outgoing facts, incoming dependencies, and anything the analysis
|
|
182
|
+
could not prove:
|
|
177
183
|
|
|
178
184
|
```text
|
|
179
185
|
app/models/user.rb
|