libs | ||
.eslintignore | ||
.eslintrc.js | ||
.gitignore | ||
index.js | ||
package.json | ||
README.md | ||
yarn.lock |
sequelize-middleware
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éthodenew 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.
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 :
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
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 :
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
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 :
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);
});
});