Tartalomjegyzék
Express - Sequelize beépített érvényesítés ES
- Szerző: Sallai András
- Copyright © 2025, Sallai András
- Licenc: CC BY-SA 4.0
- Web: https://szit.hu
Bevezetés
Az Sequelize rendelkezik beépített érvényesség-ellenőrzéssel. Itt a Sequelize 6.x verzióhoz tartozó érvényességvizsgálatot nézzük át.
Model
Egy Employee model minimális id és name mezővel:
const Employee = sequelize.define('employee', { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }, name: { type: DataTypes.STRING, allowNull: false } })
Az „allowNull: false” azt határozza meg, hogy az adatbázisban a tábla mezője lehet null érték.
Ha viszont érvényességet szeretnénk vizsgálni, akár hibaüzenettel a valaidate: {} kulcsot kell használni. Az érvényesség vizsgálat során a HTTP kérésben érkező kérésben szereplő adatokat vizsgáljuk.
A validate: {} értékén belül objektumokat vehetünk fel, vagyis újabb kulcs-éréték párok. Ilyen például, a notNull a body-ban érkező adatokra vonatkozik. A notEmpty azért kellhet, mert a notNull esetén még küldhető üres sztring. A notEmpty esetén nem. Nézzük meg name mező érvényességvizsgálatát.
const Employee = sequelize.define('employee', { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }, name: { type: DataTypes.STRING, allowNull: false, validate: { notNull: true notEmpty: true } } })
A true helyett megadhatunk JavaScript objektumként üzenet is:
const Employee = sequelize.define('employee', { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }, name: { type: DataTypes.STRING, allowNull: false, validate: { notNull: { msg: 'A név mező kötelező' }, notEmpty: { msg: 'A név nem lehet üres sztring' } } } })
Lássunk egy összetettebb kódot, ahol már több mező is szerepel, szabályos kifejezéssel is:
- employee.js
import { DataTypes } from 'sequelize' import sequelize from '../database/database.js' const Employee = sequelize.define('employee', { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }, name: { type: DataTypes.STRING, allowNull: false, validate: { notNull: { msg: 'Hiba! A név megadása kötelező!' }, notEmpty: { msg: 'Hiba! A név nem lehet üres!'} } }, city: { type: DataTypes.STRING, allowNull: true, validate: { is: { args: /^[a-z]+$/i, msg: 'Hiba! Csak betűk adhatók meg!' } } }, salary: { type: DataTypes.INTEGER, defaultValue: 300, validate: { isNumeric: { msg: 'Hiba! Csak szám adható meg fizetésnek!'} } }, birth: { type: DataTypes.DATE, defaultValue: DataTypes.NOW, validate: { isDate: { msg: 'Hiba! Csak dátum adható meg!' } } } }) sequelize.sync({ force: false }) export default Employee
Kontroller
Az érvényességet a modell-ben beállítottuk. Most nézzük egy példát, hogyan kezelhetjük az érvénytelen eseteket.
A hibakezelő részben vizsgáljuk meg, hogy érvényességi hiba történt-e:
if(error instanceof Sequelize.ValidationError) { res.status(400) }else { res.status(500) }
Megvizsgáljuk, hogy az error objektum a Sequelize.ValidationError egy példánya? Ha igen, akkor a kérés a hibás, ezért 400-as státuszkódot állítunk. Ha nem az érvényesség volt a hiba, akkor valószínűleg szerver oldali hiba, ezért a státuszkód 500 lesz.
Lehetséges teljes kód:
- employeecontroller.js
import { Sequelize } from 'sequelize' import Employee from '../models/employee.js' const EmployeeController = { async index(req, res) { try { await EmployeeController.tryIndex(req, res) }catch(error) { res.status(500) res.json({ success: false, message: 'Error! The query is failed!', error: error.message }) } }, async tryIndex(req, res) { const employees = await Employee.findAll() const result = employees.map(emp => ({ id: emp.id, name: emp.name, city: emp.city, salary: emp.salary, birth: emp.birth })) res.status(200) res.json({ success: true, data: result }) }, async show(req, res) { try { await EmployeeController.tryShow(req, res) }catch(error) { res.status(500) res.json({ success: false, message: 'Error! The query is failed!' }) } }, async tryShow(req, res) { const employee = await Employee.findByPk(req.params.id) res.status(200) res.json({ success: true, data: employee }) }, async create(req, res) { try { await EmployeeController.tryCreate(req, res) }catch(error) { if(error instanceof Sequelize.ValidationError) { res.status(400) }else { res.status(500) } const errorMessages = error.errors.map(err => err.message) res.json({ success: false, message: 'Error! The query is failed!', error: errorMessages }) } }, async tryCreate(req, res) { const employee = await Employee.create(req.body) res.status(201) res.json({ success: true, data: employee }) }, async update(req, res) { try { await EmployeeController.tryUpdate(req, res) }catch(error) { let actualMessage = ''; if(error.message == 'Fail! Record not found!') { actualMessage = error.message res.status(404) }else { res.status(500) actualMessage = 'Fail! The query is failed!' } res.json({ success: false, message: actualMessage }) } }, async tryUpdate(req, res) { const recordNumber = await Employee.update(req.body, { where: { id: req.params.id } }) if(recordNumber == 0) { throw new Error('Fail! Record not found!') } const employee = await Employee.findByPk(req.params.id) res.status(200) res.json({ success: true, data: employee }) }, async destroy(req, res) { try { await EmployeeController.tryDestroy(req, res) }catch(error) { res.status(500) res.json({ success: false, message: 'Error! The query is failed!' }) } }, async tryDestroy(req, res) { const employee = await Employee.destroy({ where: { id: req.params.id } }) res.status(200) res.json({ success: true, data: employee }) } } export default EmployeeController
A mintaprogramban a hibakezelés és a lényegi kód szét van választva, ezért látunk név függvényt:
- index()
- tryIndex()
- store()
- tryStore()
error: error.message
Például:
try { await EmployeeController.tryCreate(req, res) }catch(error) { res.status(500) res.json({ success: false, message: 'Error! The query is failed!', error: error.message }) }
Egy másik lehetőség:
const errorMessages = error.errors.map(err => err.message) //... error: errorMessges
Beépített érvényesítők
A következő kódrészlet a Sequelize 6 verziójának beépített érvényesítőit mutatja:
sequelize.define('foo', { bar: { type: DataTypes.STRING, validate: { is: /^[a-z]+$/i, // RegEx egyezés is: ["^[a-z]+$",'i'], // Mint a fenti, csak a RegEx karakterláncból áll not: /^[a-z]+$/i, // RegEx nem egyezés not: ["^[a-z]+$",'i'], // Mint a fenti, csak a RegEx karakterláncból áll isEmail: true, // email cím (foo@bar.com) isUrl: true, // URL elfogadása (https://foo.com) isIP: true, // IPv4 (129.89.23.1) vagy IPv6 formátum isIPv4: true, // IPv4 (129.89.23.1) cím isIPv6: true, // IPv6 cím isAlpha: true, // csak betűk az elfogadottak isAlphanumeric: true, // betűk és számok; ez nem érvényes: "_abc" isNumeric: true, // csak szám isInt: true, // csak egész isFloat: true, // csak valós szám isDecimal: true, // csak szám isLowercase: true, // csak kisbetűs isUppercase: true, // csak nagybetűs notNull: true, // a null nem megengedett isNull: true, // csak null a megengedett notEmpty: true, // nem lehet üres sztirng equals: 'specific value', // csak a megadott érték lehet contains: 'foo', // benne kell legyen ez a sztring rész notIn: [['foo', 'bar']], // ezek az értékek nem lehetnek isIn: [['foo', 'bar']], // csak ezek az értékek lehetnek notContains: 'bar', // csak ha nem tartalmazza ezt rész sztringet len: [2,10], // az érték hossza 2 és 10 között lehet isUUID: 4, // csak uuid a megengedett isDate: true, // csak dátum sztring lehet isAfter: "2025-04-23", // csak az adott dátum után dátum isBefore: "2025-04-23", // csak az adott dátum előtt dátum max: 23, // az érték <= 23 min: 23, // az érétk >= 23 isCreditCard: true, // csak valós credit card számok } } });
Saját érvényesítő
Készítünk egy érvényesítőt isAfterOrEqualToday néven, amihez egy névtelen függvényt rendelünk:
const YourModel = sequelize.define('YourModel', { // ... egyéb mezők ... startDate: { type: DataTypes.DATE, allowNull: true, validate: { isDate: true, isAfterOrEqualToday: function(value) { const today = new Date(); today.setHours(0, 0, 0, 0); // Mai nap éjfélkor const startDate = new Date(value); startDate.setHours(0, 0, 0, 0); if (isNaN(startDate.getTime()) || startDate < today) { throw new Error('A kezdő dátum nem lehet korábbi a mai napnál.'); } }, }, }, // ... egyéb mezők ... });
Ha nem érvényes a dátum, akkor kivételt dobunk.