@alveolus/arch 0.1.0 → 0.3.0

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.
Files changed (60) hide show
  1. package/README.md +8 -1
  2. package/dist/bin.mjs +4 -2
  3. package/dist/bin.mjs.map +1 -1
  4. package/dist/{cli-CwPCGjDg.mjs → docs-DsQHpTtV.mjs} +287 -38
  5. package/dist/docs-DsQHpTtV.mjs.map +1 -0
  6. package/dist/index.d.mts +90 -36
  7. package/dist/index.d.mts.map +1 -1
  8. package/dist/index.mjs +2 -2
  9. package/docs/core/application/command-handlers.md +617 -0
  10. package/docs/core/application/event-publishers.md +234 -0
  11. package/docs/core/application/event-translators.md +329 -0
  12. package/docs/core/application/index.md +99 -0
  13. package/docs/core/application/integration-events.md +277 -0
  14. package/docs/core/application/outbox.md +416 -0
  15. package/docs/core/application/query-handlers.md +292 -0
  16. package/docs/core/application/unit-of-work.md +352 -0
  17. package/docs/core/domain/aggregates.md +822 -0
  18. package/docs/core/domain/domain-errors.md +251 -0
  19. package/docs/core/domain/domain-events.md +292 -0
  20. package/docs/core/domain/domain-services.md +249 -0
  21. package/docs/core/domain/entities.md +431 -0
  22. package/docs/core/domain/index.md +93 -0
  23. package/docs/core/domain/ports.md +284 -0
  24. package/docs/core/domain/repositories.md +335 -0
  25. package/docs/core/domain/value-objects.md +425 -0
  26. package/docs/core/domain/views.md +265 -0
  27. package/docs/core/index.md +108 -0
  28. package/docs/core/strategic/anti-corruption-layers.md +349 -0
  29. package/docs/core/strategic/index.md +83 -0
  30. package/docs/core/strategic/open-host-services.md +287 -0
  31. package/docs/core/strategic/published-language.md +265 -0
  32. package/docs/core/utilities/result.md +413 -0
  33. package/docs/guide/agents.md +68 -0
  34. package/docs/guide/existing-project.md +105 -0
  35. package/docs/guide/getting-started.md +275 -0
  36. package/docs/guide/learning-path.md +123 -0
  37. package/docs/guide/project-layout.md +324 -0
  38. package/docs/guide/versioning.md +42 -0
  39. package/docs/integrations/index.md +112 -0
  40. package/docs/integrations/nestjs.md +169 -0
  41. package/docs/rules/index.md +183 -0
  42. package/docs/rules/layers/no-driving-shortcut.md +119 -0
  43. package/docs/rules/layers/no-impure-domain.md +189 -0
  44. package/docs/rules/layers/no-outward-import.md +184 -0
  45. package/docs/rules/layers/no-portless-adapter.md +123 -0
  46. package/docs/rules/strategic/no-cross-context-import.md +140 -0
  47. package/docs/rules/strategic/no-fat-shared-kernel.md +81 -0
  48. package/docs/rules/strategic/no-leaky-host-service.md +107 -0
  49. package/docs/rules/strategic/no-unmapped-context.md +111 -0
  50. package/docs/rules/tactical/no-aggregate-reference.md +139 -0
  51. package/docs/rules/tactical/no-foreign-command-dependency.md +119 -0
  52. package/docs/rules/tactical/no-foreign-query-dependency.md +106 -0
  53. package/docs/rules/tactical/no-loose-code.md +171 -0
  54. package/docs/rules/tactical/no-misplaced-class.md +146 -0
  55. package/docs/rules/tactical/no-public-field.md +113 -0
  56. package/docs/rules/tactical/no-stateful-service.md +102 -0
  57. package/docs/rules/tactical/no-thrown-failure.md +162 -0
  58. package/docs/rules/tooling/no-loose-disable.md +98 -0
  59. package/package.json +4 -3
  60. package/dist/cli-CwPCGjDg.mjs.map +0 -1
