This commit is contained in:
parent
e9cca58e4e
commit
d296658f64
3 changed files with 114 additions and 2 deletions
77
src/model/builder.ts
Normal file
77
src/model/builder.ts
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
import {
|
||||||
|
defineModel,
|
||||||
|
IdentifierDefinition,
|
||||||
|
ModelDefinition,
|
||||||
|
ModelShape,
|
||||||
|
} from "./model";
|
||||||
|
import {ConstructorOf} from "../utils";
|
||||||
|
import {Definition} from "./property-definition";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model definition builder.
|
||||||
|
*/
|
||||||
|
export class ModelBuilder<
|
||||||
|
T extends object,
|
||||||
|
Shape extends ModelShape<T>,
|
||||||
|
Identifier extends IdentifierDefinition<T, Shape>,
|
||||||
|
> {
|
||||||
|
/**
|
||||||
|
* The built model definition.
|
||||||
|
*/
|
||||||
|
definition: ModelDefinition<T, Shape, Identifier>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a new property.
|
||||||
|
* @param name The new property name.
|
||||||
|
* @param definition The new property definition.
|
||||||
|
*/
|
||||||
|
property<
|
||||||
|
SerializedType,
|
||||||
|
PropertyName extends Exclude<keyof T, keyof Shape>,
|
||||||
|
PropertyDefinition extends Definition<SerializedType, T[PropertyName]>,
|
||||||
|
>(name: PropertyName, definition: PropertyDefinition) {
|
||||||
|
(this.definition.properties[name] as Definition<unknown, T[typeof name]>) =
|
||||||
|
definition;
|
||||||
|
|
||||||
|
return this as unknown as ModelBuilder<
|
||||||
|
T,
|
||||||
|
Shape & {[k in PropertyName]: PropertyDefinition},
|
||||||
|
Identifier
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the model identifier.
|
||||||
|
* @param identifier The new model identifier.
|
||||||
|
*/
|
||||||
|
identifier<NewIdentifier extends IdentifierDefinition<T, Shape>>(
|
||||||
|
identifier: NewIdentifier,
|
||||||
|
) {
|
||||||
|
(this.definition.identifier as unknown) = identifier;
|
||||||
|
return this as unknown as ModelBuilder<T, Shape, NewIdentifier>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a model using the current model definition.
|
||||||
|
*/
|
||||||
|
define() {
|
||||||
|
return defineModel(this.definition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a model builder for the provided class.
|
||||||
|
* @param Class The class for which to build a model.
|
||||||
|
*/
|
||||||
|
export function newModel<
|
||||||
|
T extends object,
|
||||||
|
Shape extends ModelShape<T> = object,
|
||||||
|
Identifier extends IdentifierDefinition<T, Shape> = never,
|
||||||
|
>(Class: ConstructorOf<T>): ModelBuilder<T, Shape, Identifier> {
|
||||||
|
const builder = new ModelBuilder<T, Shape, Identifier>();
|
||||||
|
builder.definition = {
|
||||||
|
Class,
|
||||||
|
properties: {} as Shape,
|
||||||
|
};
|
||||||
|
return builder;
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
import * as property from "./properties";
|
export * as property from "./properties";
|
||||||
export {property};
|
|
||||||
|
|
||||||
export * from "./model";
|
export * from "./model";
|
||||||
export {Definition} from "./property-definition";
|
export {Definition} from "./property-definition";
|
||||||
|
export {newModel, ModelBuilder} from "./builder";
|
||||||
|
|
||||||
export {ArrayType} from "./types/array";
|
export {ArrayType} from "./types/array";
|
||||||
export {BooleanType} from "./types/boolean";
|
export {BooleanType} from "./types/boolean";
|
||||||
|
|
35
tests/builder.test.ts
Normal file
35
tests/builder.test.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import {describe, expect, test} from "vitest";
|
||||||
|
|
||||||
|
import {defineModel, newModel, s} from "../src/library";
|
||||||
|
|
||||||
|
class Testest {
|
||||||
|
foo: string;
|
||||||
|
bar: number;
|
||||||
|
baz: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("model builder", () => {
|
||||||
|
const modelBuilder = newModel(Testest)
|
||||||
|
.property("foo", s.property.string())
|
||||||
|
.property("bar", s.property.decimal())
|
||||||
|
.property("baz", s.property.boolean())
|
||||||
|
.identifier("foo");
|
||||||
|
|
||||||
|
test("build model definition", () => {
|
||||||
|
expect(modelBuilder.definition).toStrictEqual({
|
||||||
|
Class: Testest,
|
||||||
|
identifier: "foo",
|
||||||
|
properties: {
|
||||||
|
foo: s.property.string(),
|
||||||
|
bar: s.property.decimal(),
|
||||||
|
baz: s.property.boolean(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("build a model", () => {
|
||||||
|
expect(modelBuilder.define()).toStrictEqual(
|
||||||
|
defineModel(modelBuilder.definition),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue