Skip to content

Commit

Permalink
fix: changelog does not work with setters modifying internal variables
Browse files Browse the repository at this point in the history
  • Loading branch information
Maximvdw committed Jun 24, 2024
1 parent 3687f73 commit 83ab88c
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 11 deletions.
44 changes: 33 additions & 11 deletions src/data/decorators/ChangeLog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ export function createChangeLog<T extends Object>(target: T): T & SerializableCh
// Wrap all data members with a changelog to track deep changes
const metadata = DataSerializerUtils.getOwnMetadata(target.constructor);
if (metadata) {
const watchedProperties: string[] = [];
metadata.dataMembers.forEach((member) => {
watchedProperties.push(member.key);
if (target[member.key]) {
if (Array.isArray(target[member.key])) {
target[member.key].forEach((element) => {
Expand All @@ -164,16 +166,36 @@ export function createChangeLog<T extends Object>(target: T): T & SerializableCh
}
}
});
// Wrap the target in a proxy to track changes
const proxy = new Proxy(target, {
set: (obj, prop, value) => {
if (watchedProperties.includes(prop.toString())) {
if (obj[prop] !== value) {
obj[CHANGELOG_METADATA_KEY].addChange(prop.toString(), obj[prop], value);
}
obj[prop] = value;
} else {
// Get the current state of watched properties
const currentState = {};
watchedProperties.forEach((watchedProperty) => {
currentState[watchedProperty] = obj[watchedProperty];
});
obj[prop] = value;
// Determine if a setter modified another variable
watchedProperties.forEach((watchedProperty) => {
if (currentState[watchedProperty] !== obj[watchedProperty]) {
obj[CHANGELOG_METADATA_KEY].addChange(
watchedProperty,
currentState[watchedProperty],
obj[watchedProperty],
);
}
});
}
return true;
},
}) as T & SerializableChangelog;
return proxy;
}
// Wrap the target in a proxy to track changes
const proxy = new Proxy(target, {
set: (obj, prop, value) => {
if (obj[prop] !== value) {
obj[CHANGELOG_METADATA_KEY].addChange(prop.toString(), obj[prop], value);
}
obj[prop] = value;
return true;
},
}) as T & SerializableChangelog;
return proxy;
return target;
}
10 changes: 10 additions & 0 deletions test/specs/data/data.object.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
CHANGELOG_METADATA_KEY,
SerializableObject,
SerializableMapMember,
GeographicalPosition,
} from '../../../src';
import { DummySensorObject } from '../../mock/data/object/DummySensorObject';

Expand Down Expand Up @@ -327,5 +328,14 @@ describe('DataObject', () => {
});
});

it('should detect changes with setters', () => {
const object = new DataObject('test', 'Maxim');
object.setPosition(new GeographicalPosition(123, 45));
const objectWithChangelog = createChangeLog(object);
(object.position as GeographicalPosition).latitude = 456;
expect(objectWithChangelog.position[CHANGELOG_METADATA_KEY].getLatestChanges().length).to.equal(1);
expect(objectWithChangelog.position[CHANGELOG_METADATA_KEY].getLatestChanges()[0].property).to.not.equal("latitude");
expect(objectWithChangelog.position[CHANGELOG_METADATA_KEY].getLatestChanges()[0].property).to.equal("y");
});
});
});

0 comments on commit 83ab88c

Please sign in to comment.