Skip to content

Commit 8f8dafe

Browse files
committed
Objects, arrays and models changes deep checks when checking if a model is dirty.
1 parent ff9cb91 commit 8f8dafe

File tree

7 files changed

+91
-10
lines changed

7 files changed

+91
-10
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
</p>
2020

2121
<p align="center">
22-
<img alt="Version 3.2.1" src="https://img.shields.io/badge/version-3.2.1-blue" />
22+
<img alt="Version 3.2.2" src="https://img.shields.io/badge/version-3.2.2-blue" />
2323
</p>
2424

2525
## Introduction

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@sharkitek/core",
3-
"version": "3.2.1",
3+
"version": "3.2.2",
44
"description": "TypeScript library for well-designed model architectures.",
55
"keywords": [
66
"deserialization",

src/Model/Model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ export function model<ModelType extends Model<Shape, IdentifierType<Shape, Ident
243243
{
244244
this.forEachModelProperty((propertyName, propertyDefinition) => {
245245
// For each property, set its original value to its current property value.
246-
this._originalProperties[propertyName] = (this as PropertiesModel<Shape>)[propertyName];
246+
this._originalProperties[propertyName] = structuredClone(this as PropertiesModel<Shape>)[propertyName];
247247
propertyDefinition.type.resetDiff((this as PropertiesModel<Shape>)[propertyName]);
248248
});
249249
}

src/Model/Types/ArrayType.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,40 @@ export class ArrayType<SerializedValueType, SharkitekValueType> extends Type<Ser
5454
// Reset diff of all elements.
5555
value.forEach((value) => this.valueDefinition.type.resetDiff(value));
5656
}
57+
58+
propertyHasChanged(originalValue: SharkitekValueType[]|null|undefined, currentValue: SharkitekValueType[]|null|undefined): boolean
59+
{
60+
// If any array length is different, arrays are different.
61+
if (originalValue?.length != currentValue?.length) return true;
62+
// If length is undefined, values are probably not arrays.
63+
if (originalValue?.length == undefined) return false;
64+
65+
for (const key of originalValue.keys())
66+
{ // Check for any change for each value in the array.
67+
if (this.valueDefinition.type.propertyHasChanged(originalValue[key], currentValue[key]))
68+
// The value has changed, the array is different.
69+
return true;
70+
}
71+
72+
return false; // No change detected.
73+
}
74+
75+
serializedPropertyHasChanged(originalValue: SerializedValueType[] | null | undefined, currentValue: SerializedValueType[] | null | undefined): boolean
76+
{
77+
// If any array length is different, arrays are different.
78+
if (originalValue?.length != currentValue?.length) return true;
79+
// If length is undefined, values are probably not arrays.
80+
if (originalValue?.length == undefined) return false;
81+
82+
for (const key of originalValue.keys())
83+
{ // Check for any change for each value in the array.
84+
if (this.valueDefinition.type.serializedPropertyHasChanged(originalValue[key], currentValue[key]))
85+
// The value has changed, the array is different.
86+
return true;
87+
}
88+
89+
return false; // No change detected.
90+
}
5791
}
5892

5993
/**

src/Model/Types/ModelType.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ export class ModelType<Shape extends ModelShape> extends Type<SerializedModel<Sh
4848
// Reset diff of the given model.
4949
value?.resetDiff();
5050
}
51+
52+
propertyHasChanged(originalValue: Model<Shape>|null|undefined, currentValue: Model<Shape>|null|undefined): boolean
53+
{
54+
if (originalValue === undefined) return currentValue !== undefined;
55+
if (originalValue === null) return currentValue !== null;
56+
57+
// If the current value is dirty, property has changed.
58+
return currentValue.isDirty();
59+
}
5160
}
5261

5362
/**

src/Model/Types/ObjectType.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,46 @@ export class ObjectType<Shape extends ModelShape> extends Type<SerializedModel<S
6666
fieldDefinition.type.resetDiff(value?.[fieldName]);
6767
});
6868
}
69+
70+
propertyHasChanged(originalValue: PropertiesModel<Shape>|null|undefined, currentValue: PropertiesModel<Shape>|null|undefined): boolean
71+
{
72+
// Get keys arrays.
73+
const originalKeys = Object.keys(originalValue) as (keyof Shape)[];
74+
const currentKeys = Object.keys(currentValue) as (keyof Shape)[];
75+
76+
if (originalKeys.join(",") != currentKeys.join(","))
77+
// Keys have changed, objects are different.
78+
return true;
79+
80+
for (const key of originalKeys)
81+
{ // Check for any change for each value in the object.
82+
if (this.shape[key].type.propertyHasChanged(originalValue[key], currentValue[key]))
83+
// The value has changed, the object is different.
84+
return true;
85+
}
86+
87+
return false; // No change detected.
88+
}
89+
90+
serializedPropertyHasChanged(originalValue: SerializedModel<Shape>|null|undefined, currentValue: SerializedModel<Shape>|null|undefined): boolean
91+
{
92+
// Get keys arrays.
93+
const originalKeys = Object.keys(originalValue) as (keyof Shape)[];
94+
const currentKeys = Object.keys(currentValue) as (keyof Shape)[];
95+
96+
if (originalKeys.join(",") != currentKeys.join(","))
97+
// Keys have changed, objects are different.
98+
return true;
99+
100+
for (const key of originalKeys)
101+
{ // Check for any change for each value in the object.
102+
if (this.shape[key].type.serializedPropertyHasChanged(originalValue[key], currentValue[key]))
103+
// The value has changed, the object is different.
104+
return true;
105+
}
106+
107+
return false; // No change detected.
108+
}
69109
}
70110

71111
/**

tests/Model.test.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,23 +142,21 @@ it("save with modified submodels", () => {
142142
title: "this is a test",
143143
authors: [
144144
{ name: "DOE", firstName: "John", email: "test@test.test", createdAt: (new Date()).toISOString(), active: true, },
145-
{ name: "TEST", firstName: "Another", email: "another@test.test", createdAt: (new Date()).toISOString(), active: false, },
145+
{ name: "TEST", firstName: "Another", email: "another@test.test", createdAt: (new Date("1997-09-09")).toISOString(), active: false, },
146146
],
147147
text: "this is a long test.",
148148
evaluation: "25.23",
149149
tags: [ {name: "test"}, {name: "foo"} ],
150150
});
151151

152-
article.authors = article.authors.map((author) => {
153-
author.name = "TEST";
154-
return author;
155-
});
152+
article.authors[0].name = "TEST";
153+
article.authors[1].createdAt.setMonth(9);
156154

157155
expect(article.save()).toStrictEqual({
158156
id: 1,
159157
authors: [
160-
{ name: "TEST", },
161-
{}, //{ name: "TEST", firstName: "Another", email: "another@test.test" },
158+
{ name: "TEST" },
159+
{ createdAt: (new Date("1997-10-09")).toISOString() }, //{ name: "TEST", firstName: "Another", email: "another@test.test" },
162160
],
163161
});
164162
});

0 commit comments

Comments
 (0)