Bridging JavaScript and Sequelize
Sequelize does not support some JavaScript data types. We present one way to use “natural” JavaScript types with Sequelize.
Sequelize does not natively support JavaScript’s Boolean, Date, Object and Array data types. This makes it awkward to write database agnostic code compatible with NoSQL databases. It also makes it awkward to write “natural” JavaScript.
There is no avoiding the translation of some JavaScript data types to a format natural for Sequelize. The question is what’s the most convenient way to do it.
The sequelizeConvert hook
Feathers hooks are middleware which run before or after a database service call, and they are the obvious place to do the translation.
The sequelizeConvert hook, recently added to Feathers common hooks library, automates the conversion. You can call it with
const { sequelizeConvert } = require('feathers-hooks-common');const convert = {
isVerified: 'boolean',
verifyExpires: 'date',
verifyChanges: 'json',
passwordHistory: 'json',
};app.service('users').hooks({
before: { all: [ sequelizeConvert(convert) ] },
after: { all: [ sequelizeConvert(convert) ] },
});app.service('users').create({
isVerified: false, verifyExpires: Date.now() + 60 * 60 * 24 * 2,
verifyChanges: { email: 'john@gmail.com' }, passwordHistory: [],
});
The hook converts:
- JavaScript Boolean true, false to Sequelize DataTypes.INTEGER 1 and 0.
- Date types, e.g. Date.now(), to DataTypes.DATE. Dates with a
null
value are persisted asnull
by Sequelize, and returned to JavaScript asnull
. - Object and Array types to DataTypes.STRING using JSON.stringify and JSON.parse.
The hook’s signature is sequelizeConvert(convert, ignores, conversions)
where:
convert
is an object as shown above. The prop names are the field names in the record. The valid values areboolean
,date
andjson
.ignores
is an optional array of field names to not convert. Having a separateignore
which overridesconvert
is convenient in some circumstances.conversion
is an optional object containing the conversion functions. It may be used to override the default used for each JavaScript type. The default functions are:
const defaultConversions = {
boolean: {
sql: boolean => boolean ? 1 : 0,
js: numb => !!numb,
},
date: {
sql: dateNow => dateNow,
js: sqlDate => new Date(sqlDate).valueOf() || null,
},
json: {
sql: obj => JSON.stringify(obj),
js: str => JSON.parse(str),
}
};
The conversions occur automatically once you define hooks, and you no longer need to pay attention to them.
In conclusion
This article is part of a series of articles on using Sequelize in Feathers. Subscribe to The Feathers Flightpath publication to be informed of the coming articles.
As always, feel free to join Feathers Slack to join the discussion or just lurk around.