@malamute/ai-rules 1.0.0 → 1.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.
- package/README.md +272 -121
- package/bin/cli.js +5 -2
- package/configs/_shared/CLAUDE.md +52 -149
- package/configs/_shared/rules/conventions/documentation.md +324 -0
- package/configs/_shared/rules/conventions/git.md +265 -0
- package/configs/_shared/rules/conventions/npm.md +80 -0
- package/configs/_shared/{.claude/rules → rules/conventions}/performance.md +1 -1
- package/configs/_shared/rules/conventions/principles.md +334 -0
- package/configs/_shared/rules/devops/ci-cd.md +262 -0
- package/configs/_shared/rules/devops/docker.md +275 -0
- package/configs/_shared/rules/devops/nx.md +194 -0
- package/configs/_shared/rules/domain/backend/api-design.md +203 -0
- package/configs/_shared/rules/lang/csharp/async.md +220 -0
- package/configs/_shared/rules/lang/csharp/csharp.md +314 -0
- package/configs/_shared/rules/lang/csharp/linq.md +210 -0
- package/configs/_shared/rules/lang/python/async.md +337 -0
- package/configs/_shared/rules/lang/python/celery.md +476 -0
- package/configs/_shared/rules/lang/python/config.md +339 -0
- package/configs/{python/.claude/rules → _shared/rules/lang/python}/database/sqlalchemy.md +6 -1
- package/configs/_shared/rules/lang/python/deployment.md +523 -0
- package/configs/_shared/rules/lang/python/error-handling.md +330 -0
- package/configs/_shared/rules/lang/python/migrations.md +421 -0
- package/configs/_shared/rules/lang/python/python.md +172 -0
- package/configs/_shared/rules/lang/python/repository.md +383 -0
- package/configs/{python/.claude/rules → _shared/rules/lang/python}/testing.md +2 -69
- package/configs/_shared/rules/lang/typescript/async.md +447 -0
- package/configs/_shared/rules/lang/typescript/generics.md +356 -0
- package/configs/_shared/rules/lang/typescript/typescript.md +212 -0
- package/configs/_shared/rules/quality/error-handling.md +48 -0
- package/configs/_shared/rules/quality/logging.md +45 -0
- package/configs/_shared/rules/quality/observability.md +240 -0
- package/configs/_shared/rules/quality/testing-patterns.md +65 -0
- package/configs/_shared/rules/security/secrets-management.md +222 -0
- package/configs/_shared/skills/analysis/explore/SKILL.md +257 -0
- package/configs/_shared/skills/analysis/security-audit/SKILL.md +184 -0
- package/configs/_shared/skills/dev/api-endpoint/SKILL.md +126 -0
- package/configs/_shared/{.claude/commands/generate-tests.md → skills/dev/generate-tests/SKILL.md} +6 -0
- package/configs/_shared/{.claude/commands/fix-issue.md → skills/git/fix-issue/SKILL.md} +6 -0
- package/configs/_shared/{.claude/commands/review-pr.md → skills/git/review-pr/SKILL.md} +6 -0
- package/configs/_shared/skills/infra/deploy/SKILL.md +139 -0
- package/configs/_shared/skills/infra/docker/SKILL.md +95 -0
- package/configs/_shared/skills/infra/migration/SKILL.md +158 -0
- package/configs/_shared/skills/nx/nx-affected/SKILL.md +72 -0
- package/configs/_shared/skills/nx/nx-lib/SKILL.md +375 -0
- package/configs/angular/CLAUDE.md +24 -216
- package/configs/angular/{.claude/rules → rules/core}/components.md +69 -15
- package/configs/angular/rules/core/resource.md +285 -0
- package/configs/angular/rules/core/signals.md +323 -0
- package/configs/angular/rules/http.md +338 -0
- package/configs/angular/rules/routing.md +291 -0
- package/configs/angular/rules/ssr.md +312 -0
- package/configs/angular/rules/state/signal-store.md +408 -0
- package/configs/angular/{.claude/rules → rules/state}/state.md +2 -2
- package/configs/angular/{.claude/rules → rules}/testing.md +7 -7
- package/configs/angular/rules/ui/aria.md +422 -0
- package/configs/angular/rules/ui/forms.md +424 -0
- package/configs/angular/rules/ui/pipes-directives.md +335 -0
- package/configs/angular/{.claude/settings.json → settings.json} +3 -0
- package/configs/dotnet/CLAUDE.md +53 -286
- package/configs/dotnet/rules/background-services.md +552 -0
- package/configs/dotnet/rules/configuration.md +426 -0
- package/configs/dotnet/rules/ddd.md +447 -0
- package/configs/dotnet/rules/dependency-injection.md +343 -0
- package/configs/dotnet/rules/mediatr.md +320 -0
- package/configs/dotnet/rules/middleware.md +489 -0
- package/configs/dotnet/rules/result-pattern.md +363 -0
- package/configs/dotnet/rules/validation.md +388 -0
- package/configs/dotnet/settings.json +29 -0
- package/configs/fastapi/CLAUDE.md +144 -0
- package/configs/fastapi/rules/background-tasks.md +254 -0
- package/configs/fastapi/rules/dependencies.md +170 -0
- package/configs/{python/.claude → fastapi}/rules/fastapi.md +61 -1
- package/configs/fastapi/rules/lifespan.md +274 -0
- package/configs/fastapi/rules/middleware.md +229 -0
- package/configs/fastapi/rules/pydantic.md +433 -0
- package/configs/fastapi/rules/responses.md +251 -0
- package/configs/fastapi/rules/routers.md +202 -0
- package/configs/fastapi/rules/security.md +222 -0
- package/configs/fastapi/rules/testing.md +251 -0
- package/configs/fastapi/rules/websockets.md +298 -0
- package/configs/fastapi/settings.json +35 -0
- package/configs/flask/CLAUDE.md +166 -0
- package/configs/flask/rules/blueprints.md +208 -0
- package/configs/flask/rules/cli.md +285 -0
- package/configs/flask/rules/configuration.md +281 -0
- package/configs/flask/rules/context.md +238 -0
- package/configs/flask/rules/error-handlers.md +278 -0
- package/configs/flask/rules/extensions.md +278 -0
- package/configs/flask/rules/flask.md +171 -0
- package/configs/flask/rules/marshmallow.md +206 -0
- package/configs/flask/rules/security.md +267 -0
- package/configs/flask/rules/testing.md +284 -0
- package/configs/flask/settings.json +35 -0
- package/configs/nestjs/CLAUDE.md +57 -215
- package/configs/nestjs/rules/common-patterns.md +300 -0
- package/configs/nestjs/rules/filters.md +376 -0
- package/configs/nestjs/rules/interceptors.md +317 -0
- package/configs/nestjs/rules/middleware.md +321 -0
- package/configs/nestjs/{.claude/rules → rules}/modules.md +26 -0
- package/configs/nestjs/rules/pipes.md +351 -0
- package/configs/nestjs/rules/websockets.md +451 -0
- package/configs/nestjs/settings.json +31 -0
- package/configs/nextjs/CLAUDE.md +69 -331
- package/configs/nextjs/rules/api-routes.md +358 -0
- package/configs/nextjs/rules/authentication.md +355 -0
- package/configs/nextjs/{.claude/rules → rules}/components.md +52 -0
- package/configs/nextjs/rules/data-fetching.md +249 -0
- package/configs/nextjs/rules/database.md +400 -0
- package/configs/nextjs/rules/middleware.md +303 -0
- package/configs/nextjs/rules/routing.md +324 -0
- package/configs/nextjs/rules/seo.md +350 -0
- package/configs/nextjs/rules/server-actions.md +353 -0
- package/configs/nextjs/{.claude/rules → rules}/state/zustand.md +6 -6
- package/configs/nextjs/{.claude/settings.json → settings.json} +7 -0
- package/package.json +24 -9
- package/src/cli.js +218 -0
- package/src/config.js +63 -0
- package/src/index.js +4 -0
- package/src/installer.js +414 -0
- package/src/merge.js +109 -0
- package/src/tech-config.json +45 -0
- package/src/utils.js +88 -0
- package/configs/dotnet/.claude/settings.json +0 -9
- package/configs/nestjs/.claude/settings.json +0 -15
- package/configs/python/.claude/rules/flask.md +0 -332
- package/configs/python/.claude/settings.json +0 -18
- package/configs/python/CLAUDE.md +0 -273
- package/src/install.js +0 -315
- /package/configs/_shared/{.claude/rules → rules/domain/frontend}/accessibility.md +0 -0
- /package/configs/_shared/{.claude/rules → rules/security}/security.md +0 -0
- /package/configs/_shared/{.claude/skills → skills/dev}/debug/SKILL.md +0 -0
- /package/configs/_shared/{.claude/skills → skills/dev}/learning/SKILL.md +0 -0
- /package/configs/_shared/{.claude/skills → skills/dev}/spec/SKILL.md +0 -0
- /package/configs/_shared/{.claude/skills → skills/git}/review/SKILL.md +0 -0
- /package/configs/dotnet/{.claude/rules → rules}/api.md +0 -0
- /package/configs/dotnet/{.claude/rules → rules}/architecture.md +0 -0
- /package/configs/dotnet/{.claude/rules → rules}/database/efcore.md +0 -0
- /package/configs/dotnet/{.claude/rules → rules}/testing.md +0 -0
- /package/configs/nestjs/{.claude/rules → rules}/auth.md +0 -0
- /package/configs/nestjs/{.claude/rules → rules}/database/prisma.md +0 -0
- /package/configs/nestjs/{.claude/rules → rules}/database/typeorm.md +0 -0
- /package/configs/nestjs/{.claude/rules → rules}/testing.md +0 -0
- /package/configs/nestjs/{.claude/rules → rules}/validation.md +0 -0
- /package/configs/nextjs/{.claude/rules → rules}/state/redux-toolkit.md +0 -0
- /package/configs/nextjs/{.claude/rules → rules}/testing.md +0 -0
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nx-lib
|
|
3
|
+
description: Generate an Nx library for any framework with proper structure and tags
|
|
4
|
+
argument-hint: <framework> <type> <scope>/<name>
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Generate Nx Library
|
|
8
|
+
|
|
9
|
+
## Syntax
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
/nx-lib <framework> <type> <scope>/<name>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Supported Frameworks
|
|
16
|
+
|
|
17
|
+
| Framework | Generator Package |
|
|
18
|
+
|-----------|-------------------|
|
|
19
|
+
| `angular` | `@nx/angular` |
|
|
20
|
+
| `react` | `@nx/react` |
|
|
21
|
+
| `next` | `@nx/next` |
|
|
22
|
+
| `nest` | `@nx/nest` |
|
|
23
|
+
| `node` | `@nx/node` |
|
|
24
|
+
| `js` | `@nx/js` (pure TypeScript) |
|
|
25
|
+
| `dotnet` | `@nx-dotnet/core` |
|
|
26
|
+
| `python` | `@nxlv/python` |
|
|
27
|
+
|
|
28
|
+
## Library Types by Framework
|
|
29
|
+
|
|
30
|
+
### Angular
|
|
31
|
+
| Type | Description | Generator |
|
|
32
|
+
|------|-------------|-----------|
|
|
33
|
+
| `feature` | Smart components, pages, routing | `@nx/angular:lib --standalone` |
|
|
34
|
+
| `ui` | Presentational components | `@nx/angular:lib --standalone` |
|
|
35
|
+
| `data-access` | NgRx store, services | `@nx/angular:lib` + NgRx files |
|
|
36
|
+
| `util` | Pure functions, types | `@nx/js:lib` |
|
|
37
|
+
|
|
38
|
+
### React / Next.js
|
|
39
|
+
| Type | Description | Generator |
|
|
40
|
+
|------|-------------|-----------|
|
|
41
|
+
| `feature` | Pages, containers | `@nx/react:lib` or `@nx/next:lib` |
|
|
42
|
+
| `ui` | Presentational components | `@nx/react:lib` |
|
|
43
|
+
| `data-access` | Zustand/Redux, API hooks | `@nx/react:lib` |
|
|
44
|
+
| `util` | Pure functions, types | `@nx/js:lib` |
|
|
45
|
+
|
|
46
|
+
### NestJS
|
|
47
|
+
| Type | Description | Generator |
|
|
48
|
+
|------|-------------|-----------|
|
|
49
|
+
| `feature` | Module with controller | `@nx/nest:lib` + controller |
|
|
50
|
+
| `data-access` | Repository, services | `@nx/nest:lib` |
|
|
51
|
+
| `util` | Pure functions, types | `@nx/js:lib` |
|
|
52
|
+
|
|
53
|
+
### Node / JS
|
|
54
|
+
| Type | Description | Generator |
|
|
55
|
+
|------|-------------|-----------|
|
|
56
|
+
| `util` | Pure functions, types | `@nx/js:lib` |
|
|
57
|
+
| `data-access` | Services, repositories | `@nx/js:lib` |
|
|
58
|
+
|
|
59
|
+
### .NET
|
|
60
|
+
| Type | Description | Generator |
|
|
61
|
+
|------|-------------|-----------|
|
|
62
|
+
| `webapi` | ASP.NET Core Web API | `@nx-dotnet/core:app --template webapi` |
|
|
63
|
+
| `classlib` | Class library | `@nx-dotnet/core:lib --template classlib` |
|
|
64
|
+
| `feature` | Feature library (CQRS) | `@nx-dotnet/core:lib` + MediatR handlers |
|
|
65
|
+
| `data-access` | EF Core repositories | `@nx-dotnet/core:lib` + DbContext |
|
|
66
|
+
| `util` | Shared utilities | `@nx-dotnet/core:lib --template classlib` |
|
|
67
|
+
|
|
68
|
+
### Python
|
|
69
|
+
| Type | Description | Generator |
|
|
70
|
+
|------|-------------|-----------|
|
|
71
|
+
| `app` | FastAPI/Flask app | `@nxlv/python:poetry-project` |
|
|
72
|
+
| `lib` | Python library | `@nxlv/python:poetry-project --projectType=library` |
|
|
73
|
+
| `util` | Utility functions | `@nxlv/python:poetry-project --projectType=library` |
|
|
74
|
+
|
|
75
|
+
## Examples
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Angular feature library
|
|
79
|
+
/nx-lib angular feature users/list
|
|
80
|
+
|
|
81
|
+
# Angular data-access with NgRx
|
|
82
|
+
/nx-lib angular data-access users
|
|
83
|
+
|
|
84
|
+
# React UI component library
|
|
85
|
+
/nx-lib react ui shared/button
|
|
86
|
+
|
|
87
|
+
# NestJS feature module
|
|
88
|
+
/nx-lib nest feature orders
|
|
89
|
+
|
|
90
|
+
# Pure TypeScript utility
|
|
91
|
+
/nx-lib js util shared/format
|
|
92
|
+
|
|
93
|
+
# .NET class library
|
|
94
|
+
/nx-lib dotnet classlib shared/domain
|
|
95
|
+
|
|
96
|
+
# .NET Web API
|
|
97
|
+
/nx-lib dotnet webapi orders
|
|
98
|
+
|
|
99
|
+
# .NET data-access with EF Core
|
|
100
|
+
/nx-lib dotnet data-access users
|
|
101
|
+
|
|
102
|
+
# Python FastAPI app
|
|
103
|
+
/nx-lib python app api
|
|
104
|
+
|
|
105
|
+
# Python library
|
|
106
|
+
/nx-lib python lib shared/utils
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Execution Steps
|
|
110
|
+
|
|
111
|
+
### Step 1: Parse Arguments
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
/nx-lib angular data-access users/profile
|
|
115
|
+
│ │ │
|
|
116
|
+
│ │ └── scope: users, name: profile
|
|
117
|
+
│ └── type: data-access
|
|
118
|
+
└── framework: angular
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Step 2: Run Generator
|
|
122
|
+
|
|
123
|
+
Based on framework and type:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Angular feature/ui
|
|
127
|
+
nx g @nx/angular:lib <name> \
|
|
128
|
+
--directory=libs/<scope>/<type>-<name> \
|
|
129
|
+
--tags="scope:<scope>,type:<type>" \
|
|
130
|
+
--standalone \
|
|
131
|
+
--style=scss \
|
|
132
|
+
--changeDetection=OnPush
|
|
133
|
+
|
|
134
|
+
# Angular data-access
|
|
135
|
+
nx g @nx/angular:lib <name> \
|
|
136
|
+
--directory=libs/<scope>/data-access \
|
|
137
|
+
--tags="scope:<scope>,type:data-access"
|
|
138
|
+
# Then generate NgRx: actions, reducer, effects, selectors
|
|
139
|
+
|
|
140
|
+
# React/Next feature/ui
|
|
141
|
+
nx g @nx/react:lib <name> \
|
|
142
|
+
--directory=libs/<scope>/<type>-<name> \
|
|
143
|
+
--tags="scope:<scope>,type:<type>"
|
|
144
|
+
|
|
145
|
+
# NestJS feature
|
|
146
|
+
nx g @nx/nest:lib <name> \
|
|
147
|
+
--directory=libs/<scope>/feature-<name> \
|
|
148
|
+
--tags="scope:<scope>,type:feature"
|
|
149
|
+
# Then generate controller
|
|
150
|
+
|
|
151
|
+
# Pure JS/TS util
|
|
152
|
+
nx g @nx/js:lib <name> \
|
|
153
|
+
--directory=libs/<scope>/util-<name> \
|
|
154
|
+
--tags="scope:<scope>,type:util" \
|
|
155
|
+
--bundler=none
|
|
156
|
+
|
|
157
|
+
# .NET class library
|
|
158
|
+
nx g @nx-dotnet/core:lib <name> \
|
|
159
|
+
--directory=libs/<scope>/<type>-<name> \
|
|
160
|
+
--template=classlib \
|
|
161
|
+
--tags="scope:<scope>,type:<type>,framework:dotnet"
|
|
162
|
+
|
|
163
|
+
# .NET Web API
|
|
164
|
+
nx g @nx-dotnet/core:app <name> \
|
|
165
|
+
--directory=apps/<name> \
|
|
166
|
+
--template=webapi \
|
|
167
|
+
--tags="scope:<scope>,type:webapi,framework:dotnet"
|
|
168
|
+
|
|
169
|
+
# Python library
|
|
170
|
+
nx g @nxlv/python:poetry-project <name> \
|
|
171
|
+
--directory=libs/<scope>/<type>-<name> \
|
|
172
|
+
--projectType=library \
|
|
173
|
+
--tags="scope:<scope>,type:<type>,framework:python"
|
|
174
|
+
|
|
175
|
+
# Python app
|
|
176
|
+
nx g @nxlv/python:poetry-project <name> \
|
|
177
|
+
--directory=apps/<name> \
|
|
178
|
+
--projectType=application \
|
|
179
|
+
--tags="scope:<scope>,type:app,framework:python"
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Step 3: Generate Boilerplate by Type
|
|
183
|
+
|
|
184
|
+
#### Angular `data-access`
|
|
185
|
+
```
|
|
186
|
+
libs/<scope>/data-access/src/lib/
|
|
187
|
+
├── +state/
|
|
188
|
+
│ ├── <name>.actions.ts
|
|
189
|
+
│ ├── <name>.reducer.ts
|
|
190
|
+
│ ├── <name>.effects.ts
|
|
191
|
+
│ ├── <name>.selectors.ts
|
|
192
|
+
│ └── <name>.state.ts
|
|
193
|
+
├── services/
|
|
194
|
+
│ └── <name>.service.ts
|
|
195
|
+
└── index.ts
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### Angular `feature`
|
|
199
|
+
```
|
|
200
|
+
libs/<scope>/feature-<name>/src/lib/
|
|
201
|
+
├── <name>.component.ts
|
|
202
|
+
├── <name>.component.html
|
|
203
|
+
├── <name>.component.scss
|
|
204
|
+
├── <name>.routes.ts
|
|
205
|
+
└── index.ts
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### Angular `ui`
|
|
209
|
+
```
|
|
210
|
+
libs/<scope>/ui-<name>/src/lib/
|
|
211
|
+
├── <name>.component.ts
|
|
212
|
+
├── <name>.component.html
|
|
213
|
+
├── <name>.component.scss
|
|
214
|
+
└── index.ts
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### React `data-access`
|
|
218
|
+
```
|
|
219
|
+
libs/<scope>/data-access/src/lib/
|
|
220
|
+
├── store/
|
|
221
|
+
│ └── <name>.store.ts # Zustand store
|
|
222
|
+
├── hooks/
|
|
223
|
+
│ └── use-<name>.ts # Custom hooks
|
|
224
|
+
├── api/
|
|
225
|
+
│ └── <name>.api.ts # API calls
|
|
226
|
+
└── index.ts
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### NestJS `feature`
|
|
230
|
+
```
|
|
231
|
+
libs/<scope>/feature-<name>/src/lib/
|
|
232
|
+
├── <name>.module.ts
|
|
233
|
+
├── <name>.controller.ts
|
|
234
|
+
├── <name>.service.ts
|
|
235
|
+
├── dto/
|
|
236
|
+
│ ├── create-<name>.dto.ts
|
|
237
|
+
│ └── update-<name>.dto.ts
|
|
238
|
+
└── index.ts
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### JS/TS `util`
|
|
242
|
+
```
|
|
243
|
+
libs/<scope>/util-<name>/src/lib/
|
|
244
|
+
├── <name>.ts # Functions
|
|
245
|
+
├── <name>.types.ts # Types/interfaces
|
|
246
|
+
├── <name>.spec.ts # Tests
|
|
247
|
+
└── index.ts
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### .NET `webapi`
|
|
251
|
+
```
|
|
252
|
+
apps/<name>/
|
|
253
|
+
├── Controllers/
|
|
254
|
+
│ └── <Name>Controller.cs
|
|
255
|
+
├── Program.cs
|
|
256
|
+
├── appsettings.json
|
|
257
|
+
├── <Name>.Api.csproj
|
|
258
|
+
└── project.json
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
#### .NET `classlib`
|
|
262
|
+
```
|
|
263
|
+
libs/<scope>/<type>-<name>/
|
|
264
|
+
├── src/
|
|
265
|
+
│ └── <Name>.cs
|
|
266
|
+
├── <Scope>.<Type>.<Name>.csproj
|
|
267
|
+
└── project.json
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
#### .NET `data-access`
|
|
271
|
+
```
|
|
272
|
+
libs/<scope>/data-access/
|
|
273
|
+
├── src/
|
|
274
|
+
│ ├── DbContext/
|
|
275
|
+
│ │ └── AppDbContext.cs
|
|
276
|
+
│ ├── Repositories/
|
|
277
|
+
│ │ ├── I<Name>Repository.cs
|
|
278
|
+
│ │ └── <Name>Repository.cs
|
|
279
|
+
│ └── Entities/
|
|
280
|
+
│ └── <Name>.cs
|
|
281
|
+
├── <Scope>.DataAccess.csproj
|
|
282
|
+
└── project.json
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### .NET `feature` (CQRS)
|
|
286
|
+
```
|
|
287
|
+
libs/<scope>/feature-<name>/
|
|
288
|
+
├── src/
|
|
289
|
+
│ ├── Commands/
|
|
290
|
+
│ │ ├── Create<Name>/
|
|
291
|
+
│ │ │ ├── Create<Name>Command.cs
|
|
292
|
+
│ │ │ └── Create<Name>Handler.cs
|
|
293
|
+
│ │ └── Update<Name>/
|
|
294
|
+
│ │ ├── Update<Name>Command.cs
|
|
295
|
+
│ │ └── Update<Name>Handler.cs
|
|
296
|
+
│ ├── Queries/
|
|
297
|
+
│ │ └── Get<Name>/
|
|
298
|
+
│ │ ├── Get<Name>Query.cs
|
|
299
|
+
│ │ └── Get<Name>Handler.cs
|
|
300
|
+
│ └── DependencyInjection.cs
|
|
301
|
+
├── <Scope>.Feature.<Name>.csproj
|
|
302
|
+
└── project.json
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### Python `app` (FastAPI)
|
|
306
|
+
```
|
|
307
|
+
apps/<name>/
|
|
308
|
+
├── src/
|
|
309
|
+
│ └── <name>/
|
|
310
|
+
│ ├── __init__.py
|
|
311
|
+
│ ├── main.py
|
|
312
|
+
│ ├── routers/
|
|
313
|
+
│ │ └── <name>_router.py
|
|
314
|
+
│ ├── schemas/
|
|
315
|
+
│ │ └── <name>_schema.py
|
|
316
|
+
│ └── services/
|
|
317
|
+
│ └── <name>_service.py
|
|
318
|
+
├── tests/
|
|
319
|
+
│ └── test_<name>.py
|
|
320
|
+
├── pyproject.toml
|
|
321
|
+
└── project.json
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
#### Python `lib`
|
|
325
|
+
```
|
|
326
|
+
libs/<scope>/<type>-<name>/
|
|
327
|
+
├── src/
|
|
328
|
+
│ └── <name>/
|
|
329
|
+
│ ├── __init__.py
|
|
330
|
+
│ └── <name>.py
|
|
331
|
+
├── tests/
|
|
332
|
+
│ └── test_<name>.py
|
|
333
|
+
├── pyproject.toml
|
|
334
|
+
└── project.json
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Step 4: Configure project.json
|
|
338
|
+
|
|
339
|
+
```json
|
|
340
|
+
{
|
|
341
|
+
"name": "<scope>-<type>-<name>",
|
|
342
|
+
"tags": ["scope:<scope>", "type:<type>", "framework:<framework>"]
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Step 5: Update Public API (index.ts)
|
|
347
|
+
|
|
348
|
+
Export all public items appropriately for the type.
|
|
349
|
+
|
|
350
|
+
### Step 6: Verify
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
nx lint <project-name>
|
|
354
|
+
nx test <project-name>
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Output Summary
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
✓ Created library: libs/<scope>/<type>-<name>
|
|
361
|
+
|
|
362
|
+
Import path: @<org>/<scope>/<type>-<name>
|
|
363
|
+
Project name: <scope>-<type>-<name>
|
|
364
|
+
Tags: scope:<scope>, type:<type>, framework:<framework>
|
|
365
|
+
|
|
366
|
+
Files created:
|
|
367
|
+
- libs/<scope>/<type>-<name>/src/index.ts
|
|
368
|
+
- libs/<scope>/<type>-<name>/src/lib/...
|
|
369
|
+
- libs/<scope>/<type>-<name>/project.json
|
|
370
|
+
|
|
371
|
+
Next steps:
|
|
372
|
+
- Add business logic
|
|
373
|
+
- Export public API from index.ts
|
|
374
|
+
- Run: nx test <scope>-<type>-<name>
|
|
375
|
+
```
|
|
@@ -4,33 +4,32 @@
|
|
|
4
4
|
|
|
5
5
|
## Stack
|
|
6
6
|
|
|
7
|
-
- Angular 21+ (
|
|
7
|
+
- Angular 21+ (Zoneless, Signals)
|
|
8
8
|
- Nx monorepo
|
|
9
|
-
- NgRx (
|
|
10
|
-
- Vitest
|
|
9
|
+
- NgRx (Entity Adapter, Functional Effects)
|
|
10
|
+
- Vitest, Playwright
|
|
11
11
|
- TypeScript strict mode
|
|
12
12
|
|
|
13
|
-
## Architecture - Nx
|
|
13
|
+
## Architecture - Nx
|
|
14
14
|
|
|
15
15
|
```
|
|
16
|
-
apps/
|
|
17
|
-
[app-name]/
|
|
16
|
+
apps/[app-name]/
|
|
18
17
|
|
|
19
18
|
libs/
|
|
20
|
-
[domain]/ #
|
|
21
|
-
feature/ # Smart components, pages
|
|
22
|
-
data-access/ #
|
|
19
|
+
[domain]/ # users, products, checkout
|
|
20
|
+
feature/ # Smart components, pages (lazy-loaded)
|
|
21
|
+
data-access/ # NgRx store, API services
|
|
23
22
|
src/lib/+state/ # Actions, reducers, effects, selectors
|
|
24
23
|
ui/ # Dumb/presentational components
|
|
25
|
-
util/ # Domain
|
|
24
|
+
util/ # Domain helpers
|
|
26
25
|
|
|
27
26
|
shared/
|
|
28
|
-
ui/ #
|
|
29
|
-
data-access/ #
|
|
30
|
-
util/ # Pure functions
|
|
27
|
+
ui/ # Design system components
|
|
28
|
+
data-access/ # Auth, interceptors
|
|
29
|
+
util/ # Pure functions
|
|
31
30
|
```
|
|
32
31
|
|
|
33
|
-
### Dependency Rules (
|
|
32
|
+
### Dependency Rules (Nx tags)
|
|
34
33
|
|
|
35
34
|
| Type | Can import |
|
|
36
35
|
|------|------------|
|
|
@@ -39,213 +38,22 @@ libs/
|
|
|
39
38
|
| `data-access` | `data-access`, `util` only |
|
|
40
39
|
| `util` | `util` only |
|
|
41
40
|
|
|
42
|
-
##
|
|
43
|
-
|
|
44
|
-
### Zoneless by Default
|
|
45
|
-
|
|
46
|
-
- No zone.js - use signals for reactivity
|
|
47
|
-
- Use `ChangeDetectionStrategy.OnPush` on all components
|
|
48
|
-
- Never rely on zone.js for change detection
|
|
49
|
-
|
|
50
|
-
### Signals Everywhere
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
// State
|
|
54
|
-
count = signal(0);
|
|
55
|
-
items = signal<Item[]>([]);
|
|
56
|
-
|
|
57
|
-
// Derived state
|
|
58
|
-
doubleCount = computed(() => this.count() * 2);
|
|
59
|
-
isEmpty = computed(() => this.items().length === 0);
|
|
60
|
-
|
|
61
|
-
// Effects for side effects
|
|
62
|
-
effect(() => {
|
|
63
|
-
console.log('Count changed:', this.count());
|
|
64
|
-
});
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### Signal Forms (experimental but preferred)
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
// Use signal forms, NOT reactive forms
|
|
71
|
-
import { SignalForm } from '@angular/forms';
|
|
72
|
-
|
|
73
|
-
form = signalForm({
|
|
74
|
-
name: '',
|
|
75
|
-
email: '',
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// Access values
|
|
79
|
-
form.value(); // { name: '', email: '' }
|
|
80
|
-
form.controls.name(); // ''
|
|
81
|
-
form.valid(); // boolean signal
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Standalone Components (Default)
|
|
85
|
-
|
|
86
|
-
- No NgModules for components
|
|
87
|
-
- `standalone: true` is the default - don't add it
|
|
88
|
-
- Import dependencies directly in component
|
|
89
|
-
- Always use separate template files (`.html`)
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
@Component({
|
|
93
|
-
selector: 'app-example',
|
|
94
|
-
imports: [RouterModule],
|
|
95
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
96
|
-
templateUrl: './example.component.html',
|
|
97
|
-
styleUrl: './example.component.scss',
|
|
98
|
-
})
|
|
99
|
-
export class ExampleComponent {}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Inject Function
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
// Preferred
|
|
106
|
-
export class MyComponent {
|
|
107
|
-
private readonly store = inject(Store);
|
|
108
|
-
private readonly http = inject(HttpClient);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Avoid constructor injection
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Signal Inputs/Outputs (not decorators)
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
// Inputs - use input() function, NOT @Input() decorator
|
|
118
|
-
name = input<string>(); // Optional
|
|
119
|
-
name = input('default'); // With default
|
|
120
|
-
name = input.required<string>(); // Required
|
|
121
|
-
|
|
122
|
-
// Outputs - use output() function, NOT @Output() decorator
|
|
123
|
-
clicked = output<void>();
|
|
124
|
-
selected = output<Item>();
|
|
125
|
-
|
|
126
|
-
// Two-way binding - use model() function
|
|
127
|
-
value = model<string>(''); // Creates input + output pair
|
|
128
|
-
value = model.required<string>(); // Required two-way binding
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
## Component Architecture
|
|
132
|
-
|
|
133
|
-
### Smart Components (feature/)
|
|
134
|
-
|
|
135
|
-
- Located in `feature/` libs
|
|
136
|
-
- Inject store, dispatch actions
|
|
137
|
-
- Handle routing logic
|
|
138
|
-
- Pass data to UI components via inputs
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
// user-list-page.component.ts
|
|
142
|
-
@Component({
|
|
143
|
-
selector: 'app-user-list-page',
|
|
144
|
-
imports: [UserListComponent],
|
|
145
|
-
templateUrl: './user-list-page.component.html',
|
|
146
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
147
|
-
})
|
|
148
|
-
export class UserListPageComponent {
|
|
149
|
-
private readonly store = inject(Store);
|
|
150
|
-
|
|
151
|
-
users = this.store.selectSignal(selectAllUsers);
|
|
152
|
-
loading = this.store.selectSignal(selectUsersLoading);
|
|
153
|
-
|
|
154
|
-
onUserSelect(user: User): void {
|
|
155
|
-
this.store.dispatch(UserActions.selectUser({ user }));
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
```html
|
|
161
|
-
<!-- user-list-page.component.html -->
|
|
162
|
-
<app-user-list
|
|
163
|
-
[users]="users()"
|
|
164
|
-
[loading]="loading()"
|
|
165
|
-
(userSelected)="onUserSelect($event)"
|
|
166
|
-
/>
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### UI Components (ui/)
|
|
170
|
-
|
|
171
|
-
- Located in `ui/` libs
|
|
172
|
-
- NO store injection - never!
|
|
173
|
-
- Pure inputs/outputs only
|
|
174
|
-
- Fully presentational
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
// user-list.component.ts
|
|
178
|
-
@Component({
|
|
179
|
-
selector: 'app-user-list',
|
|
180
|
-
templateUrl: './user-list.component.html',
|
|
181
|
-
styleUrl: './user-list.component.scss',
|
|
182
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
183
|
-
})
|
|
184
|
-
export class UserListComponent {
|
|
185
|
-
users = input.required<User[]>();
|
|
186
|
-
loading = input(false);
|
|
187
|
-
userSelected = output<User>();
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
```html
|
|
192
|
-
<!-- user-list.component.html -->
|
|
193
|
-
@for (user of users(); track user.id) {
|
|
194
|
-
<div class="user-item" (click)="userSelected.emit(user)">
|
|
195
|
-
{{ user.name }}
|
|
196
|
-
</div>
|
|
197
|
-
} @empty {
|
|
198
|
-
<p>No users found</p>
|
|
199
|
-
}
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
## Build & Commands
|
|
41
|
+
## Commands
|
|
203
42
|
|
|
204
43
|
```bash
|
|
205
|
-
#
|
|
206
|
-
nx
|
|
207
|
-
|
|
208
|
-
#
|
|
209
|
-
nx
|
|
210
|
-
nx build [app-name] --configuration=production
|
|
211
|
-
|
|
212
|
-
# Test
|
|
213
|
-
nx test [lib-name] # Single lib
|
|
214
|
-
nx run-many -t test # All tests
|
|
215
|
-
nx affected -t test # Only affected
|
|
216
|
-
|
|
217
|
-
# Lint
|
|
218
|
-
nx lint [project-name]
|
|
219
|
-
nx run-many -t lint
|
|
220
|
-
|
|
221
|
-
# Generate
|
|
44
|
+
nx serve [app] # Dev server
|
|
45
|
+
nx build [app] --configuration=production
|
|
46
|
+
nx test [lib] # Unit tests
|
|
47
|
+
nx affected -t test # Test affected
|
|
48
|
+
nx e2e [app]-e2e # E2E tests
|
|
222
49
|
nx g @nx/angular:component [name] --project=[lib]
|
|
223
50
|
nx g @nx/angular:library [name] --directory=libs/[domain]
|
|
224
51
|
```
|
|
225
52
|
|
|
226
53
|
## Code Style
|
|
227
54
|
|
|
228
|
-
-
|
|
229
|
-
-
|
|
230
|
-
-
|
|
231
|
-
-
|
|
232
|
-
-
|
|
233
|
-
|
|
234
|
-
## RxJS Guidelines
|
|
235
|
-
|
|
236
|
-
- Prefer signals over observables when possible
|
|
237
|
-
- Use `toSignal()` to convert observables
|
|
238
|
-
- Clean subscriptions with `takeUntilDestroyed()`
|
|
239
|
-
- Avoid nested subscribes - use operators
|
|
240
|
-
|
|
241
|
-
```typescript
|
|
242
|
-
// Convert observable to signal
|
|
243
|
-
data = toSignal(this.http.get<Data[]>('/api/data'), { initialValue: [] });
|
|
244
|
-
|
|
245
|
-
// If you must use observables
|
|
246
|
-
private readonly destroyRef = inject(DestroyRef);
|
|
247
|
-
|
|
248
|
-
this.source$.pipe(
|
|
249
|
-
takeUntilDestroyed(this.destroyRef)
|
|
250
|
-
).subscribe();
|
|
251
|
-
```
|
|
55
|
+
- Folder-based structure: `user-list/user-list.component.ts`
|
|
56
|
+
- Explicit return types on public methods
|
|
57
|
+
- `readonly` for injected services
|
|
58
|
+
- `track` required in `@for` loops
|
|
59
|
+
- Prefix configurable per project (default: `app`)
|