moicle 1.3.1 → 1.4.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 CHANGED
@@ -112,7 +112,8 @@ moicle install
112
112
  | `new-feature` | "implement feature", "add feature", "build feature" |
113
113
  | `hotfix` | "fix bug", "hotfix", "urgent fix", "production issue" |
114
114
  | `pr-review` | "review pr", "check pr", "review code" |
115
- | `release` | "release", "deploy", "ship" |
115
+ | `release` | "release", "deploy" |
116
+ | `deep-debug` | "deep debug", "trace bug", "find root cause", "hard bug" |
116
117
  | `refactor` | "refactor", "clean up", "improve code" |
117
118
  | `tdd` | "tdd", "test first", "test driven" |
118
119
  | `onboarding` | "explain codebase", "onboard", "new to project" |
@@ -0,0 +1,337 @@
1
+ # DDD Architecture Reference
2
+
3
+ > **Standard architecture** for all stacks. Every project follows this structure. Stack-specific docs extend this with implementation details.
4
+
5
+ ## Overview
6
+
7
+ Domain-Driven Design with Hexagonal Architecture (Ports & Adapters). Business logic lives in the Domain layer, isolated from frameworks, databases, and UI.
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────┐
11
+ │ Application │
12
+ │ (Handlers, Controllers, UI, Listeners) │
13
+ ├─────────────────────────────────────────────────────┤
14
+ │ Domain │
15
+ │ (Entities, Value Objects, Ports, UseCases, Events) │
16
+ ├─────────────────────────────────────────────────────┤
17
+ │ Infrastructure │
18
+ │ (DB, API Clients, Cache, Messaging) │
19
+ └─────────────────────────────────────────────────────┘
20
+ ```
21
+
22
+ **Dependency Rule:** Dependencies point **inward** only. Domain depends on nothing. Application and Infrastructure depend on Domain via **ports (interfaces)**.
23
+
24
+ ---
25
+
26
+ ## Standard Directory Structure
27
+
28
+ Every project, regardless of stack, follows this structure:
29
+
30
+ ```
31
+ {project_root}/
32
+ ├── domain/
33
+ │ └── {domain}/
34
+ │ ├── entities/ # Aggregates + entities with behavior
35
+ │ ├── valueobjects/ # Immutable typed values with behavior
36
+ │ ├── ports/ # Interfaces (1 file per port)
37
+ │ ├── events/ # Domain events (1 file per event)
38
+ │ ├── usecases/ # Business logic orchestration
39
+ │ └── validators/ # (optional) Pure validation rules
40
+
41
+ ├── application/
42
+ │ ├── ports/
43
+ │ │ └── {transport}/ # HTTP handlers / UI screens / CLI
44
+ │ ├── services/ # Thin wrappers -> domain usecases
45
+ │ └── listeners/ # Event side-effects
46
+
47
+ ├── infrastructure/
48
+ │ ├── {persistence}/ # DB / API client implementations
49
+ │ ├── adapters/ # External service adapters
50
+ │ └── {shared_infra}/ # Cache, messaging, auth, logger
51
+
52
+ └── models/ # Persistence models (ORM/schema)
53
+ ```
54
+
55
+ ### Stack-Specific Mapping
56
+
57
+ | Generic | Go + Gin | React + Vite | Flutter | Laravel | Remix |
58
+ |---------|----------|-------------|---------|---------|-------|
59
+ | `domain/` | `internal/domain/` | `src/domain/` | `lib/domain/` | `app/Domain/` | `app/domain/` |
60
+ | `application/ports/{transport}/` | `application/ports/http/` | `application/ports/ui/` | `application/ports/ui/` | `app/Http/Controllers/` | `app/routes/` |
61
+ | `application/services/` | `application/services/` | `application/services/` | `application/services/` | `app/Services/` | `app/domain/{domain}/services.server.ts` |
62
+ | `application/listeners/` | `application/listeners/` | `application/listeners/` | `application/listeners/` | `app/Listeners/` | `app/listeners/` |
63
+ | `infrastructure/{persistence}/` | `infrastructure/database/` | `infrastructure/api/` | `infrastructure/api/` | `app/Infrastructure/Repositories/` | `app/infrastructure/` |
64
+ | `models/` | `internal/models/` | N/A (types in domain) | N/A (freezed in domain) | `app/Models/` | `prisma/schema.prisma` |
65
+
66
+ ---
67
+
68
+ ## Domain Layer
69
+
70
+ The heart of the system. **ZERO framework dependencies.** Only stdlib/language built-ins allowed.
71
+
72
+ ### Entities (`entities/`)
73
+
74
+ Business objects with **behavior**, not just data bags.
75
+
76
+ **Rules:**
77
+ - Constructor: `New{Entity}()` / `create{Entity}()` / `{Entity}.create()`
78
+ - State transitions via behavior methods (not direct field mutation)
79
+ - Embed/use EventCollector to raise domain events on state changes
80
+ - Guard methods: `isActive()`, `canTransitionTo()`, `isExpired()`
81
+ - Only imports: stdlib + valueobjects + shared (within same domain)
82
+
83
+ **Anti-patterns:**
84
+ - Anemic entity (only getters/setters, no behavior)
85
+ - Entity importing framework/infra packages
86
+ - Business logic outside entity (in controller or store)
87
+
88
+ ### Value Objects (`valueobjects/`)
89
+
90
+ Immutable types with behavior. Represent concepts like Money, Email, Status, Rate.
91
+
92
+ **Rules:**
93
+ - Only stdlib imports (NO external packages, NO domain/shared)
94
+ - Immutable: no setters, return new instance on change
95
+ - Behavior methods: `IsTerminal()`, `CanTransitionTo()`, `Format()`, `Validate()`
96
+ - Typed strings for enums with query methods
97
+ - Must be in `valueobjects/` directory, NOT mixed in `entities/`
98
+
99
+ ### Ports (`ports/`)
100
+
101
+ Interfaces that define how the domain communicates with the outside world. Hexagonal architecture's "ports".
102
+
103
+ **Rules:**
104
+ - One file per port interface
105
+ - Store ports: `{entity}_store` — persistence interface + related DTOs
106
+ - Adapter ports: `{adapter_name}` — external service interface
107
+ - Use domain types (entities, value objects) in signatures, NOT primitives for typed values
108
+ - Platform-agnostic naming: `URLParser`, NOT `ShopeeURLParser`
109
+ - No infrastructure imports
110
+
111
+ ### Events (`events/`)
112
+
113
+ Domain events represent something significant that happened in the domain.
114
+
115
+ **Rules:**
116
+ - One file per event
117
+ - Embed/extend base event type from shared
118
+ - Naming: `{Domain}{Action}` (e.g., `WalletWithdrawalCreated`, `OrderCompleted`)
119
+ - Carry data needed by listeners (userID, amounts, names)
120
+ - Event name string MUST match event registry
121
+
122
+ ### UseCases (`usecases/`)
123
+
124
+ Business logic orchestration. The "what" of the system.
125
+
126
+ **Rules:**
127
+ - Constructor struct/class with port dependencies (injected via interfaces)
128
+ - Split by concern: one file per action group
129
+ - Business logic lives HERE, not in store/controller/service
130
+ - Dispatch entity events after successful persistence
131
+ - No infrastructure imports (no ORM, no HTTP framework, no cache client)
132
+ - No inline interface definitions — interfaces MUST be in `ports/`
133
+
134
+ ### Validators (`validators/`) — optional
135
+
136
+ Pure validation rules. No DB access, no side effects.
137
+
138
+ ---
139
+
140
+ ## Application Layer
141
+
142
+ Thin layer that wires domain to the outside world.
143
+
144
+ ### Ports/Transport (`ports/{transport}/`)
145
+
146
+ HTTP handlers, UI screens, CLI commands. The entry point for user interactions.
147
+
148
+ **Rules:**
149
+ - Thin: parse request/input -> call service -> return response/render
150
+ - NO business logic
151
+ - Registration/wiring function: create store -> usecase -> service -> handler -> routes
152
+ - DTOs in separate file (request/response structs)
153
+
154
+ ### Services (`services/`)
155
+
156
+ Thin wrapper that delegates to domain usecases.
157
+
158
+ **Rules:**
159
+ - Orchestrate one or more usecases
160
+ - NO business logic — just delegation
161
+ - Can coordinate cross-domain calls if needed
162
+ - No infrastructure imports
163
+
164
+ ### Listeners (`listeners/`)
165
+
166
+ Handle domain event side-effects.
167
+
168
+ **Rules:**
169
+ - One file per event: `on_{event_name}`
170
+ - Side-effects only: notifications, SSE, analytics, async jobs
171
+ - Receive app/bootstrap context for accessing infrastructure
172
+ - Use background context for async work, NOT request context
173
+ - Register in event registry/bus
174
+
175
+ ---
176
+
177
+ ## Infrastructure Layer
178
+
179
+ Implements domain port interfaces. All framework/external dependencies live here.
180
+
181
+ **Rules:**
182
+ - Implements interfaces from `domain/{domain}/ports/`
183
+ - Compile-time interface check (where language supports it)
184
+ - Mapper functions between domain entities and persistence models
185
+ - NO business logic — pure persistence/communication
186
+ - Use context consistently
187
+
188
+ ---
189
+
190
+ ## Hard Rules (ALL stacks)
191
+
192
+ | # | Rule | Violation = |
193
+ |---|------|-------------|
194
+ | HR1 | Domain layer has ZERO framework/external imports | CRITICAL |
195
+ | HR2 | Domain A MUST NOT import Domain B | CRITICAL |
196
+ | HR3 | No circular imports/dependencies | CRITICAL |
197
+ | HR4 | Entities have behavior methods (not anemic) | HIGH |
198
+ | HR5 | Entities raise domain events on state changes | HIGH |
199
+ | HR6 | Ports are interfaces in `ports/` dir (not inline in usecases) | HIGH |
200
+ | HR7 | Ports use domain types, not primitives for typed values | MEDIUM |
201
+ | HR8 | UseCases contain business logic, not controllers/stores | HIGH |
202
+ | HR9 | Listeners handle side-effects, not usecases | HIGH |
203
+ | HR10 | One file per port interface | MEDIUM |
204
+ | HR11 | One file per domain event | MEDIUM |
205
+ | HR12 | Value objects only import stdlib | HIGH |
206
+ | HR13 | Service layer is thin (delegation only) | MEDIUM |
207
+ | HR14 | Controllers/handlers are thin (no business logic) | MEDIUM |
208
+ | HR15 | Infrastructure stores have no business logic | HIGH |
209
+
210
+ ---
211
+
212
+ ## Import Rules (Dependency Direction)
213
+
214
+ ```
215
+ valueobjects/ -> only stdlib
216
+ entities/ -> only stdlib + valueobjects + domain/shared
217
+ ports/ -> only stdlib + entities + valueobjects + domain/shared
218
+ events/ -> only stdlib + domain/shared
219
+ usecases/ -> entities + ports + events + valueobjects (NO infra)
220
+ validators/ -> entities + valueobjects
221
+
222
+ services/ -> usecases (thin wrapper)
223
+ ports/{transport}/ -> services + bootstrap/config + infrastructure utilities
224
+ listeners/ -> events + bootstrap/config + infrastructure utilities
225
+ infrastructure/ -> ports (implements interfaces) + models/persistence
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Domain Design Guidelines
231
+
232
+ ### How to Identify Domains
233
+
234
+ A domain is a bounded context — a cohesive area of business logic.
235
+
236
+ **Signs of a good domain boundary:**
237
+ - Has its own entities that don't belong elsewhere
238
+ - Has business rules specific to this area
239
+ - Can be described independently (e.g., "Wallet manages balances and transactions")
240
+ - Changes in this area don't require changes in other domains
241
+
242
+ **Example domains:**
243
+ | Domain | Responsibility |
244
+ |--------|---------------|
245
+ | Identity | Authentication, user profiles, sessions |
246
+ | Wallet | Balances, transactions, withdrawals |
247
+ | Catalog | Products, categories, search |
248
+ | Order | Order lifecycle, checkout, payment |
249
+ | Notification | Email, push, in-app messaging |
250
+
251
+ ### How to Identify Aggregates
252
+
253
+ An aggregate is a cluster of entities treated as a single unit for data changes.
254
+
255
+ **Rules:**
256
+ - One aggregate root per aggregate
257
+ - External references only to the aggregate root
258
+ - Transactions don't cross aggregate boundaries
259
+ - Cascade deletes within the aggregate
260
+
261
+ ### Cross-Domain Communication
262
+
263
+ Domains communicate via **domain events**, never by direct import.
264
+
265
+ ```
266
+ Domain A -> raises Event -> EventBus -> Listener -> Domain B service
267
+ ```
268
+
269
+ ---
270
+
271
+ ## Severity Levels
272
+
273
+ | Level | Meaning | Examples |
274
+ |-------|---------|---------|
275
+ | CRITICAL | Architecture broken | Build fails, circular imports, domain imports framework |
276
+ | HIGH | DDD violation | Cross-domain import, business logic in wrong layer, no ports |
277
+ | MEDIUM | Structure issue | Anemic entity, fat controller, missing events, missing tests |
278
+ | LOW | Convention issue | File naming, redundant code, DTOs in wrong package |
279
+
280
+ **ALL levels must be fixed** during review.
281
+
282
+ ---
283
+
284
+ ## Check Scripts Template
285
+
286
+ Each stack architecture doc provides specific check scripts. General pattern:
287
+
288
+ ```bash
289
+ # Phase check template (adapt per stack)
290
+
291
+ echo "=== Build ==="
292
+ {stack_build_command} && echo "PASS" || echo "FAIL"
293
+
294
+ echo "=== Lint ==="
295
+ {stack_lint_command} && echo "PASS" || echo "FAIL"
296
+
297
+ echo "=== Domain Purity ==="
298
+ # Check no framework imports in domain/
299
+ {grep_forbidden_imports_in_domain} && echo "FAIL" || echo "PASS"
300
+
301
+ echo "=== No Cross-Domain Imports ==="
302
+ # Check domain A doesn't import domain B
303
+ {check_cross_domain} && echo "FAIL" || echo "PASS"
304
+
305
+ echo "=== Tests ==="
306
+ {stack_test_command} && echo "PASS" || echo "FAIL"
307
+ ```
308
+
309
+ ---
310
+
311
+ ## Review Checklist
312
+
313
+ | Area | Checks |
314
+ |------|--------|
315
+ | Entities | Has constructor, behavior methods, event collection, no framework imports |
316
+ | Value Objects | Separate dir, stdlib only, immutable, behavior methods |
317
+ | Ports | Separate dir, 1 file per interface, domain types, no infra imports |
318
+ | Events | 1 per file, extends base event, carries data, name matches registry |
319
+ | UseCases | Uses port interfaces, split by concern, business logic here, no infra |
320
+ | Services | Thin wrapper, delegates to usecases |
321
+ | Handlers/Controllers | Thin, registration/wiring function, DTOs separate |
322
+ | Listeners | 1 per event, side-effects only, registered in event bus |
323
+ | Infrastructure | Implements port interfaces, mappers, no business logic |
324
+ | Tests | Entities, value objects, usecases all tested |
325
+
326
+ ---
327
+
328
+ ## Testing Strategy
329
+
330
+ | Layer | Test Type | Dependencies |
331
+ |-------|-----------|-------------|
332
+ | Value Objects | Unit | None (pure) |
333
+ | Entities | Unit | None (pure) |
334
+ | UseCases | Unit | Mock port interfaces |
335
+ | Infrastructure | Integration | Real DB/API (or testcontainers) |
336
+ | Handlers | Integration/E2E | Full stack |
337
+ | Listeners | Unit | Mock infrastructure |