-
Notifications
You must be signed in to change notification settings - Fork 11
Decorators less verbose and subscriptions #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
a97df72
4dc942b
c861400
f4e62be
02d5cd9
1137265
318734c
30ae888
fe0ee68
7fdbbe8
c40c450
2a59e06
30bf6fb
109932e
e238e8d
b0ab52d
c664e20
81984d7
7cafb4a
8d5e055
d5101f8
354ed22
9e2bcc0
fe87cdf
c52357b
85a57d7
2d8e76d
6adb24f
eb59629
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,13 +66,41 @@ export interface EnumValueMetadata { | |
|
|
||
| export interface FieldOption { | ||
| type?: any; | ||
| description?: string; | ||
| nonNull?: boolean; | ||
| } | ||
|
|
||
| export interface ArgumentOption { | ||
| name: string; | ||
| type?: any; | ||
| } | ||
|
|
||
| export interface ListOption { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since all these Something like: export interface DefaultOption {
description?: string;
}
export interface ObjectTypeOption extends DefaultOption { }
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes I thought about that also but kept it for next step, I was thinking about refactoring current code base, for now everything (about decorators) is in one file and maybe it would be good to split it in separate files, file per decorator + 1 common file. |
||
| description?: string; | ||
| } | ||
|
|
||
| export interface ObjectTypeOption { | ||
| description?: string; | ||
| } | ||
|
|
||
| export interface InputObjectTypeOption { | ||
| description?: string; | ||
| } | ||
|
|
||
| export interface QueryOption { | ||
| description?: string; | ||
| } | ||
|
|
||
| export interface MutationOption { | ||
| description?: string; | ||
| } | ||
|
|
||
| export interface SchemaOption { | ||
| description?: string; | ||
| type?: any; | ||
| } | ||
|
|
||
|
|
||
| export interface DescriptionMetadata { | ||
| description: string; | ||
| } | ||
|
|
@@ -230,6 +258,81 @@ function setRootMetadata(target: any, propertyKey: any, index: number, metadata: | |
| } | ||
| } | ||
|
|
||
| function setDescriptionMetadata(description: string, target: any, propertyKey: string = undefined, index: number = undefined) { | ||
| if (index >= 0) { | ||
| setArgumentMetadata(target, propertyKey, index, { | ||
| description: description, | ||
| }); | ||
| } else if (propertyKey) { | ||
| if (getFieldMetadata(target, propertyKey) != null) { | ||
| createOrSetFieldTypeMetadata(target, { | ||
| name: propertyKey, | ||
| description: description, | ||
| }); | ||
| } else if (getValueMetadata(target, propertyKey) != null) { | ||
| createOrSetValueTypeMetadata(target, { | ||
| name: propertyKey, | ||
| description: description, | ||
| }); | ||
| } else { | ||
| createPropertyDescriptionMetadata(target, description, propertyKey); | ||
| } | ||
| } else { | ||
| if (Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, target.prototype)) { | ||
| createOrSetObjectTypeMetadata(target, { | ||
| description: description, | ||
| }); | ||
| } else if (Reflect.hasMetadata(GQ_ENUM_METADATA_KEY, target.prototype)) { | ||
| createOrSetEnumTypeMetadata(target, { | ||
| description: description, | ||
| }); | ||
| } else { | ||
| createDescriptionMetadata(target, description); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| function setNonNullMetadata(target: any, propertyKey: string, index: number) { | ||
| if (index >= 0) { | ||
| setArgumentMetadata(target, propertyKey, index, { | ||
| isNonNull: true, | ||
| }); | ||
| } else { | ||
| createOrSetFieldTypeMetadata(target, { | ||
| name: propertyKey, | ||
| isNonNull: true, | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| function setPaginationMetadata(target: any, propertyKey: string, methodDescriptor: TypedPropertyDescriptor<any>) { | ||
|
|
||
| createOrSetFieldTypeMetadata(target, { | ||
| name: propertyKey, | ||
| isPagination: true, | ||
| }); | ||
|
|
||
| let originalMethod = methodDescriptor.value; | ||
|
|
||
| return { | ||
| value: async function (...args: any[]) { | ||
| let [data, count] = await originalMethod.apply(this, args); | ||
|
|
||
| let metadata: FieldTypeMetadata = Reflect.getMetadata(GQ_FIELDS_KEY, target)[0]; | ||
| let indexMap: { [name: string]: number; } = {}; | ||
| metadata.args.forEach((arg: ArgumentMetadata) => { | ||
| indexMap[arg.name] = arg.index; | ||
| }); | ||
|
|
||
| let limit = args[indexMap['limit']]; | ||
| let offset = args[indexMap['offset']]; | ||
|
|
||
| return new PaginationResponse(count, data, new PageInfo(count, offset, limit)); | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
|
|
||
| export function EnumType() { | ||
| return function (target: any) { | ||
| createOrSetEnumTypeMetadata(target, { | ||
|
|
@@ -238,21 +341,35 @@ export function EnumType() { | |
| } as Function; | ||
| } | ||
|
|
||
| export function ObjectType() { | ||
| export function ObjectType(option?: ObjectTypeOption) { | ||
| return function (target: any) { | ||
| createOrSetObjectTypeMetadata(target, { | ||
| name: target.name, | ||
| isInput: false, | ||
| }); | ||
|
|
||
| if (option) { | ||
| // description | ||
| if (option.description) { | ||
| setDescriptionMetadata(option.description, target); | ||
| } | ||
| } | ||
| } as Function; | ||
| } | ||
|
|
||
| export function InputObjectType() { | ||
| export function InputObjectType(option?: InputObjectTypeOption) { | ||
| return function (target: any) { | ||
| createOrSetObjectTypeMetadata(target, { | ||
| name: target.name, | ||
| isInput: true, | ||
| }); | ||
|
|
||
| if (option) { | ||
| // description | ||
| if (option.description) { | ||
| setDescriptionMetadata(option.description, target); | ||
| } | ||
| } | ||
| } as Function; | ||
| } | ||
|
|
||
|
|
@@ -262,6 +379,19 @@ export function Field(option?: FieldOption) { | |
| name: propertyKey, | ||
| explicitType: option && option.type, | ||
| }); | ||
|
|
||
| if (option) { | ||
| // description | ||
| if (option.description) { | ||
| setDescriptionMetadata(option.description, target, propertyKey); | ||
| } | ||
|
|
||
| // nonNull | ||
| if (option.nonNull) { | ||
| setNonNullMetadata(target, propertyKey, 0); | ||
| } | ||
| } | ||
|
|
||
| } as Function; | ||
| } | ||
|
|
||
|
|
@@ -276,16 +406,7 @@ export function Value(value?: any) { | |
|
|
||
| export function NonNull() { | ||
| return function (target: any, propertyKey: any, index?: number) { | ||
| if (index >= 0) { | ||
| setArgumentMetadata(target, propertyKey, index, { | ||
| isNonNull: true, | ||
| }); | ||
| } else { | ||
| createOrSetFieldTypeMetadata(target, { | ||
| name: propertyKey, | ||
| isNonNull: true, | ||
| }); | ||
| } | ||
| setNonNullMetadata(target, propertyKey, index); | ||
| } as Function; | ||
| } | ||
|
|
||
|
|
@@ -307,33 +428,12 @@ export function Before(middleware: Middleware) { | |
| export function Pagination() { | ||
| return function (target: any, propertyKey: any, methodDescriptor: any) { | ||
|
|
||
| createOrSetFieldTypeMetadata(target, { | ||
| name: propertyKey, | ||
| isPagination: true, | ||
| }); | ||
|
|
||
| let originalMethod = methodDescriptor.value; | ||
| setPaginationMetadata(target, propertyKey, methodDescriptor); | ||
|
|
||
| return { | ||
| value: async function (...args: any[]) { | ||
| let [data, count] = await originalMethod.apply(this, args); | ||
|
|
||
| let metadata: FieldTypeMetadata = Reflect.getMetadata(GQ_FIELDS_KEY, target)[0]; | ||
| let indexMap: { [name: string]: number; } = {}; | ||
| metadata.args.forEach((arg: ArgumentMetadata) => { | ||
| indexMap[arg.name] = arg.index; | ||
| }); | ||
|
|
||
| let limit = args[indexMap['limit']]; | ||
| let offset = args[indexMap['offset']]; | ||
|
|
||
| return new PaginationResponse(count, data, new PageInfo(count, offset, limit)); | ||
| }, | ||
| }; | ||
| } as Function; | ||
| } | ||
|
|
||
| export function List() { | ||
| export function List(option?: ListOption) { | ||
| return function (target: any, propertyKey: any, index?: number) { | ||
| if (index >= 0) { | ||
| setArgumentMetadata(target, propertyKey, index, { | ||
|
|
@@ -345,6 +445,14 @@ export function List() { | |
| isList: true, | ||
| }); | ||
| } | ||
|
|
||
| if (option) { | ||
| // description | ||
| if (option.description) { | ||
| setDescriptionMetadata(option.description, target, propertyKey, index); | ||
| } | ||
| } | ||
|
|
||
| } as Function; | ||
| } | ||
|
|
||
|
|
@@ -370,7 +478,7 @@ export function Ctx() { | |
| } as Function; | ||
| } | ||
|
|
||
| export function OrderBy(params?: {extraColumns: string[], shouldIgnoreSchemaFields?: boolean } | string[]) { | ||
| export function OrderBy(params?: { extraColumns: string[], shouldIgnoreSchemaFields?: boolean } | string[]) { | ||
| return function (target: any, propertyKey: any, index: number) { | ||
| setArgumentMetadata(target, propertyKey, index, { | ||
| name: 'orderBy', | ||
|
|
@@ -381,41 +489,11 @@ export function OrderBy(params?: {extraColumns: string[], shouldIgnoreSchemaFiel | |
|
|
||
| export function Description(body: string) { | ||
| return function (target: any, propertyKey?: any, index?: number) { | ||
| if (index >= 0) { | ||
| setArgumentMetadata(target, propertyKey, index, { | ||
| description: body, | ||
| }); | ||
| } else if (propertyKey) { | ||
| if (getFieldMetadata(target, propertyKey) != null) { | ||
| createOrSetFieldTypeMetadata(target, { | ||
| name: propertyKey, | ||
| description: body, | ||
| }); | ||
| } else if (getValueMetadata(target, propertyKey) != null) { | ||
| createOrSetValueTypeMetadata(target, { | ||
| name: propertyKey, | ||
| description: body, | ||
| }); | ||
| } else { | ||
| createPropertyDescriptionMetadata(target, body, propertyKey); | ||
| } | ||
| } else { | ||
| if (Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, target.prototype)) { | ||
| createOrSetObjectTypeMetadata(target, { | ||
| description: body, | ||
| }); | ||
| } else if (Reflect.hasMetadata(GQ_ENUM_METADATA_KEY, target.prototype)) { | ||
| createOrSetEnumTypeMetadata(target, { | ||
| description: body, | ||
| }); | ||
| } else { | ||
| createDescriptionMetadata(target, body); | ||
| } | ||
| } | ||
| setDescriptionMetadata(body, target, propertyKey, index); | ||
| } as Function; | ||
| } | ||
|
|
||
| export function Query(option?: any) { | ||
| export function Query(option?: QueryOption) { | ||
| return function (target: any, propertyKey: any) { | ||
| if (Reflect.hasMetadata(GQ_QUERY_KEY, target)) { | ||
| let metadata = Reflect.getMetadata(GQ_QUERY_KEY, target); | ||
|
|
@@ -424,10 +502,18 @@ export function Query(option?: any) { | |
| } else { | ||
| Reflect.defineMetadata(GQ_QUERY_KEY, [propertyKey], target); | ||
| } | ||
|
|
||
| if (option) { | ||
| // description | ||
| if (option.description) { | ||
| setDescriptionMetadata(option.description, target, propertyKey); | ||
| } | ||
| } | ||
|
|
||
| } as Function; | ||
| } | ||
|
|
||
| export function Mutation(option?: any) { | ||
| export function Mutation(option?: MutationOption) { | ||
| return function (target: any, propertyKey: any) { | ||
| if (Reflect.hasMetadata(GQ_MUTATION_KEY, target)) { | ||
| let metadata = Reflect.getMetadata(GQ_MUTATION_KEY, target); | ||
|
|
@@ -436,12 +522,27 @@ export function Mutation(option?: any) { | |
| } else { | ||
| Reflect.defineMetadata(GQ_MUTATION_KEY, [propertyKey], target); | ||
| } | ||
|
|
||
| if (option) { | ||
| // description | ||
| if (option.description) { | ||
| setDescriptionMetadata(option.description, target, propertyKey); | ||
| } | ||
| } | ||
|
|
||
| } as Function; | ||
| } | ||
|
|
||
| export function Schema() { | ||
| export function Schema(option?: SchemaOption) { | ||
| return function (target: Function) { | ||
| Reflect.defineMetadata('gq_schema', {}, target); | ||
|
|
||
| if (option) { | ||
| // description | ||
| if (option.description) { | ||
| setDescriptionMetadata(option.description, target); | ||
| } | ||
| } | ||
| } as Function; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,8 @@ | |
| "outDir": "lib" | ||
| }, | ||
| "exclude": [ | ||
| "node_modules", "lib", "examples" | ||
| "node_modules", | ||
| "lib", | ||
| "examples" | ||
| ] | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about the pagination? It would be nice to have it here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I agree, but first I've implemented just description field to get your feedback and pagination can be implemented with the same way later.