Skip to content

Commit 1b23996

Browse files
authored
Merge pull request #207 from lypitech/dev
Backend Documentation Force reason: Time limit
2 parents 36f1ec1 + ec95e3c commit 1b23996

1 file changed

Lines changed: 298 additions & 8 deletions

File tree

HOWTOCONTRIBUTE.md

Lines changed: 298 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,305 @@
22

33
# DEV-500 ‒ `AREA` ‒ How to contribute
44

5-
Thanks for your interest in contributing to this project!
5+
# Ajouter un nouveau service (Trigger Driver)
66

7-
At the moment, contribution guidelines are not finished yet. We're still figuring out our workflow,
8-
coding standards and project structure.
7+
## Principe
98

10-
**Regularly check back here for updates on how to contribute :)**
9+
Chaque service apporte un **driver** qui implémente un contrat commun et s'enregistre automatiquement dans le **registry** via un multi-provider (`TRIGGER_DRIVERS`).
1110

12-
## What you can do now
11+
Le core (`TriggerModule` et `TriggerService`) n'a aucune dépendance directe vers vos services.
12+
13+
<aside>
14+
15+
**Structure des fichiers :**
16+
17+
```
18+
trigger/
19+
contracts/trigger-driver.ts
20+
tokens.ts
21+
trigger.module.ts
22+
trigger.service.ts
23+
services/
24+
<votre-service>/
25+
<service>.driver.ts
26+
<service>;.module.ts
27+
(optionnel) <service>.controller.ts
28+
```
29+
30+
</aside>
31+
32+
---
33+
34+
## 1. Contrat à implémenter
35+
36+
Tous les drivers doivent implémenter l'interface `TriggerDriver` :
37+
38+
```tsx
39+
// trigger/contracts/trigger-driver.ts
40+
export interface TriggerDriver {
41+
readonly key: string; // ex: 'discord:webhook'
42+
supports(trigger: Trigger): boolean; // si ce driver gère ce trigger
43+
onCreate?(t: Trigger, params?: any): Promise&lt;void&gt;;
44+
onRemove?(t: Trigger): Promise&lt;void&gt;;
45+
fire?(t: Trigger, payload?: any): Promise&lt;void&gt;;
46+
}
47+
```
48+
49+
---
50+
51+
## 2. Token du registry
52+
53+
Le token permet d'injecter tous les drivers dans le service principal :
54+
55+
```tsx
56+
// trigger/tokens.ts
57+
export const TRIGGER_DRIVERS = Symbol('TRIGGER_DRIVERS');
58+
```
59+
60+
---
61+
62+
## 3. Créer votre driver
63+
64+
### Exemple : Discord Webhook
65+
66+
```tsx
67+
// trigger/services/discord/discord.driver.ts
68+
import { Injectable, UnauthorizedException } from '@nestjs/common';
69+
import { TriggerDriver } from '../../contracts/trigger-driver';
70+
import { Trigger } from '../../schemas/trigger.schema';
71+
72+
@Injectable()
73+
export class DiscordWebhookDriver implements TriggerDriver {
74+
readonly key = 'discord:webhook';
75+
76+
supports(t: Trigger) {
77+
return t.service_name === 'discord' &amp;&amp; t.trigger_type === 'webhook';
78+
}
79+
80+
async onCreate(t: Trigger) {
81+
// Optionnel : enregistrer un webhook côté Discord si besoin
82+
// Utilisez t.input pour la config (ex: { channelId, secret }).
83+
}
84+
85+
async onRemove(t: Trigger) {
86+
// Optionnel : supprimer le webhook côté Discord
87+
}
88+
89+
async fire(t: Trigger, payload?: any) {
90+
const url = t.input?.webhookUrl;
91+
if (!url) throw new UnauthorizedException('Webhook URL manquant');
92+
// Exemple : envoyer un message via un webhook Discord
93+
// await axios.post(url, { content: String(payload ?? '') });
94+
}
95+
}
96+
```
97+
98+
<aside>
99+
100+
**Le champ `input` du modèle Trigger** contient toute la configuration spécifique à ce service.
101+
102+
**Exemples :**
103+
104+
- `{ webhookUrl: "...", channelId: "..." }`
105+
- `{ every: 5 }`
106+
- `{ repo: "myrepo", event: "push" }`
107+
</aside>
108+
109+
---
110+
111+
## 4. Créer le module du service
112+
113+
```tsx
114+
// trigger/services/discord/discord.module.ts
115+
import { Module } from '@nestjs/common';
116+
import { TRIGGER_DRIVERS } from '../../tokens';
117+
import { DiscordWebhookDriver } from './discord.driver';
118+
119+
@Module({
120+
providers: [
121+
DiscordWebhookDriver,
122+
{ provide: TRIGGER_DRIVERS, useExisting: DiscordWebhookDriver },
123+
],
124+
exports: [],
125+
})
126+
export class DiscordModule {}
127+
```
128+
129+
Ce provider multi-instance permet à Nest d'injecter tous les drivers enregistrés dans le `TriggerService`.
130+
131+
---
132+
133+
## 5. Brancher le module dans le core
134+
135+
```tsx
136+
// trigger/trigger.module.ts
137+
@Module({
138+
imports: [
139+
MongooseModule.forFeature([{ name: Trigger.name, schema: TriggerSchema }]),
140+
// autres services déjà existants
141+
DiscordModule, // ajoute votre service ici
142+
],
143+
providers: [TriggerService],
144+
exports: [TriggerService],
145+
})
146+
export class TriggerModule {}
147+
```
148+
149+
---
150+
151+
## 6. Exemple de création et d'utilisation
152+
153+
### Modèle Trigger (extrait)
154+
155+
```tsx
156+
@Prop({ type: MongooseSchema.Types.Mixed, default: {} })
157+
input?: Record&lt;string, any&gt; | null;
158+
```
159+
160+
### Création d'un trigger
161+
162+
```tsx
163+
// Exemple : webhook Discord
164+
await triggerService.create({
165+
service_name: 'discord',
166+
name: 'notify-on-event',
167+
trigger_type: 'webhook',
168+
input: { webhookUrl: 'https://discordapp.com/api/webhooks/...' },
169+
});
170+
171+
// Exemple : trigger interval
172+
await triggerService.create({
173+
service_name: 'area',
174+
name: 'heartbeat',
175+
trigger_type: 'interval',
176+
input: { every: 10 },
177+
});
178+
```
179+
180+
### Déclenchement
181+
182+
- **Webhook entrant :** via un contrôleur HTTP → `triggerService.fire(uuid, body)`
183+
- **Interval :** déclenché automatiquement par le driver interval
184+
185+
---
186+
187+
## 7. (Optionnel) Contrôleur webhook
188+
189+
Si votre service reçoit des webhooks externes :
190+
191+
```tsx
192+
// trigger/services/discord/discord.controller.ts
193+
import { Controller, Post, Body, Param } from '@nestjs/common';
194+
import { TriggerService } from '../../trigger.service';
195+
196+
@Controller('hooks/discord')
197+
export class DiscordWebhookController {
198+
constructor(private readonly triggers: TriggerService) {}
199+
200+
@Post(':uuid')
201+
async inbound(@Param('uuid') uuid: string, @Body() body: any) {
202+
// TODO: vérifier la signature si nécessaire
203+
return this.triggers.fire(uuid, body);
204+
}
205+
}
206+
```
207+
208+
<aside>
209+
210+
N'oubliez pas d'ajouter le contrôleur dans le `DiscordModule` :
211+
212+
```tsx
213+
@Module({
214+
controllers: [DiscordWebhookController],
215+
providers: [
216+
DiscordWebhookDriver,
217+
{ provide: TRIGGER_DRIVERS, useExisting: DiscordWebhookDriver },
218+
],
219+
})
220+
export class DiscordModule {}
221+
```
222+
223+
</aside>
224+
225+
---
226+
227+
## 8. Checklist rapide
228+
229+
| **Vérification** | **Description** |
230+
| --- | --- |
231+
| `supports()` | Retourne true/false selon service_name et trigger_type |
232+
| `onCreate()` | Configure la ressource externe (webhook, cron, etc.) |
233+
| `onRemove()` | Supprime la ressource distante proprement |
234+
| `fire()` | Exécute la logique de déclenchement |
235+
| Module | Fournit`{ provide: TRIGGER_DRIVERS, useExisting: ... }` |
236+
| Tests | Création / suppression / déclenchement fonctionnels |
237+
| Logs | Chaque driver utilise Logger pour traçabilité |
238+
239+
---
240+
241+
## 9. Exemple minimal complet
242+
243+
- **Driver**
244+
245+
```tsx
246+
// trigger/services/myservice/myservice.driver.ts
247+
import { Injectable } from '@nestjs/common';
248+
import { TriggerDriver } from '../../contracts/trigger-driver';
249+
import { Trigger } from '../../schemas/trigger.schema';
250+
251+
@Injectable()
252+
export class MyServiceWebhookDriver implements TriggerDriver {
253+
readonly key = 'myservice:webhook';
254+
255+
supports(t: Trigger) {
256+
return t.service_name === 'myservice' &amp;&amp; t.trigger_type === 'webhook';
257+
}
258+
259+
async onCreate(t: Trigger) {
260+
// Setup distant (si nécessaire)
261+
}
262+
263+
async fire(t: Trigger, payload?: any) {
264+
// Votre logique métier ici
265+
}
266+
}
267+
```
268+
269+
- **Module**
270+
271+
```tsx
272+
// trigger/services/myservice/myservice.module.ts
273+
import { Module } from '@nestjs/common';
274+
import { TRIGGER_DRIVERS } from '../../tokens';
275+
import { MyServiceWebhookDriver } from './myservice.driver';
276+
277+
@Module({
278+
providers: [
279+
MyServiceWebhookDriver,
280+
{ provide: TRIGGER_DRIVERS, useExisting: MyServiceWebhookDriver },
281+
],
282+
})
283+
export class MyServiceModule {}
284+
```
285+
286+
- **Controller (optionnel)**
287+
288+
```tsx
289+
// trigger/services/myservice/myservice.controller.ts
290+
import { Controller, Post, Param, Body } from '@nestjs/common';
291+
import { TriggerService } from '../../trigger.service';
292+
293+
@Controller('hooks/myservice')
294+
export class MyServiceController {
295+
constructor(private readonly triggers: TriggerService) {}
296+
297+
@Post(':uuid')
298+
async inbound(@Param('uuid') uuid: string, @Body() body: any) {
299+
return this.triggers.fire(uuid, body);
300+
}
301+
}
302+
```
303+
304+
305+
---
13306

14-
- Star the repository and follow updates
15-
- Open issues for **bugs, questions or suggestions**
16-
- Explore the codebase (mobile app, web app, backend)

0 commit comments

Comments
 (0)