sequelize-temporal
Advanced tools
Comparing version 2.0.0 to 2.1.0
@@ -5,3 +5,4 @@ declare module 'sequelize-temporal' { | ||
full?:boolean, | ||
skipIfSilent?:boolean | ||
skipIfSilent?:boolean, | ||
reloadIgnoredAttributes?:string[] | ||
} | ||
@@ -8,0 +9,0 @@ |
40
index.js
@@ -8,3 +8,4 @@ var _ = require('lodash'); | ||
full: false, | ||
skipIfSilent: false | ||
skipIfSilent: false, | ||
reloadIgnoredAttributes: ['deletedAt'] | ||
}; | ||
@@ -40,4 +41,5 @@ | ||
var attributes = model.getAttributes(); | ||
var excludedAttributes = ["Model","unique","primaryKey","autoIncrement", "set", "get", "_modelAttribute"]; | ||
var historyAttributes = _(model.rawAttributes).mapValues(function(v){ | ||
var historyAttributes = _(attributes).mapValues(function(v){ | ||
v = excludeAttributes(v, excludedAttributes); | ||
@@ -75,5 +77,35 @@ // remove the "NOW" defaultValue for the default timestamps | ||
var dataValues = (!temporalOptions.full && obj._previousDataValues) || obj.dataValues; | ||
var historyRecord = modelHistory.create(dataValues, {transaction: options.transaction}); | ||
async function getDataValues() { | ||
if (!temporalOptions.full) { | ||
return obj._previousDataValues || obj.dataValues; | ||
} | ||
/** | ||
* This is the initial record of a new entity, just use the attributes that were used. | ||
*/ | ||
if (obj._options.isNewRecord) { | ||
return obj.dataValues; | ||
} | ||
const attributesToReload = Object.keys(attributes).filter(attribute => { | ||
if (!temporalOptions.reloadIgnoredAttributes.includes(attribute) && !(attribute in obj.dataValues)) { | ||
return true; | ||
} | ||
}); | ||
/** | ||
* In 'full' mode, it's important that we are able to save a History version even though the caller initially fetched | ||
* a partial instance. We do so at the cost of an extra SELECT to get up-to-date values (remember that in 'full' mode | ||
* we are using afterX hooks, so this works). | ||
* Model.reload() will do its magic to merge the newly fetched values directly in dataValues. #gg | ||
*/ | ||
if (attributesToReload.length > 0) { | ||
await obj.reload({attributes: attributesToReload, transaction: options.transaction, paranoid: false, include: []}) | ||
} | ||
return obj.dataValues; | ||
} | ||
var historyRecord = getDataValues().then(dataValues => modelHistory.create(dataValues, {transaction: options.transaction})); | ||
if(temporalOptions.blocking){ | ||
@@ -80,0 +112,0 @@ return historyRecord; |
{ | ||
"name": "sequelize-temporal", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"description": "Temporal tables for Sequelize", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -75,11 +75,24 @@ Temporal tables for Sequelize | ||
{ | ||
/* runs the insert within the sequelize hook chain, disable | ||
for increased performance without warranties */ | ||
blocking: true, | ||
/* By default sequelize-temporal persist only changes, and saves the previous state in the history table. | ||
The "full" option saves all transactions into the temporal database | ||
(i.e. this includes the latest state.) | ||
This allows to only query the hostory table to get the full history of an entity. | ||
*/ | ||
full: false | ||
/** | ||
* Runs the insert within the sequelize hook chain, disable for increased performance without warranties | ||
*/ | ||
blocking: true, | ||
/** | ||
* By default sequelize-temporal persist only changes, and saves the previous state in the history table. | ||
* The "full" option saves all transactions into the temporal database (i.e. this includes the latest state.) | ||
* This allows to only query the hostory table to get the full history of an entity. | ||
*/ | ||
full: false, | ||
/** | ||
* Whether to skip inserting an History line if the update() call is silent. | ||
*/ | ||
skipIfSilent: false, | ||
/** | ||
* This library will sometimes reload() an updated entity because it misses a few attributes. In order to minimize | ||
* the number of extra SQL queries, an heuristic is applied to perform the reload() only if necessary. This mainly | ||
* boils down to "is this attribute <x> missing ?". | ||
* The `reloadIgnoredAttributes` can be used to ignore certain attributes from this check. | ||
*/ | ||
reloadIgnoredAttributes: ['deletedAt'] | ||
} | ||
``` | ||
@@ -86,0 +99,0 @@ |
@@ -24,3 +24,4 @@ var Temporal = require('../'); | ||
dialect: 'sqlite', | ||
storage: __dirname + '/.test.sqlite' | ||
storage: __dirname + '/.test.sqlite', | ||
logging: process.env.LOGGING === 'true' ? console.log : false | ||
}); | ||
@@ -329,2 +330,26 @@ User = Temporal(sequelize.define('User', { | ||
it('onUpdate: should store the previous version to the historyDB even if entity was partially loaded' , async function(){ | ||
const created = await User.create({ name: 'name' }); | ||
const user = await User.findByPk(created.id, { attributes: ['id', 'name'] }); // Don't fetch timestamps | ||
await user.update({ name: 'newName' }); | ||
await user.update({ name: 'thirdName' }); | ||
const history = await UserHistory.findAll(); | ||
assert.equal(history.length, 3, 'initial revision and to updates saved'); | ||
const [initial, firstUpdate, secondUpdate] = history; | ||
assert.equal(+initial.createdAt, +firstUpdate.createdAt, 'createdAt was saved during first update, despite not being eagerly loaded'); | ||
assert.equal(+initial.createdAt, +secondUpdate.createdAt, 'createdAt was saved during second update, despite not being eagerly loaded'); | ||
assert.isAtLeast(firstUpdate.updatedAt, initial.createdAt, 'updatedAt was saved during first update'); | ||
assert.isAtLeast(secondUpdate.updatedAt, firstUpdate.updatedAt, 'updatedAt was saved during second update'); | ||
assert.equal('name', initial.name); | ||
assert.equal('newName', firstUpdate.name); | ||
assert.equal('thirdName', secondUpdate.name); | ||
}); | ||
}); | ||
@@ -331,0 +356,0 @@ |
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
28453
494
140
1