sequelize-middleware/README.md

218 lines
6.7 KiB
Markdown
Raw Permalink Normal View History

2020-02-02 17:55:19 +01:00
# sequelize-middleware
2020-02-11 20:37:34 +01:00
[![pipeline status](https://framagit.org/dbroqua/sequelize-middleware/badges/develop/pipeline.svg)](https://framagit.org/dbroqua/sequelize-middleware/commits/develop) [![coverage report](https://framagit.org/dbroqua/sequelize-middleware/badges/develop/coverage.svg)](https://framagit.org/dbroqua/sequelize-middleware/commits/develop)
2020-02-10 16:13:42 +01:00
Sequelize-middleware est un module NodeJS permettant d'automatiser la création d'une API REST utilisant Sequelize comme SGBD.
Sequelize-middleware s'appuie également sur Joi pour valider les données reçues ainsi que les appels API effectuées.
## Fonctionnalités
Ce module est découpé en 3 fonctionnalités principales :
* Le `Middleware`, partie centrale du projet
* `ErrorBuilder` qui permet de surcharger la méthode `new Error()`
* `ResponseFormater` qui se charge de formater les données retournée au client final
### Middleware
Méthode par défaut, permettant de générer tout le code propre à un endpoint.
```js
import Middleware from "sequelize-middleare";
import models from "../models";
import params from "../rules/Endpoint";
const middleware = new Middleware(params, models);
middleware.getAll(req, callback);
```
#### Initilisation
Le constructeur doit recevoir 2 paramètres :
* params
* models
`params` représente le fichier des règles pour cet endpoint.
`models` fait référence au fichier `models/index.js` généré par Sequelize.
Le fichier params doit ressembler à ceci :
```js
import Joi from "@hapi/joi";
const models = require("../models"); // Facultatif
const Rules = {
model: "Areas", // Nom de la collection Sequelize
crud: { // Liste des rôles (req.user.roles) autorisés en fonction de l'action
read: ["installer", "admin", "user"],
write: ["installer", "admin"],
edit: ["installer", "admin"],
delete: ["installer", "admin"]
},
includes: [ // Liste des inclusions à faire lors d'un getOne/getAll
{
collection: "Devices", // Nom de la collection à inclure
requiredRole: ["installer", "admin", "user"], // Rôles autorisés à voir cette inclusion
required: false, // Sauf cas particulier toujours mettre false
model: models.AreasDevices, // Nom du modèle Sequelize à inclure
include: [ // Liste des sous-inclusions
{
collection: "Device",
requiredRole: ["installer", "admin", "user"]
}
]
}
],
format: { // Formatage des données en fonction du rôle de l'utilisateur (dans le cas ou l'on veut surcharger le formatage du modèle)
user: {
idRetourne: "_idSql", // Clé retournée: Clé du modèle
id: "id",
nom: "name"
}
},
itemId: "areaId", // Id de l'item dans la req.params
validate: { // Définition des des règles de valeurs acceptées en fonction du verbe
// Création d'un nouvele élément
create: Joi.object({
name: Joi.string().required(),
type: Joi.string()
.valid("OFFICE", "COMMUNAL-AREAS")
.required()
}),
// Mise à jour d'un élément
update: Joi.object({
name: Joi.string(),
type: Joi.string().valid("OFFICE", "COMMUNAL-AREAS")
}),
// Sélection d'un élément (req.params)
item: Joi.object({
areaId: Joi.number().required()
}),
// Sélection d'une liste d'éléments (req.query)
list: Joi.object({
limit: Joi.number()
.integer()
.min(1)
.max(50),
page: Joi.number()
.integer()
.min(1),
type: Joi.string().valid("OFFICE", "COMMUNAL-AREAS"),
sort: Joi.string()
.valid("id", "name", "type", "createdAt", "updatedAt")
.only(),
order: Joi.string()
.valid("asc", "desc")
.only()
})
.with("limit", "page")
.with("page", "limit")
.with("sort", "order")
.with("order", "sort")
},
removeKeys: {
// Permet de supprimer automatiquement des valeurs de requêtes
item: ["partnerId"] // Sur la sélection d'un item on supprime req.params.partnerId
},
override: {
list: { // Permet de convertir des paramètres reçus via req.query pour en générer des filtres complexes
filters: {
'category': { // On converti req.query.category
$or: [
{
categoryId: '_TERM_',
},
{
categoriesId: {
$contains: '_TERM_',
},
},
],
},
'countryId': { // On converti req.query pour dire à Sequelize que ça correspond à $Details.countryId$
'$Details.countryId$': '_TERM_',
}
},
},
create: {
// Création d'un nouvel item
body: [
// On modifie req.body
{
append: "offerId", // On rajoute un attribut offerId
from: "params", // Que l'on prends dans req.params
value: "offerId" // Et dont la clé est offerId
}
]
}
},
restrictOn: { // Permet de rajouter des restrictions en fonction des rôles
update: [ // Lors d'une mise à jour au autorise l'utilisateur à modifier uniquement les éléments donc state est égal à NEW.
{
roles: ['user'],
type: 'raw', // raw permet de forcer une valeur, sinon user/params/body/query
field: 'state',
value: 'NEW',
},
],
delete: [],
list: [],
create: []
},
};
export default Rules;
```
### ErrorBuilder
```js
import { ErrorBuilder } from "sequelize-middleare";
```
Ce module permet de remplacer la méthode `new Error()` de JS en ajoutant la possibilité de générer un code d'erreur qui sera ensuite retourné via `res.status().json()`.
Le code reçu doit être un `float` dont la partie entière représente un code HTTP valide et la partie réelle représente un code d'erreur plus détaillé de l'erreur.
Exemples d'utilistion :
```js
import { ErrorBuilder } from "sequelize-middleare";
new ErrorBuilder(406.0, "Erreur générique de type 406");
new ErrorBuilder(406.1, "Le champs mot de passe est absent");
new ErrorBuilder(406.2, "Le champs mot de passe doit contenir 8 caractères minimum");
...
```
### ResponseFormater
```js
import { ResponseFormater } from "sequelize-middleare";
```
Ce module permet de formater à la fois le json ainsi que le code http retourné au client une fois que le middleware à fini son traitement.
Exemples d'utilisation :
```js
import { ResponseFormater } from "sequelize-middleare";
router
.route("/")
.get(passport.authenticate(["jwt"]), function(req, res, next) {
middleware.getAll(req, (err, response) => {
ResponseFormater(req, res, next, err, response);
});
})
.post(passport.authenticate(["jwt"]), function(req, res, next) {
middleware.createOne(req, (err, response) => {
ResponseFormater(req, res, next, err, response);
});
});
```