Skip to content

Commit f6a7a09

Browse files
authored
Merge pull request #21 from indigotech/feature/union
Feature - Union Type
2 parents def85da + eac7b48 commit f6a7a09

File tree

16 files changed

+153
-7
lines changed

16 files changed

+153
-7
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Apart from the decorators listed on the original documentation, we have added si
1313
- @Query: It can be used multiple times on the same file. This way we make it possible to break queries into different folders.
1414
- @Mutation: It can be used multiple times on the same file. This way we make it possible to break queries into different folders.
1515
- @UseContainer: Sets the IoC container to be used in order to instantiate the decorated clas.
16+
- @Uniontype: It can be used to create `GraphQLUnionType` objects.
1617

1718
#### GraphQL Decorator Examples
1819

src/decorator.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import { OrderByTypeFactory } from './order-by.type-factory';
88
import { PageInfo } from './page-info.type';
99
import { PaginationResponse } from './pagination.type';
1010

11+
export * from './decorator/';
12+
export * from './metadata/options';
13+
1114
export const GQ_QUERY_KEY = 'gq_query';
1215
export const GQ_MUTATION_KEY = 'gq_mutation';
1316
export const GQ_SUBSCRIPTION_KEY = 'gq_subscription';
@@ -17,8 +20,6 @@ export const GQ_OBJECT_METADATA_KEY = 'gq_object_type';
1720
export const GQ_ENUM_METADATA_KEY = 'gq_enum_type';
1821
export const GQ_DESCRIPTION_KEY = 'gq_description';
1922

20-
21-
2223
export interface TypeMetadata {
2324
name?: string;
2425
description?: string;

src/decorator/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './union-type.decorator';
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { MetadataStorage } from '../metadata-storage';
2+
import { UnionOption } from '../metadata';
3+
4+
/**
5+
* Union Type. ref: http://graphql.org/learn/schema/#union-types
6+
* @param option Options for a Union Type
7+
*/
8+
export function UnionType<T>(option: UnionOption<T>) {
9+
return function (target: any) {
10+
MetadataStorage.addUnionMetadata({
11+
name: target.name,
12+
types: option.types,
13+
resolver: option.resolver,
14+
description: option.description,
15+
});
16+
} as Function;
17+
}

src/field_type_factory.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@ import {
1111
RootMetadata,
1212
TypeMetadata,
1313
} from './decorator';
14+
import { MetadataStorage } from './metadata-storage';
15+
1416
import { SchemaFactoryError, SchemaFactoryErrorType } from './schema_factory';
1517

1618
import { IoCContainer } from './ioc-container';
1719
import { OrderByTypeFactory } from './order-by.type-factory';
1820
import { PaginationType } from './pagination.type';
1921
import { enumTypeFactory } from './enum.type-factory';
2022
import { objectTypeFactory } from './object_type_factory';
23+
import { unionTypeFactory } from './type-factory';
24+
2125

2226
export interface ResolverHolder {
2327
fn: Function;
@@ -43,12 +47,15 @@ function convertType(typeFn: Function, metadata: TypeMetadata, isInput: boolean,
4347
} else if (typeFn === Boolean) {
4448
returnType = graphql.GraphQLBoolean;
4549
} else if (typeFn && typeFn.prototype && Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, typeFn.prototype)) {
46-
// recursively call objectFactory
47-
returnType = objectTypeFactory(typeFn, isInput);
50+
// recursively call objectFactory
51+
returnType = objectTypeFactory(typeFn, isInput);
4852
}
49-
} else {
53+
} else {
5054
returnType = metadata.explicitType;
51-
if (returnType && returnType.prototype && Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, returnType.prototype)) {
55+
56+
if (returnType && returnType.prototype && MetadataStorage.containsUnionMetadata(returnType.name)) {
57+
returnType = unionTypeFactory(returnType.name, isInput);
58+
} else if (returnType && returnType.prototype && Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, returnType.prototype)) {
5259
// recursively call objectFactory
5360
returnType = objectTypeFactory(returnType, isInput);
5461
} else if (returnType && returnType.prototype && Reflect.hasMetadata(GQ_ENUM_METADATA_KEY, returnType.prototype)) {

src/metadata-storage/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './metadata-storage';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { UnionTypeMetadata } from '../metadata/types/union.metadata';
2+
3+
const unionMetadata: UnionTypeMetadata[] = [];
4+
5+
const MetadataStorage = {
6+
7+
addUnionMetadata: function(metadata: UnionTypeMetadata) {
8+
unionMetadata.push(metadata);
9+
},
10+
getUnionMetadata: function(): UnionTypeMetadata[] {
11+
return unionMetadata;
12+
},
13+
containsUnionMetadata: function(name: string) {
14+
return unionMetadata.some(metadata => metadata.name === name);
15+
},
16+
};
17+
18+
export { MetadataStorage };

src/metadata/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './options';
2+
export * from './types';

src/metadata/options/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './union.option';
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Arguments for a Union type on graphql schema
3+
*/
4+
export interface UnionOption<T> {
5+
/**
6+
* (Optional) Description
7+
*/
8+
description?: string;
9+
10+
/**
11+
* Concrete object types
12+
*/
13+
types: any[];
14+
15+
/**
16+
* Resolver function to inform schema what type should be returned based on the value provided
17+
*/
18+
resolver: (obj: T, context: any, info: any) => Promise<string> | string | null;
19+
}

0 commit comments

Comments
 (0)