From d63f248b62adfe62871517159097610e20a7b2cf Mon Sep 17 00:00:00 2001 From: paean99 <> Date: Fri, 18 Jan 2019 23:32:30 +0000 Subject: [PATCH 1/3] array of dynamic decorators --- src/modules/user/CreateUser.ts | 35 +++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/modules/user/CreateUser.ts b/src/modules/user/CreateUser.ts index f431243..ee5db33 100644 --- a/src/modules/user/CreateUser.ts +++ b/src/modules/user/CreateUser.ts @@ -5,25 +5,44 @@ import { ClassType, InputType, Field, - UseMiddleware + Authorized } from "type-graphql"; import { RegisterInput } from "./register/RegisterInput"; import { User } from "../../entity/User"; import { Product } from "../../entity/Product"; -import { Middleware } from "type-graphql/interfaces/Middleware"; + +function myNewDecorator(value: any) { + console.log("myNewDecorator value: ", value); + return function( + target: any, + propertyKey: string, + descriptor: PropertyDescriptor + ) { + console.log("target: ", target); + console.log("propertyKey: ", propertyKey); + console.log("descriptor: ", descriptor); + }; +} function createResolver( suffix: string, returnType: T, inputType: X, entity: any, - middleware?: Middleware[] + decorator: any[] ) { + const decoratorFactory = (decos: any[]): Function => { + return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => + decos.map((deco: () => Function) => + deco()(target, propertyKey, descriptor) + ); + }; + @Resolver() class BaseResolver { + @decoratorFactory(decorator) @Mutation(() => returnType, { name: `create${suffix}` }) - @UseMiddleware(...(middleware || [])) - async create(@Arg("data", () => inputType) data: any) { + create(@Arg("data", () => inputType) data: any) { return entity.create(data).save(); } } @@ -41,11 +60,13 @@ export const CreateUserResolver = createResolver( "User", User, RegisterInput, - User + User, + [Authorized, myNewDecorator] ); export const CreateProductResolver = createResolver( "Product", Product, ProductInput, - Product + Product, + [Authorized, myNewDecorator] ); From a59852197aa3d421fe7a5f5e767e6c770a8f9fe9 Mon Sep 17 00:00:00 2001 From: paean99 <> Date: Sat, 19 Jan 2019 05:31:22 +0000 Subject: [PATCH 2/3] adding Dynamic methods with decorators --- src/modules/user/CreateUser.ts | 110 +++++++++++++++++++-------------- src/utils/createSchema.ts | 8 +-- 2 files changed, 69 insertions(+), 49 deletions(-) diff --git a/src/modules/user/CreateUser.ts b/src/modules/user/CreateUser.ts index ee5db33..dafe7bd 100644 --- a/src/modules/user/CreateUser.ts +++ b/src/modules/user/CreateUser.ts @@ -1,72 +1,92 @@ -import { - Resolver, - Mutation, - Arg, - ClassType, - InputType, - Field, - Authorized -} from "type-graphql"; +import { Resolver, Mutation, Arg, ClassType, Query } from "type-graphql"; import { RegisterInput } from "./register/RegisterInput"; import { User } from "../../entity/User"; -import { Product } from "../../entity/Product"; -function myNewDecorator(value: any) { - console.log("myNewDecorator value: ", value); - return function( - target: any, - propertyKey: string, - descriptor: PropertyDescriptor - ) { - console.log("target: ", target); - console.log("propertyKey: ", propertyKey); - console.log("descriptor: ", descriptor); - }; +const methodList: { + createM: (data: any) => void; + deleteM: (data: any) => void; +} = { + createM: (data: any) => { + console.log("create data: ", data); + }, + deleteM: (data: any) => { + console.log("delete data: ", data); + } +}; + +// @ts-ignore +interface BaseResolver { + createM?: typeof methodList.createM; + deleteM?: typeof methodList.deleteM; + [key: string]: any; } +// @ts-ignore function createResolver( suffix: string, returnType: T, inputType: X, entity: any, - decorator: any[] -) { - const decoratorFactory = (decos: any[]): Function => { - return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => - decos.map((deco: () => Function) => - deco()(target, propertyKey, descriptor) - ); - }; + methods: any[] +): any { + function classDecorator(): any { + return function( + target: any, + propertyKey: string, + descriptor: PropertyDescriptor + ) { + methods.forEach(method => { + // @ts-ignore + target.prototype[method] = methodList[method]; + const targetMethod = target.prototype[method]; + const targetPrototype = target.prototype; + const methodKey = Object.keys(targetPrototype).find( + key => targetPrototype[key] === targetMethod + ); + // @ts-ignore + Query(() => User, { nullable: true })( + targetPrototype, + // @ts-ignore + methodKey, + { + value: targetMethod, + writable: true, + enumerable: false, + configurable: true + } + ); + }); + console.log("target: ", target); + console.log("propertyKey: ", propertyKey); + console.log("descriptor: ", descriptor); + }; + } + @classDecorator() @Resolver() class BaseResolver { - @decoratorFactory(decorator) @Mutation(() => returnType, { name: `create${suffix}` }) - create(@Arg("data", () => inputType) data: any) { + create( + @Arg("data", () => inputType) + data: any + ) { return entity.create(data).save(); } + + /* constructor() { + methods.forEach(method => { + BaseResolver.prototype[method] = createM; + }); + } */ } return BaseResolver; } -@InputType() -class ProductInput { - @Field() - name: string; -} - export const CreateUserResolver = createResolver( "User", User, RegisterInput, User, - [Authorized, myNewDecorator] -); -export const CreateProductResolver = createResolver( - "Product", - Product, - ProductInput, - Product, - [Authorized, myNewDecorator] + ["createM", "deleteM"] ); diff --git a/src/utils/createSchema.ts b/src/utils/createSchema.ts index 39a7768..21b103a 100644 --- a/src/utils/createSchema.ts +++ b/src/utils/createSchema.ts @@ -7,8 +7,8 @@ import { LogoutResolver } from "../modules/user/Logout"; import { MeResolver } from "../modules/user/Me"; import { RegisterResolver } from "../modules/user/Register"; import { - CreateUserResolver, - CreateProductResolver + CreateUserResolver + //CreateProductResolver } from "../modules/user/CreateUser"; export const createSchema = () => @@ -21,8 +21,8 @@ export const createSchema = () => LogoutResolver, MeResolver, RegisterResolver, - CreateUserResolver, - CreateProductResolver + CreateUserResolver + //CreateProductResolver ], authChecker: ({ context: { req } }) => { return !!req.session.userId; From 3346bf4e9c9f88c77cfd66d28981fff41c877be9 Mon Sep 17 00:00:00 2001 From: paean99 <> Date: Wed, 23 Jan 2019 22:43:32 +0000 Subject: [PATCH 3/3] let the query decorator be dynamic --- src/modules/user/CreateUser.ts | 94 +++++++++++++++++++++++----------- src/modules/user/Login.ts | 6 ++- 2 files changed, 69 insertions(+), 31 deletions(-) diff --git a/src/modules/user/CreateUser.ts b/src/modules/user/CreateUser.ts index dafe7bd..b5a35eb 100644 --- a/src/modules/user/CreateUser.ts +++ b/src/modules/user/CreateUser.ts @@ -1,22 +1,37 @@ -import { Resolver, Mutation, Arg, ClassType, Query } from "type-graphql"; -import { RegisterInput } from "./register/RegisterInput"; +import { Arg, ClassType, Mutation, Query, Resolver } from "type-graphql"; import { User } from "../../entity/User"; +import { RegisterInput } from "./register/RegisterInput"; -const methodList: { - createM: (data: any) => void; - deleteM: (data: any) => void; -} = { - createM: (data: any) => { - console.log("create data: ", data); +const methodList = { + query: { + genre: Query, + list: { + findAll: (data: any) => { + console.log("query findAll data: ", data); + }, + findOne: (data: any) => { + console.log("query findOne data: ", data); + } + } }, - deleteM: (data: any) => { - console.log("delete data: ", data); + mutation: { + genre: Mutation, + list: { + createM: (data: any) => { + console.log("mutation create data: ", data); + }, + deleteM: (data: any) => { + console.log("mutation delete data: ", data); + } + } } }; // @ts-ignore interface BaseResolver { + // @ts-ignore createM?: typeof methodList.createM; + // @ts-ignore deleteM?: typeof methodList.deleteM; [key: string]: any; } @@ -27,7 +42,7 @@ function createResolver( returnType: T, inputType: X, entity: any, - methods: any[] + operations: any[] ): any { function classDecorator(): any { return function( @@ -35,26 +50,26 @@ function createResolver( propertyKey: string, descriptor: PropertyDescriptor ) { - methods.forEach(method => { + operations.forEach(oper => { // @ts-ignore - target.prototype[method] = methodList[method]; - const targetMethod = target.prototype[method]; - const targetPrototype = target.prototype; - const methodKey = Object.keys(targetPrototype).find( - key => targetPrototype[key] === targetMethod - ); + const deco = methodList[oper.genre].genre; // @ts-ignore - Query(() => User, { nullable: true })( - targetPrototype, + oper.meth.forEach(method => { + // @ts-ignore + target.prototype[method] = methodList[oper.genre].list[method]; + //const targetMethod = target.prototype[method]; + const targetPrototype = target.prototype; + const methodKey = method; // @ts-ignore - methodKey, - { - value: targetMethod, - writable: true, - enumerable: false, - configurable: true - } - ); + deco(() => returnType, { + name: `${method}${suffix}`, + nullable: true + })( + targetPrototype, + // @ts-ignore + methodKey + ); + }); }); console.log("target: ", target); console.log("propertyKey: ", propertyKey); @@ -88,5 +103,26 @@ export const CreateUserResolver = createResolver( User, RegisterInput, User, - ["createM", "deleteM"] + [{ genre: "query", meth: ["findAll", "findOne"] }] ); + +/* + * List of type-graphql decorators and their needed parameters: + * ParameterDecorator: prototype, propertyKey, parameterIndex + * Arg, Args, Ctx, Info, PubSub, Root, + * + * ClassDecorator: target + * ArgsType, InputType, InterfaceType, ObjectType, Resolver, + * + * MethodAndPropDecorator: prototype, propertyKey, descriptor + * Authorized, Field, + * + * MethodDecorator: prototype, propertyKey/methodName + * FieldResolver, Mutation, Query, Subscription, + * + * UseMiddleware can be: MethodAndPropDecorator, MethodDecorator , PropertyDecorator + * + * registerEnumType accepts enumObj and EnumConfig + * createUnionType to be seen better + * + */ diff --git a/src/modules/user/Login.ts b/src/modules/user/Login.ts index 02aa53f..2c9811f 100644 --- a/src/modules/user/Login.ts +++ b/src/modules/user/Login.ts @@ -1,6 +1,5 @@ -import { Resolver, Mutation, Arg, Ctx } from "type-graphql"; import bcrypt from "bcryptjs"; - +import { Arg, Ctx, Mutation, Resolver } from "type-graphql"; import { User } from "../../entity/User"; import { MyContext } from "../../types/MyContext"; @@ -15,16 +14,19 @@ export class LoginResolver { const user = await User.findOne({ where: { email } }); if (!user) { + console.log("LOGIN: no user"); return null; } const valid = await bcrypt.compare(password, user.password); if (!valid) { + console.log("LOGIN: invalid password"); return null; } if (!user.confirmed) { + console.log("LOGIN: user not confirmed"); return null; }