npm package: @sfp-group/notify
Description: Help to easily send notifications between multiple services like SMS,Mail and Push
Author: Fiacre Dossou AYEDOUN
Latest version: 0.0.5

# @sfp-group/notify

> Help to easily send notifications between multiple services like SMS,Mail and Push for Adonis JS 5+

[![typescript-image]][typescript-url]
[![npm-image]][npm-url]
[![license-image]][license-url]

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

## Table of contents

- [Installation](#installation)
- [Required](#Required)
- [Sample Usage](#sample-usage)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

# Installation

Run:

```bash
npm i  @sfp-group/notify
```

Install provider:

```bash
node ace configure @sfp-group/notify
```

# Required

Pour différer les taches, nous avons entrepris la mise en gestionnaire queue.
Comme vous en douté, nous avons une dépendance `pg-boss`
qui permet de gérer les tâches en queue.

Pour la bonne marche de la dépendance, nous devons installer l'extension postgres `pgcrypto`

> CREATE EXTENSION pgcrypto;

Pour plus d'information [pg-boss Docs](https://github.com/timgit/pg-boss/blob/master/docs/readme.md)

# Sample Usage

---

## Configuration des évènements

Pour configurer un évènement, editer dans le fichier `contracts/notify.ts` <br/>

```ts
declare module "@ioc:Adonis/Addons/Notify" {
  interface NotifyEventList {
    "notify:contract-rib-changed": {
      // perment la validation de l'entrée vers l'utilisateur
      contract_id: number;
      transporter_name: string;
      old_rib: string;
      new_rib: string;
    };
  }
}
```

Dans cette exemple nous avons déclaré un évènement `notify:contract-rib-changed`
qui attends en paramètre la structure de donnée en valeur.

Nous devons maintenant définir les données templates à utiliser
pour chaque canal de notification

> sms, mail, push

Pour l'effectuer, dirigeons-nous vers le fichier `config/notify.ts`

```ts
...
events: {
"notify:contract-rib-changed": {
  description: "Alert mail lors de la soumission du plan d'évacuation",
  templates: {
    "mail": "email.contract-rib-changed",
    "sms": "sms.contract-rib-changed"
  },
}
```

> *Attention lorsqu'un template n'existe pas pour un canal, La notification n'est pas envoyé ce dernier.*

**Après cette configuration, vous êtes prêt à envoyer des notifications**

## Déclencher des évènements
Une fois la configuration terminée, nous pouvons maintenant utiliser notre extension d'adonis<br/>
En partant de l'exemple précédant 
```ts
...
import Notify from "@ioc:Adonis/Addons/Notify";

export default class UpdateRibTransporter extends Service {
    public static validate():TypedSchema {
        return {
            id: schema.number(),
            newRib: schema.string()
        };
    }

    public async execute(payload: Record<string, any>): Promise<any> {
        ...
        await Notify.send(
            "notify:contract-rib-changed",
            {
                contract_id: 1,
                transporter_name: "John Doe",
                old_rib: "238392289292",
                new_rib: "892786289287",
            },
            ["sms", "normal"]
        );
        
    }
}
```

## Créer un fournisseur de destinataire

Pour créer le notifiable aller dans l'instance notifiable(``User``)
pour implementer l'interface ```NotifiableInterface```

```ts
class User  extends BaseModel implements NotifiableInterface{
    public fullName: string;
    public id: string | number;
    public phone: string;
    public email: string;
    public getRecipient(): Recipient {
        return {
            id: this.id,
            name: this.fullName,
            phone: this.phone,
            email: this.email,
        };
    }

}
```
Une fois interface implementer, Nous allons alors définir la classe
qui va nous permettre récupérer les destinataires,

```ts
type NotifyTable = { table: string; id: number | string };

export default class NotifiableProvider implements  NotifiableProviderInterface{
    public async execute(notices: Array<NotifyTable>): Promise<NotifiableInterface[]> {
        const result:NotifiableInterface[] = [];
        for(let notice of notices){
            if(notice.table === User.table){
                const user = await User.find(notice.id);
                if(user) result.push(user);
            }
            if(notice.table === Role.table){
                const role = await Role.find(notice.id);
                if(role) {
                    await role.load('users')
                    result.push(...(role.users as unknown as NotifiableInterface[]));
                }
            }
        }
        return result;
    }

}
```

## Definition des services et models
[Suivez les instructions de l'implémentation](./implementation.md)

# Option avancées

---



## Service
### Créer un Service
 ```ts
// Adonis/Addons/Notify/Driver/MailSender
 import {
    MailNotifyWay,
    NotifyServiceContract,
} from "@ioc:Adonis/Addons/Notify";
import Mail, { MessageContract } from "@ioc:Adonis/Addons/Mail";

export default class MailSender implements NotifyServiceContract {
    constructor(public settings: Record<any, any> | undefined) {}
    
    
    public async execute(
        notifiable: Record<MailNotifyWay, { name: string; email: string; }[]>,
        subject: string,
        content: string
    ): Promise<void> {
        await Mail.send((message) => {
            this.toWay(message.to, notifiable.mail_to);
            this.toWay(message.bcc, notifiable.mail_bcc);
            this.toWay(message.cc, notifiable.mail_cc);
            message.subject(subject).html(content);
        });
    }

    private toWay(
        fn: (address: string, name?: string) => MessageContract,
        emails: Array<{ name: string; email: string; }>
    ) {
        emails.map(({ email, name }) => fn(email, name));
    }
}
 ```
### Configuration
La configuration d'un service consiste à le declarer dans le fichier de configurer 
pour qu'il soit choisir dynamiquement par l'administrateur<br/>
Editer le fichier `config/notify.ts`

```ts
services: {
    local_mail: {
        type: "mail",
            name: "Adonis Mailer",
            driver: "Adonis/Addons/Notify/Driver/MailSender",
    },
    ...
},
```





## Toute la configuration


```ts
import { NotifyConfig } from "@ioc:Adonis/Addons/Notify";

const config: NotifyConfig = {
  channels: {
    normal: "mail",
    high: ["sms", "mail"],
    critical: ["push"],
  },
  events: {
    "notify:alert-submit": {
      description: "Alert mail lors de la soumission du plan d'évacuation",
      templates: {
        "mail": "email.notify-alert-submit",
        "sms": "sms.notify-alert-submit",
      },
    },
  },
  provider: "App/NotifiableProvider",
  services: {
    mail: {
      type: "mail",
      name: "Adonis Mailer",
      driver: "@sfp-group/drivers/MailSender",
    },
    kopen_sms: {
      type: "sms",
      name: "KOPENSMS",
      driver: "App/Notification/Services/KOpenSmsSender",
    },
  },
};

export default config;

```

[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
[typescript-url]: "typescript"
[npm-image]: https://img.shields.io/npm/v/%40fickou%2Fadonis-controller-helpers.svg?style=for-the-badge&logo=npm
[npm-url]: https://www.npmjs.com/package/adonis-request-throttler "npm"
[license-image]: https://img.shields.io/npm/l/%40fickou%2Fadonis-controller-helpers?color=blueviolet&style=for-the-badge
[license-url]: LICENSE.md "license"