add builder
This commit is contained in:
@ -7,6 +7,9 @@ import ConfigurationDefinition, { DefinitionType } from "#configuration/configur
|
||||
import definitionValidators from "#configuration/configurationValidatior";
|
||||
import Server from "#framework/server/server";
|
||||
import getlogger, { defaultLogger } from "#logger";
|
||||
import {Builder} from "#framework/builder/builder";
|
||||
|
||||
const x = Builder<App>(Server);
|
||||
|
||||
const app: App = new (class extends App {
|
||||
public options (setDefinitions: (...definitions: ConfigurationDefinition[]) => void): void {
|
||||
|
||||
@ -15,13 +15,15 @@ export class RepoId extends Identifier<string> {
|
||||
}
|
||||
}
|
||||
export default class Repo extends Aggregate<RepoId>{
|
||||
|
||||
|
||||
private readonly _id?: RepoId;
|
||||
private _name = "";
|
||||
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
||||
private readonly _count = 1;
|
||||
|
||||
private readonly _userAssignment: UserAssignment[] = [];
|
||||
|
||||
public constructor (id: RepoId| undefined) {
|
||||
|
||||
public constructor (id: RepoId | undefined) {
|
||||
super();
|
||||
this._id = id;
|
||||
}
|
||||
@ -41,14 +43,21 @@ export default class Repo extends Aggregate<RepoId>{
|
||||
public get path (): string {
|
||||
return "/" + this._name;
|
||||
}
|
||||
|
||||
|
||||
public get userAssignment (): UserAssignment[] {
|
||||
return this._userAssignment;
|
||||
}
|
||||
|
||||
// public static builder (): IBuilder<Repo> {
|
||||
// return (<unknown> Builder(Repo)) as IBuilder<Repo>;
|
||||
// }
|
||||
public addUserAssignment (ua: UserAssignment): UserAssignment[] {
|
||||
this._userAssignment.push(ua);
|
||||
return this._userAssignment;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IRepoBuider {
|
||||
name: string;
|
||||
id: RepoId;
|
||||
addUserAssignment: UserAssignment;
|
||||
}
|
||||
|
||||
export class RepoIdGenerator implements IdentifierGenerator<RepoId> {
|
||||
|
||||
@ -2,7 +2,7 @@ import { ValueObject } from "#ddd";
|
||||
import { UserId } from "../user/user.entity";
|
||||
// import { Builder, IBuilder } from "builder-pattern";
|
||||
|
||||
enum UserRight {
|
||||
export enum UserRight {
|
||||
Read = "read",
|
||||
AppendOnly = "append",
|
||||
Write = "write"
|
||||
@ -13,7 +13,7 @@ export class UserAssignment extends ValueObject {
|
||||
|
||||
private readonly _userId: UserId;
|
||||
|
||||
private constructor (userId: UserId, right: UserRight) {
|
||||
public constructor (userId: UserId, right: UserRight) {
|
||||
super();
|
||||
this._userId = userId;
|
||||
this._right = right;
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import Repo from "#domain/repo/repo.entity";
|
||||
import { reflect } from "typescript-rtti";
|
||||
import Repo, { IRepoBuider, RepoId } from "#domain/repo/repo.entity";
|
||||
import { UserAssignment, UserRight } from "#domain/repo/userAssignment.entity";
|
||||
import { UserId } from "#domain/user/user.entity";
|
||||
import { reflect, ReflectedArrayRef, ReflectedClassRef, ReflectedUnionRef } from "typescript-rtti";
|
||||
|
||||
export type IBuilder<T> = {
|
||||
[k in keyof T]-?: (arg: T[k]) => IBuilder<T>
|
||||
@ -8,19 +10,96 @@ export type IBuilder<T> = {
|
||||
build(): T;
|
||||
};
|
||||
|
||||
type Clazz<T> = new(...args: unknown[]) => T;
|
||||
type Clazz<T> = new (...args: unknown[]) => T;
|
||||
|
||||
type Constructor<Params extends readonly any[] = readonly any[], Result = any> = new (...params: Params) => Result;
|
||||
type Constructor<Params extends readonly any[] = readonly any[], Result = any> = new (...params: Params) => Result;
|
||||
|
||||
interface Foo {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export function Builder<Type> (type: Constructor): IBuilder<Type> {
|
||||
console.log(reflect(type).class.prototype);
|
||||
const parameters: { name: string; class: any }[] = [];
|
||||
const properties = new Map<string, { name: string; class: any, aggregation?: string, parameter: boolean }>();
|
||||
for (const property of reflect(type).properties) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!property.name.startsWith("_") && property.class.super !== null) {
|
||||
if (property.type instanceof ReflectedClassRef) {
|
||||
properties.set(property.name, { name: property.name, class: property.type.class, parameter: false });
|
||||
}
|
||||
else if (property.type instanceof ReflectedUnionRef) {
|
||||
properties.set(property.name, { name: property.name, class: (<ReflectedClassRef<unknown>>property.type.types.filter(t => t instanceof ReflectedClassRef)[0]).class, parameter: false });
|
||||
}
|
||||
else if (property.type instanceof ReflectedArrayRef) {
|
||||
properties.set(property.name, { name: property.name, class: (<ReflectedClassRef<unknown>>property.type.elementType).class, aggregation: "array", parameter: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const parameter of reflect(type).parameters) {
|
||||
const name = parameter.rawMetadata.n;
|
||||
parameters.push({ name: name, class: properties.get(parameter.name) });
|
||||
if (properties.get(name) !== undefined)
|
||||
(properties.get(name) as { parameter: boolean }).parameter = true;
|
||||
}
|
||||
|
||||
const values = new Map<string, unknown>();
|
||||
const builder = new Proxy(
|
||||
{},
|
||||
{}
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
get (_target, prop) {
|
||||
if (typeof prop === "string" && prop.startsWith("add")) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
||||
const tprop = prop.charAt(3).toLocaleLowerCase() + prop.substring(4);
|
||||
return (x: unknown): unknown => {
|
||||
if (properties.get(tprop)?.aggregation === "array") {
|
||||
if (!values.has(tprop))
|
||||
values.set(tprop, []);
|
||||
(values.get(tprop) as Array<unknown>).push(x);
|
||||
} else {
|
||||
values.set(tprop, x);
|
||||
}
|
||||
return builder;
|
||||
};
|
||||
} else if ("build" === prop) {
|
||||
const params: unknown[] = [];
|
||||
for (const param of parameters) {
|
||||
params.push(values.get(param.name));
|
||||
}
|
||||
const obj: Foo = new type(params);
|
||||
for (const propertyname of properties.keys()) {
|
||||
const prop = properties.get(propertyname);
|
||||
if (values.has(propertyname) && !prop?.parameter) {
|
||||
if (prop?.aggregation === "array") {
|
||||
const desc = Object.getOwnPropertyDescriptor(obj, propertyname);
|
||||
if (desc?.set === undefined) {
|
||||
const methodeName = "add" + propertyname.charAt(0).toUpperCase() + propertyname.slice(1);
|
||||
for (const value of (values.get(propertyname) as Array<unknown>)) {
|
||||
(obj[methodeName] as ((t: unknown) => unknown))(value);
|
||||
}
|
||||
} else {
|
||||
obj[propertyname] = values.get(propertyname);
|
||||
}
|
||||
} else {
|
||||
obj[propertyname] = values.get(propertyname);
|
||||
}
|
||||
}
|
||||
}
|
||||
return () => obj;
|
||||
}
|
||||
|
||||
return (x: unknown): unknown => {
|
||||
values.set(prop.toString(), x);
|
||||
return builder;
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return builder as IBuilder<Type>;
|
||||
}
|
||||
|
||||
const builder = Builder<Repo>(Repo);
|
||||
builder.name("").build();
|
||||
const ua1 = new UserAssignment(new UserId("test"), UserRight.Read);
|
||||
const ua2 = new UserAssignment(new UserId("test2"), UserRight.Read);
|
||||
const builder = Builder<IRepoBuider>(Repo);
|
||||
const x = builder.id(new RepoId("test")).name("name").addUserAssignment(ua1).addUserAssignment(ua2).build();
|
||||
console.log(x);
|
||||
Reference in New Issue
Block a user