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 {property};
|
||||
export * as property from "./properties";
|
||||
|
||||
export * from "./model";
|
||||
export {Definition} from "./property-definition";
|
||||
export {newModel, ModelBuilder} from "./builder";
|
||||
|
||||
export {ArrayType} from "./types/array";
|
||||
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