@absolute/change-tracker-node-sdk
Version:
ChangeTracker SDK for Node.js
114 lines (88 loc) • 4.42 kB
JavaScript
const {Field, Row, RowStatus, Table} = require('../models')
/**
* diff - produces a new Row which contains the differences between prev and next model
* @param {Row} prev - model before change
* @param {Row} next - model after change
* @returns {Row} a Row that contains differences between prev and next
**/
function diff(prev, next) {
const diffModel = new Row();
const prevIsValid = isValidModel(prev);
const nextIsValid = isValidModel(next);
if (prevIsValid) diffModel.key = prev.key;
if (!prevIsValid && nextIsValid) diffModel.key = next.key;
if (!prevIsValid && !nextIsValid) {
console.error('ChangeTracker, diff: missing or invalid diff models');
return null;
}
if (!nextIsValid) diffModel.state = RowStatus.Deleted;
if (!prevIsValid) diffModel.state = RowStatus.New;
if (prevIsValid)
for (let field of prev.fields) {
//ignore default field values ('', null, undefined)
if (diffModel.state === RowStatus.Deleted && isDefaultValue(field.prevValue)) continue;
const diffField = new Field(field.name, field.prevValue)
diffModel.fields.push(diffField);
}
if (nextIsValid) {
for (let field of next.fields) {
//ignore default field values ('', null, undefined)
if (diffModel.state === RowStatus.New && isDefaultValue(field.prevValue)) continue;
let diffField = diffModel.fields.find(el =>
(el.name + '').toLowerCase() === (field.name + '').toLowerCase());
if (!diffField) {
diffField = new Field(field.name, undefined, field.prevValue);
diffModel.fields.push(diffField);
} else
diffField.nextValue = field.prevValue;
}
}
// Prende solo quelli differenti
diffModel.fields = diffModel.fields.filter(el => (el.prevValue + '').toLowerCase() !== (el.nextValue + '').toLowerCase());
if (!diffModel.state)
diffModel.state = diffModel.fields.length > 0
? RowStatus.Modified
: RowStatus.Unchanged;
if (prev && Array.isArray(prev.tables) && prev.tables.length > 0)
for (let table of prev.tables) {
const addedTable = new Table(table.name);
diffModel.tables.push(addedTable);
for (let row of table.rows) {
const nextTable = next && Array.isArray(next.tables) &&
next.tables.find(el => (el.name + '') === (table.name + ''));
const nextRow = nextTable && Array.isArray(nextTable.rows) && nextTable.rows.find(el => el.key === row.key);
const diffRow = diff(row, nextRow);
if (diffRow && isFull(diffRow))
addedTable.rows.push(diffRow);
}
}
if (next && Array.isArray(next.tables) && next.tables.length > 0)
for (let table of next.tables) {
let addedTable = diffModel.tables.find(el => el.name === table.name);
if (!addedTable) {
addedTable = new Table(table.name);
diffModel.tables.push(addedTable);
}
for (let row of table.rows) {
const prevTable = prev && Array.isArray(prev.tables) &&
prev.tables.find(el => (el.name + '') === (table.name + ''));
const prevRow = prevTable && Array.isArray(prevTable.rows) && prevTable.rows.find(el => el.key === row.key);
const diffRow = diff(prevRow, row);
const alreadyRow = addedTable.rows.find(el => el.key === row.key);
if (!alreadyRow && diffRow && isFull(diffRow))
addedTable.rows.push(diffRow);
}
}
diffModel.tables = diffModel.tables.filter(el => Array.isArray(el.rows) && el.rows.length > 0);
return diffModel;
}
function isValidModel(row) {
return typeof row === 'object' && row != null && row instanceof Row;
}
function isDefaultValue(value) {
return typeof value === 'undefined' || value === null || value === '';
}
function isFull(model) {
return Array.isArray(model.fields) && model.fields.length > 0 || Array.isArray(model.tables) && model.tables.some(el => el.rows.some(isFull));
}
module.exports = {diff}