json-sequelize
v1.2.0
Published
Translate JSON schemas to Sequelize model definitions
Downloads
96
Maintainers
Readme
json-sequelize
Translate JSON Schemas to Sequelize model definitions.
Install
npm i --save json-sequelize
Use
Simply provide a valid JSON schema to the sequelizer
function.
const { sequelizer } = require('json-sequelize')
const schema = {
title: 'User Schema',
unique: ['username', 'email'],
required: ['username', 'email', 'password'],
properties: {
id: { type: 'integer' },
active: { type: 'boolean' },
username: { type: 'string', maxLength: 255 },
password: { type: 'string' },
email: { type: 'string', format: 'email' },
role: { type: 'string', enum: ['admin', 'staff', 'guest'], default: 'guest' },
tags: { type: 'array', items: { type: 'string' } },
createdAt: { type: 'string', format: 'date-time' }
}
}
const model = sequelizer(schema)
console.log(model)
Yields:
{
id: { type: Sequelize.INTEGER },
active: { type: Sequelize.BOOLEAN },
username: { type: Sequelize.STRING, unique: true, allowNull: false },
password: { type: Sequelize.TEXT, allowNull: false },
email: { type: Sequelize.TEXT, unique: true, allowNull: false },
role: { type: Sequelize.ENUM('admin', 'staff', 'guest'), defaultValue: 'guest' },
tags: { type: Sequelize.JSONB },
createdAt: { type: Sequelize.DATE, defaultValue: Sequelize.NOW }
}
Mixins
You can provide one or more Mixin
s to the sequelizer
function, each with a selector
and a handler
.
Mixin handler
The handler
must be a Function
that returns a new Sequelize model definition or SKIP
if ignoring selected properties.
The handler
function gets called with an object containing:
schema
- the schema objectkey
- the current property keyproperty
- the current property objectdefinition
- the current model definitionSKIP
- Symbol required to exclude a propertySequelize
- the Sequelize object
Using handler
to ignore props
Sometimes it can be useful to include computed properties in the JSON Schema but to exclude them in the Sequelize model definitions.
const schema {
computed: ['beep', 'boop'],
properties: {
id: {},
beep: {},
boop: {}
}
}
const mixin = {
handler: ({ key, schema, SKIP }) => schema.computed.includes(key) && SKIP
}
The resulting model will only include the id
property:
{
id: {}
}
Using handler
to modify props
Typically, the handler
is used to update one or more properties with Sequelize definitions.
const schema = {
properties: {
id: { type: 'integer' }
}
}
const mixin = {
selector: 'id',
handler: ({ Sequelize }) => ({
type: Sequelize.STRING,
defaultValue: () => nanoid(),
primaryKey: true
})
}
const model = sequelizer(schema, mixin)
The resulting model:
{
id: { type: Sequelize.STRING, primaryKey: true, defaultValue: [Function Anonymous] }
}
The above model definition will be replicated in each of the following examples:
Mixin selector
The selector
can be a String
, Object
, or Function
:
Mixin selector
(String
)
The simplest way is providing the property key as a String
:
const mixin = {
selector: 'id',
handler: () => ({/* */})
}
Mixin selector
(Object
)
Another way is to provide a matching key:value pair to match one or more of the schema.properties
:
const mixin = {
selector: { type: 'integer' },
handler: ({ Sequelize }) => ({/* */})
}
Using the key
property, allows targeting by schema.properties
keys. This approach is equivalent to providing the value as a plain String
.
const mixin = {
selector: { key: 'id' },
handler: () => ({/* */})
}
Mixin selector
(Function
)
A function will execute against each property in schema.properties
and should return a truthy value.
const mixin = {
selector: ({ key }) => key === 'id',
handler: () => ({/* */})
}
The selector
function gets called with an object containing:
schema
- the schema objectkey
- the property keyproperty
- the property object
Multiple Mixins
Combining mixins is done by adding them to an array, where each mixin will run consecutively.
const model = sequelizer(schema, [mixin1, mixin2, ...mixins])
Tests
Run npm test
to run tests.
Run npm coverage
to produce a test coverage report.
Credits
Originally forked from ronalddddd/sequelizer - upgraded to a purely functional style with some added sugar.