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 type - The model property type.
|
||||||
* @param options - Property definition options.
|
* @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[]>
|
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.
|
* @param valueType - Type of the array values.
|
||||||
*/
|
*/
|
||||||
constructor(protected valueType: Type<SerializedValueType, SharkitekValueType>)
|
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/DecimalType";
|
||||||
export * from "./Model/Types/ModelType";
|
export * from "./Model/Types/ModelType";
|
||||||
export * from "./Model/Types/NumericType";
|
export * from "./Model/Types/NumericType";
|
||||||
|
export * from "./Model/Types/ObjectType";
|
||||||
export * from "./Model/Types/StringType";
|
export * from "./Model/Types/StringType";
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
ModelDefinition,
|
ModelDefinition,
|
||||||
SDefine, ModelIdentifier
|
SDefine, ModelIdentifier
|
||||||
} from "../src";
|
} from "../src";
|
||||||
|
import {SObject} from "../src/Model/Types/ObjectType";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Another test model.
|
* Another test model.
|
||||||
|
@ -54,6 +55,9 @@ class Article extends Model<Article>
|
||||||
authors: Author[] = [];
|
authors: Author[] = [];
|
||||||
text: string;
|
text: string;
|
||||||
evaluation: number;
|
evaluation: number;
|
||||||
|
tags: {
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
|
||||||
protected SIdentifier(): ModelIdentifier<Article>
|
protected SIdentifier(): ModelIdentifier<Article>
|
||||||
{
|
{
|
||||||
|
@ -68,6 +72,11 @@ class Article extends Model<Article>
|
||||||
authors: SDefine(SArray(SModel(Author))),
|
authors: SDefine(SArray(SModel(Author))),
|
||||||
text: SDefine(SString),
|
text: SDefine(SString),
|
||||||
evaluation: SDefine(SDecimal),
|
evaluation: SDefine(SDecimal),
|
||||||
|
tags: SDefine(SArray(
|
||||||
|
SObject({
|
||||||
|
name: SDefine(SString),
|
||||||
|
})
|
||||||
|
)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,6 +91,7 @@ it("deserialize", () => {
|
||||||
],
|
],
|
||||||
text: "this is a long test.",
|
text: "this is a long test.",
|
||||||
evaluation: "25.23",
|
evaluation: "25.23",
|
||||||
|
tags: [ {name: "test"}, {name: "foo"} ],
|
||||||
}).serialize()).toStrictEqual({
|
}).serialize()).toStrictEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "this is a test",
|
title: "this is a test",
|
||||||
|
@ -91,6 +101,7 @@ it("deserialize", () => {
|
||||||
],
|
],
|
||||||
text: "this is a long test.",
|
text: "this is a long test.",
|
||||||
evaluation: "25.23",
|
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.text = "this is a long test.";
|
||||||
article.evaluation = 25.23;
|
article.evaluation = 25.23;
|
||||||
|
article.tags = [];
|
||||||
|
article.tags.push({name: "test"});
|
||||||
|
article.tags.push({name: "foo"});
|
||||||
|
|
||||||
expect(article.isNew()).toBeTruthy();
|
expect(article.isNew()).toBeTruthy();
|
||||||
expect(article.getIdentifier()).toStrictEqual(1);
|
expect(article.getIdentifier()).toStrictEqual(1);
|
||||||
|
@ -116,6 +130,7 @@ it("create and check state then serialize", () => {
|
||||||
],
|
],
|
||||||
text: "this is a long test.",
|
text: "this is a long test.",
|
||||||
evaluation: "25.23",
|
evaluation: "25.23",
|
||||||
|
tags: [ {name: "test"}, {name: "foo"} ],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -130,6 +145,7 @@ it("deserialize then save", () => {
|
||||||
],
|
],
|
||||||
text: "this is a long test.",
|
text: "this is a long test.",
|
||||||
evaluation: "25.23",
|
evaluation: "25.23",
|
||||||
|
tags: [ {name: "test"}, {name: "foo"} ],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(article.isNew()).toBeFalsy();
|
expect(article.isNew()).toBeFalsy();
|
||||||
|
@ -156,6 +172,7 @@ it("save with modified submodels", () => {
|
||||||
],
|
],
|
||||||
text: "this is a long test.",
|
text: "this is a long test.",
|
||||||
evaluation: "25.23",
|
evaluation: "25.23",
|
||||||
|
tags: [ {name: "test"}, {name: "foo"} ],
|
||||||
});
|
});
|
||||||
|
|
||||||
article.authors = article.authors.map((author) => {
|
article.authors = article.authors.map((author) => {
|
||||||
|
|
Loading…
Reference in a new issue