sequelize-version
Automatically version (audit, log) your sequelize models, tracking all the changes (create, update, delete) by generating a version of the model than can be used for easy querying, see the changes made, or whatever you want. The version model uses sequelize hooks to persist the data.
Installation
npm i sequelize-version --save
or
yarn add sequelize-version
Features
- Custom settings (version prefix, suffix, schema and more)
- Supports transaction
Usage
const Sequelize = require('sequelize');
const Version = require('sequelize-version');
const sequelize = new Sequelize(...);
const Person = sequelize.define('Person', ...);
const PersonVersion = new Version(Person);
Options
Name | Type | Default | Description |
---|---|---|---|
prefix | string |
'version' |
Prefix for table name and version attributes |
suffix | string |
Table name suffix | |
attributePrefix | string |
Overrides prefix for version attribute fields | |
schema | string |
Version model schema, uses origin model schema as default | |
sequelize | sequelize |
Sequelize instance, uses origin model sequelize as default | |
exclude | Array<string> |
Attributes to ignore | |
tableUnderscored | boolean |
true |
Use underscore in version table name |
underscored | boolean |
true |
Use underscore in version attributes |
Examples
Checking versions
// let's create a person for test
let person = await Person.build({name: 'Jack'}).save();
// now we change a name
person.name = 'Jack Johnson';
// update
await person.save();
// and delete
await person.destroy();
// finally, get the versions
const versions = await PersonVersion.findAll({where : {id: person.id}});
// or, even simpler
const versionsByInstance = await person.getVersions();
// this way too
const versionsByModel = await Person.getVersions({where : {id: person.id}});
// versions added
console.log(JSON.parse(JSON.stringify(versions)));
/*
[
{
version_id: 1,
version_type: 1,
version_timestamp: 2017-08-02T16:08:09.956Z,
id: 1,
name: 'Jack'
},
{
version_id: 2,
version_type: 2,
version_timestamp: 2017-08-02T16:18:09.958Z,
id: 1,
name: 'Jack Johnson'
},
{
version_id: 3,
version_type: 3,
version_timestamp: 2017-08-02T16:18:09.959Z,
id: 1,
name: 'Jack Johnson'
},
]
*/
Custom options
//customization examples
const customOptions = {
//table name and version attributes prefix
prefix: '',
//table name suffix
suffix: 'log',
//attribute prefix (overrides default - prefix)
attributePrefix: 'revision',
//version model schema
schema: 'audit',
//you can use another sequelize instance (overrides default - sequelize from origin model)
sequelize: new Sequelize(...),
//attributes to ignore from origin model
exclude: ['createdAt', 'updatedAt'],
//table name with underscore, true as default
tableUnderscored: true,
//attributes with underscore, true as default
underscored: true,
}
// single options
const VersionModel = new Version(Model, customOptions);
// global options
Version.defaults = customOptions;
Transaction
//version uses the origin model transaction
sequelize.transaction(transaction => {
return Person.build({name: 'Jack'}).save({transaction});
});
//or, if you are using cls - http://docs.sequelizejs.com/manual/tutorial/transactions.html#automatically-pass-transactions-to-all-queries
sequelize.transaction(() => {
return Person.build({name: 'Jack'}).save();
})
Querying
// default scopes created in version model (created, updated, deleted)
const versionCreated = await VersionModel.scope('created').find({where: {id: person.id}});
const versionUpdates = await VersionModel.scope('updated').findAll();
const versionDeleted = await VersionModel.scope('deleted').find({where: {id: person.id}});
// using origin model
const allVersions = await Person.getVersions({where : {name: {like: 'Jack%'}}});
// using instance from origin model
const person = await Person.findById(1);
const versionsForOnlyThisPerson = await person.getVersions({where: {name: {like: '%Johnson'}}});
Important Notes
This lib uses sequelize hooks to be able to track the changes. When using class methods, it is necessary to use the individualHooks: true
option to make this possible. In such cases, this can cause a dramatic reduction in performance. See more at: https://sequelize.org/master/manual/hooks.html.
// This will select all records that are about to be deleted and emit `beforeDestroy` and `afterDestroy` on each instance.
await Model.destroy({
where: { accessLevel: 0 },
individualHooks: true
});
// This will select all records that are about to be updated and emit `beforeUpdate` and `afterUpdate` on each instance.
await Model.update({ username: 'Jack' }, {
where: { accessLevel: 0 },
individualHooks: true
});
License
The files included in this repository are licensed under the MIT license.