@@ -0,0 +1,275 @@
1
+ ---
2
+ description: "Install @alveolus/core and @alveolus/arch, write your first aggregate in TypeScript and check your Domain-Driven Design architecture with alveolus arch check."
3
+ ---
4
+
5
+ # Getting started
6
+
7
+ Alveolus comes as two packages: `@alveolus/core`, the building blocks your code extends, and
8
+ `@alveolus/arch`, the command that checks your project keeps the architecture.
9
+
10
+ <dl class="al-glance">
11
+ <dt>Runtime</dt><dd>Node.js 24 or later, ES modules or CommonJS</dd>
12
+ <dt>TypeScript</dt><dd><code>"module": "node20"</code> or <code>"nodenext"</code>, no decorator</dd>
13
+ <dt>Packages</dt><dd><code>@alveolus/core</code> as a dependency, <code>@alveolus/arch</code> as a development dependency</dd>
14
+ <dt>Config</dt><dd><a href="#configure-the-checks"><code>alveolus.config.ts</code></a>, at the root of the project</dd>
15
+ <dt>Command</dt><dd><a href="#run-the-checks"><code>npx alveolus arch check</code></a></dd>
16
+ </dl>
17
+
18
+ ::: warning
19
+ Alveolus is at `0.x`: a minor version may still rename a rule or a configuration key, and the
20
+ changelog says what to do. See [Versioning](./versioning.md).
21
+ :::
22
+
23
+ ::: tip New to DDD?
24
+ The [learning path](./learning-path.md) gives the order in which to read the docs.
25
+ :::
26
+
27
+ ## In four steps
28
+
29
+ <div class="al-cards al-cards-2">
30
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">1</span><a href="#install">Install</a></span>Add the building blocks to your code and the checks to your development tools.</div>
31
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">2</span><a href="#use-the-building-blocks">Extend a building block</a></span>Each class of your domain and application says what it is by extending one.</div>
32
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">3</span><a href="#configure-the-checks">Describe your contexts</a></span>Tell the checks where the code is and which folders are bounded contexts.</div>
33
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">4</span><a href="#run-the-checks">Run the checks</a></span>In your terminal while you code, and in continuous integration on every change.</div>
34
+ </div>
35
+
36
+ ## Prerequisites
37
+
38
+ The packages are ES modules described by an `exports` map, so TypeScript must resolve packages the
39
+ way Node.js does. Node.js 24 also loads them from a CommonJS application, such as a default NestJS
40
+ one.
41
+
42
+ ```json [tsconfig.json]
43
+ {
44
+ "compilerOptions": {
45
+ "module": "node20"
46
+ }
47
+ }
48
+ ```
49
+
50
+ `"nodenext"` works as well. No decorator and no `emitDecoratorMetadata` are needed: the building
51
+ blocks are plain classes, wired by hand or by your framework. See
52
+ [Integrations](../integrations/index.md).
53
+
54
+ ## Install
55
+
56
+ `@alveolus/core` ends up in your domain: it is a dependency. `@alveolus/arch` only checks the
57
+ code: it is a development dependency.
58
+
59
+ ::: code-group
60
+
61
+ ```sh [pnpm]
62
+ pnpm add @alveolus/core
63
+ pnpm add -D @alveolus/arch
64
+ ```
65
+
66
+ ```sh [npm]
67
+ npm install @alveolus/core
68
+ npm install -D @alveolus/arch
69
+ ```
70
+
71
+ ```sh [yarn]
72
+ yarn add @alveolus/core
73
+ yarn add -D @alveolus/arch
74
+ ```
75
+
76
+ ```sh [bun]
77
+ bun add @alveolus/core
78
+ bun add -d @alveolus/arch
79
+ ```
80
+
81
+ :::
82
+
83
+ `@alveolus/core` has no runtime dependency.
84
+
85
+ ## Use the building blocks
86
+
87
+ Every building block is an abstract class. Import the one you need from `@alveolus/core` and
88
+ extend it: the class then says what it is, to the reader and to the checks.
89
+
90
+ ```ts [src/ordering/domain/value-objects/order-id.identifier.ts]
91
+ // [!code word:Identifier]
92
+ import { Identifier } from "@alveolus/core";
93
+
94
+ export class OrderId extends Identifier<string, "OrderId"> {}
95
+ ```
96
+
97
+ Each building block also has its own entry point, such as `@alveolus/core/aggregates` or
98
+ `@alveolus/core/result`. Both forms give the same classes.
99
+
100
+ ::: tip Where to start
101
+ Start from a use case: the [aggregate](../core/domain/aggregates.md) that keeps its rules, then the
102
+ [command handler](../core/application/command-handlers.md) that calls it. The
103
+ [building blocks](../core/index.md) overview shows how they fit together.
104
+ :::
105
+
106
+ ## Configure the checks
107
+
108
+ Create `alveolus.config.ts` at the root of the project. It says where the source code is, which
109
+ folders are bounded contexts and which subdomain each one implements; everything else has a
110
+ default.
111
+
112
+ ```sh
113
+ npx alveolus init
114
+ ```
115
+
116
+ writes a starting one, with the [instructions for a coding agent](./agents.md); it never
117
+ overwrites a file. Or write it yourself:
118
+
119
+ ```ts [alveolus.config.ts]
120
+ import { defineConfig } from "@alveolus/arch";
121
+
122
+ export default defineConfig({
123
+ boundedContexts: { catalog: "catalog", notifications: "notifications", ordering: "ordering" },
124
+ root: "src",
125
+ subdomains: { core: ["catalog", "ordering"], generic: ["notifications"] },
126
+ });
127
+ ```
128
+
129
+ A [core](./project-layout.md#core-supporting-generic) context is checked by every rule. A
130
+ supporting or generic one is checked only at its boundary: it may be written any way you like, as
131
+ long as it reaches the other contexts through their open host services.
132
+
133
+ ### Options
134
+
135
+ | Option | Default | What it does |
136
+ | --- | --- | --- |
137
+ | `root` | required | The source folder. |
138
+ | `tsconfig` | `"tsconfig.json"` | The TypeScript configuration the sources are read with, relative to the project folder. |
139
+ | `boundedContexts` | required | Each bounded context and its folder, relative to `root`. `"modules/ordering"` works. |
140
+ | `sharedKernel` | `"shared-kernel"` | The folder shared by every bounded context, relative to `root`. |
141
+ | `subdomains` | required | The [subdomain](./project-layout.md#core-supporting-generic) each bounded context implements: `{ core: ["ordering"], supporting: ["billing"], generic: ["notifications"] }`. Every context is listed once. |
142
+ | `contextMap` | none | For each bounded context, the ones it consumes: `{ payments: ["ledger"] }`. Checked for cycles; without it, only cycles are reported. |
143
+ | `compositionRoot` | `"*.module.ts"` | The file, at the root of a bounded context, that wires it. |
144
+ | `domainDependencies` | `{}` | npm packages the domain may import, besides `@alveolus/core`. |
145
+ | `applicationDependencies` | `{}` | npm packages the application may import, besides `@alveolus/core` and `domainDependencies`. |
146
+ | `ignore` | test files | More files to leave out, as globs from the project folder. |
147
+ | `layout.extraFolders` | `{}` | Folders of your own under `domain/` or `application/`, besides those of the building blocks: `{ domain: ["specifications"] }`. |
148
+ | `rules` | every rule `"error"` | The level of a rule: `"error"` fails the check, `"warn"` and `"info"` only report, `"off"` silences it: `{ "tactical/no-public-field": "warn" }`. |
149
+
150
+ `domainDependencies` and `applicationDependencies` take `true` for every name of a package, or the
151
+ list of names allowed:
152
+
153
+ ```ts
154
+ domainDependencies: { "decimal.js": true, "date-fns": ["addDays"] },
155
+ ```
156
+
157
+ Tests and their companions are always left out, whatever `ignore` says: `*.spec.ts`, `*.test.ts`,
158
+ `*.e2e-spec.ts`, `*.fixture.ts`, `*.stories.ts`, `__tests__/` and `__mocks__/`.
159
+
160
+ ## Run the checks
161
+
162
+ ```sh
163
+ npx alveolus arch check
164
+ ```
165
+
166
+ On a project that keeps the rules, the command prints `No violation` and exits with code 0.
167
+ Otherwise it lists each violation, with what is allowed instead, and exits with code 1:
168
+
169
+ ```
170
+ src/ordering/domain/aggregates/order.aggregate.ts
171
+ 1 error layers/no-impure-domain: The domain imports @nestjs/common: add it
172
+ to domainDependencies if the domain really needs it.
173
+
174
+ 1 violation
175
+ ```
176
+
177
+ Each violation names its rule: the [rules](../rules/index.md) explain what each one checks and why.
178
+ The same pages are installed with the package, for the terminal and for a
179
+ [coding agent](./agents.md):
180
+
181
+ ```sh
182
+ npx alveolus explain layers/no-impure-domain
183
+ npx alveolus explain aggregates
184
+ npx alveolus explain
185
+ ```
186
+
187
+ A rule by its id, a building block or a guide by its name, and without argument the list of
188
+ topics.
189
+
190
+ ### Options
191
+
192
+ | Option | What it does |
193
+ | --- | --- |
194
+ | `--project <dir>` | The project folder. Defaults to the current folder. |
195
+ | `--config <file>` | The configuration file. Defaults to `alveolus.config.ts`. |
196
+ | `--tsconfig <file>` | The TypeScript configuration the sources are read with. Defaults to `tsconfig.json`, or to the `tsconfig` of the configuration file. |
197
+ | `--format json` | Prints the violations as JSON, for tools and agents. |
198
+ | `--format sarif` | Prints SARIF 2.1.0, for GitHub code scanning and the other analysers: upload it with `github/codeql-action/upload-sarif`. |
199
+
200
+ The exit code says what happened: `0` when no error is reported (warnings and infos never fail
201
+ the check), `1` when at least one error is, `2` when the configuration or the analysis itself
202
+ failed, with the reason on stderr. The summary counts the files analysed: `No violation in 142
203
+ files` on `0 files` would hide a wrong `root`.
204
+
205
+ ### Run it in continuous integration
206
+
207
+ So that no change lands without the check, add it to your scripts and run it with your other
208
+ checks:
209
+
210
+ ```json [package.json]
211
+ {
212
+ "scripts": {
213
+ "lint:arch": "alveolus arch check"
214
+ }
215
+ }
216
+ ```
217
+
218
+ ::: tip For coding agents
219
+ Give your agent the command and `--format json`: each violation says what is allowed instead, so
220
+ the agent can fix its own code before you review it.
221
+ :::
222
+
223
+ ## Adopt it on an existing project
224
+
225
+ The short version; the [guide for an existing project](./existing-project.md) has the whole path.
226
+
227
+ An existing project rarely keeps every rule from the start. A baseline lets you turn the checks on
228
+ today, and fix the past over time:
229
+
230
+ <div class="al-cards al-cards-2">
231
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">1</span>Record the current violations</span>Run <code>npx alveolus arch baseline</code>: it writes them to <code>alveolus.baseline.json</code>.</div>
232
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">2</span>Commit the file</span>From then on, <code>check</code> fails only on violations that are not in the baseline, and says how many it ignored.</div>
233
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">3</span>Fix them over time</span>Each fix removes a violation from what the baseline covers. New code keeps every rule.</div>
234
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">4</span>Record it again</span>Run <code>baseline</code> after a round of fixes: the file only shrinks. It refuses to grow, unless you pass <code>--allow-growth</code>.</div>
235
+ </div>
236
+
237
+ ### How a violation is recognised
238
+
239
+ Each entry of the baseline keeps the rule, the file, the symbol and a fingerprint of the reported
240
+ line: a short hash of its text, blind to indentation and spacing.
241
+
242
+ <div class="al-cards al-cards-2">
243
+ <div class="al-card"><span class="al-card-title">Still baselined</span>The code around it moves, the file is reformatted: the line keeps its text, so its fingerprint.</div>
244
+ <div class="al-card"><span class="al-card-title">Reported again</span>The line itself changes. Touching a baselined line is the moment to fix it.</div>
245
+ </div>
246
+
247
+ When a baselined violation is fixed, `check` says so (`4 fixed` in the summary, and a note on
248
+ stderr) without failing: run `baseline` again to drop the entries.
249
+
250
+ A new violation never hides behind a fixed one: a second `throw` in the same file has another
251
+ line, so another fingerprint. A baseline written before fingerprints existed matches nothing:
252
+ `check` says so, and `baseline` writes it again.
253
+
254
+ ## Turn a violation off
255
+
256
+ A violation can be right to keep for a while. Turn it off where it stands, with the rule and a
257
+ reason, and the reviewer sees both:
258
+
259
+ ```ts
260
+ // alveolus-disable-next-line layers/no-impure-domain: legacy pool, removed with ORD-412
261
+ import { Pool } from "pg";
262
+ ```
263
+
264
+ The summary counts the disabled violations, `--format json` lists them with their reason, and a
265
+ comment that names no rule, gives no reason or disables nothing is reported by
266
+ [`tooling/no-loose-disable`](../rules/tooling/no-loose-disable.md). For a whole file, use
267
+ `ignore`; for a whole rule, `rules`; for the past, the baseline.
268
+
269
+ ## See also
270
+
271
+ - [Learning path](./learning-path.md), the order in which to read the docs when you are new to DDD
272
+ - [Project layout](./project-layout.md), the folders and layers the checks expect
273
+ - [Building blocks](../core/index.md), the classes your code extends
274
+ - [Rules](../rules/index.md), what `alveolus arch check` verifies
275
+ - [Integrations](../integrations/index.md), to wire Alveolus into NestJS or another framework
@@ -0,0 +1,123 @@
1
+ ---
2
+ description: "New to Domain-Driven Design? A reading order through the Alveolus docs, from bounded contexts to aggregates, handlers and architecture checks, in TypeScript."
3
+ ---
4
+
5
+ # Learning path
6
+
7
+ New to Domain-Driven Design? Read the pages in this order: each step builds on the one before, and
8
+ each page explains one idea with the same `Order` example.
9
+
10
+ ::: info An introduction, not a course
11
+ These pages explain each idea as far as you need it to use Alveolus. They are not a complete course
12
+ on Domain-Driven Design. For the whole picture, read the books:
13
+
14
+ - *Domain-Driven Design: Tackling Complexity in the Heart of Software*, Eric Evans, 2003
15
+ - *Implementing Domain-Driven Design*, Vaughn Vernon, 2013
16
+ - *Domain-Driven Design Distilled*, Vaughn Vernon, 2016
17
+ - *Learning Domain-Driven Design*, Vlad Khononov, 2021
18
+ :::
19
+
20
+ <dl class="al-glance">
21
+ <dt>For</dt><dd>Developers who know TypeScript and have never used Domain-Driven Design</dd>
22
+ <dt>You need</dt><dd>TypeScript and classes, nothing about DDD</dd>
23
+ <dt>Order</dt><dd>The one of <em>Domain-Driven Design Distilled</em> (Vaughn Vernon, 2016): split the system first, then model each part</dd>
24
+ </dl>
25
+
26
+ ::: tip Already know DDD?
27
+ Go straight to [Getting started](./getting-started.md) and come back to a page when you need it.
28
+ :::
29
+
30
+ ## Why DDD
31
+
32
+ Software gets hard to change when its code no longer says what the business means. DDD puts the
33
+ business at the center of the code, in its own words.
34
+
35
+ <div class="al-cards al-cards-2">
36
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">1</span><a href="../core/">Building blocks</a></span>What Alveolus gives you: the patterns of DDD as classes your code extends.</div>
37
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">2</span><a href="../core/domain/">The domain</a></span>Why the model of the business lives apart from frameworks and databases.</div>
38
+ </div>
39
+
40
+ ## Split the system
41
+
42
+ Before writing a class, decide where its words apply. A "product" in the catalog and a "product" in
43
+ ordering are not the same thing: each part of the system gets its own model.
44
+
45
+ <div class="al-cards al-cards-2">
46
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">3</span><a href="../core/strategic/">Strategic design</a></span>What a bounded context is, and why contexts never share their models.</div>
47
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">4</span><a href="./project-layout">Project layout</a></span>Where every class goes: one folder per context, with its domain, application and adapters inside, and who may import what.</div>
48
+ </div>
49
+
50
+ ## Model the rules
51
+
52
+ Inside a context, the domain holds the business rules. Start from the smallest pieces and build up
53
+ to the aggregate, the object that keeps the rules of an order.
54
+
55
+ <div class="al-cards al-cards-2">
56
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">5</span><a href="../core/domain/value-objects">Value objects</a></span>Values such as an amount or an <code>OrderId</code>, checked once and never changed.</div>
57
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">6</span><a href="../core/domain/entities">Entities</a></span>Objects that keep their identity while they change, such as an order line.</div>
58
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">7</span><a href="../core/domain/aggregates">Aggregates</a></span>The <code>Order</code> and its lines, changed as one unit through the root that keeps the rules.</div>
59
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">8</span><a href="../core/domain/domain-errors">Domain errors</a></span>Expected failures, such as an empty order, named in the business's words.</div>
60
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">9</span><a href="../core/utilities/result">Result</a></span>How a method returns a domain error instead of throwing it.</div>
61
+ </div>
62
+
63
+ ## Record what happened
64
+
65
+ When the rules accept a change, the aggregate records it as a fact other code can react to.
66
+
67
+ <div class="al-cards al-cards-2">
68
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">10</span><a href="../core/domain/domain-events">Domain events</a></span>Facts named in the past tense, such as <code>OrderPlaced</code>.</div>
69
+ </div>
70
+
71
+ ## Reach the outside world
72
+
73
+ The domain still needs things it does not own: a rule spread over several objects, a price from
74
+ elsewhere, a place to store orders. It asks for them in its own words.
75
+
76
+ <div class="al-cards al-cards-2">
77
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">11</span><a href="../core/domain/domain-services">Domain services</a></span>Rules that no single object owns.</div>
78
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">12</span><a href="../core/domain/ports">Ports</a></span>What the domain needs from outside, as abstract classes.</div>
79
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">13</span><a href="../core/domain/repositories">Repositories</a></span>The ports that load and save aggregates and views.</div>
80
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">14</span><a href="../core/domain/views">Views</a></span>The read-only shape a query returns.</div>
81
+ </div>
82
+
83
+ ## Run a use case
84
+
85
+ The application layer turns a request, such as "place this order", into a call to the domain, and
86
+ saves the result.
87
+
88
+ <div class="al-cards al-cards-2">
89
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">15</span><a href="../core/application/">The application</a></span>How a request flows from the outside to the domain and back.</div>
90
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">16</span><a href="../core/application/command-handlers">Command handlers</a></span>Load an aggregate, call one method, save it.</div>
91
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">17</span><a href="../core/application/query-handlers">Query handlers</a></span>Read a view, without loading an aggregate.</div>
92
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">18</span><a href="../core/application/unit-of-work">Unit of Work</a></span>All the writes of a use case kept together, or none.</div>
93
+ </div>
94
+
95
+ ## Talk to other contexts
96
+
97
+ Contexts never import each other. They tell each other what happened in plain JSON, and each one
98
+ translates what it reads into its own model.
99
+
100
+ <div class="al-cards al-cards-2">
101
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">19</span><a href="../core/application/event-translators">Event translators</a></span>Turn domain events into messages for other contexts.</div>
102
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">20</span><a href="../core/application/integration-events">Integration events</a></span>Versioned JSON messages other contexts receive.</div>
103
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">21</span><a href="../core/application/event-publishers">Event publishers</a></span>The port that sends them to a broker.</div>
104
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">22</span><a href="../core/application/outbox">Outbox</a></span>How no message is lost when the change is saved.</div>
105
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">23</span><a href="../core/strategic/published-language">Published Language</a></span>The JSON contract between contexts.</div>
106
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">24</span><a href="../core/strategic/open-host-services">Open host services</a></span>The one entry point other contexts may call.</div>
107
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">25</span><a href="../core/strategic/anti-corruption-layers">Anti-corruption layers</a></span>Translate another context into your own words.</div>
108
+ </div>
109
+
110
+ ## Keep it on track
111
+
112
+ Each idea above becomes a rule the checks verify, so the code keeps it whoever writes it.
113
+
114
+ <div class="al-cards al-cards-2">
115
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">26</span><a href="../rules/">Rules</a></span>What <code>alveolus arch check</code> reports, and why.</div>
116
+ <div class="al-card"><span class="al-card-title"><span class="al-card-step">27</span><a href="./getting-started">Getting started</a></span>Install Alveolus and run the checks on your project.</div>
117
+ </div>
118
+
119
+ ## See also
120
+
121
+ - [Getting started](./getting-started.md), to install Alveolus and run the checks
122
+ - [Project layout](./project-layout.md), the folders and layers of a project
123
+ - [Building blocks](../core/index.md), every class `@alveolus/core` gives