add builder
This commit is contained in:
@ -7,6 +7,9 @@ import ConfigurationDefinition, { DefinitionType } from "#configuration/configur
|
|||||||
import definitionValidators from "#configuration/configurationValidatior";
|
import definitionValidators from "#configuration/configurationValidatior";
|
||||||
import Server from "#framework/server/server";
|
import Server from "#framework/server/server";
|
||||||
import getlogger, { defaultLogger } from "#logger";
|
import getlogger, { defaultLogger } from "#logger";
|
||||||
|
import {Builder} from "#framework/builder/builder";
|
||||||
|
|
||||||
|
const x = Builder<App>(Server);
|
||||||
|
|
||||||
const app: App = new (class extends App {
|
const app: App = new (class extends App {
|
||||||
public options (setDefinitions: (...definitions: ConfigurationDefinition[]) => void): void {
|
public options (setDefinitions: (...definitions: ConfigurationDefinition[]) => void): void {
|
||||||
|
|||||||
@ -15,13 +15,15 @@ export class RepoId extends Identifier<string> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default class Repo extends Aggregate<RepoId>{
|
export default class Repo extends Aggregate<RepoId>{
|
||||||
|
|
||||||
private readonly _id?: RepoId;
|
private readonly _id?: RepoId;
|
||||||
private _name = "";
|
private _name = "";
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
||||||
|
private readonly _count = 1;
|
||||||
|
|
||||||
private readonly _userAssignment: UserAssignment[] = [];
|
private readonly _userAssignment: UserAssignment[] = [];
|
||||||
|
|
||||||
public constructor (id: RepoId| undefined) {
|
public constructor (id: RepoId | undefined) {
|
||||||
super();
|
super();
|
||||||
this._id = id;
|
this._id = id;
|
||||||
}
|
}
|
||||||
@ -41,14 +43,21 @@ export default class Repo extends Aggregate<RepoId>{
|
|||||||
public get path (): string {
|
public get path (): string {
|
||||||
return "/" + this._name;
|
return "/" + this._name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get userAssignment (): UserAssignment[] {
|
public get userAssignment (): UserAssignment[] {
|
||||||
return this._userAssignment;
|
return this._userAssignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static builder (): IBuilder<Repo> {
|
public addUserAssignment (ua: UserAssignment): UserAssignment[] {
|
||||||
// return (<unknown> Builder(Repo)) as IBuilder<Repo>;
|
this._userAssignment.push(ua);
|
||||||
// }
|
return this._userAssignment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRepoBuider {
|
||||||
|
name: string;
|
||||||
|
id: RepoId;
|
||||||
|
addUserAssignment: UserAssignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RepoIdGenerator implements IdentifierGenerator<RepoId> {
|
export class RepoIdGenerator implements IdentifierGenerator<RepoId> {
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { ValueObject } from "#ddd";
|
|||||||
import { UserId } from "../user/user.entity";
|
import { UserId } from "../user/user.entity";
|
||||||
// import { Builder, IBuilder } from "builder-pattern";
|
// import { Builder, IBuilder } from "builder-pattern";
|
||||||
|
|
||||||
enum UserRight {
|
export enum UserRight {
|
||||||
Read = "read",
|
Read = "read",
|
||||||
AppendOnly = "append",
|
AppendOnly = "append",
|
||||||
Write = "write"
|
Write = "write"
|
||||||
@ -13,7 +13,7 @@ export class UserAssignment extends ValueObject {
|
|||||||
|
|
||||||
private readonly _userId: UserId;
|
private readonly _userId: UserId;
|
||||||
|
|
||||||
private constructor (userId: UserId, right: UserRight) {
|
public constructor (userId: UserId, right: UserRight) {
|
||||||
super();
|
super();
|
||||||
this._userId = userId;
|
this._userId = userId;
|
||||||
this._right = right;
|
this._right = right;
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import Repo from "#domain/repo/repo.entity";
|
import Repo, { IRepoBuider, RepoId } from "#domain/repo/repo.entity";
|
||||||
import { reflect } from "typescript-rtti";
|
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> = {
|
export type IBuilder<T> = {
|
||||||
[k in keyof T]-?: (arg: T[k]) => IBuilder<T>
|
[k in keyof T]-?: (arg: T[k]) => IBuilder<T>
|
||||||
@ -8,19 +10,96 @@ export type IBuilder<T> = {
|
|||||||
build(): 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> {
|
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(
|
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>;
|
return builder as IBuilder<Type>;
|
||||||
}
|
}
|
||||||
|
const ua1 = new UserAssignment(new UserId("test"), UserRight.Read);
|
||||||
const builder = Builder<Repo>(Repo);
|
const ua2 = new UserAssignment(new UserId("test2"), UserRight.Read);
|
||||||
builder.name("").build();
|
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