Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"scripts": {
"build": "rimraf lib && tsc",
"lint": "tslint \"src/**/*.ts\"",
"test": "npm run build && npm run lint && mocha lib/**/*.spec.js",
"test": "npm run build && npm run lint && mocha lib/*.spec.js lib/**/*.spec.js",
"watch": "tsc -w",
"watch-test": "mocha lib/**/*.spec.js --watch"
},
Expand Down
19 changes: 7 additions & 12 deletions src/decorator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,34 @@
import 'reflect-metadata';
import * as D from './decorator';
import * as graphql from 'graphql';
import { FieldTypeMetadata, GQ_FIELDS_KEY, getFieldMetadata, GQ_OBJECT_METADATA_KEY, ObjectTypeMetadata } from './decorator';
import { FieldTypeMetadata, GQ_FIELDS_KEY, getFieldMetadata } from './decorator';
import { ObjectTypeMetadata } from './metadata/types';
import { getMetadataBuilder } from './metadata-builder';

const assert = require('assert');

describe('Decorators', function () {
describe('@ObjectType', function () {
it('creates a ObjectTypeMetadata which isInput is false', function () {
@D.ObjectType() class Obj { @D.Field() someField: any; }
const actual = Reflect.getMetadata(GQ_OBJECT_METADATA_KEY, Obj.prototype) as ObjectTypeMetadata;
const actual = getMetadataBuilder().buildObjectTypeMetadata(Obj)[0];
assert(actual.isInput === false);
assert(actual.name === 'Obj');
});

it('sets description to ObjectTypeMetadata with @Description', function () {
@D.Description('this is a object type') @D.ObjectType()
class Obj { @D.Field() someField: any; }
const actual = Reflect.getMetadata(GQ_OBJECT_METADATA_KEY, Obj.prototype) as ObjectTypeMetadata;
assert(actual.isInput === false);
assert(actual.name === 'Obj');
assert(actual.description === 'this is a object type');
});
});

describe('@InputObjectType', function () {
it('creates a ObjectTypeMetadata which isInput is true', function () {
@D.InputObjectType() class Obj { @D.Field() someField: any; }
const actual = Reflect.getMetadata(GQ_OBJECT_METADATA_KEY, Obj.prototype) as ObjectTypeMetadata;
const actual = getMetadataBuilder().buildObjectTypeMetadata(Obj)[0];
assert(actual.isInput === true);
assert(actual.name === 'Obj');
});

it('sets description to ObjectTypeMetadata which isInput is true with description option', function () {
@D.InputObjectType({ description: 'some input' }) class Obj { }
const actual = Reflect.getMetadata(GQ_OBJECT_METADATA_KEY, Obj.prototype) as ObjectTypeMetadata;
const actual = getMetadataBuilder().buildObjectTypeMetadata(Obj)[0];
assert(actual.isInput === true);
assert(actual.description === 'some input');
});
Expand Down
57 changes: 1 addition & 56 deletions src/decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export const GQ_QUERY_KEY = 'gq_query';
export const GQ_MUTATION_KEY = 'gq_mutation';
export const GQ_SUBSCRIPTION_KEY = 'gq_subscription';
export const GQ_FIELDS_KEY = 'gq_fields';
export const GQ_OBJECT_METADATA_KEY = 'gq_object_type';
export const GQ_DESCRIPTION_KEY = 'gq_description';

export interface TypeMetadata {
Expand Down Expand Up @@ -46,12 +45,6 @@ export interface FieldTypeMetadata extends RootMetadata {
context?: ContextMetadata;
}

export interface ObjectTypeMetadata {
name?: string;
description?: string;
isInput?: boolean;
}

export interface DefaultOption {
description?: string;
}
Expand Down Expand Up @@ -95,16 +88,6 @@ function mergeDescriptionMetadata(target: any, sourceMetadata: any): any {
return sourceMetadata;
}

function createOrSetObjectTypeMetadata(target: any, metadata: ObjectTypeMetadata) {
if (!Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, target.prototype)) {
let mergedMetadata = mergeDescriptionMetadata(target, metadata);
Reflect.defineMetadata(GQ_OBJECT_METADATA_KEY, mergedMetadata, target.prototype);
} else {
const originalMetadata = Reflect.getMetadata(GQ_OBJECT_METADATA_KEY, target.prototype) as ObjectTypeMetadata;
Object.assign(originalMetadata, metadata);
}
}

function createOrSetFieldTypeMetadata(target: any, metadata: FieldTypeMetadata) {
let fieldDefs: FieldTypeMetadata[];
if (!Reflect.hasMetadata(GQ_FIELDS_KEY, target)) {
Expand Down Expand Up @@ -215,13 +198,7 @@ function setDescriptionMetadata(description: string, target: any, propertyKey: s
createPropertyDescriptionMetadata(target, description, propertyKey);
}
} else {
if (Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, target.prototype)) {
createOrSetObjectTypeMetadata(target, {
description: description,
});
} else {
createDescriptionMetadata(target, description);
}
createDescriptionMetadata(target, description);
}
}

Expand Down Expand Up @@ -265,38 +242,6 @@ function setPaginationMetadata(target: any, propertyKey: string, methodDescripto
};
}

export function ObjectType(option?: DefaultOption) {
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(option?: DefaultOption) {
return function (target: any) {
createOrSetObjectTypeMetadata(target, {
name: target.name,
isInput: true,
});

if (option) {
// description
if (option.description) {
setDescriptionMetadata(option.description, target);
}
}
} as Function;
}

export function Field(option?: FieldOption) {
return function (target: any, propertyKey: any, methodDescriptor?: any) {
createOrSetFieldTypeMetadata(target, {
Expand Down
2 changes: 1 addition & 1 deletion src/decorator/enum-type.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { getMetadataArgsStorage } from '../metadata-builder';
* It can be used just like {@link ObjectType} in order to create {@link GraphQLEnumType} objects.
* See [GraphQL Documentation - Enum Types]{@http://graphql.org/learn/schema/#enumeration-types}
*
* @param option Options for a Enum Type
* @param option Options for an Enum Type
*/
export function EnumType(option?: EnumOption) {
return function (target: any) {
Expand Down
1 change: 1 addition & 0 deletions src/decorator/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './enum-type.decorator';
export * from './union-type.decorator';
export * from './object-type.decorator';
34 changes: 34 additions & 0 deletions src/decorator/object-type.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ObjectOption } from '../metadata/options';
import { getMetadataArgsStorage } from '../metadata-builder';

/**
* It is used to create {@link GraphQLObjectType} objects.
* See [GraphQL Documentation - Object Types]{@http://graphql.org/learn/schema/#object-types-and-fields}
*
* @param option Options for an Object Type
*/
export function ObjectType(option?: ObjectOption) {
return CreateObjectType(false, option);
}

/**
* It is used to create {@link GraphQLInputObjectType} objects.
* See [GraphQL Documentation - Input Types]{@http://graphql.org/learn/schema/#input-types}
*
* @param option Options for an Input Object Type
*/
export function InputObjectType(option?: ObjectOption) {
return CreateObjectType(true, option);
}

function CreateObjectType(isInput: boolean, option?: ObjectOption) {
return function (target: any) {
getMetadataArgsStorage().objects.push({
target: target,
name: target.name,
description: option ? option.description : null,
isInput: isInput,
});
};
}

2 changes: 1 addition & 1 deletion src/decorator/union-type.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { UnionOption } from '../metadata';
* Union Type.
* See [GraphQL Documentation - Union Types]{@link http://graphql.org/learn/schema/#union-types}
*
* @param option Options for a Union Type
* @param option Options for an Union Type
*/
export function UnionType<T>(option: UnionOption<T>) {
return function (target: any) {
Expand Down
2 changes: 1 addition & 1 deletion src/field_type_factory.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as graphql from 'graphql';

import { fieldTypeFactory, resolverFactory, clearFieldTypeCache } from './field_type_factory';

import { clearObjectTypeRepository } from './object_type_factory';
import { clearObjectTypeRepository } from './type-factory';

const assert = require('assert');

Expand Down
7 changes: 3 additions & 4 deletions src/field_type_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
ContextMetadata,
FieldTypeMetadata,
GQ_FIELDS_KEY,
GQ_OBJECT_METADATA_KEY,
Middleware,
RootMetadata,
TypeMetadata,
Expand All @@ -17,7 +16,7 @@ import { SchemaFactoryError, SchemaFactoryErrorType } from './schema_factory';
import { IoCContainer } from './ioc-container';
import { OrderByTypeFactory } from './order-by.type-factory';
import { PaginationType } from './pagination.type';
import { objectTypeFactory } from './object_type_factory';
import { objectTypeFactory } from './type-factory';
import { unionTypeFactory, enumTypeFactory } from './type-factory';


Expand All @@ -44,7 +43,7 @@ function convertType(typeFn: Function, metadata: TypeMetadata, isInput: boolean,
returnType = graphql.GraphQLString;
} else if (typeFn === Boolean) {
returnType = graphql.GraphQLBoolean;
} else if (typeFn && typeFn.prototype && Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, typeFn.prototype)) {
} else if (typeFn && typeFn.prototype && getMetadataArgsStorage().filterObjectTypeByClass(typeFn).length > 0) {
// recursively call objectFactory
returnType = objectTypeFactory(typeFn, isInput);
}
Expand All @@ -53,7 +52,7 @@ function convertType(typeFn: Function, metadata: TypeMetadata, isInput: boolean,

if (returnType && returnType.prototype && getMetadataArgsStorage().filterUnionTypeByClass(returnType).length > 0) {
returnType = unionTypeFactory(returnType, isInput);
} else if (returnType && returnType.prototype && Reflect.hasMetadata(GQ_OBJECT_METADATA_KEY, returnType.prototype)) {
} else if (returnType && returnType.prototype && getMetadataArgsStorage().filterObjectTypeByClass(returnType).length > 0) {
// recursively call objectFactory
returnType = objectTypeFactory(returnType, isInput);
} else if (returnType && returnType.prototype && getMetadataArgsStorage().filterEnumsByClass(returnType).length > 0) {
Expand Down
6 changes: 6 additions & 0 deletions src/metadata-builder/metadata-args.storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
EnumTypeArg,
EnumValueArg,
UnionTypeArgs,
ObjectTypeArg,
} from '../metadata/args';

/**
Expand All @@ -20,6 +21,7 @@ export class MetadataArgsStorage {
enums: EnumTypeArg[] = [];
enumValues: EnumValueArg[] = [];
union: UnionTypeArgs[] = [];
objects: ObjectTypeArg[] = [];

filterEnumsByClass(target: any): EnumTypeArg[] {
return this.enums.filter(item => item.target === target);
Expand All @@ -32,5 +34,9 @@ export class MetadataArgsStorage {
filterUnionTypeByClass(target: any): UnionTypeArgs[] {
return this.union.filter(item => item.target === target);
}

filterObjectTypeByClass(target: any): ObjectTypeArg[] {
return this.objects.filter(item => item.target === target);
}
}

12 changes: 12 additions & 0 deletions src/metadata-builder/metadata.builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
EnumTypeMetadata,
EnumValueMetadata,
UnionTypeMetadata,
ObjectTypeMetadata,
} from '../metadata/types';

import { getMetadataArgsStorage } from './metadata-args.storage';
Expand Down Expand Up @@ -43,6 +44,17 @@ export class MetadataBuilder {
}));
}

buildObjectTypeMetadata(target: any): ObjectTypeMetadata[] | undefined {
return getMetadataArgsStorage()
.filterObjectTypeByClass(target)
.map(objectArg => ({
target: objectArg.target,
name: objectArg.name,
description: objectArg.description,
isInput: objectArg.isInput,
}));
}

protected buildEnumValueMetadata(target: any): EnumValueMetadata[] | undefined {
return getMetadataArgsStorage()
.filterEnumValuesByClass(target)
Expand Down
1 change: 1 addition & 0 deletions src/metadata/args/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './enum-type.arg';
export * from './union-type.arg';
export * from './object-type.arg';
6 changes: 6 additions & 0 deletions src/metadata/args/object-type.arg.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface ObjectTypeArg {
target: any;
name: string;
description?: string;
isInput: boolean;
}
1 change: 1 addition & 0 deletions src/metadata/options/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './enum.option';
export * from './union.option';
export * from './object.option';
9 changes: 9 additions & 0 deletions src/metadata/options/object.option.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Arguments for an Object type on graphql schema
*/
export interface ObjectOption {
/**
* (Optional) Description
*/
description?: string;
}
1 change: 1 addition & 0 deletions src/metadata/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './enum.metadata';
export * from './union.metadata';
export * from './object.metadata';
6 changes: 6 additions & 0 deletions src/metadata/types/object.metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface ObjectTypeMetadata {
target: string;
name: string;
description?: string;
isInput: boolean;
}
Loading