From d0df60fc6c2d76e7c8dc2e5e4f6f6f8609db6492 Mon Sep 17 00:00:00 2001 From: Felipe Sabino Date: Tue, 24 Oct 2017 19:53:12 -0200 Subject: [PATCH 1/4] initial commit for union type schema definition --- src/decorator.spec.ts | 1 + src/decorator.ts | 32 +++++++++++++++++++++-- src/field_type_factory.ts | 14 +++++++--- src/metadata-storage.ts | 18 +++++++++++++ src/metadatas.ts | 6 +++++ src/object_type_factory.ts | 4 +++ src/schema_factory.spec.ts | 52 +++++++++++++++++++++++++++++++++++++- src/schema_factory.ts | 2 +- src/union.type-factory.ts | 21 +++++++++++++++ 9 files changed, 142 insertions(+), 8 deletions(-) create mode 100644 src/metadata-storage.ts create mode 100644 src/metadatas.ts create mode 100644 src/union.type-factory.ts diff --git a/src/decorator.spec.ts b/src/decorator.spec.ts index b3a9085..5f5d5c7 100644 --- a/src/decorator.spec.ts +++ b/src/decorator.spec.ts @@ -153,4 +153,5 @@ describe('Decorators', function () { assert(actual.isList === true); }); }); + }); diff --git a/src/decorator.ts b/src/decorator.ts index b8c2293..de66088 100644 --- a/src/decorator.ts +++ b/src/decorator.ts @@ -4,9 +4,11 @@ import * as graphql from 'graphql'; import { GraphQLType } from 'graphql'; import { IoCContainer } from './ioc-container'; +import MetadataStorage from './metadata-storage'; import { OrderByTypeFactory } from './order-by.type-factory'; import { PageInfo } from './page-info.type'; import { PaginationResponse } from './pagination.type'; +import { UnionTypeMetadata } from './metadatas'; export const GQ_QUERY_KEY = 'gq_query'; export const GQ_MUTATION_KEY = 'gq_mutation'; @@ -16,8 +18,7 @@ export const GQ_VALUES_KEY = 'gq_values'; export const GQ_OBJECT_METADATA_KEY = 'gq_object_type'; export const GQ_ENUM_METADATA_KEY = 'gq_enum_type'; export const GQ_DESCRIPTION_KEY = 'gq_description'; - - +export const GQ_UNION_KEY = 'gq_union'; export interface TypeMetadata { name?: string; @@ -87,6 +88,11 @@ export interface SchemaOption extends DefaultOption { type?: any; } +export interface UnionOpton extends DefaultOption { + description?: string; + types: any[]; + resolver: (obj: T, context: any, info: any) => Promise | string | null; +} export interface DescriptionMetadata { description: string; @@ -117,6 +123,16 @@ function createOrSetObjectTypeMetadata(target: any, metadata: ObjectTypeMetadata } } +function createOrSetUnionTypeMetadata(target: any, metadata: UnionTypeMetadata) { + if (!Reflect.hasMetadata(GQ_UNION_KEY, target.prototype)) { + let mergedMetadata = mergeDescriptionMetadata(target, metadata); + Reflect.defineMetadata(GQ_UNION_KEY, mergedMetadata, target.prototype); + } else { + const originalMetadata = Reflect.getMetadata(GQ_UNION_KEY, target.prototype) as UnionTypeMetadata; + Object.assign(originalMetadata, metadata); + } +} + function createOrSetEnumTypeMetadata(target: any, metadata: EnumTypeMetadata) { if (!Reflect.hasMetadata(GQ_ENUM_METADATA_KEY, target.prototype)) { let mergedMetadata = mergeDescriptionMetadata(target, metadata); @@ -351,6 +367,18 @@ export function ObjectType(option?: DefaultOption) { } as Function; } + +export function UnionType(option: UnionOpton) { + return function (target: any) { + MetadataStorage.addUnionMetadata({ + name: target.name, + types: option.types, + resolver: option.resolver, + description: option.description, + }); + } as Function; +} + export function InputObjectType(option?: DefaultOption) { return function (target: any) { createOrSetObjectTypeMetadata(target, { diff --git a/src/field_type_factory.ts b/src/field_type_factory.ts index 067d784..17b71af 100644 --- a/src/field_type_factory.ts +++ b/src/field_type_factory.ts @@ -11,6 +11,8 @@ import { RootMetadata, TypeMetadata, } from './decorator'; +import MetadataStorage from './metadata-storage'; + import { SchemaFactoryError, SchemaFactoryErrorType } from './schema_factory'; import { IoCContainer } from './ioc-container'; @@ -18,6 +20,7 @@ import { OrderByTypeFactory } from './order-by.type-factory'; import { PaginationType } from './pagination.type'; import { enumTypeFactory } from './enum.type-factory'; import { objectTypeFactory } from './object_type_factory'; +import { unionTypeFactory } from './union.type-factory'; export interface ResolverHolder { fn: Function; @@ -43,12 +46,15 @@ function convertType(typeFn: Function, metadata: TypeMetadata, isInput: boolean, } else if (typeFn === Boolean) { returnType = graphql.GraphQLBoolean; } else if (typeFn && typeFn.prototype && Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, typeFn.prototype)) { - // recursively call objectFactory - returnType = objectTypeFactory(typeFn, isInput); + // recursively call objectFactory + returnType = objectTypeFactory(typeFn, isInput); } - } else { + } else { returnType = metadata.explicitType; - if (returnType && returnType.prototype && Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, returnType.prototype)) { + + if (returnType && returnType.prototype && MetadataStorage.containsUnionMetadata(returnType.name)) { + returnType = unionTypeFactory(returnType.name, isInput); + } else if (returnType && returnType.prototype && Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, returnType.prototype)) { // recursively call objectFactory returnType = objectTypeFactory(returnType, isInput); } else if (returnType && returnType.prototype && Reflect.hasMetadata(GQ_ENUM_METADATA_KEY, returnType.prototype)) { diff --git a/src/metadata-storage.ts b/src/metadata-storage.ts new file mode 100644 index 0000000..0d5454b --- /dev/null +++ b/src/metadata-storage.ts @@ -0,0 +1,18 @@ +import { UnionTypeMetadata } from './metadatas'; + +const unionMetadata: UnionTypeMetadata[] = []; + +const MetadataStorage = { + + addUnionMetadata: function(metadata: UnionTypeMetadata) { + unionMetadata.push(metadata); + }, + getUnionMetadata: function(): UnionTypeMetadata[] { + return unionMetadata; + }, + containsUnionMetadata: function(name: string) { + return unionMetadata.some(metadata => metadata.name === name); + }, +}; + +export default MetadataStorage; diff --git a/src/metadatas.ts b/src/metadatas.ts new file mode 100644 index 0000000..cb5878f --- /dev/null +++ b/src/metadatas.ts @@ -0,0 +1,6 @@ +export interface UnionTypeMetadata { + name?: string; + description?: string; + types: any[]; + resolver: (obj: any, context: any, info: any) => Promise | string | null; +} diff --git a/src/object_type_factory.ts b/src/object_type_factory.ts index 88b37b6..d02ff04 100644 --- a/src/object_type_factory.ts +++ b/src/object_type_factory.ts @@ -12,6 +12,10 @@ export function clearObjectTypeRepository() { objectTypeRepository = {}; } +export function objectTypeByName(name: string): any { + return objectTypeRepository[name]; +} + export function objectTypeFactory(target: Function, isInput?: boolean) { const objectTypeMetadata = Reflect.getMetadata(GQ_OBJECT_METADATA_KEY, target.prototype) as ObjectTypeMetadata; const typeFromRepository = objectTypeRepository[objectTypeMetadata.name]; diff --git a/src/schema_factory.spec.ts b/src/schema_factory.spec.ts index 6ad32bd..a40f298 100644 --- a/src/schema_factory.spec.ts +++ b/src/schema_factory.spec.ts @@ -5,7 +5,7 @@ import * as graphql from 'graphql'; import { SchemaFactoryError, SchemaFactoryErrorType, schemaFactory } from './schema_factory'; -import { GraphQLString } from 'graphql'; +import { GraphQLString, printSchema } from 'graphql'; import { OrderByItem } from './order-by-item'; import { clearFieldTypeCache } from './field_type_factory'; import { clearObjectTypeRepository } from './object_type_factory'; @@ -354,4 +354,54 @@ describe('schemaFactory', function() { }); + describe('UnionType', () => { + + it('creates schema with union type', () => { + + @D.ObjectType() + class ObjA { @D.Field() fieldA: string; } + + @D.ObjectType() + class ObjB { @D.Field() fieldB: string; } + + type MyType = ObjA | ObjB; + @D.UnionType({ + types: [ObjA, ObjB], + resolver: (obj: any): string | null => { + if (obj.fieldA) { return 'ObjA'; } + if (obj.fieldB) { return 'ObjB'; } + return null; + }, + }) + class MyUnionType { } + + + @D.ObjectType() class Query { + @D.Field({ type: MyUnionType }) + async aQuery(): Promise { + return { fieldA: '' }; + } + } + @D.Schema() class Schema { @D.Query() query: Query; } + const schema = schemaFactory(Schema); + const ast = parse(` + query { + aQuery { + ...on ObjA { + fieldA + } + ...on ObjB { + fieldB + } + } + }`); + + assert.deepEqual(validate(schema, ast), []); + + }); + + }); + + + }); diff --git a/src/schema_factory.ts b/src/schema_factory.ts index c644011..2e01b8d 100644 --- a/src/schema_factory.ts +++ b/src/schema_factory.ts @@ -1,9 +1,9 @@ import * as graphql from 'graphql'; import { FieldTypeMetadata, GQ_FIELDS_KEY, GQ_MUTATION_KEY, GQ_OBJECT_METADATA_KEY, GQ_QUERY_KEY, GQ_SUBSCRIPTION_KEY } from './decorator'; +import { GraphQLNamedType, GraphQLObjectType, GraphQLSchema } from 'graphql'; import { mutationObjectTypeFactory, queryObjectTypeFactory, subscriptionObjectTypeFactory } from './object_type_factory'; -import { GraphQLSchema, GraphQLObjectType } from 'graphql'; import { fieldTypeFactory } from './field_type_factory'; export enum SchemaFactoryErrorType { diff --git a/src/union.type-factory.ts b/src/union.type-factory.ts new file mode 100644 index 0000000..ddde5db --- /dev/null +++ b/src/union.type-factory.ts @@ -0,0 +1,21 @@ +import * as graphql from 'graphql'; +import MetadataStorage from './metadata-storage'; +import { UnionTypeMetadata } from './metadatas'; +import { GQ_OBJECT_METADATA_KEY } from './decorator'; +import { objectTypeFactory } from './object_type_factory'; + +export function unionTypeFactory(name: string, isInput: boolean): graphql.GraphQLUnionType { + return MetadataStorage.getUnionMetadata() + .filter(union => union.name === name) + .map(union => { + return new graphql.GraphQLUnionType({ + description: union.description, + name: union.name, + resolveType: union.resolver, + types: union.types + .map(type => objectTypeFactory(type, isInput)) + .filter(_ => _), //filter null values + }); + }) + .find((_, index) => index === 0) || null; +} From 9dfa9914e3d482f5cadde31c93dfb779069e8967 Mon Sep 17 00:00:00 2001 From: Felipe Sabino Date: Wed, 25 Oct 2017 11:55:50 -0200 Subject: [PATCH 2/4] refactoring union decorator structure --- src/decorator.spec.ts | 1 - src/decorator.ts | 32 ++----------------- src/decorator/index.ts | 1 + src/decorator/union-type.decorator.ts | 17 ++++++++++ src/field_type_factory.ts | 5 +-- src/index.ts | 2 ++ src/metadata-storage/index.ts | 1 + .../metadata-storage.ts | 4 +-- src/metadata/index.ts | 2 ++ src/metadata/options/index.ts | 1 + src/metadata/options/union.option.ts | 19 +++++++++++ src/metadata/types/index.ts | 1 + .../types/union.metadata.ts} | 2 +- src/object_type_factory.ts | 4 --- src/schema_factory.spec.ts | 9 +++--- src/schema_factory.ts | 2 +- src/type-factory/index.ts | 1 + src/{ => type-factory}/union.type-factory.ts | 7 ++-- 18 files changed, 62 insertions(+), 49 deletions(-) create mode 100644 src/decorator/index.ts create mode 100644 src/decorator/union-type.decorator.ts create mode 100644 src/metadata-storage/index.ts rename src/{ => metadata-storage}/metadata-storage.ts (80%) create mode 100644 src/metadata/index.ts create mode 100644 src/metadata/options/index.ts create mode 100644 src/metadata/options/union.option.ts create mode 100644 src/metadata/types/index.ts rename src/{metadatas.ts => metadata/types/union.metadata.ts} (89%) create mode 100644 src/type-factory/index.ts rename src/{ => type-factory}/union.type-factory.ts (73%) diff --git a/src/decorator.spec.ts b/src/decorator.spec.ts index 5f5d5c7..b3a9085 100644 --- a/src/decorator.spec.ts +++ b/src/decorator.spec.ts @@ -153,5 +153,4 @@ describe('Decorators', function () { assert(actual.isList === true); }); }); - }); diff --git a/src/decorator.ts b/src/decorator.ts index de66088..b8c2293 100644 --- a/src/decorator.ts +++ b/src/decorator.ts @@ -4,11 +4,9 @@ import * as graphql from 'graphql'; import { GraphQLType } from 'graphql'; import { IoCContainer } from './ioc-container'; -import MetadataStorage from './metadata-storage'; import { OrderByTypeFactory } from './order-by.type-factory'; import { PageInfo } from './page-info.type'; import { PaginationResponse } from './pagination.type'; -import { UnionTypeMetadata } from './metadatas'; export const GQ_QUERY_KEY = 'gq_query'; export const GQ_MUTATION_KEY = 'gq_mutation'; @@ -18,7 +16,8 @@ export const GQ_VALUES_KEY = 'gq_values'; export const GQ_OBJECT_METADATA_KEY = 'gq_object_type'; export const GQ_ENUM_METADATA_KEY = 'gq_enum_type'; export const GQ_DESCRIPTION_KEY = 'gq_description'; -export const GQ_UNION_KEY = 'gq_union'; + + export interface TypeMetadata { name?: string; @@ -88,11 +87,6 @@ export interface SchemaOption extends DefaultOption { type?: any; } -export interface UnionOpton extends DefaultOption { - description?: string; - types: any[]; - resolver: (obj: T, context: any, info: any) => Promise | string | null; -} export interface DescriptionMetadata { description: string; @@ -123,16 +117,6 @@ function createOrSetObjectTypeMetadata(target: any, metadata: ObjectTypeMetadata } } -function createOrSetUnionTypeMetadata(target: any, metadata: UnionTypeMetadata) { - if (!Reflect.hasMetadata(GQ_UNION_KEY, target.prototype)) { - let mergedMetadata = mergeDescriptionMetadata(target, metadata); - Reflect.defineMetadata(GQ_UNION_KEY, mergedMetadata, target.prototype); - } else { - const originalMetadata = Reflect.getMetadata(GQ_UNION_KEY, target.prototype) as UnionTypeMetadata; - Object.assign(originalMetadata, metadata); - } -} - function createOrSetEnumTypeMetadata(target: any, metadata: EnumTypeMetadata) { if (!Reflect.hasMetadata(GQ_ENUM_METADATA_KEY, target.prototype)) { let mergedMetadata = mergeDescriptionMetadata(target, metadata); @@ -367,18 +351,6 @@ export function ObjectType(option?: DefaultOption) { } as Function; } - -export function UnionType(option: UnionOpton) { - return function (target: any) { - MetadataStorage.addUnionMetadata({ - name: target.name, - types: option.types, - resolver: option.resolver, - description: option.description, - }); - } as Function; -} - export function InputObjectType(option?: DefaultOption) { return function (target: any) { createOrSetObjectTypeMetadata(target, { diff --git a/src/decorator/index.ts b/src/decorator/index.ts new file mode 100644 index 0000000..9b2030a --- /dev/null +++ b/src/decorator/index.ts @@ -0,0 +1 @@ +export * from './union-type.decorator'; diff --git a/src/decorator/union-type.decorator.ts b/src/decorator/union-type.decorator.ts new file mode 100644 index 0000000..75a2b29 --- /dev/null +++ b/src/decorator/union-type.decorator.ts @@ -0,0 +1,17 @@ +import { MetadataStorage } from '../metadata-storage'; +import { UnionOpton } from '../metadata'; + +/** + * Union Type. ref: http://graphql.org/learn/schema/#union-types + * @param option Options for a Union Type + */ +export function UnionType(option: UnionOpton) { + return function (target: any) { + MetadataStorage.addUnionMetadata({ + name: target.name, + types: option.types, + resolver: option.resolver, + description: option.description, + }); + } as Function; +} diff --git a/src/field_type_factory.ts b/src/field_type_factory.ts index 17b71af..453c967 100644 --- a/src/field_type_factory.ts +++ b/src/field_type_factory.ts @@ -11,7 +11,7 @@ import { RootMetadata, TypeMetadata, } from './decorator'; -import MetadataStorage from './metadata-storage'; +import { MetadataStorage } from './metadata-storage'; import { SchemaFactoryError, SchemaFactoryErrorType } from './schema_factory'; @@ -20,7 +20,8 @@ import { OrderByTypeFactory } from './order-by.type-factory'; import { PaginationType } from './pagination.type'; import { enumTypeFactory } from './enum.type-factory'; import { objectTypeFactory } from './object_type_factory'; -import { unionTypeFactory } from './union.type-factory'; +import { unionTypeFactory } from './type-factory'; + export interface ResolverHolder { fn: Function; diff --git a/src/index.ts b/src/index.ts index ed019c7..727f035 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,6 @@ export * from './decorator'; +export * from './decorator/'; +export * from './metadata/options'; export { schemaFactory } from './schema_factory'; export * from './order-by-item'; export * from './pagination.type'; diff --git a/src/metadata-storage/index.ts b/src/metadata-storage/index.ts new file mode 100644 index 0000000..c3c7e5d --- /dev/null +++ b/src/metadata-storage/index.ts @@ -0,0 +1 @@ +export * from './metadata-storage'; diff --git a/src/metadata-storage.ts b/src/metadata-storage/metadata-storage.ts similarity index 80% rename from src/metadata-storage.ts rename to src/metadata-storage/metadata-storage.ts index 0d5454b..e203274 100644 --- a/src/metadata-storage.ts +++ b/src/metadata-storage/metadata-storage.ts @@ -1,4 +1,4 @@ -import { UnionTypeMetadata } from './metadatas'; +import { UnionTypeMetadata } from '../metadata/types/union.metadata'; const unionMetadata: UnionTypeMetadata[] = []; @@ -15,4 +15,4 @@ const MetadataStorage = { }, }; -export default MetadataStorage; +export { MetadataStorage }; diff --git a/src/metadata/index.ts b/src/metadata/index.ts new file mode 100644 index 0000000..e83e2b5 --- /dev/null +++ b/src/metadata/index.ts @@ -0,0 +1,2 @@ +export * from './options'; +export * from './types'; diff --git a/src/metadata/options/index.ts b/src/metadata/options/index.ts new file mode 100644 index 0000000..3829125 --- /dev/null +++ b/src/metadata/options/index.ts @@ -0,0 +1 @@ +export * from './union.option'; diff --git a/src/metadata/options/union.option.ts b/src/metadata/options/union.option.ts new file mode 100644 index 0000000..8323dae --- /dev/null +++ b/src/metadata/options/union.option.ts @@ -0,0 +1,19 @@ +/** + * Arguments for a Union type on graphql schema + */ +export interface UnionOpton { + /** + * (Optional) Description + */ + description?: string; + + /** + * Concrete object types + */ + types: any[]; + + /** + * Resolver function to inform schema what type should be returned based on the value provided + */ + resolver: (obj: T, context: any, info: any) => Promise | string | null; +} diff --git a/src/metadata/types/index.ts b/src/metadata/types/index.ts new file mode 100644 index 0000000..d88db6f --- /dev/null +++ b/src/metadata/types/index.ts @@ -0,0 +1 @@ +export * from './union.metadata'; diff --git a/src/metadatas.ts b/src/metadata/types/union.metadata.ts similarity index 89% rename from src/metadatas.ts rename to src/metadata/types/union.metadata.ts index cb5878f..66c218f 100644 --- a/src/metadatas.ts +++ b/src/metadata/types/union.metadata.ts @@ -1,5 +1,5 @@ export interface UnionTypeMetadata { - name?: string; + name: string; description?: string; types: any[]; resolver: (obj: any, context: any, info: any) => Promise | string | null; diff --git a/src/object_type_factory.ts b/src/object_type_factory.ts index d02ff04..88b37b6 100644 --- a/src/object_type_factory.ts +++ b/src/object_type_factory.ts @@ -12,10 +12,6 @@ export function clearObjectTypeRepository() { objectTypeRepository = {}; } -export function objectTypeByName(name: string): any { - return objectTypeRepository[name]; -} - export function objectTypeFactory(target: Function, isInput?: boolean) { const objectTypeMetadata = Reflect.getMetadata(GQ_OBJECT_METADATA_KEY, target.prototype) as ObjectTypeMetadata; const typeFromRepository = objectTypeRepository[objectTypeMetadata.name]; diff --git a/src/schema_factory.spec.ts b/src/schema_factory.spec.ts index a40f298..c3f97c8 100644 --- a/src/schema_factory.spec.ts +++ b/src/schema_factory.spec.ts @@ -1,11 +1,12 @@ import 'reflect-metadata'; import * as D from './decorator'; +import * as DD from './decorator/'; import * as graphql from 'graphql'; import { SchemaFactoryError, SchemaFactoryErrorType, schemaFactory } from './schema_factory'; -import { GraphQLString, printSchema } from 'graphql'; +import { GraphQLString } from 'graphql'; import { OrderByItem } from './order-by-item'; import { clearFieldTypeCache } from './field_type_factory'; import { clearObjectTypeRepository } from './object_type_factory'; @@ -365,11 +366,11 @@ describe('schemaFactory', function() { class ObjB { @D.Field() fieldB: string; } type MyType = ObjA | ObjB; - @D.UnionType({ + @DD.UnionType({ types: [ObjA, ObjB], resolver: (obj: any): string | null => { - if (obj.fieldA) { return 'ObjA'; } - if (obj.fieldB) { return 'ObjB'; } + if (obj.fieldA) { return ObjA.name; } + if (obj.fieldB) { return ObjB.name; } return null; }, }) diff --git a/src/schema_factory.ts b/src/schema_factory.ts index 2e01b8d..6adb0fa 100644 --- a/src/schema_factory.ts +++ b/src/schema_factory.ts @@ -1,7 +1,7 @@ import * as graphql from 'graphql'; import { FieldTypeMetadata, GQ_FIELDS_KEY, GQ_MUTATION_KEY, GQ_OBJECT_METADATA_KEY, GQ_QUERY_KEY, GQ_SUBSCRIPTION_KEY } from './decorator'; -import { GraphQLNamedType, GraphQLObjectType, GraphQLSchema } from 'graphql'; +import { GraphQLObjectType, GraphQLSchema } from 'graphql'; import { mutationObjectTypeFactory, queryObjectTypeFactory, subscriptionObjectTypeFactory } from './object_type_factory'; import { fieldTypeFactory } from './field_type_factory'; diff --git a/src/type-factory/index.ts b/src/type-factory/index.ts new file mode 100644 index 0000000..6544cd6 --- /dev/null +++ b/src/type-factory/index.ts @@ -0,0 +1 @@ +export * from './union.type-factory'; diff --git a/src/union.type-factory.ts b/src/type-factory/union.type-factory.ts similarity index 73% rename from src/union.type-factory.ts rename to src/type-factory/union.type-factory.ts index ddde5db..27eb412 100644 --- a/src/union.type-factory.ts +++ b/src/type-factory/union.type-factory.ts @@ -1,8 +1,7 @@ import * as graphql from 'graphql'; -import MetadataStorage from './metadata-storage'; -import { UnionTypeMetadata } from './metadatas'; -import { GQ_OBJECT_METADATA_KEY } from './decorator'; -import { objectTypeFactory } from './object_type_factory'; +import { MetadataStorage } from '../metadata-storage'; +import { UnionTypeMetadata } from '../metadata'; +import { objectTypeFactory } from '../object_type_factory'; export function unionTypeFactory(name: string, isInput: boolean): graphql.GraphQLUnionType { return MetadataStorage.getUnionMetadata() From 2b508932eec15fb36167554daf2b3b3dd6487814 Mon Sep 17 00:00:00 2001 From: Felipe Sabino Date: Wed, 25 Oct 2017 12:22:00 -0200 Subject: [PATCH 3/4] Added @UnionType to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6ae38b3..2cfedbe 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Apart from the decorators listed on the original documentation, we have added si - @Query: It can be used multiple times on the same file. This way we make it possible to break queries into different folders. - @Mutation: It can be used multiple times on the same file. This way we make it possible to break queries into different folders. - @UseContainer: Sets the IoC container to be used in order to instantiate the decorated clas. +- @Uniontype: It can be used to create `GraphQLUnionType` objects. #### GraphQL Decorator Examples From eac7b481c6b94557b4512cf3657cd02a9349b924 Mon Sep 17 00:00:00 2001 From: Felipe Sabino Date: Wed, 25 Oct 2017 13:55:05 -0200 Subject: [PATCH 4/4] CR fixes for union type --- src/decorator.ts | 5 +++-- src/decorator/union-type.decorator.ts | 4 ++-- src/index.ts | 2 -- src/metadata/options/union.option.ts | 2 +- src/schema_factory.spec.ts | 3 +-- src/type-factory/union.type-factory.ts | 4 ++-- 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/decorator.ts b/src/decorator.ts index b8c2293..9df18c3 100644 --- a/src/decorator.ts +++ b/src/decorator.ts @@ -8,6 +8,9 @@ import { OrderByTypeFactory } from './order-by.type-factory'; import { PageInfo } from './page-info.type'; import { PaginationResponse } from './pagination.type'; +export * from './decorator/'; +export * from './metadata/options'; + export const GQ_QUERY_KEY = 'gq_query'; export const GQ_MUTATION_KEY = 'gq_mutation'; export const GQ_SUBSCRIPTION_KEY = 'gq_subscription'; @@ -17,8 +20,6 @@ export const GQ_OBJECT_METADATA_KEY = 'gq_object_type'; export const GQ_ENUM_METADATA_KEY = 'gq_enum_type'; export const GQ_DESCRIPTION_KEY = 'gq_description'; - - export interface TypeMetadata { name?: string; description?: string; diff --git a/src/decorator/union-type.decorator.ts b/src/decorator/union-type.decorator.ts index 75a2b29..59f7e37 100644 --- a/src/decorator/union-type.decorator.ts +++ b/src/decorator/union-type.decorator.ts @@ -1,11 +1,11 @@ import { MetadataStorage } from '../metadata-storage'; -import { UnionOpton } from '../metadata'; +import { UnionOption } from '../metadata'; /** * Union Type. ref: http://graphql.org/learn/schema/#union-types * @param option Options for a Union Type */ -export function UnionType(option: UnionOpton) { +export function UnionType(option: UnionOption) { return function (target: any) { MetadataStorage.addUnionMetadata({ name: target.name, diff --git a/src/index.ts b/src/index.ts index 727f035..ed019c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,4 @@ export * from './decorator'; -export * from './decorator/'; -export * from './metadata/options'; export { schemaFactory } from './schema_factory'; export * from './order-by-item'; export * from './pagination.type'; diff --git a/src/metadata/options/union.option.ts b/src/metadata/options/union.option.ts index 8323dae..cbbf7ae 100644 --- a/src/metadata/options/union.option.ts +++ b/src/metadata/options/union.option.ts @@ -1,7 +1,7 @@ /** * Arguments for a Union type on graphql schema */ -export interface UnionOpton { +export interface UnionOption { /** * (Optional) Description */ diff --git a/src/schema_factory.spec.ts b/src/schema_factory.spec.ts index c3f97c8..f4b6ca5 100644 --- a/src/schema_factory.spec.ts +++ b/src/schema_factory.spec.ts @@ -1,7 +1,6 @@ import 'reflect-metadata'; import * as D from './decorator'; -import * as DD from './decorator/'; import * as graphql from 'graphql'; import { SchemaFactoryError, SchemaFactoryErrorType, schemaFactory } from './schema_factory'; @@ -366,7 +365,7 @@ describe('schemaFactory', function() { class ObjB { @D.Field() fieldB: string; } type MyType = ObjA | ObjB; - @DD.UnionType({ + @D.UnionType({ types: [ObjA, ObjB], resolver: (obj: any): string | null => { if (obj.fieldA) { return ObjA.name; } diff --git a/src/type-factory/union.type-factory.ts b/src/type-factory/union.type-factory.ts index 27eb412..387a987 100644 --- a/src/type-factory/union.type-factory.ts +++ b/src/type-factory/union.type-factory.ts @@ -3,7 +3,7 @@ import { MetadataStorage } from '../metadata-storage'; import { UnionTypeMetadata } from '../metadata'; import { objectTypeFactory } from '../object_type_factory'; -export function unionTypeFactory(name: string, isInput: boolean): graphql.GraphQLUnionType { +export function unionTypeFactory(name: string, isInput: boolean): graphql.GraphQLUnionType | undefined { return MetadataStorage.getUnionMetadata() .filter(union => union.name === name) .map(union => { @@ -16,5 +16,5 @@ export function unionTypeFactory(name: string, isInput: boolean): graphql.GraphQ .filter(_ => _), //filter null values }); }) - .find((_, index) => index === 0) || null; + .find((_, index) => index === 0); }