Objects, arrays and models changes deep checks when checking if a model is dirty.
This commit is contained in:
parent
ff9cb91f73
commit
8f8dafed5b
7 changed files with 91 additions and 10 deletions
|
@ -19,7 +19,7 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="Version 3.2.1" src="https://img.shields.io/badge/version-3.2.1-blue" />
|
<img alt="Version 3.2.2" src="https://img.shields.io/badge/version-3.2.2-blue" />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@sharkitek/core",
|
"name": "@sharkitek/core",
|
||||||
"version": "3.2.1",
|
"version": "3.2.2",
|
||||||
"description": "TypeScript library for well-designed model architectures.",
|
"description": "TypeScript library for well-designed model architectures.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"deserialization",
|
"deserialization",
|
||||||
|
|
|
@ -243,7 +243,7 @@ export function model<ModelType extends Model<Shape, IdentifierType<Shape, Ident
|
||||||
{
|
{
|
||||||
this.forEachModelProperty((propertyName, propertyDefinition) => {
|
this.forEachModelProperty((propertyName, propertyDefinition) => {
|
||||||
// For each property, set its original value to its current property value.
|
// For each property, set its original value to its current property value.
|
||||||
this._originalProperties[propertyName] = (this as PropertiesModel<Shape>)[propertyName];
|
this._originalProperties[propertyName] = structuredClone(this as PropertiesModel<Shape>)[propertyName];
|
||||||
propertyDefinition.type.resetDiff((this as PropertiesModel<Shape>)[propertyName]);
|
propertyDefinition.type.resetDiff((this as PropertiesModel<Shape>)[propertyName]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,40 @@ export class ArrayType<SerializedValueType, SharkitekValueType> extends Type<Ser
|
||||||
// Reset diff of all elements.
|
// Reset diff of all elements.
|
||||||
value.forEach((value) => this.valueDefinition.type.resetDiff(value));
|
value.forEach((value) => this.valueDefinition.type.resetDiff(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
propertyHasChanged(originalValue: SharkitekValueType[]|null|undefined, currentValue: SharkitekValueType[]|null|undefined): boolean
|
||||||
|
{
|
||||||
|
// If any array length is different, arrays are different.
|
||||||
|
if (originalValue?.length != currentValue?.length) return true;
|
||||||
|
// If length is undefined, values are probably not arrays.
|
||||||
|
if (originalValue?.length == undefined) return false;
|
||||||
|
|
||||||
|
for (const key of originalValue.keys())
|
||||||
|
{ // Check for any change for each value in the array.
|
||||||
|
if (this.valueDefinition.type.propertyHasChanged(originalValue[key], currentValue[key]))
|
||||||
|
// The value has changed, the array is different.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // No change detected.
|
||||||
|
}
|
||||||
|
|
||||||
|
serializedPropertyHasChanged(originalValue: SerializedValueType[] | null | undefined, currentValue: SerializedValueType[] | null | undefined): boolean
|
||||||
|
{
|
||||||
|
// If any array length is different, arrays are different.
|
||||||
|
if (originalValue?.length != currentValue?.length) return true;
|
||||||
|
// If length is undefined, values are probably not arrays.
|
||||||
|
if (originalValue?.length == undefined) return false;
|
||||||
|
|
||||||
|
for (const key of originalValue.keys())
|
||||||
|
{ // Check for any change for each value in the array.
|
||||||
|
if (this.valueDefinition.type.serializedPropertyHasChanged(originalValue[key], currentValue[key]))
|
||||||
|
// The value has changed, the array is different.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // No change detected.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -48,6 +48,15 @@ export class ModelType<Shape extends ModelShape> extends Type<SerializedModel<Sh
|
||||||
// Reset diff of the given model.
|
// Reset diff of the given model.
|
||||||
value?.resetDiff();
|
value?.resetDiff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
propertyHasChanged(originalValue: Model<Shape>|null|undefined, currentValue: Model<Shape>|null|undefined): boolean
|
||||||
|
{
|
||||||
|
if (originalValue === undefined) return currentValue !== undefined;
|
||||||
|
if (originalValue === null) return currentValue !== null;
|
||||||
|
|
||||||
|
// If the current value is dirty, property has changed.
|
||||||
|
return currentValue.isDirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -66,6 +66,46 @@ export class ObjectType<Shape extends ModelShape> extends Type<SerializedModel<S
|
||||||
fieldDefinition.type.resetDiff(value?.[fieldName]);
|
fieldDefinition.type.resetDiff(value?.[fieldName]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
propertyHasChanged(originalValue: PropertiesModel<Shape>|null|undefined, currentValue: PropertiesModel<Shape>|null|undefined): boolean
|
||||||
|
{
|
||||||
|
// Get keys arrays.
|
||||||
|
const originalKeys = Object.keys(originalValue) as (keyof Shape)[];
|
||||||
|
const currentKeys = Object.keys(currentValue) as (keyof Shape)[];
|
||||||
|
|
||||||
|
if (originalKeys.join(",") != currentKeys.join(","))
|
||||||
|
// Keys have changed, objects are different.
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (const key of originalKeys)
|
||||||
|
{ // Check for any change for each value in the object.
|
||||||
|
if (this.shape[key].type.propertyHasChanged(originalValue[key], currentValue[key]))
|
||||||
|
// The value has changed, the object is different.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // No change detected.
|
||||||
|
}
|
||||||
|
|
||||||
|
serializedPropertyHasChanged(originalValue: SerializedModel<Shape>|null|undefined, currentValue: SerializedModel<Shape>|null|undefined): boolean
|
||||||
|
{
|
||||||
|
// Get keys arrays.
|
||||||
|
const originalKeys = Object.keys(originalValue) as (keyof Shape)[];
|
||||||
|
const currentKeys = Object.keys(currentValue) as (keyof Shape)[];
|
||||||
|
|
||||||
|
if (originalKeys.join(",") != currentKeys.join(","))
|
||||||
|
// Keys have changed, objects are different.
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (const key of originalKeys)
|
||||||
|
{ // Check for any change for each value in the object.
|
||||||
|
if (this.shape[key].type.serializedPropertyHasChanged(originalValue[key], currentValue[key]))
|
||||||
|
// The value has changed, the object is different.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // No change detected.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -142,23 +142,21 @@ it("save with modified submodels", () => {
|
||||||
title: "this is a test",
|
title: "this is a test",
|
||||||
authors: [
|
authors: [
|
||||||
{ name: "DOE", firstName: "John", email: "test@test.test", createdAt: (new Date()).toISOString(), active: true, },
|
{ name: "DOE", firstName: "John", email: "test@test.test", createdAt: (new Date()).toISOString(), active: true, },
|
||||||
{ name: "TEST", firstName: "Another", email: "another@test.test", createdAt: (new Date()).toISOString(), active: false, },
|
{ name: "TEST", firstName: "Another", email: "another@test.test", createdAt: (new Date("1997-09-09")).toISOString(), active: false, },
|
||||||
],
|
],
|
||||||
text: "this is a long test.",
|
text: "this is a long test.",
|
||||||
evaluation: "25.23",
|
evaluation: "25.23",
|
||||||
tags: [ {name: "test"}, {name: "foo"} ],
|
tags: [ {name: "test"}, {name: "foo"} ],
|
||||||
});
|
});
|
||||||
|
|
||||||
article.authors = article.authors.map((author) => {
|
article.authors[0].name = "TEST";
|
||||||
author.name = "TEST";
|
article.authors[1].createdAt.setMonth(9);
|
||||||
return author;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(article.save()).toStrictEqual({
|
expect(article.save()).toStrictEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
authors: [
|
authors: [
|
||||||
{ name: "TEST", },
|
{ name: "TEST" },
|
||||||
{}, //{ name: "TEST", firstName: "Another", email: "another@test.test" },
|
{ createdAt: (new Date("1997-10-09")).toISOString() }, //{ name: "TEST", firstName: "Another", email: "another@test.test" },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue