@volontariapp/domain-event 3.6.13 → 3.6.14
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/CHANGELOG.md +16 -0
- package/README.md +132 -0
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.6.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- README bump
|
|
8
|
+
|
|
9
|
+
- Updated dependencies []:
|
|
10
|
+
- @volontariapp/contracts@4.3.2
|
|
11
|
+
- @volontariapp/database@3.4.4
|
|
12
|
+
- @volontariapp/errors@0.6.1
|
|
13
|
+
- @volontariapp/errors-nest@0.13.1
|
|
14
|
+
- @volontariapp/logger@0.2.6
|
|
15
|
+
- @volontariapp/messaging@2.10.1
|
|
16
|
+
- @volontariapp/outbox@0.9.41
|
|
17
|
+
- @volontariapp/shared@0.8.1
|
|
18
|
+
|
|
3
19
|
## 3.6.13
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# @volontariapp/domain-event
|
|
2
|
+
|
|
3
|
+
## Overview & Domain Driven Design (DDD)
|
|
4
|
+
|
|
5
|
+
Le package `domain-event` encapsule la **logique métier centrale absolue** relative aux **Événements** (Events) de la plateforme Volontariapp.
|
|
6
|
+
Conçu selon les principes stricts de la **Clean Architecture** et du **Domain-Driven Design (DDD)**, ce domaine est complètement **agnostique de l'infrastructure**. Il ne connaît ni NestJS, ni TypeORM, ni gRPC.
|
|
7
|
+
|
|
8
|
+
Ce package est partagé transversalement (DRY) entre :
|
|
9
|
+
- Le microservice métier (`ms-event`)
|
|
10
|
+
- Les Workers asynchrones
|
|
11
|
+
- Les Post-Processors
|
|
12
|
+
|
|
13
|
+
> [!TIP]
|
|
14
|
+
> **Pourquoi cette isolation ?**
|
|
15
|
+
> Si l'API HTTP/gRPC tombe en panne, ou si le framework change, les Workers et le domaine continuent de fonctionner de manière totalement autonome grâce à cette isolation stricte de la logique métier.
|
|
16
|
+
|
|
17
|
+
## Architecture du Domaine
|
|
18
|
+
|
|
19
|
+
```mermaid
|
|
20
|
+
classDiagram
|
|
21
|
+
direction TB
|
|
22
|
+
|
|
23
|
+
namespace DomainLayer {
|
|
24
|
+
class EventService {
|
|
25
|
+
<<Domain Service>>
|
|
26
|
+
+createEvent(params)
|
|
27
|
+
+validateParticipation()
|
|
28
|
+
}
|
|
29
|
+
class EventEntity {
|
|
30
|
+
<<Entity>>
|
|
31
|
+
+id: Uuid
|
|
32
|
+
+title: string
|
|
33
|
+
+location: EventLocation
|
|
34
|
+
+status: EventStatus
|
|
35
|
+
+publish()
|
|
36
|
+
}
|
|
37
|
+
class EventLocation {
|
|
38
|
+
<<Value Object>>
|
|
39
|
+
-latitude: number
|
|
40
|
+
-longitude: number
|
|
41
|
+
+isValid()
|
|
42
|
+
}
|
|
43
|
+
class IEventRepository {
|
|
44
|
+
<<Interface>>
|
|
45
|
+
+save(EventEntity)
|
|
46
|
+
+findById(Uuid)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
namespace InfraLayer {
|
|
51
|
+
class PostgresEventRepository {
|
|
52
|
+
<<Implementation>>
|
|
53
|
+
-typeOrmRepository
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
EventService --> EventEntity : Orchestre
|
|
58
|
+
EventEntity *-- EventLocation : Contient
|
|
59
|
+
EventService --> IEventRepository : Utilise (DIP)
|
|
60
|
+
PostgresEventRepository ..|> IEventRepository : Implémente
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Structure des Dossiers
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
src/
|
|
67
|
+
├── entities/ # Entités mutables du domaine (ex: EventEntity, TagEntity)
|
|
68
|
+
├── value-objects/ # Objets immuables validant des règles précises (ex: EventLocation)
|
|
69
|
+
├── services/ # Domain Services pour la logique impliquant plusieurs entités
|
|
70
|
+
├── repositories/ # Interfaces des Repositories (Contrats) et implémentations Infra
|
|
71
|
+
├── models/ # Modèles DTOs / Mappers
|
|
72
|
+
├── database/ # Définition des triggers ou logiques SQL pures (si applicables)
|
|
73
|
+
└── test/ # Factories et mocks du domaine
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Exemples d'Implémentation
|
|
77
|
+
|
|
78
|
+
### 1. Value Object & Entity
|
|
79
|
+
L'utilisation de Value Objects empêche le passage de types primitifs (Primitive Obsession) et garantit que seules des données valides existent en mémoire.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// value-objects/event-location.value-object.ts
|
|
83
|
+
export class EventLocation {
|
|
84
|
+
constructor(
|
|
85
|
+
public readonly latitude: number,
|
|
86
|
+
public readonly longitude: number
|
|
87
|
+
) {
|
|
88
|
+
if (latitude < -90 || latitude > 90) throw new DomainError('Invalid latitude');
|
|
89
|
+
if (longitude < -180 || longitude > 180) throw new DomainError('Invalid longitude');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// entities/event.entity.ts
|
|
94
|
+
export class EventEntity {
|
|
95
|
+
constructor(
|
|
96
|
+
public readonly id: string,
|
|
97
|
+
public title: string,
|
|
98
|
+
public location: EventLocation // Typage fort, impossible d'avoir une string
|
|
99
|
+
) {}
|
|
100
|
+
|
|
101
|
+
public relocate(newLocation: EventLocation): void {
|
|
102
|
+
// Logique métier encapsulée dans l'entité
|
|
103
|
+
this.location = newLocation;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 2. Domain Service
|
|
109
|
+
Le service de domaine orchestre les règles qui ne rentrent pas dans une seule entité, en utilisant des abstractions (Inversion de Dépendance).
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// services/event-creation.service.ts
|
|
113
|
+
export class EventCreationService {
|
|
114
|
+
constructor(
|
|
115
|
+
private readonly eventRepo: IEventRepository,
|
|
116
|
+
private readonly userSvc: IUserServiceStub
|
|
117
|
+
) {}
|
|
118
|
+
|
|
119
|
+
async create(userId: string, payload: CreateEventPayload): Promise<EventEntity> {
|
|
120
|
+
const user = await this.userSvc.getUserStatus(userId);
|
|
121
|
+
if (!user.isVerified) {
|
|
122
|
+
throw new DomainError('USER_NOT_VERIFIED', 'Unverified users cannot create events');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const location = new EventLocation(payload.lat, payload.lng);
|
|
126
|
+
const event = new EventEntity(uuidv4(), payload.title, location);
|
|
127
|
+
|
|
128
|
+
await this.eventRepo.save(event);
|
|
129
|
+
return event;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volontariapp/domain-event",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.14",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"provenance": true
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@nestjs/typeorm": "^11.0.1",
|
|
45
45
|
"@types/jest": "^30.0.0",
|
|
46
46
|
"@types/node": "^22.10.7",
|
|
47
|
-
"@volontariapp/testing": "1.0.
|
|
47
|
+
"@volontariapp/testing": "1.0.2",
|
|
48
48
|
"jest": "^30.3.0",
|
|
49
49
|
"pg": "^8.20.0",
|
|
50
50
|
"reflect-metadata": "^0.2.2",
|
|
@@ -55,14 +55,14 @@
|
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@nestjs/common": "^11.0.1",
|
|
58
|
-
"@volontariapp/contracts": "4.3.
|
|
59
|
-
"@volontariapp/database": "3.4.
|
|
60
|
-
"@volontariapp/errors": "0.6.
|
|
61
|
-
"@volontariapp/errors-nest": "0.13.
|
|
62
|
-
"@volontariapp/logger": "0.2.
|
|
63
|
-
"@volontariapp/messaging": "2.10.
|
|
64
|
-
"@volontariapp/outbox": "0.9.
|
|
65
|
-
"@volontariapp/shared": "0.8.
|
|
58
|
+
"@volontariapp/contracts": "4.3.2",
|
|
59
|
+
"@volontariapp/database": "3.4.4",
|
|
60
|
+
"@volontariapp/errors": "0.6.1",
|
|
61
|
+
"@volontariapp/errors-nest": "0.13.1",
|
|
62
|
+
"@volontariapp/logger": "0.2.6",
|
|
63
|
+
"@volontariapp/messaging": "2.10.1",
|
|
64
|
+
"@volontariapp/outbox": "0.9.41",
|
|
65
|
+
"@volontariapp/shared": "0.8.1",
|
|
66
66
|
"class-transformer": "^0.5.1"
|
|
67
67
|
}
|
|
68
68
|
}
|