|
1 |
| -# @angular-architects/ddd -- DDD Plugin for Nx |
| 1 | +# @angular-architects/ddd – DDD Plugin for Angular Nx Monorepos |
2 | 2 |
|
3 |
| -see [../../readme.md](../../README.md) |
| 3 | +## Versions |
| 4 | + |
| 5 | +The package versions are aligned with the _Angular_ version. |
| 6 | + |
| 7 | +* for **Nx < 19 and NG 17** use _v17.0.5_. |
| 8 | +* for **Nx < 20 and NG 18** use _v18.0.1_. |
| 9 | +* for **Nx >= 20 and NG 18** use _v18.1.0_. |
| 10 | +* for **Nx >= 20 and NG 19** use _v19.0.2_. |
| 11 | + |
| 12 | +**Breaking change** in v18.1.0: |
| 13 | + |
| 14 | +The naming of the **Nx** `includePaths` has changed to only use one "/" (due to **npm** restrictions). |
| 15 | + |
| 16 | +Until v18.0.1, the generated `includePaths` were like this, which is illegal in **npm**: |
| 17 | + |
| 18 | +```json |
| 19 | + "@org/booking/domain": ["libs/booking/domain/src/index.ts"], |
| 20 | + "@org/booking/feature-test": ["libs/booking/feature-test/src/index.ts"] |
| 21 | +``` |
| 22 | + |
| 23 | +Starting with v18.1.0, the generated `includePaths` are using dashes instead: |
| 24 | + |
| 25 | +```json |
| 26 | + "@org/booking-domain": ["libs/booking/domain/src/index.ts"], |
| 27 | + "@org/booking-feature-test": ["libs/booking/feature-test/src/index.ts"] |
| 28 | +``` |
| 29 | + |
| 30 | +## About |
| 31 | + |
| 32 | +This plugin installs some schematics which automate slicing your Nx workspace into domains and layers according to Nrwl's best practices and our ideas about [client-side DDD with Angular](https://www.softwarearchitekt.at/aktuelles/sustainable-angular-architectures-1/): |
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | +The generated access restrictions prevent unwanted access between libraries respecting layers and domains: |
| 37 | + |
| 38 | + |
| 39 | + |
| 40 | +## Features |
| 41 | + |
| 42 | +- 🗺️ Generating domains with domain libraries including a facades, models, and data services |
| 43 | +- ⚙️ Generating feature libraries including a feature components using the facades |
| 44 | +- 🙅♂️ Adding linting rules for access restrictions between domains as proposed by Nrwl |
| 45 | +- 🙅♀️ Adding linting rules for access restrictions between layers as proposed by Nrwl (supports tslint and eslint) |
| 46 | +- 🔥 Optionally generates skeleton for NGRX and integrates it into the DDD design (`--ngrx` switch, needs @ngrx/schematics) |
| 47 | +- 💥 Supports Standalone Components |
| 48 | + |
| 49 | +### Features Overview Video |
| 50 | + |
| 51 | +<a href="https://www.youtube.com/watch?v=39JLXMEE7Ds" target="_blank"></a> |
| 52 | + |
| 53 | +## Usage |
| 54 | + |
| 55 | +Add this plugin to a Nx workspace: |
| 56 | + |
| 57 | +``` |
| 58 | +npm i @angular-architects/ddd |
| 59 | +nx g @angular-architects/ddd:init |
| 60 | +``` |
| 61 | + |
| 62 | +Instead, you can also use ng add, however, Nx currently emits a warning when using ng add: |
| 63 | + |
| 64 | +``` |
| 65 | +nx add @angular-architects/ddd |
| 66 | +``` |
| 67 | + |
| 68 | +Add domains and features manually: |
| 69 | + |
| 70 | +``` |
| 71 | +nx g @angular-architects/ddd:domain booking --addApp |
| 72 | +nx g @angular-architects/ddd:domain boarding --addApp |
| 73 | +nx g @angular-architects/ddd:feature search --domain booking --entity flight |
| 74 | +nx g @angular-architects/ddd:feature cancel --domain booking |
| 75 | +nx g @angular-architects/ddd:feature manage --domain boarding |
| 76 | +``` |
| 77 | + |
| 78 | +For NGRX support, just add the `--ngrx` switch: |
| 79 | + |
| 80 | +``` |
| 81 | +nx g @angular-architects/ddd:domain luggage --addApp --ngrx |
| 82 | +nx g @angular-architects/ddd:feature checkin --domain luggage --entity luggage-list --ngrx |
| 83 | +[...] |
| 84 | +``` |
| 85 | + |
| 86 | +This example assumes that you have an app `flight-app` in place. |
| 87 | + |
| 88 | +These schematics also wire up the individual libs. To see the result, create a dependency graph: |
| 89 | + |
| 90 | +``` |
| 91 | +npm run dep-graph |
| 92 | +``` |
| 93 | + |
| 94 | + |
| 95 | + |
| 96 | +To see that the skeleton works end-to-end, call the generated feature component in your `app.component.html`: |
| 97 | + |
| 98 | +```html |
| 99 | +<booking-search></booking-search> |
| 100 | +``` |
| 101 | + |
| 102 | +You don't need any TypeScript or Angular imports. The plugin already took care about that. After running the example, you should see something like this: |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | +## Standalone Components |
| 107 | + |
| 108 | +All generators have a switch ``--standalone`` to support Standalone Components: |
| 109 | + |
| 110 | +``` |
| 111 | +ng g @angular-architects/ddd:domain booking --addApp --standalone |
| 112 | +
|
| 113 | +ng g @angular-architects/ddd:feature search --domain booking --entity flight --standalone |
| 114 | +``` |
| 115 | + |
| 116 | +Don't mix Standalone Components and traditional ones within the same domain. |
| 117 | + |
| 118 | +**Since version 19**, standalone **defaults to true**. |
| 119 | + |
| 120 | +## Generated Structure |
| 121 | + |
| 122 | +The included schematics generate a folder for each domain. This folder contains feature libs as well as a library with the domain logic: |
| 123 | + |
| 124 | + |
| 125 | + |
| 126 | +The domain layer is subdivided into three parts: |
| 127 | + |
| 128 | + |
| 129 | + |
| 130 | +### Generated Structure for Domain Library |
| 131 | + |
| 132 | +- **application:** Contains application services. This is a DDD term for what we call facades in Angular nowadays. They orchestrate everything for a use case given so that a feature component only needs to communicate with one such facade. Also, it hides details for state management. While the generates facades just use a `BehaviorSubject`, feel free to add a library like NGRX underneath. As such a modifications changes nothing from the component's perspective, you can use facades to introduce NGRX later on demand. |
| 133 | +- **entities:** Client-side data model including logic operating on it (like validations). |
| 134 | +- **infrastructure:** Services for communicating with the backend. |
| 135 | + |
| 136 | +## Consider Automatically Checking Access Restrictions |
| 137 | + |
| 138 | +As the access restrictions defined with Nx use linting, you can check against them at the command line too. Hence, you might consider including this into your automated build process. |
| 139 | + |
| 140 | + |
| 141 | + |
| 142 | +## Demo Application |
| 143 | + |
| 144 | +see https://github.com/angular-architects/ddd-demo |
| 145 | + |
| 146 | +## Resources |
| 147 | + |
| 148 | +- [Nx](https://nx.dev/web) |
| 149 | +- [Nrwl's eBook about monorepos and best practices](https://go.nrwl.io/angular-enterprise-monorepo-patterns-new-book) |
| 150 | +- [Recording of session about this architecture](https://www.youtube.com/watch?v=94HFD391zkE&t=1s) |
| 151 | +- [Article series about DDD with Angular](https://www.softwarearchitekt.at/aktuelles/sustainable-angular-architectures-1/) |
| 152 | +- [Our eBook on Enterprise Angular](https://www.angulararchitects.io/en/ebooks/micro-frontends-and-moduliths-with-angular/) |
| 153 | + |
| 154 | +## More Architecture |
| 155 | + |
| 156 | +- [Enterprise Architecture Workshop](https://www.angulararchitects.io/en/training/advanced-angular-architecture-workshop/) |
| 157 | +- [Angular Architects Blog](https://www.angulararchitects.io/en/blog/) |
| 158 | + |
| 159 | +## Get in touch with authors |
| 160 | + |
| 161 | +- [ManfredSteyer on X](https://x.com/ManfredSteyer), [LXT on X](https://x.com/LXT) |
0 commit comments