Add a simple object type and other improvements.
This commit is contained in:
parent
eb920a3d6d
commit
bb5eed5162
5 changed files with 98 additions and 3 deletions
|
@ -28,7 +28,7 @@ export class Definition<SerializedType, SharkitekType>
|
|||
* @param type - The model property type.
|
||||
* @param options - Property definition options.
|
||||
*/
|
||||
export function SDefine<SerializedType, SharkitekType>(type: Type<SerializedType, SharkitekType>, options: DefinitionOptions<SerializedType, SharkitekType> = {})
|
||||
export function SDefine<SerializedType, SharkitekType>(type: Type<SerializedType, SharkitekType>, options: DefinitionOptions<SerializedType, SharkitekType> = {}): Definition<SerializedType, SharkitekType>
|
||||
{
|
||||
return new Definition(type, options);
|
||||
return new Definition<SerializedType, SharkitekType>(type, options);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import {Type} from "./Type";
|
|||
export class ArrayType<SerializedValueType, SharkitekValueType> extends Type<SerializedValueType[], SharkitekValueType[]>
|
||||
{
|
||||
/**
|
||||
* Constructs a new array type of Sharkitek model property.
|
||||
* Constructs a new array type of a Sharkitek model property.
|
||||
* @param valueType - Type of the array values.
|
||||
*/
|
||||
constructor(protected valueType: Type<SerializedValueType, SharkitekValueType>)
|
||||
|
|
77
src/Model/Types/ObjectType.ts
Normal file
77
src/Model/Types/ObjectType.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
import {Type} from "./Type";
|
||||
import {Definition} from "../Definition";
|
||||
|
||||
/**
|
||||
* Type of a simple object.
|
||||
*/
|
||||
export class ObjectType<Keys extends symbol|string> extends Type<Record<Keys, any>, Record<Keys, any>>
|
||||
{
|
||||
/**
|
||||
* Constructs a new object type of a Sharkitek model property.
|
||||
* @param fieldsTypes Object fields types.
|
||||
*/
|
||||
constructor(protected fieldsTypes: Record<Keys, Definition<unknown, unknown>>)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
deserialize(value: Record<Keys, any>): Record<Keys, any>
|
||||
{
|
||||
if (value === undefined) return undefined;
|
||||
if (value === null) return null;
|
||||
|
||||
return Object.fromEntries(
|
||||
// For each defined field, deserialize its value according to its type.
|
||||
(Object.entries(this.fieldsTypes) as [Keys, Definition<any, any>][]).map(([fieldName, fieldDefinition]) => (
|
||||
// Return an entry with the current field name and the deserialized value.
|
||||
[fieldName, fieldDefinition.type.deserialize(value[fieldName])]
|
||||
))
|
||||
) as Record<Keys, any>;
|
||||
}
|
||||
|
||||
serialize(value: Record<Keys, any>): Record<Keys, any>
|
||||
{
|
||||
if (value === undefined) return undefined;
|
||||
if (value === null) return null;
|
||||
|
||||
return Object.fromEntries(
|
||||
// For each defined field, serialize its value according to its type.
|
||||
(Object.entries(this.fieldsTypes) as [Keys, Definition<any, any>][]).map(([fieldName, fieldDefinition]) => (
|
||||
// Return an entry with the current field name and the serialized value.
|
||||
[fieldName, fieldDefinition.type.serialize(value[fieldName])]
|
||||
))
|
||||
) as Record<Keys, any>;
|
||||
}
|
||||
|
||||
serializeDiff(value: Record<Keys, any>): Record<Keys, any>
|
||||
{
|
||||
if (value === undefined) return undefined;
|
||||
if (value === null) return null;
|
||||
|
||||
return Object.fromEntries(
|
||||
// For each defined field, serialize its diff value according to its type.
|
||||
(Object.entries(this.fieldsTypes) as [Keys, Definition<any, any>][]).map(([fieldName, fieldDefinition]) => (
|
||||
// Return an entry with the current field name and the serialized diff value.
|
||||
[fieldName, fieldDefinition.type.serializeDiff(value[fieldName])]
|
||||
))
|
||||
) as Record<Keys, any>;
|
||||
}
|
||||
|
||||
resetDiff(value: Record<Keys, any>): void
|
||||
{
|
||||
// For each field, reset its diff.
|
||||
(Object.entries(this.fieldsTypes) as [Keys, Definition<any, any>][]).forEach(([fieldName, fieldDefinition]) => {
|
||||
// Reset diff of the current field.
|
||||
fieldDefinition.type.resetDiff(value[fieldName]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of a simple object.
|
||||
* @param fieldsTypes Object fields types.
|
||||
*/
|
||||
export function SObject<Keys extends symbol|string>(fieldsTypes: Record<Keys, Definition<unknown, unknown>>): ObjectType<Keys>
|
||||
{
|
||||
return new ObjectType<Keys>(fieldsTypes);
|
||||
}
|
|
@ -10,4 +10,5 @@ export * from "./Model/Types/DateType";
|
|||
export * from "./Model/Types/DecimalType";
|
||||
export * from "./Model/Types/ModelType";
|
||||
export * from "./Model/Types/NumericType";
|
||||
export * from "./Model/Types/ObjectType";
|
||||
export * from "./Model/Types/StringType";
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
ModelDefinition,
|
||||
SDefine, ModelIdentifier
|
||||
} from "../src";
|
||||
import {SObject} from "../src/Model/Types/ObjectType";
|
||||
|
||||
/**
|
||||
* Another test model.
|
||||
|
@ -54,6 +55,9 @@ class Article extends Model<Article>
|
|||
authors: Author[] = [];
|
||||
text: string;
|
||||
evaluation: number;
|
||||
tags: {
|
||||
name: string;
|
||||
}[];
|
||||
|
||||
protected SIdentifier(): ModelIdentifier<Article>
|
||||
{
|
||||
|
@ -68,6 +72,11 @@ class Article extends Model<Article>
|
|||
authors: SDefine(SArray(SModel(Author))),
|
||||
text: SDefine(SString),
|
||||
evaluation: SDefine(SDecimal),
|
||||
tags: SDefine(SArray(
|
||||
SObject({
|
||||
name: SDefine(SString),
|
||||
})
|
||||
)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -82,6 +91,7 @@ it("deserialize", () => {
|
|||
],
|
||||
text: "this is a long test.",
|
||||
evaluation: "25.23",
|
||||
tags: [ {name: "test"}, {name: "foo"} ],
|
||||
}).serialize()).toStrictEqual({
|
||||
id: 1,
|
||||
title: "this is a test",
|
||||
|
@ -91,6 +101,7 @@ it("deserialize", () => {
|
|||
],
|
||||
text: "this is a long test.",
|
||||
evaluation: "25.23",
|
||||
tags: [ {name: "test"}, {name: "foo"} ],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -104,6 +115,9 @@ it("create and check state then serialize", () => {
|
|||
];
|
||||
article.text = "this is a long test.";
|
||||
article.evaluation = 25.23;
|
||||
article.tags = [];
|
||||
article.tags.push({name: "test"});
|
||||
article.tags.push({name: "foo"});
|
||||
|
||||
expect(article.isNew()).toBeTruthy();
|
||||
expect(article.getIdentifier()).toStrictEqual(1);
|
||||
|
@ -116,6 +130,7 @@ it("create and check state then serialize", () => {
|
|||
],
|
||||
text: "this is a long test.",
|
||||
evaluation: "25.23",
|
||||
tags: [ {name: "test"}, {name: "foo"} ],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -130,6 +145,7 @@ it("deserialize then save", () => {
|
|||
],
|
||||
text: "this is a long test.",
|
||||
evaluation: "25.23",
|
||||
tags: [ {name: "test"}, {name: "foo"} ],
|
||||
});
|
||||
|
||||
expect(article.isNew()).toBeFalsy();
|
||||
|
@ -156,6 +172,7 @@ it("save with modified submodels", () => {
|
|||
],
|
||||
text: "this is a long test.",
|
||||
evaluation: "25.23",
|
||||
tags: [ {name: "test"}, {name: "foo"} ],
|
||||
});
|
||||
|
||||
article.authors = article.authors.map((author) => {
|
||||
|
|
Loading…
Reference in a new issue