From e74277bdb06f8b40f6912804c135e53e1a9891ba Mon Sep 17 00:00:00 2001 From: Tomasz Robaczewski Date: Sat, 16 Dec 2017 00:21:18 +0100 Subject: [PATCH] Rewrite internals + simplify decorators api --- CHANGELOG.md | 11 + README.md | 19 +- ROADMAP.md | 49 + TODO.md | 14 - lib/abstract/IGraphQLMetadata.ts | 5 - lib/decorators/argsType.ts | 9 - lib/decorators/enum.ts | 2 +- lib/decorators/fields.ts | 114 +- lib/decorators/helpers.ts | 13 + lib/decorators/input.ts | 12 +- lib/decorators/interface.ts | 5 +- lib/decorators/type.ts | 7 +- lib/decorators/typesInferention.ts | 38 - lib/factories/createSchema.ts | 14 +- lib/factories/createUnion.ts | 14 +- lib/fields-metadata/FieldConfig.ts | 89 + lib/fields-metadata/FieldsMetadata.ts | 36 + lib/index.ts | 1 - lib/metadata/ArgumentMapMetadata.ts | 17 - lib/metadata/FieldsMetadata.ts | 80 - lib/metadata/InputObjectTypeMetadata.ts | 40 - lib/metadata/InterfaceTypeMetadata.ts | 55 - lib/metadata/ObjectTypeMetadata.ts | 48 - lib/types-conversion/ArgumentsTypeProxy.ts | 36 + lib/types-conversion/TypeProxy.ts | 77 + lib/types-conversion/TypeWrapper.ts | 38 + lib/types-metadata/BaseTypeMetadata.ts | 24 + lib/types-metadata/InterfaceTypeMetadata.ts | 45 + lib/types-metadata/ParamsMetadata.ts | 43 + lib/types-metadata/TypeMetadata.ts | 42 + lib/utils/ConfigData.ts | 18 + lib/utils/core.ts | 9 + lib/utils/metadata.ts | 7 +- lib/{metadata => utils}/metadataFactories.ts | 6 +- lib/utils/types.ts | 2 +- package.json | 19 +- spec/decorators/args.spec.ts | 32 - spec/decorators/fields.spec.ts | 138 +- spec/decorators/input.spec.ts | 18 +- spec/decorators/interface.spec.ts | 4 +- spec/decorators/type.spec.ts | 89 +- spec/factories/createEnum.spec.ts | 2 +- spec/factories/createUnion.spec.ts | 10 +- spec/integration/buildingSchema.spec.ts | 51 +- spec/integration/queries.spec.ts | 4 +- spec/integration/types/Address.ts | 14 + spec/integration/types/Asset.ts | 30 +- spec/integration/types/Company.ts | 7 +- spec/integration/types/CreateAddressParams.ts | 11 + spec/integration/types/CreateCompanyParams.ts | 15 + spec/integration/types/CreateUserParams.ts | 15 + spec/integration/types/Mutation.ts | 28 +- spec/integration/types/Query.ts | 6 +- spec/integration/types/SearchResult.ts | 2 +- spec/integration/types/User.ts | 10 +- spec/integration/types/UserSearch.ts | 6 +- spec/metadata/FieldsMetadata.spec.ts | 90 +- spec/metadata/InterfaceTypeMetadata.spec.ts | 25 +- ...eMetadata.spec.ts => TypeMetadata.spec.ts} | 30 +- spec/types-conversion/TypeProxy.spec.ts | 90 + spec/types-conversion/TypeWrapper.spec.ts | 51 + yarn-error.log | 1842 +++++++++++++++++ yarn.lock | 124 +- 63 files changed, 3076 insertions(+), 726 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 ROADMAP.md delete mode 100644 TODO.md delete mode 100644 lib/abstract/IGraphQLMetadata.ts delete mode 100644 lib/decorators/argsType.ts create mode 100644 lib/decorators/helpers.ts delete mode 100644 lib/decorators/typesInferention.ts create mode 100644 lib/fields-metadata/FieldConfig.ts create mode 100644 lib/fields-metadata/FieldsMetadata.ts delete mode 100644 lib/metadata/ArgumentMapMetadata.ts delete mode 100644 lib/metadata/FieldsMetadata.ts delete mode 100644 lib/metadata/InputObjectTypeMetadata.ts delete mode 100644 lib/metadata/InterfaceTypeMetadata.ts delete mode 100644 lib/metadata/ObjectTypeMetadata.ts create mode 100644 lib/types-conversion/ArgumentsTypeProxy.ts create mode 100644 lib/types-conversion/TypeProxy.ts create mode 100644 lib/types-conversion/TypeWrapper.ts create mode 100644 lib/types-metadata/BaseTypeMetadata.ts create mode 100644 lib/types-metadata/InterfaceTypeMetadata.ts create mode 100644 lib/types-metadata/ParamsMetadata.ts create mode 100644 lib/types-metadata/TypeMetadata.ts create mode 100644 lib/utils/ConfigData.ts rename lib/{metadata => utils}/metadataFactories.ts (75%) delete mode 100644 spec/decorators/args.spec.ts create mode 100644 spec/integration/types/Address.ts create mode 100644 spec/integration/types/CreateAddressParams.ts create mode 100644 spec/integration/types/CreateCompanyParams.ts create mode 100644 spec/integration/types/CreateUserParams.ts rename spec/metadata/{ObjectTypeMetadata.spec.ts => TypeMetadata.spec.ts} (64%) create mode 100644 spec/types-conversion/TypeProxy.spec.ts create mode 100644 spec/types-conversion/TypeWrapper.spec.ts create mode 100644 yarn-error.log diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..13dd525 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +#CHANGELOG + +## 0.0.3 +- move graphql to peerDependencies +- upgrade dependencies + +## 0.4.0 +- complete rewrite of internals +- upgrade dependencies +- remove `@args` and `@argsType` decorators in favor of `@params` and `@input`. [**Breaking change**] + diff --git a/README.md b/README.md index 909eb06..e6e2860 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,10 @@ [![Build Status](https://travis-ci.org/robak86/gql-schema.svg?branch=master)](https://travis-ci.org/robak86/gql-schema) [![Coverage Status](https://coveralls.io/repos/github/robak86/gql-schema/badge.svg?branch=master)](https://coveralls.io/github/robak86/gql-schema?branch=master) -Yet another experimental library for defining graphql schemas using decorators. Alpha version - use at your own risk. +Yet another library for defining graphql schemas using decorators. + +**Warning**: This software is still at an early stage of development. Use at your own risk! + ## Getting started @@ -58,7 +61,7 @@ main(); ## ```@type``` decorator ```typescript -import {type, field, list, nonNull, nonNullItems, resolve, description, id, argsType, args} from 'gql-schema'; +import {type, field, list, nonNull, nonNullItems, resolve, description, id, input, params} from 'gql-schema'; import {GraphQLString, GraphQLInt} from "graphql"; const resolveFunction = (_, args:SomeParams, ctx):Partial => { @@ -87,7 +90,7 @@ class SomeType { nonNullableListWithNullItemsForbidden: string[] } -@argsType() +@input() class SomeParams { @field(GraphQLString) @nonNull() someParam:string @@ -96,7 +99,7 @@ class SomeParams { @type() class Query { @field(SomeType) @nonNull() - @args(SomeParams) @resolve(resolveFunction) + @params(SomeParams) @resolve(resolveFunction) someData:SomeType } ``` @@ -124,7 +127,7 @@ type Query { ## ```@input``` decorator ```typescript -import {field, input, nonNull, args, argsType, resolve, type} from 'gql-schema'; +import {field, input, nonNull, params, input, resolve, type} from 'gql-schema'; import {GraphQLString} from "graphql"; const createUser = (_, args:CreateUserParams, ctx):Partial => { @@ -152,7 +155,7 @@ class NewUserAddressParams { city:string; } -@argsType() +@input() class CreateUserParams { @field(NewUserParams) @nonNull() userParams:NewUserParams; @@ -187,7 +190,7 @@ class User { @type() class Mutation { @field(User) @nonNull() - @args(CreateUserParams) @resolve(createUser) + @params(CreateUserParams) @resolve(createUser) createUser:User } ``` @@ -244,7 +247,7 @@ class BackgroundJob { Given annotated classes will produce following schema definition. ```graphql schema -type BackgroundJob{ +type BackgroundJob { status: Status! } diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..a0e27b1 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,49 @@ +# ROADMAP + +### Add support for inheritance +- investigate possible pitfalls + +```typescript +class PersistedObject { + @id() + id:string + + @field(CustomGraphQLDateScalar) + createdAt:Date + + @field(CustomGraphQLDateScalar) + updatedAt:Date +} + +@type() +class User extends PersistedObject {} +``` + +should generate: + +```graphql +type User { + id: ID + createdAt: CustomGraphQLDateScalar + updateAt: CustomGraphQLDateScalar +} +``` + +### Infer basic types from ts metadata +- investigate if it makes sense, because this feature would be very limited - only for couple of types. + +### Improve error handling and error messages +- add assertions for all setters in fields metadata +- add validation of field configuration +- add more descriptive logs for all errors thrown from Metadata classes during native object creation +- assert one metadata object is attached to class + +### Refactoring +- use one convention for private fields +- currently all metadata classes knows how to build graphql types - investigate if extracting this into separate "strategy like" classes makes sens +- getOrCreateForClass and getForClass can be merged to one method +```typescript +class SomeMetadata { + static getForClass(attachIfMissing:boolean = false){} +} +``` \ No newline at end of file diff --git a/TODO.md b/TODO.md deleted file mode 100644 index c4cfc3e..0000000 --- a/TODO.md +++ /dev/null @@ -1,14 +0,0 @@ -* infer basic types from ts metadata -* add decorators/factories for defining scalars -* consider setting NotNull for true as default for all @fields -* consider setting NotNull and NotNullItem for true for all @arrays -* GRAPHQL_METADATA_KEY cannot be shared by all metadata objects -* assert one metadata object is attached to class -* getOrCreateForClass and getForClass can be merged to one method -```typescript -class SomeMetadata { - static getForClass(attachIfDoesntExists:boolean = false){ - - } -} -``` \ No newline at end of file diff --git a/lib/abstract/IGraphQLMetadata.ts b/lib/abstract/IGraphQLMetadata.ts deleted file mode 100644 index f1df6ea..0000000 --- a/lib/abstract/IGraphQLMetadata.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const GRAPHQL_METADATA_KEY:string = '__GRAPHQL_METADATA'; - -export interface IGraphQLMetadata { - toGraphQLType():any -} \ No newline at end of file diff --git a/lib/decorators/argsType.ts b/lib/decorators/argsType.ts deleted file mode 100644 index b77c34c..0000000 --- a/lib/decorators/argsType.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {ArgumentMapMetadata} from "../metadata/ArgumentMapMetadata"; -import {Type as Klass} from "../utils/types"; - -export const argsType = () => { - return >(klass:T_FUNCTION):T_FUNCTION => { - ArgumentMapMetadata.getOrCreateForClass(klass); - return klass; - } -}; \ No newline at end of file diff --git a/lib/decorators/enum.ts b/lib/decorators/enum.ts index 7047a10..08272c5 100644 --- a/lib/decorators/enum.ts +++ b/lib/decorators/enum.ts @@ -1,7 +1,7 @@ import {enumsRegistry} from "../registry/typesRegistry"; /*** - * It makes enum being acceptable as type for @field decorator + * It makes native typescript enum being acceptable as type for @field decorator * @param {string} name * @param {Object} enumType * @param props diff --git a/lib/decorators/fields.ts b/lib/decorators/fields.ts index e7195be..cecabc9 100644 --- a/lib/decorators/fields.ts +++ b/lib/decorators/fields.ts @@ -1,67 +1,47 @@ -import {FieldConfig, FieldsMetadata} from "../metadata/FieldsMetadata"; -import {invariant} from "../utils/core"; -import * as _ from 'lodash'; -import {GraphQLID} from "graphql"; -import {ArgsType, FieldType} from "./typesInferention"; - - -function patchField(target, propertyKey, partialConfig:Partial) { - let fieldsMetadata:FieldsMetadata = FieldsMetadata.getOrCreateForClass(target.constructor); - fieldsMetadata.patchConfig(propertyKey, partialConfig); -} - -export const id = ():PropertyDecorator => { - return (target:Object, propertyKey:string) => patchField(target, propertyKey, { - type: GraphQLID - }) -}; - -export const field = (type:FieldType):PropertyDecorator => { - invariant(!!type, `@field decorator called with undefined or null value`); - return (target:Object, propertyKey:string) => patchField(target, propertyKey, {type}) -}; - -export const fieldLazy = (thunkType:() => (FieldType)):PropertyDecorator => { - invariant(_.isFunction(thunkType), `@fieldThunk decorator called with non function param`); - return (target:Object, propertyKey:string) => patchField(target, propertyKey, {thunkType}) -}; - -export const nonNull = ():PropertyDecorator => { - return (target:Object, propertyKey:string) => patchField(target, propertyKey, {nonNull: true}) -}; - -export const nonNullItems = ():PropertyDecorator => { - return (target:Object, propertyKey:string) => patchField(target, propertyKey, {nonNullItem: true}) -}; - -export const description = (description:string):PropertyDecorator => { - return (target:Object, propertyKey:string) => patchField(target, propertyKey, {description}) -}; - -export const args = (argsType:ArgsType):PropertyDecorator => { - return (target:Object, propertyKey:string) => patchField(target, propertyKey, {args: argsType}) -}; - -export const resolve = (resolve:Function):PropertyDecorator => { - return (target:Object, propertyKey:string) => patchField(target, propertyKey, {resolve}) -}; - -export const list = (type:FieldType):PropertyDecorator => { - invariant(!!type, `@array decorator called with undefined or null value`); - return (target:Object, propertyKey:string) => { - patchField(target, propertyKey, { - array: true, - type - }) - } -}; - -export const listLazy = (thunkType:() => FieldType):PropertyDecorator => { - invariant(!!thunkType, `@arrayThunk decorator called with undefined or null value`); - return (target:Object, propertyKey:string) => { - patchField(target, propertyKey, { - array: true, - thunkType - }) - } -}; \ No newline at end of file +import {GraphQLFieldResolver, GraphQLID} from "graphql"; +import {FieldType} from "../types-conversion/TypeProxy"; +import {ArgsType} from "../types-conversion/ArgumentsTypeProxy"; +import {createFieldDecorator} from "./helpers"; + +export const id = ():PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setType(GraphQLID) +}); + +export const field = (type:FieldType):PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setType(type); +}); + +export const fieldThunk = (thunkType:() => (FieldType)):PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setTypeThunk(thunkType); +}); + +export const nonNull = ():PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setNonNullConstraint() +}); + +export const nonNullItems = ():PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setNonNullItemsConstraint() +}); +export const description = (description:string):PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setDescription(description) +}); + +export const params = (argsType:ArgsType):PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setParamsType(argsType) +}); + +export const paramsThunk = (argsType:() => ArgsType):PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setParamsThunk(argsType) +}); + +export const resolve = (resolve:GraphQLFieldResolver):PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setResolver(resolve); +}); + +export const list = (type:FieldType):PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setListType(type) +}); + +export const listThunk = (thunkType:() => FieldType):PropertyDecorator => createFieldDecorator(fieldConfig => { + fieldConfig.setListTypeThunk(thunkType) +}); \ No newline at end of file diff --git a/lib/decorators/helpers.ts b/lib/decorators/helpers.ts new file mode 100644 index 0000000..3d1a57c --- /dev/null +++ b/lib/decorators/helpers.ts @@ -0,0 +1,13 @@ +import {FieldsMetadata} from "../fields-metadata/FieldsMetadata"; +import {FieldConfig} from "../fields-metadata/FieldConfig"; + +export function createFieldDecorator(updateFieldsMetadata:(fieldConfig:FieldConfig) => void):PropertyDecorator { + return (target:Object, propertyKey:string) => { + try { + let meta = FieldsMetadata.getOrCreateForClass(target.constructor); + updateFieldsMetadata(meta.getField(propertyKey)); + } catch (e) { + throw new Error(`Class: ${target.constructor.name}, property: ${propertyKey}. Error message: ${e.message}`) + } + } +} \ No newline at end of file diff --git a/lib/decorators/input.ts b/lib/decorators/input.ts index f47e091..d424c49 100644 --- a/lib/decorators/input.ts +++ b/lib/decorators/input.ts @@ -1,12 +1,10 @@ -import {Type as Klass} from "../utils/types"; -import {InputConfig, InputObjectTypeMetadata} from "../metadata/InputObjectTypeMetadata"; +import {ClassType as Klass} from "../utils/types"; +import {InputConfig, ParamsMetadata} from "../types-metadata/ParamsMetadata"; - -export const input = (config:InputConfig = {}) => { +export const input = (config:Partial = {}) => { return >(klass:T_FUNCTION):T_FUNCTION => { - let inputMetadata = InputObjectTypeMetadata.getOrCreateForClass(klass); - inputMetadata.setConfig(config); - + let paramsMetadata = ParamsMetadata.getOrCreateForClass(klass); + paramsMetadata.setConfig(config); return klass; } }; \ No newline at end of file diff --git a/lib/decorators/interface.ts b/lib/decorators/interface.ts index 9f1aca4..679a720 100644 --- a/lib/decorators/interface.ts +++ b/lib/decorators/interface.ts @@ -1,10 +1,9 @@ -import {InterfaceTypeMetadata, TypeConfig} from "../metadata/InterfaceTypeMetadata"; +import {InterfaceTypeMetadata, InterfaceTypeConfig} from "../types-metadata/InterfaceTypeMetadata"; -export const interfaceType = (config:TypeConfig = {}):ClassDecorator => { +export const interfaceType = (config:Partial = {}):ClassDecorator => { return (klass:TFunction):TFunction => { let objectTypeMetadata = InterfaceTypeMetadata.getOrCreateForClass(klass); objectTypeMetadata.setConfig(config); - return klass; }; }; \ No newline at end of file diff --git a/lib/decorators/type.ts b/lib/decorators/type.ts index b4f72d4..1ea305b 100644 --- a/lib/decorators/type.ts +++ b/lib/decorators/type.ts @@ -1,10 +1,9 @@ -import {ObjectTypeMetadata, TypeConfig} from "../metadata/ObjectTypeMetadata"; +import {TypeConfigParams, TypeMetadata} from "../types-metadata/TypeMetadata"; -export const type = (config:TypeConfig = {}):ClassDecorator => { +export const type = (config:Partial = {}):ClassDecorator => { return (klass:TFunction):TFunction => { - let objectTypeMetadata = ObjectTypeMetadata.getOrCreateForClass(klass); + let objectTypeMetadata = TypeMetadata.getOrCreateForClass(klass); objectTypeMetadata.setConfig(config); - return klass; }; }; \ No newline at end of file diff --git a/lib/decorators/typesInferention.ts b/lib/decorators/typesInferention.ts deleted file mode 100644 index 34ab1c2..0000000 --- a/lib/decorators/typesInferention.ts +++ /dev/null @@ -1,38 +0,0 @@ -import {Type} from "../utils/types"; -import {GraphQLInputObjectType, GraphQLType, isType} from "graphql"; -import {getMetadata} from "../utils/metadata"; -import * as _ from 'lodash'; -import {enumsRegistry} from "../registry/typesRegistry"; - -export type ArgsType = - GraphQLInputObjectType | - Type - -export type FieldType = - GraphQLType | - Type | - Object; - -export function inferGraphQLType(klass:FieldType, allowedMetaData:Function[] = []) { - if (isType(klass)) { - return klass; - } - - if (enumsRegistry.hasEnum(klass)) { - return enumsRegistry.getGraphQLEnumType(klass); - } - - if (_.isFunction(klass)) { - let metadata = getMetadata(klass as any); - if (allowedMetaData.length > 0) { - let validType = allowedMetaData.some(metadataClass => metadata instanceof metadataClass); - if (!validType) { - throw Error(`Annotated ${klass.name} passed as type property is incompatible: Allowed types are ${allowedMetaData}`) - } - } - - return metadata.toGraphQLType(); - } - - throw new Error(`Cannot infer type for ${JSON.stringify(klass)}`) -} \ No newline at end of file diff --git a/lib/factories/createSchema.ts b/lib/factories/createSchema.ts index f3723f5..e3e4ccf 100644 --- a/lib/factories/createSchema.ts +++ b/lib/factories/createSchema.ts @@ -1,19 +1,19 @@ import {GraphQLSchema} from "graphql"; -import {ObjectTypeMetadata} from "../metadata/ObjectTypeMetadata"; import {someOrThrow} from "../utils/core"; +import {TypeMetadata} from "../types-metadata/TypeMetadata"; export function createSchema(annotatedRootClass, annotatedMutationClass):GraphQLSchema { let query = someOrThrow( - ObjectTypeMetadata.getForClass(annotatedRootClass), - 'Class provided as query root is not decorated with @type.define'); + TypeMetadata.getForClass(annotatedRootClass), + 'Class provided as query root is not decorated with @type'); let mutation = someOrThrow( - ObjectTypeMetadata.getForClass(annotatedMutationClass), - 'Class provided as query root is not decorated with @type.define') + TypeMetadata.getForClass(annotatedMutationClass), + 'Class provided as query root is not decorated with @type'); return new GraphQLSchema({ - query: query.toGraphQLType(), - mutation: mutation.toGraphQLType() + query: query.toGraphQLObjectType(), + mutation: mutation.toGraphQLObjectType() }) } \ No newline at end of file diff --git a/lib/factories/createUnion.ts b/lib/factories/createUnion.ts index 8f058a0..9fed688 100644 --- a/lib/factories/createUnion.ts +++ b/lib/factories/createUnion.ts @@ -1,15 +1,13 @@ import {GraphQLObjectType, GraphQLUnionType, Thunk} from "graphql"; - -import {ObjectTypeMetadata} from "../metadata/ObjectTypeMetadata"; import * as _ from 'lodash'; -import {inferGraphQLType} from "../decorators/typesInferention"; +import {TypeProxy} from "../types-conversion/TypeProxy"; + -export function createUnion(name:string, types:Thunk>, resolveType):GraphQLUnionType { +//TODO: rename to - unionType +export function createUnion(name:string, types:Thunk>, resolveType):GraphQLUnionType { return new GraphQLUnionType({ name, - types: _.castArray(types).map(type => inferGraphQLType(type as any, [ObjectTypeMetadata])), - resolveType: (value, context) => { - return inferGraphQLType(resolveType(value,context)); - } + types: _.castArray(types).map(type => TypeProxy.inferType(type)) as any, //TODO: fix types + resolveType: (value, context) => TypeProxy.inferType(resolveType(value, context)) as any //TODO: fix types }); } \ No newline at end of file diff --git a/lib/fields-metadata/FieldConfig.ts b/lib/fields-metadata/FieldConfig.ts new file mode 100644 index 0000000..57e6dc5 --- /dev/null +++ b/lib/fields-metadata/FieldConfig.ts @@ -0,0 +1,89 @@ +import {FieldType, TypeProxy} from "../types-conversion/TypeProxy"; +import {TypeWrapper} from "../types-conversion/TypeWrapper"; +import { + GraphQLArgumentConfig, GraphQLFieldConfig, GraphQLFieldResolver, GraphQLInputFieldConfig, + GraphQLInputType, GraphQLOutputType +} from "graphql"; +import {ArgsType, ArgumentsTypeProxy} from "../types-conversion/ArgumentsTypeProxy"; + + +//TODO: throw errors from setters for wrong data +export class FieldConfig { + private type = new TypeProxy(); + private compositeType:TypeWrapper = new TypeWrapper(); + private description:string; + private args:ArgumentsTypeProxy; + private resolveFn:GraphQLFieldResolver; + private defaultValue; + + setDefaultValue(val:any) { + this.defaultValue = val; + } + + setParamsType(paramsFieldType:ArgsType) { + this.args = new ArgumentsTypeProxy(); + this.args.setType(paramsFieldType); + } + + setParamsThunk(paramsFieldTypeThunk:() => ArgsType) { + this.args = new ArgumentsTypeProxy(); + this.args.setTypeThunk(paramsFieldTypeThunk); + } + + setResolver(resolveFn:GraphQLFieldResolver) { + this.resolveFn = resolveFn; + } + + setType(fieldType:FieldType) { + this.type.setType(fieldType); + } + + setTypeThunk(fieldTypeThunk:() => FieldType) { + this.type.setTypeThunk(fieldTypeThunk); + } + + setNonNullConstraint() { + this.compositeType.setNonNullConstraint(); + } + + setNonNullItemsConstraint() { + this.compositeType.setNonNullItemsConstraint(); + } + + setListType(fieldType:FieldType) { + this.type.setType(fieldType); + this.compositeType.setArray(); + } + + setListTypeThunk(fieldType:FieldType) { + this.type.setTypeThunk(fieldType); + this.compositeType.setArray(); + } + + setDescription(name:string) { + this.description = name; + } + + toGraphQLInputFieldConfig():GraphQLArgumentConfig | GraphQLInputFieldConfig { + let type = this.type.toGraphQLType() as GraphQLInputType; + type = this.compositeType.wrap(type) as GraphQLInputType; + + return { + defaultValue: this.defaultValue, + description: this.description, + type + } + } + + toGraphQLFieldConfig():GraphQLFieldConfig { + let type = this.type.toGraphQLType(); + type = this.compositeType.wrap(type) as GraphQLOutputType; + + return { + type, + args: this.args && this.args.toGraphQLType() as any, + resolve: this.resolveFn, + description: this.description + } + } +} \ No newline at end of file diff --git a/lib/fields-metadata/FieldsMetadata.ts b/lib/fields-metadata/FieldsMetadata.ts new file mode 100644 index 0000000..19d8403 --- /dev/null +++ b/lib/fields-metadata/FieldsMetadata.ts @@ -0,0 +1,36 @@ +import 'reflect-metadata'; +import {metadataGet, metadataGetOrSet} from "../utils/metadataFactories"; +import {FieldConfig} from "./FieldConfig"; +import {GraphQLFieldConfigMap, GraphQLInputFieldConfigMap} from "graphql"; +import {propagateErrorWithContext} from "../utils/core"; +import * as _ from "lodash"; + +const FIELDS_METADATA_KEY = '__FIELDS_METADATA_KEY'; + +export class FieldsMetadata { + static getForClass = metadataGet(FIELDS_METADATA_KEY); + static getOrCreateForClass = metadataGetOrSet(FIELDS_METADATA_KEY, FieldsMetadata); + + + protected _fields:{ [fieldName:string]:FieldConfig } = {}; + + getField(fieldName:string):FieldConfig { + return this._fields[fieldName] || (this._fields[fieldName] = new FieldConfig()) + } + + getFields():{ [fieldName:string]:FieldConfig } { + return this._fields; + } + + toGraphQLFieldConfigMap():GraphQLFieldConfigMap { + return _.mapValues(this.getFields(), (fieldConfig, fieldName) => { + return propagateErrorWithContext(fieldName, () => fieldConfig.toGraphQLFieldConfig()) + }); + } + + toGraphQLInputFieldConfigMap():GraphQLInputFieldConfigMap{ + return _.mapValues(this.getFields(), (fieldConfig, fieldName) => { + return propagateErrorWithContext(`fieldName: ${fieldName}`, () => fieldConfig.toGraphQLInputFieldConfig()) + }); + } +} \ No newline at end of file diff --git a/lib/index.ts b/lib/index.ts index 9e37a20..00eb964 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,7 +1,6 @@ export * from './decorators/type'; export * from './decorators/input'; export * from './decorators/fields'; -export * from './decorators/argsType'; export * from './decorators/enum'; export * from './decorators/interface'; diff --git a/lib/metadata/ArgumentMapMetadata.ts b/lib/metadata/ArgumentMapMetadata.ts deleted file mode 100644 index a07a588..0000000 --- a/lib/metadata/ArgumentMapMetadata.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {GRAPHQL_METADATA_KEY, IGraphQLMetadata} from "../abstract/IGraphQLMetadata"; -import {GraphQLFieldConfigArgumentMap} from "graphql"; -import {FieldsMetadata} from "./FieldsMetadata"; -import {metadataGet, metadataGetOrSet} from "./metadataFactories"; -import {someOrThrow} from "../utils/core"; - -export class ArgumentMapMetadata implements IGraphQLMetadata { - static getForClass = metadataGet(GRAPHQL_METADATA_KEY); - static getOrCreateForClass = metadataGetOrSet(GRAPHQL_METADATA_KEY, ArgumentMapMetadata); - - constructor(private klass) {} - - toGraphQLType():GraphQLFieldConfigArgumentMap { - let fieldsMetadata:FieldsMetadata = someOrThrow(FieldsMetadata.getForClass(this.klass), `Missing fields definition for ${this.klass.name}`); - return fieldsMetadata.getFields() as any; - } -} \ No newline at end of file diff --git a/lib/metadata/FieldsMetadata.ts b/lib/metadata/FieldsMetadata.ts deleted file mode 100644 index ce92b80..0000000 --- a/lib/metadata/FieldsMetadata.ts +++ /dev/null @@ -1,80 +0,0 @@ -import 'reflect-metadata'; -import {GraphQLFieldConfig, GraphQLFieldConfigMap, GraphQLList, GraphQLNonNull, Thunk} from "graphql"; -import {metadataGet, metadataGetOrSet} from "./metadataFactories"; -import * as _ from 'lodash'; -import {invariant, isPresent} from "../utils/core"; -import {ArgumentMapMetadata} from "./ArgumentMapMetadata"; -import {ArgsType, FieldType, inferGraphQLType} from "../decorators/typesInferention"; -import {resolveThunk} from "../utils/graphql"; - - -const FIELDS_METADATA_KEY = '__FIELDS_METADATA_KEY'; - -export interface FieldConfig { - type:FieldType - thunkType:Thunk - nonNull:boolean - array:boolean - nonNullItem:boolean - resolve?:Function - description?:string - args?:ArgsType - thunkArgs:Thunk - deprecationReason?:string; -} - - -function convertFieldConfigToGraphQL(config:Partial):GraphQLFieldConfig { - let type = inferGraphQLType(config.type || resolveThunk(config.thunkType)); - invariant(!!type, `Cannot infer type`); //TODO: add more reliable way for checking if type is correct - - let args = isPresent(config.args || resolveThunk(config.thunkArgs)) ? inferGraphQLType(config.args as any, [ArgumentMapMetadata]) : null; - - if (config.nonNullItem && config.array) { - type = new GraphQLList(new GraphQLNonNull(type)) - } - - if (!config.nonNullItem && config.array) { - type = new GraphQLList(type) - } - - if (config.nonNull) { - type = new GraphQLNonNull(type); - } - - let {resolve, deprecationReason, description} = _.cloneDeep(config); - return {resolve, deprecationReason, description, type, args} as GraphQLFieldConfig; -} - -export class FieldsMetadata { - static getForClass = metadataGet(FIELDS_METADATA_KEY); - static getOrCreateForClass = metadataGetOrSet(FIELDS_METADATA_KEY, FieldsMetadata); - - private fields:{ [fieldName:string]:Partial } = {}; - - constructor(private klass) {} - - getField(fieldName:string):Partial { - return this.fields[fieldName]; - } - - patchConfig(fieldName:string, partialConfig:Partial) { - this.fields[fieldName] = { - ...this.existingPropsOrDefaults(fieldName), - ...partialConfig - } - } - - getFields():GraphQLFieldConfigMap { - invariant(Object.keys(this.fields).length > 0, `Missing fields definition for ${this.klass.name} class`); - return _.mapValues(this.fields, convertFieldConfigToGraphQL); - } - - private existingPropsOrDefaults(fieldName:string) { - return this.fields[fieldName] || { - nonNull: false, - array: false, - nonNullItem: false - }; - } -} \ No newline at end of file diff --git a/lib/metadata/InputObjectTypeMetadata.ts b/lib/metadata/InputObjectTypeMetadata.ts deleted file mode 100644 index b3f158d..0000000 --- a/lib/metadata/InputObjectTypeMetadata.ts +++ /dev/null @@ -1,40 +0,0 @@ -import 'reflect-metadata'; -import * as _ from 'lodash'; - -import {GraphQLInputObjectType} from "graphql"; -import {GRAPHQL_METADATA_KEY, IGraphQLMetadata} from "../abstract/IGraphQLMetadata"; -import {metadataGet, metadataGetOrSet} from "./metadataFactories"; -import {someOrThrow} from "../utils/core"; -import {FieldsMetadata} from "./FieldsMetadata"; - -export interface InputConfig { - name?: string; - description?: string; -} - -export class InputObjectTypeMetadata implements IGraphQLMetadata { - static getForClass = metadataGet(GRAPHQL_METADATA_KEY); - static getOrCreateForClass = metadataGetOrSet(GRAPHQL_METADATA_KEY, InputObjectTypeMetadata); - - - private _config:InputConfig; - - constructor(private klass) { - this.toGraphQLType = _.memoize(this.toGraphQLType); - this._config = {name: klass.name}; - } - - setConfig(config:InputConfig) { - this._config = {...this._config, ...config}; - } - - toGraphQLType():GraphQLInputObjectType { - let fieldsMetadata = someOrThrow(FieldsMetadata.getForClass(this.klass), `Missing fields definition for ${this.klass.name}`); - - return new GraphQLInputObjectType({ - name: this._config.name, - fields: () => fieldsMetadata.getFields() as any, - description: this._config.description - }) - } -} \ No newline at end of file diff --git a/lib/metadata/InterfaceTypeMetadata.ts b/lib/metadata/InterfaceTypeMetadata.ts deleted file mode 100644 index b588531..0000000 --- a/lib/metadata/InterfaceTypeMetadata.ts +++ /dev/null @@ -1,55 +0,0 @@ -import 'reflect-metadata'; - -import {GRAPHQL_METADATA_KEY, IGraphQLMetadata} from "../abstract/IGraphQLMetadata"; -import {isPresent, someOrThrow} from "../utils/core"; -import {metadataGet, metadataGetOrSet} from "./metadataFactories"; -import * as _ from 'lodash'; -import {FieldsMetadata} from "./FieldsMetadata"; -import {GraphQLInterfaceType, GraphQLResolveInfo, GraphQLTypeResolver} from "graphql"; -import {inferGraphQLType} from "../decorators/typesInferention"; -import {Type} from "../utils/types"; - - -export type TypeResolverForAnnotatedClass = ( - value: TSource, - context: TContext, - info: GraphQLResolveInfo -) => Type - - -export interface TypeConfig { - name?:string; - description?:string; - resolveType?:GraphQLTypeResolver | TypeResolverForAnnotatedClass; -} - -export class InterfaceTypeMetadata implements IGraphQLMetadata { - static getForClass = metadataGet(GRAPHQL_METADATA_KEY); - static getOrCreateForClass = metadataGetOrSet(GRAPHQL_METADATA_KEY, InterfaceTypeMetadata); - - private _config:TypeConfig; - - constructor(private klass:Function) { - this.toGraphQLType = _.memoize(this.toGraphQLType); - this._config = {name: klass.name}; - } - - setConfig(config:TypeConfig) { - this._config = {...this._config, ...config}; - } - - toGraphQLType():GraphQLInterfaceType { - let fieldsMetadata = someOrThrow(FieldsMetadata.getForClass(this.klass), `Missing fields definition for ${this.klass.name}`); - - let resolveType = isPresent(this._config.resolveType) ? - (value, context, info) => inferGraphQLType(this._config.resolveType(value, context, info)) : - null; - - return new GraphQLInterfaceType({ - name: this._config.name, - description: this._config.description, - resolveType, - fields: () => fieldsMetadata.getFields() - }) - } -} \ No newline at end of file diff --git a/lib/metadata/ObjectTypeMetadata.ts b/lib/metadata/ObjectTypeMetadata.ts deleted file mode 100644 index 9770fc3..0000000 --- a/lib/metadata/ObjectTypeMetadata.ts +++ /dev/null @@ -1,48 +0,0 @@ -import 'reflect-metadata'; -import {GraphQLInterfaceType, GraphQLIsTypeOfFn, GraphQLObjectType, Thunk} from "graphql"; -import {GRAPHQL_METADATA_KEY, IGraphQLMetadata} from "../abstract/IGraphQLMetadata"; -import {isPresent, someOrThrow} from "../utils/core"; -import {Type} from "../utils/types"; -import {metadataGet, metadataGetOrSet} from "./metadataFactories"; -import * as _ from 'lodash'; -import {FieldsMetadata} from "./FieldsMetadata"; -import {resolveThunk} from "../utils/graphql"; -import {inferGraphQLType} from "../decorators/typesInferention"; -import {InterfaceTypeMetadata} from "./InterfaceTypeMetadata"; - -export interface TypeConfig { - name?:string; - interfaces?:Thunk>>; - isTypeOf?:GraphQLIsTypeOfFn; //#TODO: autopopulate with instanceof - description?:string -} - -export class ObjectTypeMetadata implements IGraphQLMetadata { - static getForClass = metadataGet(GRAPHQL_METADATA_KEY); - static getOrCreateForClass = metadataGetOrSet(GRAPHQL_METADATA_KEY, ObjectTypeMetadata); - - private _config:TypeConfig; - - constructor(private klass:Function) { - this.toGraphQLType = _.memoize(this.toGraphQLType); - this._config = {name: klass.name}; - } - - setConfig(config:TypeConfig) { - this._config = {...this._config, ...config}; - } - - toGraphQLType():GraphQLObjectType { - let fieldsMetadata = someOrThrow(FieldsMetadata.getForClass(this.klass), `Missing fields definition for ${this.klass.name}`); - - let interfaces = isPresent(this._config.interfaces) ? - resolveThunk(this._config.interfaces).map(type => inferGraphQLType(type, [InterfaceTypeMetadata])) : null; - - return new GraphQLObjectType({ - name: this._config.name, - interfaces, - description: this._config.description, - fields: () => fieldsMetadata.getFields() - }) - } -} \ No newline at end of file diff --git a/lib/types-conversion/ArgumentsTypeProxy.ts b/lib/types-conversion/ArgumentsTypeProxy.ts new file mode 100644 index 0000000..57fc86e --- /dev/null +++ b/lib/types-conversion/ArgumentsTypeProxy.ts @@ -0,0 +1,36 @@ +import {GraphQLFieldConfigArgumentMap, Thunk} from "graphql"; + +import * as _ from "lodash"; +import {resolveThunk} from "../utils/graphql"; +import {ParamsMetadata} from "../types-metadata/ParamsMetadata"; +import {invariant} from "../utils/core"; +import {ClassType} from "../utils/types"; + +export type ArgsType = + GraphQLFieldConfigArgumentMap | + ClassType + +export class ArgumentsTypeProxy { + private _type:ArgsType; + private _typeThunk:Thunk; + + setType(type:ArgsType) { + this._type = type; + } + + setTypeThunk(typeThunk:Thunk) { + this._typeThunk = typeThunk; + } + + toGraphQLType():GraphQLFieldConfigArgumentMap { + let type = (this._type || resolveThunk(this._typeThunk)) as GraphQLFieldConfigArgumentMap; + + if (_.isFunction(type)) { + let metadata = ParamsMetadata.getForClass(type); + invariant(!!metadata, `Missing ParamsMetadata for ${type}. Decorate class using @params decorator`); + return metadata.toGraphQLFieldConfigArgumentMap(); + } + + throw new Error(`Cannot infer type for ${JSON.stringify(type)}`) + } +} \ No newline at end of file diff --git a/lib/types-conversion/TypeProxy.ts b/lib/types-conversion/TypeProxy.ts new file mode 100644 index 0000000..ed0678d --- /dev/null +++ b/lib/types-conversion/TypeProxy.ts @@ -0,0 +1,77 @@ +import {enumsRegistry} from "../registry/typesRegistry"; +import {GraphQLType, isType, Thunk} from "graphql"; +import * as _ from "lodash"; +import {resolveThunk} from "../utils/graphql"; +import {TypeMetadata} from "../types-metadata/TypeMetadata"; +import {invariant} from "../utils/core"; +import {getMetadata} from "../utils/metadata"; +import {ParamsMetadata} from "../types-metadata/ParamsMetadata"; +import {InterfaceTypeMetadata} from "../types-metadata/InterfaceTypeMetadata"; +import {ClassType} from "../utils/types"; + +export type FieldType = + GraphQLType | + ClassType | + Object; + +export class TypeProxy { + static inferType(type:FieldType):GraphQLType { + let proxy = new TypeProxy(); + proxy.setType(type); + return proxy.toGraphQLType() + } + + static inferTypeThunk(typeThunk:() => FieldType):GraphQLType { + let proxy = new TypeProxy(); + proxy.setTypeThunk(typeThunk); + return proxy.toGraphQLType() + } + + private _type:FieldType; + private _typeThunk:Thunk; + + setType(type:FieldType) { + this._type = type; + } + + setTypeThunk(typeThunk:Thunk) { + this._typeThunk = typeThunk; + } + + toGraphQLType():GraphQLType { + return this.inferType(); + } + + private inferType():GraphQLType { + let type = this._type || resolveThunk(this._typeThunk); + + if (isType(type)) { + return type; + } + + if (enumsRegistry.hasEnum(type)) { + return enumsRegistry.getGraphQLEnumType(type); + } + + if (_.isFunction(type)) { + let metadata = getMetadata(type as any); + invariant(!!metadata, `Missing TypeMetadata for ${type}. Decorate class using @type decorator.`); + + if (metadata instanceof ParamsMetadata) { + return metadata.toGraphQLInputObjectType(); + } + + if (metadata instanceof TypeMetadata) { + return metadata.toGraphQLObjectType(); + } + + if (metadata instanceof InterfaceTypeMetadata) { + return metadata.toGraphQLInterfaceType(); + } + + throw new Error(`Unknown metadata found ${metadata}`) + } + + throw new Error(`Cannot infer type for ${JSON.stringify(type)}`) + } +} \ No newline at end of file diff --git a/lib/types-conversion/TypeWrapper.ts b/lib/types-conversion/TypeWrapper.ts new file mode 100644 index 0000000..b4dc01e --- /dev/null +++ b/lib/types-conversion/TypeWrapper.ts @@ -0,0 +1,38 @@ +import {GraphQLList, GraphQLNonNull, GraphQLType} from "graphql"; +import {invariant} from "../utils/core"; + +export class TypeWrapper { + private _isArray:boolean = false; + private _isNonNull:boolean = false; + private _hasNonNullItems:boolean = false; + + setArray() { + this._isArray = true; + } + + setNonNullConstraint() { + this._isNonNull = true; + } + + setNonNullItemsConstraint() { + this._hasNonNullItems = true; + } + + wrap(type:GraphQLType):GraphQLType { + invariant(!(this._hasNonNullItems && !this._isArray), `@nonNullItems used without @list decorator is not supported`); + + if (this._hasNonNullItems && this._isArray) { + type = new GraphQLList(new GraphQLNonNull(type)) + } + + if (!this._hasNonNullItems && this._isArray) { + type = new GraphQLList(type) + } + + if (this._isNonNull) { + type = new GraphQLNonNull(type); + } + + return type; + } +} \ No newline at end of file diff --git a/lib/types-metadata/BaseTypeMetadata.ts b/lib/types-metadata/BaseTypeMetadata.ts new file mode 100644 index 0000000..7a6d2bb --- /dev/null +++ b/lib/types-metadata/BaseTypeMetadata.ts @@ -0,0 +1,24 @@ +import {ConfigData} from "../utils/ConfigData"; +import {FieldsMetadata} from "../fields-metadata/FieldsMetadata"; +import {invariant} from "../utils/core"; + +export const GRAPHQL_METADATA_KEY:string = '__GRAPHQL_METADATA'; + +export class BaseTypeMetadata { + protected config:ConfigData = new ConfigData(); + + constructor(protected klass) { + this.config.set('name', this.klass.name); + } + + setConfig(config:Partial) { + this.config.setConfig(config); + } + + protected getFieldsMetadata():FieldsMetadata { + let fieldsMetadata = FieldsMetadata.getForClass(this.klass); + invariant(!!fieldsMetadata, `Missing fields definition for ${this.klass.constructor.name}, ${this.klass}`); + + return fieldsMetadata; + } +} \ No newline at end of file diff --git a/lib/types-metadata/InterfaceTypeMetadata.ts b/lib/types-metadata/InterfaceTypeMetadata.ts new file mode 100644 index 0000000..e1ec164 --- /dev/null +++ b/lib/types-metadata/InterfaceTypeMetadata.ts @@ -0,0 +1,45 @@ +import 'reflect-metadata'; +import {isPresent} from "../utils/core"; +import {metadataGet, metadataGetOrSet} from "../utils/metadataFactories"; +import {GraphQLInterfaceType, GraphQLObjectType, GraphQLResolveInfo, GraphQLTypeResolver} from "graphql"; +import {ClassType} from "../utils/types"; +import {TypeProxy} from "../types-conversion/TypeProxy"; +import {BaseTypeMetadata, GRAPHQL_METADATA_KEY} from "./BaseTypeMetadata"; + +export type TypeResolverForAnnotatedClass = (value:TSource, + context:TContext, + info:GraphQLResolveInfo) => ClassType + +export interface InterfaceTypeConfig { + name:string; + description?:string; + resolveType?:GraphQLTypeResolver | TypeResolverForAnnotatedClass; +} + +export class InterfaceTypeMetadata extends BaseTypeMetadata { + static getForClass = metadataGet(GRAPHQL_METADATA_KEY); + static getOrCreateForClass = metadataGetOrSet(GRAPHQL_METADATA_KEY, InterfaceTypeMetadata); + + private _memoizedInterfaceType:GraphQLInterfaceType; + + toGraphQLInterfaceType():GraphQLInterfaceType { + return this._memoizedInterfaceType || (this._memoizedInterfaceType = this.buildGraphQLInterfaceType()); + } + + private buildGraphQLInterfaceType():GraphQLInterfaceType { + + //TODO: create some type proxy class + let resolveType:GraphQLTypeResolver = isPresent(this.config.get('resolveType')) ? + (value, context, info) => TypeProxy.inferType(this.config.get('resolveType')(value, context, info)) as GraphQLObjectType : + null; + + let fieldsThunk = () => this.getFieldsMetadata().toGraphQLFieldConfigMap(); + + return new GraphQLInterfaceType({ + name: this.config.get('name'), + description: this.config.get('description'), + resolveType, + fields: fieldsThunk + }) + } +} \ No newline at end of file diff --git a/lib/types-metadata/ParamsMetadata.ts b/lib/types-metadata/ParamsMetadata.ts new file mode 100644 index 0000000..67d381a --- /dev/null +++ b/lib/types-metadata/ParamsMetadata.ts @@ -0,0 +1,43 @@ +import {BaseTypeMetadata, GRAPHQL_METADATA_KEY} from "./BaseTypeMetadata"; +import {GraphQLFieldConfigArgumentMap, GraphQLInputObjectType} from "graphql"; +import {metadataGet, metadataGetOrSet} from "../utils/metadataFactories"; +import {propagateErrorWithContext} from "../utils/core"; + +export interface InputConfig { + name:string; + description?:string; +} + +export class ParamsMetadata extends BaseTypeMetadata { + static getForClass = metadataGet(GRAPHQL_METADATA_KEY); + static getOrCreateForClass = metadataGetOrSet(GRAPHQL_METADATA_KEY, ParamsMetadata); + + private _memoizedInputType:GraphQLInputObjectType; + private _memoizedArgumentsType:GraphQLFieldConfigArgumentMap; + + toGraphQLInputObjectType():GraphQLInputObjectType { + return this._memoizedInputType || (this._memoizedInputType = this.buildGraphQLInputObjectType()); + } + + toGraphQLFieldConfigArgumentMap():GraphQLFieldConfigArgumentMap { + return this._memoizedArgumentsType || (this._memoizedArgumentsType = this.buildGraphQLFieldConfigArgumentMap()); + } + + private buildGraphQLInputObjectType():GraphQLInputObjectType { + return propagateErrorWithContext(this.klass.name, () => { + let fieldsThunk = this.getFieldsMetadata().toGraphQLInputFieldConfigMap(); + + return new GraphQLInputObjectType({ + name: this.config.get('name'), + description: this.config.get('description'), + fields: fieldsThunk + }) + }) + } + + private buildGraphQLFieldConfigArgumentMap():GraphQLFieldConfigArgumentMap { + return propagateErrorWithContext(this.klass.name, () => { + return this.getFieldsMetadata().toGraphQLInputFieldConfigMap() + }) + } +} \ No newline at end of file diff --git a/lib/types-metadata/TypeMetadata.ts b/lib/types-metadata/TypeMetadata.ts new file mode 100644 index 0000000..e4e5618 --- /dev/null +++ b/lib/types-metadata/TypeMetadata.ts @@ -0,0 +1,42 @@ +import {BaseTypeMetadata, GRAPHQL_METADATA_KEY} from "./BaseTypeMetadata"; +import {metadataGet, metadataGetOrSet} from "../utils/metadataFactories"; +import {GraphQLInterfaceType, GraphQLIsTypeOfFn, GraphQLObjectType, Thunk} from "graphql"; +import {isPresent, propagateErrorWithContext} from "../utils/core"; +import {resolveThunk} from "../utils/graphql"; +import {TypeProxy} from "../types-conversion/TypeProxy"; +import {ClassType} from "../utils/types"; + +export interface TypeConfigParams { + name:string; + interfaces?:Thunk>>; + isTypeOf?:GraphQLIsTypeOfFn; //#TODO: autopopulate with instanceof + description?:string +} + +export class TypeMetadata extends BaseTypeMetadata { + static getForClass = metadataGet(GRAPHQL_METADATA_KEY); + static getOrCreateForClass = metadataGetOrSet(GRAPHQL_METADATA_KEY, TypeMetadata); + + private _memoizedGraphQLObjectType:GraphQLObjectType; + + toGraphQLObjectType():GraphQLObjectType { + return this._memoizedGraphQLObjectType || (this._memoizedGraphQLObjectType = this.buildGraphQLObjectType()); + } + + private buildGraphQLObjectType():GraphQLObjectType { + return propagateErrorWithContext(this.klass.name, () => { + let fieldsThunk = () => this.getFieldsMetadata().toGraphQLFieldConfigMap(); + + let interfaces = isPresent(this.config.get('interfaces')) ? + resolveThunk(this.config.get('interfaces')).map(type => TypeProxy.inferType(type) as GraphQLInterfaceType) : + null; + + return new GraphQLObjectType({ + name: this.config.get('name'), + description: this.config.get('description'), + interfaces, + fields: fieldsThunk + }) + }) + } +} \ No newline at end of file diff --git a/lib/utils/ConfigData.ts b/lib/utils/ConfigData.ts new file mode 100644 index 0000000..f9ab321 --- /dev/null +++ b/lib/utils/ConfigData.ts @@ -0,0 +1,18 @@ +export class ConfigData { + protected configData:T = {} as T; + + setConfig(config:Partial) { + this.configData = { + ...this.configData as any, + ...config as any + } + } + + set(key:K, val:T[K]) { + return this.configData[key] = val; + } + + get(key:K):T[K] { + return this.configData[key]; + } +} \ No newline at end of file diff --git a/lib/utils/core.ts b/lib/utils/core.ts index af7d834..a6ce650 100644 --- a/lib/utils/core.ts +++ b/lib/utils/core.ts @@ -25,4 +25,13 @@ export function invariant(condition:boolean, message:string) { } } +export function propagateErrorWithContext(ctx:string, fn:() => T):T { + try { + return fn(); + } catch (e) { + let error = new Error(`[${ctx}] ${e.message}`); + throw error + } +} + export function noop() {} \ No newline at end of file diff --git a/lib/utils/metadata.ts b/lib/utils/metadata.ts index 6837ce2..8f3339c 100644 --- a/lib/utils/metadata.ts +++ b/lib/utils/metadata.ts @@ -1,7 +1,6 @@ -import {GRAPHQL_METADATA_KEY, IGraphQLMetadata} from "../abstract/IGraphQLMetadata"; -import {Type} from "./types"; import {someOrThrow} from "./core"; +import {BaseTypeMetadata, GRAPHQL_METADATA_KEY} from "../types-metadata/BaseTypeMetadata"; -export function getMetadata(klass:Type):IGraphQLMetadata { - return someOrThrow(Reflect.getMetadata(GRAPHQL_METADATA_KEY, klass), `Missing GraphQL metadata for ${klass.name}`); +export function getMetadata(klass:Object):BaseTypeMetadata { + return someOrThrow(Reflect.getMetadata(GRAPHQL_METADATA_KEY, klass), `Missing GraphQL metadata for ${klass.constructor.name}`); } \ No newline at end of file diff --git a/lib/metadata/metadataFactories.ts b/lib/utils/metadataFactories.ts similarity index 75% rename from lib/metadata/metadataFactories.ts rename to lib/utils/metadataFactories.ts index a0b113b..e9004bc 100644 --- a/lib/metadata/metadataFactories.ts +++ b/lib/utils/metadataFactories.ts @@ -1,10 +1,10 @@ -import {Type} from "../utils/types"; +import {ClassType} from "./types"; -export function metadataGet(metadataKey:string): (klass) => T { +export function metadataGet(metadataKey:string):(klass) => T { return (klass) => Reflect.getMetadata(metadataKey, klass); } -export function metadataGetOrSet(metadataKey:string, MetadataClass:Type): (klass) => T { +export function metadataGetOrSet(metadataKey:string, MetadataClass:ClassType):(klass) => T { return (klass) => { let nodeMetadata = Reflect.getOwnMetadata(metadataKey, klass); diff --git a/lib/utils/types.ts b/lib/utils/types.ts index 559b9b4..eb3972f 100644 --- a/lib/utils/types.ts +++ b/lib/utils/types.ts @@ -1,4 +1,4 @@ -export interface Type { +export interface ClassType { new(...args:any[]):T; } diff --git a/package.json b/package.json index 8e00817..c40b93b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gql-schema", - "version": "0.0.3", + "version": "0.4.0", "description": "Yet another experimental library for defining graphql schemas using decorators.", "repository": "https://github.com/robak86/gql-schema", "main": "lib/index.js", @@ -10,29 +10,36 @@ "build:copy": "cp package.json ./dist/lib/ && cp README.md ./dist/lib/", "build:compile": "tsc", "build:dist": "npm run build:clean && npm run build:copy && npm run build:compile", - "build:watch": "npm run build:clean && npm run build:copy && tsc --watch --sourceMap", - "build:coverage": "nyc --reporter=text-lcov mocha -- -- spec dist/spec/**/*.spec.js | coveralls" + "build:watch": "npm run build:clean && npm run build:copy && tsc --watch --sourceMap --pretty", + "build:coverage": "nyc --reporter=text-lcov mocha -- -- spec dist/spec/**/*.spec.js | coveralls", + "build:coverage:local": "nyc --reporter=text-lcov mocha -- -- spec dist/spec/**/*.spec.js" }, "author": "Tomasz Robaczewski", "license": "MIT", "devDependencies": { "@types/chai": "^4.0.0", - "@types/graphql": "^0.11.6", + "@types/graphql": "^0.11.7", "@types/lodash": "^4.14.65", "@types/mocha": "^2.2.41", + "@types/sinon": "^4.1.2", "chai": "^4.0.2", "coveralls": "^2.13.1", "mocha": "^3.4.2", "nyc": "^11.0.3", "reflect-metadata": "^0.1.10", + "sinon": "^4.1.3", "source-map-support": "^0.4.15", "typescript": "^2.6.1" }, "dependencies": { - "graphql": "^0.11.7", "lodash": "^4.17.4" }, "peerDependencies": { - "graphql": "^0.11.7" + "graphql": "0.11.7" + }, + "nyc": { + "exclude": [ + "dist/spec/**/*.js" + ] } } diff --git a/spec/decorators/args.spec.ts b/spec/decorators/args.spec.ts deleted file mode 100644 index b7ae0a8..0000000 --- a/spec/decorators/args.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {GraphQLString} from "graphql"; -import {expect} from 'chai'; -import {ArgumentMapMetadata} from "../../lib/metadata/ArgumentMapMetadata"; -import {field} from "../../lib"; -import {argsType} from "../../lib/decorators/argsType"; - - -describe("argsType decorator", () => { - describe("@argsType()", () => { - @argsType() - class SomeArgsType { - @field(GraphQLString) _:string - } - - it("attaches metadata object", () => { - expect(ArgumentMapMetadata.getForClass(SomeArgsType)).to.be.instanceof(ArgumentMapMetadata) - }); - }); - - describe("@field", () => { - it("registers property", () => { - @argsType() - class SomeClass { - @field(GraphQLString) - arg1:string - } - - let graphQLFieldConfigArgumentMap = ArgumentMapMetadata.getOrCreateForClass(SomeClass).toGraphQLType(); - expect(graphQLFieldConfigArgumentMap['arg1'].type).to.eq(GraphQLString) - }); - }); -}); \ No newline at end of file diff --git a/spec/decorators/fields.spec.ts b/spec/decorators/fields.spec.ts index cd48096..b550826 100644 --- a/spec/decorators/fields.spec.ts +++ b/spec/decorators/fields.spec.ts @@ -1,28 +1,27 @@ -import {GraphQLID, GraphQLString} from "graphql"; -import {FieldsMetadata} from "../../lib/metadata/FieldsMetadata"; +import {GraphQLFieldConfig, GraphQLID, GraphQLList, GraphQLNonNull, GraphQLString} from "graphql"; +import {FieldsMetadata} from "../../lib/fields-metadata/FieldsMetadata"; import {expect} from 'chai'; -import {id, field, fieldLazy, list, listLazy, description, nonNull, nonNullItems} from '../../lib/'; -import {decorateEnum} from "../../lib/decorators/enum"; +import {description, field, fieldThunk, id, list, listThunk, nonNull, nonNullItems} from '../../lib/'; + +function getSpecField(klass, propertyKey:string = 'someField'):GraphQLFieldConfig { + return FieldsMetadata.getForClass(klass).getField(propertyKey).toGraphQLFieldConfig(); +} describe("fields decorators", () => { + let fieldConfig:GraphQLFieldConfig; + describe("@id()", () => { class SomeClass { - @id() - someField:string + @id() someField:string; } - let fieldConfig; beforeEach(() => { - fieldConfig = FieldsMetadata.getForClass(SomeClass).getField('someField'); + fieldConfig = getSpecField(SomeClass) }); - it("adds type to property config", () => { + it("sets correct type on GraphQLFieldConfig", () => { expect(fieldConfig.type).to.eq(GraphQLID); }); - - it("uses defaults values", () => { - expect(fieldConfig.nonNull).to.eq(false); - }); }); describe("@field()", () => { @@ -31,41 +30,27 @@ describe("fields decorators", () => { someField:string } - let fieldConfig; beforeEach(() => { - fieldConfig = FieldsMetadata.getForClass(SomeClass).getField('someField'); + fieldConfig = getSpecField(SomeClass) }); - it("sets type for field config", () => { + it("sets correct type on GraphQLFieldConfig", () => { expect(fieldConfig.type).to.eq(GraphQLString); }); - - it("uses defaults values", () => { - expect(fieldConfig.nonNull).to.eq(false); - expect(fieldConfig.array).to.eq(false); - expect(fieldConfig.nonNullItem).to.eq(false); - }); }); - describe("@fieldLazy()", () => { + describe("@fieldThunk()", () => { class SomeClass { - @fieldLazy(() => GraphQLString) + @fieldThunk(() => GraphQLString) someField:string } - let fieldConfig; beforeEach(() => { - fieldConfig = FieldsMetadata.getForClass(SomeClass).getField('someField'); + fieldConfig = getSpecField(SomeClass) }); - it("adds thunkType to property config", () => { - expect(fieldConfig.thunkType()).to.eq(GraphQLString); - }); - - it("uses defaults values", () => { - expect(fieldConfig.nonNull).to.eq(false); - expect(fieldConfig.array).to.eq(false); - expect(fieldConfig.nonNullItem).to.eq(false); + it("sets correct type on GraphQLFieldConfig", () => { + expect(fieldConfig.type).to.eq(GraphQLString); }); }); @@ -75,71 +60,76 @@ describe("fields decorators", () => { someField:string } - let fieldConfig; beforeEach(() => { - fieldConfig = FieldsMetadata.getForClass(SomeClass).getField('someField'); - }); - - it("adds type to property config", () => { - expect(fieldConfig.type).to.eq(GraphQLString); + fieldConfig = getSpecField(SomeClass) }); - it("sets list config property to true", () => { - expect(fieldConfig.array).to.eq(true); + it("sets correct type on GraphQLFieldConfig", () => { + expect(fieldConfig.type).to.eql(new GraphQLList(GraphQLString)); }); }); - describe("@listLazy()", () => { + describe("@listThunk()", () => { class SomeClass { - @listLazy(() => GraphQLString) + @listThunk(() => GraphQLString) someField:string } - let fieldConfig; beforeEach(() => { - fieldConfig = FieldsMetadata.getForClass(SomeClass).getField('someField'); + fieldConfig = getSpecField(SomeClass) }); - it("adds type to property config", () => { - expect(fieldConfig.thunkType()).to.eq(GraphQLString); - }); - - it("sets list config property to true", () => { - expect(fieldConfig.array).to.eq(true); + it("sets correct type on GraphQLFieldConfig", () => { + expect(fieldConfig.type).to.eql(new GraphQLList(GraphQLString)); }); }); describe("decorators chaining", () => { - class SomeClass { - @description('Some Field description') - @list(GraphQLString) @nonNull() @nonNullItems() - someField:string - } + describe("chaining decorators for non list type", () => { + class SomeClass { + @description('Some Field description') + @field(GraphQLString) @nonNull() + someField:string + } - let fieldConfig; - beforeEach(() => { - fieldConfig = FieldsMetadata.getForClass(SomeClass).getField('someField'); - }); + beforeEach(() => { + fieldConfig = getSpecField(SomeClass) + }); - it("adds type to property config", () => { - expect(fieldConfig.type).to.eq(GraphQLString); - }); + it("adds type to property config", () => { + expect(fieldConfig.type).to.eql(new GraphQLNonNull(GraphQLString)); + }); - it("sets list config property to true", () => { - expect(fieldConfig.array).to.eq(true); + it("sets description", () => { + expect(fieldConfig.description).to.eq('Some Field description'); + }); }); - it("sets nonNullItem", () => { - expect(fieldConfig.nonNullItem).to.eq(true); - }); + describe("chaining decorators for list type", () => { + class SomeClass { + @description('Some Field description') + @list(GraphQLString) @nonNull() @nonNullItems() + someField:string + } - it("sets nonNull", () => { - expect(fieldConfig.nonNull).to.eq(true); - }); + beforeEach(() => { + fieldConfig = getSpecField(SomeClass) + }); + + it("adds type to property config", () => { + expect(fieldConfig.type).to.eql(new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLString)))); + }); - it("sets description", () => { - expect(fieldConfig.description).to.eq('Some Field description'); + it("sets description", () => { + expect(fieldConfig.description).to.eq('Some Field description'); + }); }); }); + describe("throwing errors on forbidden decorators combination", () => { + it('throws error for @field() and @nonNullItems() combination'); + it('throws error for @field() and @list() used at the same time'); + it('throws error for @field() and @listThunk() used at the same time'); + it('throws error for @fieldThunk() and @list() used at the same time'); + }); }); \ No newline at end of file diff --git a/spec/decorators/input.spec.ts b/spec/decorators/input.spec.ts index ba67978..f9b00ed 100644 --- a/spec/decorators/input.spec.ts +++ b/spec/decorators/input.spec.ts @@ -1,8 +1,8 @@ -import {input} from "../../lib/decorators/input"; -import {InputObjectTypeMetadata} from "../../lib/metadata/InputObjectTypeMetadata"; import {expect} from 'chai'; +import {input} from "../../lib"; import {GraphQLInputField, GraphQLObjectType, GraphQLString} from "graphql"; -import {field} from "../../lib/index"; +import {field} from "../../lib"; +import {ParamsMetadata} from "../../lib/types-metadata/ParamsMetadata"; describe("@input", () => { @@ -13,15 +13,15 @@ describe("@input", () => { } it("attaches metadata object", () => { - expect(InputObjectTypeMetadata.getForClass(SomeInputParams)).to.be.instanceof(InputObjectTypeMetadata) + expect(ParamsMetadata.getForClass(SomeInputParams)).to.be.instanceof(ParamsMetadata) }); it("sets default name using class name", () => { - expect(InputObjectTypeMetadata.getForClass(SomeInputParams).toGraphQLType().name).to.eq('SomeInputParams'); + expect(ParamsMetadata.getForClass(SomeInputParams).toGraphQLInputObjectType().name).to.eq('SomeInputParams'); }); it("sets description property", () => { - expect(InputObjectTypeMetadata.getForClass(SomeInputParams).toGraphQLType().description).to.eq('Some description'); + expect(ParamsMetadata.getForClass(SomeInputParams).toGraphQLInputObjectType().description).to.eq('Some description'); }); }); @@ -35,7 +35,7 @@ describe("@input", () => { describe("type", () => { it("properly passes native type", () => { - let graphQLObjectType = InputObjectTypeMetadata.getOrCreateForClass(SomeInputParams).toGraphQLType(); + let graphQLObjectType = ParamsMetadata.getOrCreateForClass(SomeInputParams).toGraphQLInputObjectType(); let someFieldField:GraphQLInputField = graphQLObjectType.getFields()['someField']; expect(someFieldField.name).to.eq('someField'); @@ -58,11 +58,11 @@ describe("@input", () => { } it("it accepts annotated class as type parameter", () => { - let graphQLObjectType = InputObjectTypeMetadata.getOrCreateForClass(NewUserParams).toGraphQLType(); + let graphQLObjectType = ParamsMetadata.getOrCreateForClass(NewUserParams).toGraphQLInputObjectType(); let someFieldField:GraphQLInputField = graphQLObjectType.getFields()['address']; let someFieldGraphQLObjectType:GraphQLObjectType = someFieldField.type as any; - expect(someFieldGraphQLObjectType).to.eql(InputObjectTypeMetadata.getForClass(NewUserAddressParams).toGraphQLType()); + expect(someFieldGraphQLObjectType).to.eql(ParamsMetadata.getForClass(NewUserAddressParams).toGraphQLInputObjectType()); }); }); }); diff --git a/spec/decorators/interface.spec.ts b/spec/decorators/interface.spec.ts index 6ded4e9..6b23ef6 100644 --- a/spec/decorators/interface.spec.ts +++ b/spec/decorators/interface.spec.ts @@ -2,7 +2,7 @@ import {expect} from 'chai'; import {GraphQLString} from "graphql"; import {field} from "../../lib"; import {interfaceType} from "../../lib/decorators/interface"; -import {InterfaceTypeMetadata} from "../../lib/metadata/InterfaceTypeMetadata"; +import {InterfaceTypeMetadata} from "../../lib/types-metadata/InterfaceTypeMetadata"; describe("@interfaceType", () => { describe("@interfaceType()", () => { @@ -17,7 +17,7 @@ describe("@interfaceType", () => { }); it("sets default name using class name", () => { - expect(InterfaceTypeMetadata.getForClass(SomeType).toGraphQLType().name).to.eq('SomeType'); + expect(InterfaceTypeMetadata.getForClass(SomeType).toGraphQLInterfaceType().name).to.eq('SomeType'); }); }); }); \ No newline at end of file diff --git a/spec/decorators/type.spec.ts b/spec/decorators/type.spec.ts index d2a19ea..29306b2 100644 --- a/spec/decorators/type.spec.ts +++ b/spec/decorators/type.spec.ts @@ -1,13 +1,8 @@ import {expect} from 'chai'; import {GraphQLEnumType, GraphQLField, GraphQLObjectType, GraphQLString} from "graphql"; -import {ObjectTypeMetadata} from "../../lib/metadata/ObjectTypeMetadata"; -import {createUnion} from "../../lib/factories/createUnion"; import * as _ from 'lodash/fp'; -import {createEnum} from "../../lib/factories/createEnum"; -import {type} from "../../lib/decorators/type"; -import {field, args, resolve} from "../../lib"; -import {argsType} from "../../lib/index"; -import {decorateEnum} from "../../lib/decorators/enum"; +import {createEnum, decorateEnum, field, input, params, resolve, type} from "../../lib"; +import {TypeMetadata} from "../../lib/types-metadata/TypeMetadata"; describe("@type", () => { describe("@type()", () => { @@ -18,11 +13,11 @@ describe("@type", () => { } it("attaches metadata object", () => { - expect(ObjectTypeMetadata.getForClass(SomeType)).to.be.instanceof(ObjectTypeMetadata) + expect(TypeMetadata.getForClass(SomeType)).to.be.instanceof(TypeMetadata) }); it("sets default name using class name", () => { - expect(ObjectTypeMetadata.getForClass(SomeType).toGraphQLType().name).to.eq('SomeType'); + expect(TypeMetadata.getForClass(SomeType).toGraphQLObjectType().name).to.eq('SomeType'); }); }); @@ -39,7 +34,7 @@ describe("@type", () => { describe("resolve", () => { it("properly passes resolve function to GraphQLFieldMap", () => { - let graphQLObjectType = ObjectTypeMetadata.getOrCreateForClass(SomeType).toGraphQLType(); + let graphQLObjectType = TypeMetadata.getOrCreateForClass(SomeType).toGraphQLObjectType(); let someFieldField:GraphQLField = graphQLObjectType.getFields()['someField']; expect(someFieldField.resolve).to.eq(resolveFunction); }); @@ -47,7 +42,7 @@ describe("@type", () => { describe("type", () => { it("properly passes native type", () => { - let graphQLObjectType = ObjectTypeMetadata.getOrCreateForClass(SomeType).toGraphQLType(); + let graphQLObjectType = TypeMetadata.getOrCreateForClass(SomeType).toGraphQLObjectType(); let someFieldField:GraphQLField = graphQLObjectType.getFields()['someField']; expect(someFieldField.name).to.eq('someField'); @@ -70,41 +65,44 @@ describe("@type", () => { } it("it accepts annotated class as type parameter", () => { - let graphQLObjectType = ObjectTypeMetadata.getOrCreateForClass(SomeType).toGraphQLType(); + let graphQLObjectType = TypeMetadata.getOrCreateForClass(SomeType).toGraphQLObjectType(); let someFieldField:GraphQLField = graphQLObjectType.getFields()['someField']; let someFieldGraphQLObjectType:GraphQLObjectType = someFieldField.type as any; - expect(someFieldGraphQLObjectType).to.eql(ObjectTypeMetadata.getForClass(SomeOtherType).toGraphQLType()); + expect(someFieldGraphQLObjectType).to.eql(TypeMetadata.getForClass(SomeOtherType).toGraphQLObjectType()); }); }); describe("union type created with createUnion", () => { - @type() - class UnionType1 { - @field(GraphQLString) - someField:SomeOtherType; - } - - @type() - class UnionType2 { - @field(GraphQLString) - someField:SomeOtherType; - } - - type SomeUnion = UnionType1 | UnionType2; - const SomeUnionType = createUnion('SomeUnionType', [UnionType1, UnionType2], _.noop); - - @type() - class SomeOtherType { - @field(SomeUnionType) - someField:SomeUnion; - } - - it("uses GraphQLUnionType native type", () => { - let graphQLObjectType = ObjectTypeMetadata.getOrCreateForClass(SomeOtherType).toGraphQLType(); - let someFieldField:GraphQLField = graphQLObjectType.getFields()['someField']; - expect(someFieldField.type).to.eql(SomeUnionType); - }); + // @type() + // class UnionType1 { + // @field(GraphQLString) + // someField:SomeOtherType; + // } + // + // @type() + // class UnionType2 { + // @field(GraphQLString) + // someField:SomeOtherType; + // } + // + // type SomeUnion = UnionType1 | UnionType2; + // // FieldsMetadata.getOrCreateForClass(UnionType1); + // // let wtf = FieldsMetadata.getForClass(UnionType1); + // + // const SomeUnionType = createUnion('SomeUnionType', [UnionType1, UnionType2], _.noop); + // + // @type() + // class SomeOtherType { + // @field(SomeUnionType) + // someField:SomeUnion; + // } + // + // it("uses GraphQLUnionType native type", () => { + // let graphQLObjectType = TypeMetadata.getOrCreateForClass(SomeOtherType).toGraphQLObjectType(); + // let someFieldField:GraphQLField = graphQLObjectType.getFields()['someField']; + // expect(someFieldField.type).to.eql(SomeUnionType); + // }); }); describe("enum type created with createEnum", () => { @@ -118,7 +116,7 @@ describe("@type", () => { } it("uses GraphQLUnionType native type", () => { - let graphQLObjectType = ObjectTypeMetadata.getOrCreateForClass(SomeOtherType).toGraphQLType(); + let graphQLObjectType = TypeMetadata.getOrCreateForClass(SomeOtherType).toGraphQLObjectType(); let statusField:GraphQLField = graphQLObjectType.getFields()['status']; expect(statusField.type).to.eql(StatusType); }); @@ -129,6 +127,7 @@ describe("@type", () => { started = 'started', stopped = 'stopped' } + decorateEnum('Status', Status); @type() @@ -138,7 +137,7 @@ describe("@type", () => { } it("uses GraphQLEnumType native type", () => { - let graphQLObjectType = ObjectTypeMetadata.getOrCreateForClass(SomeOtherType).toGraphQLType(); + let graphQLObjectType = TypeMetadata.getOrCreateForClass(SomeOtherType).toGraphQLObjectType(); let statusField:GraphQLField = graphQLObjectType.getFields()['status']; let type:GraphQLEnumType = statusField.type as any; expect(type).to.be.instanceOf(GraphQLEnumType); @@ -157,7 +156,7 @@ describe("@type", () => { describe("arguments", () => { - @argsType() + @input() class SomeFieldArguments { @field(GraphQLString) someArgument:string; @@ -166,12 +165,12 @@ describe("@type", () => { @type() class SomeType { @field(GraphQLString) - @args(SomeFieldArguments) + @params(SomeFieldArguments) someField:string; } - it("accepts annotated class for args parameter", () => { - let graphQLObjectType = ObjectTypeMetadata.getOrCreateForClass(SomeType).toGraphQLType(); + it("accepts annotated class for params parameter", () => { + let graphQLObjectType = TypeMetadata.getOrCreateForClass(SomeType).toGraphQLObjectType(); let someFieldArgs = graphQLObjectType.getFields()['someField'].args; expect(someFieldArgs[0].type).to.eq(GraphQLString); expect(someFieldArgs[0].name).to.eq('someArgument'); diff --git a/spec/factories/createEnum.spec.ts b/spec/factories/createEnum.spec.ts index 2c55f9b..1618118 100644 --- a/spec/factories/createEnum.spec.ts +++ b/spec/factories/createEnum.spec.ts @@ -1,4 +1,4 @@ -import {createEnum} from "../../lib/factories/createEnum"; +import {createEnum} from "../../lib"; import {expect} from 'chai'; import {GraphQLEnumType} from "graphql"; diff --git a/spec/factories/createUnion.spec.ts b/spec/factories/createUnion.spec.ts index c342725..6e5dab2 100644 --- a/spec/factories/createUnion.spec.ts +++ b/spec/factories/createUnion.spec.ts @@ -1,10 +1,10 @@ -import {type} from "../../lib/decorators/type"; -import {createUnion} from "../../lib/factories/createUnion"; +import {type} from "../../lib"; +import {createUnion} from "../../lib"; import * as _ from 'lodash'; -import {ObjectTypeMetadata} from "../../lib/metadata/ObjectTypeMetadata"; import {expect} from 'chai'; import {GraphQLString} from "graphql"; import {field} from "../../lib"; +import {TypeMetadata} from "../../lib/types-metadata/TypeMetadata"; describe(".createUnion", () => { let SomeUnionTypeDefinition; @@ -29,8 +29,8 @@ describe(".createUnion", () => { describe("inferring of decorated type classes", () => { it("accepts decorated classes", () => { let types = SomeUnionTypeDefinition.getTypes(); - expect(types[0]).to.eq(ObjectTypeMetadata.getForClass(SomeType).toGraphQLType()); - expect(types[1]).to.eq(ObjectTypeMetadata.getForClass(SomeOtherType).toGraphQLType()); + expect(types[0]).to.eq(TypeMetadata.getForClass(SomeType).toGraphQLObjectType()); + expect(types[1]).to.eq(TypeMetadata.getForClass(SomeOtherType).toGraphQLObjectType()); }); }); }); \ No newline at end of file diff --git a/spec/integration/buildingSchema.spec.ts b/spec/integration/buildingSchema.spec.ts index 409ab87..2ba4687 100644 --- a/spec/integration/buildingSchema.spec.ts +++ b/spec/integration/buildingSchema.spec.ts @@ -1,7 +1,7 @@ import {buildASTSchema, parse, printType} from "graphql"; import {expect} from 'chai'; import {GraphQLSchema} from "graphql/type/schema"; -import {createSchema} from "../../lib/factories/createSchema"; +import {createSchema} from "../../lib"; import {Mutation} from "./types/Mutation"; import {Query} from "./types/Query"; @@ -12,7 +12,7 @@ function createdSchemaFromDecoratedClasses():GraphQLSchema { function createSchemaFromDefinition():GraphQLSchema { const definition = ` - # User search address params + """User search address params""" input UserSearchAddressParams { street: String } @@ -24,11 +24,18 @@ function createSchemaFromDefinition():GraphQLSchema { type User { id: ID! - firstName:String + firstName: String firstNameUpperCase: String + address: Address employers: [Company!]! role: UserRole! } + + type Address { + id: ID + streetName: String + city: String + } type Query { someQuery: String @@ -38,27 +45,39 @@ function createSchemaFromDefinition():GraphQLSchema { images: [Image!]! audioAssets: [AudioAsset!]! } - + type Mutation { - someMutation: String + createUser(firstName: String!, lastName: String!, address: CreateAddressParams): User + createAddress(streetName: String, city: String): Address + createCompany(companyName: String): Company + createCompanyWrapped(input: CreateCompanyParams!): Company + } + + input CreateCompanyParams { + companyName: String } + input CreateAddressParams { + streetName: String + city: String + } + type Company { employees:[User!]! } - + enum UserRole { admin stuff guest } - + interface Asset { id: ID! size: Int! mimeType: String! } - + type Image implements Asset { id: ID! size: Int! @@ -66,14 +85,14 @@ function createSchemaFromDefinition():GraphQLSchema { width: Int height: Int } - + type AudioAsset implements Asset { id: ID! size: Int! mimeType: String! length: Int } - + union SearchResult = User | Company `; return buildASTSchema(parse(definition)); @@ -99,6 +118,12 @@ describe("building schema", () => { }); }); + describe("type Address", () => { + it("generates proper type", () => { + expectTypesEqual('Address'); + }); + }); + describe("type Mutation", () => { it("generates proper type", () => { expectTypesEqual('Mutation'); @@ -111,13 +136,13 @@ describe("building schema", () => { }); }); - describe("input UserSearchAddressParams", () => { + describe("input CreateAddressParams", () => { it("generates proper type", () => { - expectTypesEqual('UserSearchAddressParams'); + expectTypesEqual('CreateAddressParams'); }); }); - describe("enum UserSearchAddressParams", () => { + describe("input UserSearchAddressParams", () => { it("generates proper type", () => { expectTypesEqual('UserSearchAddressParams'); }); diff --git a/spec/integration/queries.spec.ts b/spec/integration/queries.spec.ts index 29c4c26..705fb75 100644 --- a/spec/integration/queries.spec.ts +++ b/spec/integration/queries.spec.ts @@ -1,5 +1,5 @@ import {graphql, GraphQLSchema} from "graphql"; -import {createSchema} from "../../lib/factories/createSchema"; +import {createSchema} from "../../lib"; import {Query} from "./types/Query"; import {Mutation} from "./types/Mutation"; import {expect} from 'chai'; @@ -70,7 +70,7 @@ describe("root query", () => { }); }); - describe("query with args", () => { + describe("query with params", () => { it("returns correct data", async () => { let query = ` query Users($firstName: String){ diff --git a/spec/integration/types/Address.ts b/spec/integration/types/Address.ts new file mode 100644 index 0000000..60ae95c --- /dev/null +++ b/spec/integration/types/Address.ts @@ -0,0 +1,14 @@ +import {field, id, type} from "../../../lib"; +import {GraphQLString} from "graphql"; + +@type() +export class Address { + @id() + id:string; + + @field(GraphQLString) + streetName:string; + + @field(GraphQLString) + city:string; +} \ No newline at end of file diff --git a/spec/integration/types/Asset.ts b/spec/integration/types/Asset.ts index 8eea580..dbde517 100644 --- a/spec/integration/types/Asset.ts +++ b/spec/integration/types/Asset.ts @@ -4,26 +4,26 @@ import {nonNull} from "../../../lib/decorators/fields"; import {AudioAsset} from "./AudioAsset"; -@interfaceType({ - resolveType: (asset) => { - if (asset.mime === 'image/jpg'){ - return Image - } - - if (asset.mime === 'audio/mp3'){ - return AudioAsset - } - - throw new Error("Unknown asset type") - } -}) +@interfaceType({resolveType}) export class Asset { @id() @nonNull() id:string; @field(GraphQLInt) @nonNull() - size: number; + size:number; @field(GraphQLString) @nonNull() - mimeType: string; + mimeType:string; +} + +function resolveType(asset) { + if (asset.mime === 'image/jpg') { + return Image + } + + if (asset.mime === 'audio/mp3') { + return AudioAsset + } + + throw new Error("Unknown asset type") } \ No newline at end of file diff --git a/spec/integration/types/Company.ts b/spec/integration/types/Company.ts index 59a46ec..6d70ee2 100644 --- a/spec/integration/types/Company.ts +++ b/spec/integration/types/Company.ts @@ -1,8 +1,7 @@ -import {type} from "../../../lib/decorators/type"; -import {field, id, listLazy} from "../../../lib/"; +import {nonNull, type} from "../../../lib"; +import {field, id, listThunk} from "../../../lib/"; import {User} from "./User"; import {GraphQLString} from "graphql"; -import {nonNull} from "../../../lib/index"; @type() export class Company { @@ -12,6 +11,6 @@ export class Company { @field(GraphQLString) name:string; - @listLazy(() => User) + @listThunk(() => User) employees:User[]; } diff --git a/spec/integration/types/CreateAddressParams.ts b/spec/integration/types/CreateAddressParams.ts new file mode 100644 index 0000000..f89b28f --- /dev/null +++ b/spec/integration/types/CreateAddressParams.ts @@ -0,0 +1,11 @@ +import {field, input} from "../../../lib"; +import {GraphQLString} from "graphql"; + +@input() +export class CreateAddressParams { + @field(GraphQLString) + streetName:string; + + @field(GraphQLString) + city:string +} \ No newline at end of file diff --git a/spec/integration/types/CreateCompanyParams.ts b/spec/integration/types/CreateCompanyParams.ts new file mode 100644 index 0000000..70171e9 --- /dev/null +++ b/spec/integration/types/CreateCompanyParams.ts @@ -0,0 +1,15 @@ +import {field, input, nonNull} from "../../../lib"; +import {GraphQLString} from "graphql"; + +@input() +export class CreateCompanyParams { + @field(GraphQLString) + companyName:string; +} + + +@input() +export class CreateCompanyParamsWrapped { + @field(CreateCompanyParams) @nonNull() + input:CreateCompanyParams +} \ No newline at end of file diff --git a/spec/integration/types/CreateUserParams.ts b/spec/integration/types/CreateUserParams.ts new file mode 100644 index 0000000..cb9fc89 --- /dev/null +++ b/spec/integration/types/CreateUserParams.ts @@ -0,0 +1,15 @@ +import {field, input, nonNull} from "../../../lib"; +import {GraphQLString} from "graphql"; +import {CreateAddressParams} from "./CreateAddressParams"; + +@input() +export class CreateUserParams { + @field(GraphQLString) @nonNull() + firstName:string; + + @field(GraphQLString) @nonNull() + lastName:string; + + @field(CreateAddressParams) + address:CreateAddressParams +} \ No newline at end of file diff --git a/spec/integration/types/Mutation.ts b/spec/integration/types/Mutation.ts index 665f8d0..123d397 100644 --- a/spec/integration/types/Mutation.ts +++ b/spec/integration/types/Mutation.ts @@ -1,10 +1,26 @@ -import {type} from "../../../lib/decorators/type"; - -import {GraphQLString} from "graphql"; -import {field} from "../../../lib/index"; +import {field, params, paramsThunk, type} from "../../../lib"; +import {User} from "./User"; +import {CreateUserParams} from "./CreateUserParams"; +import {CreateAddressParams} from "./CreateAddressParams"; +import {Address} from "./Address"; +import {Company} from "./Company"; +import {CreateCompanyParams, CreateCompanyParamsWrapped} from "./CreateCompanyParams"; @type() export class Mutation { - @field(GraphQLString) - someMutation:string + @field(User) + @params(CreateUserParams) + createUser:User; + + @params(CreateAddressParams) + @field(Address) + createAddress:Address; + + @field(Company) + @paramsThunk(() => CreateCompanyParams) + createCompany:Company; + + @field(Company) + @paramsThunk(() => CreateCompanyParamsWrapped) + createCompanyWrapped:Company; } \ No newline at end of file diff --git a/spec/integration/types/Query.ts b/spec/integration/types/Query.ts index 17820a7..edaf8b1 100644 --- a/spec/integration/types/Query.ts +++ b/spec/integration/types/Query.ts @@ -1,6 +1,6 @@ -import {type} from "../../../lib/decorators/type"; +import {type} from "../../../lib"; import {GraphQLString} from "graphql"; -import {list, field, nonNull, args, resolve, nonNullItems} from "../../../lib/"; +import {field, list, nonNull, nonNullItems, params, resolve} from "../../../lib/"; import {User} from "./User"; import {UsersArguments} from "./UserSearch"; import {resolveFakeSearch, resolveUsers} from "../resolvers/queries"; @@ -17,7 +17,7 @@ export class Query { someQuery:string; @list(User) @nonNull() @nonNullItems() - @args(UsersArguments) @resolve(resolveUsers) + @params(UsersArguments) @resolve(resolveUsers) users:User[]; @list(SearchResultType) @nonNull() @nonNullItems() diff --git a/spec/integration/types/SearchResult.ts b/spec/integration/types/SearchResult.ts index 098fe35..354f380 100644 --- a/spec/integration/types/SearchResult.ts +++ b/spec/integration/types/SearchResult.ts @@ -1,6 +1,6 @@ import {User} from "./User"; import {Company} from "./Company"; -import {createUnion} from "../../../lib/factories/createUnion"; +import {createUnion} from "../../../lib"; import {GraphQLUnionType} from "graphql"; diff --git a/spec/integration/types/User.ts b/spec/integration/types/User.ts index f10bdf8..8e40976 100644 --- a/spec/integration/types/User.ts +++ b/spec/integration/types/User.ts @@ -1,9 +1,10 @@ import {Company} from "./Company"; -import {listLazy, field, id, nonNull, resolve, nonNullItems} from "../../../lib/"; +import {field, id, listThunk, nonNull, nonNullItems, resolve} from "../../../lib/"; import {GraphQLString} from "graphql"; -import {type} from "../../../lib/decorators/type"; +import {type} from "../../../lib"; import {resolveEmployersForUser} from "../resolvers/queries"; import {UserRole} from "./UserRole"; +import {Address} from "./Address"; @type() @@ -17,7 +18,10 @@ export class User { @field(GraphQLString) @resolve((user:User) => user.firstName.toUpperCase()) firstNameUpperCase:string; - @listLazy(() => Company) @nonNull() @nonNullItems() + @field(Address) + address:Address; + + @listThunk(() => Company) @nonNull() @nonNullItems() @resolve(resolveEmployersForUser) employers:Company[]; diff --git a/spec/integration/types/UserSearch.ts b/spec/integration/types/UserSearch.ts index 706cb8b..de99e9e 100644 --- a/spec/integration/types/UserSearch.ts +++ b/spec/integration/types/UserSearch.ts @@ -1,7 +1,5 @@ -import {input} from "../../../lib/decorators/input"; +import {input, field} from "../../../lib"; import {GraphQLString} from "graphql"; -import {field} from "../../../lib/"; -import {argsType} from "../../../lib/decorators/argsType"; @input({description: `User search address params`}) @@ -19,7 +17,7 @@ export class UserSearchParams { address:UserSearchAddressParams } -@argsType() +@input() export class UsersArguments { @field(UserSearchParams) params:UserSearchParams diff --git a/spec/metadata/FieldsMetadata.spec.ts b/spec/metadata/FieldsMetadata.spec.ts index b31913e..d7a659f 100644 --- a/spec/metadata/FieldsMetadata.spec.ts +++ b/spec/metadata/FieldsMetadata.spec.ts @@ -1,13 +1,28 @@ -import {noop} from "../../lib/utils/core"; import {expect} from 'chai'; import {GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLString} from "graphql"; -import {FieldsMetadata} from "../../lib/metadata/FieldsMetadata"; -import {type} from "../../lib/decorators/type"; -import {field} from "../../lib/decorators/fields"; +import {FieldsMetadata} from "../../lib/fields-metadata/FieldsMetadata"; +import {field, type} from "../../lib"; describe("FieldsTypeMetadata", () => { - describe("static getForClass", noop); - describe("static getOrCreateForClass", noop); + + describe("static getOrCreateForClass", () => { + let SomeClass; + + beforeEach(() => { + SomeClass = class {}; + }); + + it('assigns new instance of FieldsMetadata', () => { + FieldsMetadata.getOrCreateForClass(SomeClass); + expect(FieldsMetadata.getForClass(SomeClass)).to.be.instanceOf(FieldsMetadata); + }); + + it('returns the same instance of FieldsMetadata', () => { + let firstGet = FieldsMetadata.getOrCreateForClass(SomeClass); + let secondGet = FieldsMetadata.getOrCreateForClass(SomeClass); + expect(firstGet).to.eq(secondGet); + }); + }); describe(".toGraphQLType", () => { let SomeClass, @@ -18,53 +33,58 @@ describe("FieldsTypeMetadata", () => { someClassFieldsMetadata = FieldsMetadata.getOrCreateForClass(SomeClass); }); - describe(".patchConfig", () => { it("sets type", () => { - someClassFieldsMetadata.patchConfig('field', {type: GraphQLString}); - expect(someClassFieldsMetadata.getFields()['field'].type).to.eql(GraphQLString); + someClassFieldsMetadata.getField('field').setType(GraphQLString); + expect(someClassFieldsMetadata.getFields()['field'].toGraphQLFieldConfig().type).to.eql(GraphQLString); }); it("sets thunkType and resolves it", () => { - someClassFieldsMetadata.patchConfig('field', {thunkType: () => GraphQLString}); - expect(someClassFieldsMetadata.getFields()['field'].type).to.eql(GraphQLString); + someClassFieldsMetadata.getField('field').setTypeThunk(() => GraphQLString); + expect(someClassFieldsMetadata.getFields()['field'].toGraphQLFieldConfig().type).to.eql(GraphQLString); }); it("wraps type with GraphQLList if list property is set to true", () => { - someClassFieldsMetadata.patchConfig('field', {type: GraphQLString, array: true}); - expect(someClassFieldsMetadata.getFields()['field'].type).to.eql(new GraphQLList(GraphQLString)); + someClassFieldsMetadata.getField('field').setListType(GraphQLString); + expect(someClassFieldsMetadata.getFields()['field'].toGraphQLFieldConfig().type).to.eql(new GraphQLList(GraphQLString)); }); it("wraps type with GraphQLNonNull if list property is set to true", () => { - someClassFieldsMetadata.patchConfig('field', {type: GraphQLString, nonNull: true}); - expect(someClassFieldsMetadata.getFields()['field'].type).to.eql(new GraphQLNonNull(GraphQLString)); + someClassFieldsMetadata.getField('field').setType(GraphQLString); + someClassFieldsMetadata.getField('field').setNonNullConstraint(); + expect(someClassFieldsMetadata.getFields()['field'].toGraphQLFieldConfig().type).to.eql(new GraphQLNonNull(GraphQLString)); }); it("wraps type with GraphQLNonNull and GraphQLList for nonNull and array properties set to true", () => { - someClassFieldsMetadata.patchConfig('field', {type: GraphQLString, nonNull: true, array: true}); - expect(someClassFieldsMetadata.getFields()['field'].type).to.eql(new GraphQLNonNull(new GraphQLList(GraphQLString))); + someClassFieldsMetadata.getField('field').setListType(GraphQLString); + someClassFieldsMetadata.getField('field').setNonNullConstraint(); + expect(someClassFieldsMetadata.getFields()['field'].toGraphQLFieldConfig().type).to.eql(new GraphQLNonNull(new GraphQLList(GraphQLString))); }); it("wraps type using GraphQLNonNull and GraphQLList for nonNull, array, nonNullItem properties set to true", () => { - someClassFieldsMetadata.patchConfig('field', { - type: GraphQLString, - nonNull: true, - array: true, - nonNullItem: true - }); - expect(someClassFieldsMetadata.getFields()['field'].type).to + let field = someClassFieldsMetadata.getField('field'); + field.setListType(GraphQLString); + field.setNonNullConstraint(); + field.setNonNullItemsConstraint(); + + + expect(someClassFieldsMetadata.getFields()['field'].toGraphQLFieldConfig().type).to .eql(new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLString)))); }); it("only pass valid GraphQLFieldConfigMap properties", () => { - someClassFieldsMetadata.patchConfig('field', {type: GraphQLString}); - expect(Object.keys(someClassFieldsMetadata.getFields()['field']).sort()).to.eql([ - "args", - "deprecationReason", - "description", - "resolve", - "type" - ]) + someClassFieldsMetadata.getField('field').setType(GraphQLString); + someClassFieldsMetadata.getField('field').setDescription('some description'); + expect(someClassFieldsMetadata.getFields()['field'].toGraphQLFieldConfig().description).to + .eql('some description'); + + // expect(Object.keys(someClassFieldsMetadata.getFields()['field']).sort()).to.eql([ + // "args", + // "deprecationReason", + // "description", + // "resolve", + // "type" + // ]) }); it("creates GraphQLType for annotated class passed as type", () => { @@ -73,8 +93,10 @@ describe("FieldsTypeMetadata", () => { @field(GraphQLString) someField:string; } - someClassFieldsMetadata.patchConfig('field', {type: SomeClass}); - expect(someClassFieldsMetadata.getFields()['field'].type).to.be.instanceOf(GraphQLObjectType) + (SomeClass as any).kurwa = "WTF"; + + someClassFieldsMetadata.getField('field').setType(SomeClass); + expect(someClassFieldsMetadata.getFields()['field'].toGraphQLFieldConfig().type).to.be.instanceOf(GraphQLObjectType) }); }); }); diff --git a/spec/metadata/InterfaceTypeMetadata.spec.ts b/spec/metadata/InterfaceTypeMetadata.spec.ts index 552dd4d..9c9ec4f 100644 --- a/spec/metadata/InterfaceTypeMetadata.spec.ts +++ b/spec/metadata/InterfaceTypeMetadata.spec.ts @@ -1,11 +1,11 @@ import {noop} from "../../lib/utils/core"; -import {InterfaceTypeMetadata} from "../../lib/metadata/InterfaceTypeMetadata"; import {expect} from 'chai'; import {GraphQLInterfaceType, GraphQLString} from "graphql"; -import {FieldsMetadata} from "../../lib/metadata/FieldsMetadata"; -import {type} from "../../lib/decorators/type"; -import {field} from "../../lib/decorators/fields"; -import {ObjectTypeMetadata} from "../../lib/metadata/ObjectTypeMetadata"; +import {field, type} from "../../lib"; +import {InterfaceTypeMetadata} from "../../lib/types-metadata/InterfaceTypeMetadata"; +import {FieldsMetadata} from "../../lib/fields-metadata/FieldsMetadata"; +import {TypeMetadata} from "../../lib/types-metadata/TypeMetadata"; + describe("InterfaceTypeMetadata", () => { describe("static getForClass", noop); @@ -20,21 +20,21 @@ describe("InterfaceTypeMetadata", () => { SomeInterface = class {}; someInterfaceMetadata = InterfaceTypeMetadata.getOrCreateForClass(SomeInterface); someInterfaceFieldsMetadata = FieldsMetadata.getOrCreateForClass(SomeInterface); - someInterfaceFieldsMetadata.patchConfig('requiredDummyField', {type: GraphQLString}); + someInterfaceFieldsMetadata.getField('requiredDummyField').setType(GraphQLString); }); it("returns GraphQLInterfaceType", () => { - expect(someInterfaceMetadata.toGraphQLType()).to.be.instanceOf(GraphQLInterfaceType); + expect(someInterfaceMetadata.toGraphQLInterfaceType()).to.be.instanceOf(GraphQLInterfaceType); }); it("it pass name property to GraphQLInterfaceType instance", () => { someInterfaceMetadata.setConfig({name: 'SomeName'}); - expect(someInterfaceMetadata.toGraphQLType().name).to.eq('SomeName'); + expect(someInterfaceMetadata.toGraphQLInterfaceType().name).to.eq('SomeName'); }); it("it pass description property to GraphQLInterfaceType instance", () => { someInterfaceMetadata.setConfig({description: 'Some description'}); - expect(someInterfaceMetadata.toGraphQLType().description).to.eq('Some description'); + expect(someInterfaceMetadata.toGraphQLInterfaceType().description).to.eq('Some description'); }); it("infers annotated types from resolveType function", () => { @@ -44,8 +44,9 @@ describe("InterfaceTypeMetadata", () => { } someInterfaceMetadata.setConfig({name: 'SomeName', resolveType: () => SomeClass}); - expect(someInterfaceMetadata.toGraphQLType().resolveType(null, null, null)).to - .eql(ObjectTypeMetadata.getForClass(SomeClass).toGraphQLType()) + expect(someInterfaceMetadata.toGraphQLInterfaceType().resolveType(null, null, null)).to + .eql(TypeMetadata.getForClass(SomeClass).toGraphQLObjectType()) }); }); -}); \ No newline at end of file +}); + diff --git a/spec/metadata/ObjectTypeMetadata.spec.ts b/spec/metadata/TypeMetadata.spec.ts similarity index 64% rename from spec/metadata/ObjectTypeMetadata.spec.ts rename to spec/metadata/TypeMetadata.spec.ts index f0696bf..a1f3b81 100644 --- a/spec/metadata/ObjectTypeMetadata.spec.ts +++ b/spec/metadata/TypeMetadata.spec.ts @@ -1,42 +1,42 @@ import {noop} from "../../lib/utils/core"; -import {ObjectTypeMetadata} from "../../lib/metadata/ObjectTypeMetadata"; + import {expect} from 'chai'; import {GraphQLInterfaceType, GraphQLObjectType, GraphQLString} from "graphql"; -import {FieldsMetadata} from "../../lib/metadata/FieldsMetadata"; -import {interfaceType} from "../../lib/decorators/interface"; -import {field} from "../../lib/decorators/fields"; -import {InterfaceTypeMetadata} from "../../lib/metadata/InterfaceTypeMetadata"; +import {FieldsMetadata} from "../../lib/fields-metadata/FieldsMetadata"; +import {field, interfaceType} from "../../lib"; +import {InterfaceTypeMetadata} from "../../lib/types-metadata/InterfaceTypeMetadata"; +import {TypeMetadata} from "../../lib/types-metadata/TypeMetadata"; -describe("ObjectTypeMetadata", () => { +describe("TypeMetadata", () => { describe("static getForClass", noop); describe("static getOrCreateForClass", noop); describe(".toGraphQLType", () => { let SomeClass, - someClassMetadata:ObjectTypeMetadata, + someClassMetadata:TypeMetadata, someClassFieldsMetadata:FieldsMetadata; beforeEach(() => { SomeClass = class {}; - someClassMetadata = ObjectTypeMetadata.getOrCreateForClass(SomeClass); + someClassMetadata = TypeMetadata.getOrCreateForClass(SomeClass); someClassMetadata.setConfig({name: 'SomeClass'}); someClassFieldsMetadata = FieldsMetadata.getOrCreateForClass(SomeClass); - someClassFieldsMetadata.patchConfig('requiredDummyField', {type: GraphQLString}); + someClassFieldsMetadata.getField('requiredDummyField').setType(GraphQLString); }); it("returns GraphQLObjectType", () => { - expect(someClassMetadata.toGraphQLType()).to.be.instanceOf(GraphQLObjectType); + expect(someClassMetadata.toGraphQLObjectType()).to.be.instanceOf(GraphQLObjectType); }); it("it pass name property to GraphQLObjectType instance", () => { someClassMetadata.setConfig({name: 'SomeName'}); - expect(someClassMetadata.toGraphQLType().name).to.eq('SomeName'); + expect(someClassMetadata.toGraphQLObjectType().name).to.eq('SomeName'); }); it("it pass description property to GraphQLObjectType instance", () => { someClassMetadata.setConfig({description: 'Some description'}); - expect(someClassMetadata.toGraphQLType().description).to.eq('Some description'); + expect(someClassMetadata.toGraphQLObjectType().description).to.eq('Some description'); }); it("pass interfaces property to GraphQLObjectType instance", () => { @@ -51,7 +51,7 @@ describe("ObjectTypeMetadata", () => { }); someClassMetadata.setConfig({name: 'SomeClass', interfaces: [SomeInterface]}); - expect(someClassMetadata.toGraphQLType().getInterfaces()).to.eql([SomeInterface]); + expect(someClassMetadata.toGraphQLObjectType().getInterfaces()).to.eql([SomeInterface]); }); it("pass annotated class in interface array ", () => { @@ -63,8 +63,8 @@ describe("ObjectTypeMetadata", () => { } someClassMetadata.setConfig({name: 'SomeClass', interfaces: [SomeInterface]}); - expect(someClassMetadata.toGraphQLType().getInterfaces()).to.eql([ - InterfaceTypeMetadata.getForClass(SomeInterface).toGraphQLType() + expect(someClassMetadata.toGraphQLObjectType().getInterfaces()).to.eql([ + InterfaceTypeMetadata.getForClass(SomeInterface).toGraphQLInterfaceType() ]); }); }); diff --git a/spec/types-conversion/TypeProxy.spec.ts b/spec/types-conversion/TypeProxy.spec.ts new file mode 100644 index 0000000..10ccdc5 --- /dev/null +++ b/spec/types-conversion/TypeProxy.spec.ts @@ -0,0 +1,90 @@ +import {GraphQLEnumType, GraphQLInt, GraphQLString} from "graphql"; +import {TypeProxy} from "../../lib/types-conversion/TypeProxy"; +import {expect} from 'chai'; +import {TypeMetadata} from "../../lib/types-metadata/TypeMetadata"; +import * as sinon from 'sinon'; +import {ParamsMetadata} from "../../lib/types-metadata/ParamsMetadata"; +import {InterfaceTypeMetadata} from "../../lib/types-metadata/InterfaceTypeMetadata"; +import {enumsRegistry} from "../../lib/registry/typesRegistry"; + +describe("TypeProxy", () => { + describe(".toGraphQLType()", () => { + describe("converting native types", () => { + describe("GraphQLString", () => { + it(`returns GraphQLString`, () => { + expect(TypeProxy.inferType(GraphQLString)).to.eq(GraphQLString); + expect(TypeProxy.inferTypeThunk(() => GraphQLString)).to.eq(GraphQLString); + }); + }); + + describe("GraphQLInt", () => { + expect(TypeProxy.inferType(GraphQLInt)).to.eq(GraphQLInt); + expect(TypeProxy.inferTypeThunk(() => GraphQLInt)).to.eq(GraphQLInt); + }); + }); + + describe("converting type decorated with TypeMetadata", () => { + let SomeClass; + + beforeEach(() => { + SomeClass = class {}; + let typeMetadata = TypeMetadata.getOrCreateForClass(SomeClass); + sinon.stub(typeMetadata, 'toGraphQLObjectType').returns(GraphQLString); + }); + + it('returns object returned by toGraphQLObjectType on TypeMetadata', () => { + expect(TypeProxy.inferType(SomeClass)).to.eq(GraphQLString); + }); + }); + + describe("converting type decorated with ParamsMetadata", () => { + let SomeClass; + + beforeEach(() => { + SomeClass = class {}; + let paramsMetadata = ParamsMetadata.getOrCreateForClass(SomeClass); + sinon.stub(paramsMetadata, 'toGraphQLInputObjectType').returns(GraphQLString); + }); + + it('returns object returned by toGraphQLInputObjectType on TypeMetadata', () => { + expect(TypeProxy.inferType(SomeClass)).to.eq(GraphQLString); + }); + }); + + describe("converting type decorated with InterfaceMetadata", () => { + let SomeClass; + + beforeEach(() => { + SomeClass = class {}; + let interfaceMetadata = InterfaceTypeMetadata.getOrCreateForClass(SomeClass); + sinon.stub(interfaceMetadata, 'toGraphQLInterfaceType').returns(GraphQLString); + }); + + it('returns object returned by toGraphQLInterfaceType on InterfaceMetadata', () => { + expect(TypeProxy.inferType(SomeClass)).to.eq(GraphQLString); + }); + }); + + describe("converting enum type", () => { + enum Enum { + A = 'a', + B = 'b' + } + + beforeEach(() => { + enumsRegistry.registerEnum('Enum', Enum, 'SomeEnumDescription'); + }); + + it('returns object returned by toGraphQLInterfaceType on InterfaceMetadata', () => { + expect(TypeProxy.inferType(Enum)).to.eql(new GraphQLEnumType({ + name: 'Enum', + description: 'SomeEnumDescription', + values: { + A: {value: 'a'}, + B: {value: 'b'} + } + })); + }); + }); + }); +}); \ No newline at end of file diff --git a/spec/types-conversion/TypeWrapper.spec.ts b/spec/types-conversion/TypeWrapper.spec.ts new file mode 100644 index 0000000..c4ff9b5 --- /dev/null +++ b/spec/types-conversion/TypeWrapper.spec.ts @@ -0,0 +1,51 @@ +import {TypeWrapper} from "../../lib/types-conversion/TypeWrapper"; +import {GraphQLList, GraphQLNonNull, GraphQLString} from "graphql"; +import {expect} from 'chai'; + +describe("TypeWrapper", () => { + let typeWrapper:TypeWrapper; + + beforeEach(() => { + typeWrapper = new TypeWrapper(); + }); + + describe("wrapping with list type", () => { + it('wraps with GraphQLList type', () => { + typeWrapper.setArray(); + expect(typeWrapper.wrap(GraphQLString)).to.eql(new GraphQLList(GraphQLString)) + }); + }); + + describe("wrapping with nonNull", () => { + it('wraps with GraphQLNonNull type', () => { + typeWrapper.setNonNullConstraint(); + expect(typeWrapper.wrap(GraphQLString)).to.eql(new GraphQLNonNull(GraphQLString)) + }); + }); + + describe("wrapping with list and nonNull ", () => { + it('wraps with GraphQLNonNull type', () => { + typeWrapper.setArray(); + typeWrapper.setNonNullConstraint(); + + expect(typeWrapper.wrap(GraphQLString)).to.eql(new GraphQLNonNull(new GraphQLList(GraphQLString))); + }); + }); + + describe("wrapping with list, nonNull and nonNullItems", () => { + it('wraps with GraphQLNonNull type', () => { + typeWrapper.setArray(); + typeWrapper.setNonNullConstraint(); + typeWrapper.setNonNullItemsConstraint(); + + expect(typeWrapper.wrap(GraphQLString)).to.eql(new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLString)))); + }); + }); + + describe("wrapping with nonNullItems", () => { + it('throws error', () => { + typeWrapper.setNonNullItemsConstraint(); + expect(() => typeWrapper.wrap(GraphQLString)).to.throw() + }); + }); +}); \ No newline at end of file diff --git a/yarn-error.log b/yarn-error.log new file mode 100644 index 0000000..701519b --- /dev/null +++ b/yarn-error.log @@ -0,0 +1,1842 @@ +Arguments: + /Users/robak/.nvm/versions/node/v8.9.1/bin/node /Users/robak/.nvm/versions/node/v8.9.1/bin/yarn install + +PATH: + /Users/robak/.nvm/versions/node/v8.9.1/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + +Yarn version: + 1.3.2 + +Node version: + 8.9.1 + +Platform: + darwin x64 + +npm manifest: + { + "name": "gql-schema", + "version": "0.0.1", + "description": "Yet another experimental library for defining graphql schemas using decorators.", + "repository": "https://github.com/robak86/gql-schema", + "main": "lib/index.js", + "scripts": { + "test": "mocha --require dist/spec/SpecHelper.js dist/spec/**/*.spec.js", + "build:clean": "rm -rf ./dist && mkdir -p dist/lib", + "build:copy": "cp package.json ./dist/lib/ && cp README.md ./dist/lib/", + "build:compile": "tsc", + "build:dist": "npm run build:clean && npm run build:copy && npm run build:compile", + "build:watch": "npm run build:clean && npm run build:copy && tsc --watch --sourceMap", + "build:coverage": "nyc --reporter=text-lcov mocha -- -- spec dist/spec/**/*.spec.js | coveralls" + }, + "author": "Tomasz Robaczewski", + "license": "MIT", + "devDependencies": { + "@types/chai": "^4.0.0", + "@types/graphql": "^0.9.1", + "@types/lodash": "^4.14.65", + "@types/mocha": "^2.2.41", + "chai": "^4.0.2", + "coveralls": "^2.13.1", + "mocha": "^3.4.2", + "nyc": "^11.0.3", + "reflect-metadata": "^0.1.10", + "source-map-support": "^0.4.15", + "typescript": "^2.4.2" + }, + "dependencies": { + "graphql": "^0.10.5", + "lodash": "^4.17.4" + } + } + +yarn manifest: + No manifest + +Lockfile: + # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. + # yarn lockfile v1 + + + "@types/chai@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.0.tgz#4c9adabd2d04265769e6d9e847e86cc404dc7dcd" + + "@types/graphql@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.1.tgz#b04ebe84bc997cc60dbea2ed4d0d4342c737f99d" + + "@types/lodash@^4.14.65": + version "4.14.65" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.65.tgz#a0f78d71ffcd3c02628d5f616410c98c424326d5" + + "@types/mocha@^2.2.41": + version "2.2.41" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608" + + align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + + amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + + ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + + ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + + ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + + append-transform@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" + dependencies: + default-require-extensions "^1.0.0" + + archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + + argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + + arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + + arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + + array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + + arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + + asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + + assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + + assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + + assertion-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" + + async@^1.4.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + + asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + + aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + + aws4@^1.2.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + + babel-code-frame@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" + dependencies: + chalk "^1.1.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + + babel-generator@^6.18.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.25.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.2.0" + source-map "^0.5.0" + trim-right "^1.0.1" + + babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + + babel-runtime@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.10.0" + + babel-template@^6.16.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.25.0" + babel-types "^6.25.0" + babylon "^6.17.2" + lodash "^4.2.0" + + babel-traverse@^6.18.0, babel-traverse@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1" + dependencies: + babel-code-frame "^6.22.0" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.25.0" + babylon "^6.17.2" + debug "^2.2.0" + globals "^9.0.0" + invariant "^2.2.0" + lodash "^4.2.0" + + babel-types@^6.18.0, babel-types@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e" + dependencies: + babel-runtime "^6.22.0" + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^1.0.1" + + babylon@^6.17.2, babylon@^6.17.4: + version "6.17.4" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a" + + balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + + bcrypt-pbkdf@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + dependencies: + tweetnacl "^0.14.3" + + boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + + brace-expansion@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + + braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + + browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + + builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + + caching-transform@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" + dependencies: + md5-hex "^1.2.0" + mkdirp "^0.5.1" + write-file-atomic "^1.1.4" + + camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + + camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + + camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + + caseless@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" + + center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + + chai@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.0.2.tgz#2f7327c4de6f385dd7787999e2ab02697a32b83b" + dependencies: + assertion-error "^1.0.1" + check-error "^1.0.1" + deep-eql "^2.0.1" + get-func-name "^2.0.0" + pathval "^1.0.0" + type-detect "^4.0.0" + + chalk@^1.1.0, chalk@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + + check-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + + cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + + cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + + code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + + combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + + commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + + commander@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + + commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + + concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + + convert-source-map@^1.3.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" + + core-js@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" + + coveralls@^2.13.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.13.1.tgz#d70bb9acc1835ec4f063ff9dac5423c17b11f178" + dependencies: + js-yaml "3.6.1" + lcov-parse "0.0.10" + log-driver "1.2.5" + minimist "1.2.0" + request "2.79.0" + + cross-spawn@^4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + + cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + + cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + + dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + + debug-log@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" + + debug@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b" + dependencies: + ms "0.7.2" + + debug@^2.2.0, debug@^2.6.3: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + dependencies: + ms "2.0.0" + + decamelize@^1.0.0, decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + + deep-eql@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-2.0.2.tgz#b1bac06e56f0a76777686d50c9feb75c2ed7679a" + dependencies: + type-detect "^3.0.0" + + default-require-extensions@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" + dependencies: + strip-bom "^2.0.0" + + delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + + detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + + diff@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + + ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + + error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + + escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + + esprima@^2.6.0: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + + esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + + execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + + expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + + expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + + extend@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + + extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + + extsprintf@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" + + filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + + fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + + find-cache-dir@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + dependencies: + commondir "^1.0.1" + mkdirp "^0.5.1" + pkg-dir "^1.0.0" + + find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + + find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + + for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + + for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + + foreground-child@^1.5.3, foreground-child@^1.5.6: + version "1.5.6" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" + dependencies: + cross-spawn "^4" + signal-exit "^3.0.0" + + forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + + form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + + fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + + generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + + generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + + get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + + get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + + get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + + getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + + glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + + glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + + glob@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + + glob@^7.0.5, glob@^7.0.6: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + + globals@^9.0.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + + graceful-fs@^4.1.11, graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + + "graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + + graphql@^0.10.5: + version "0.10.5" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.5.tgz#c9be17ca2bdfdbd134077ffd9bbaa48b8becd298" + dependencies: + iterall "^1.1.0" + + growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + + handlebars@^4.0.3: + version "4.0.10" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" + dependencies: + async "^1.4.0" + optimist "^0.6.1" + source-map "^0.4.4" + optionalDependencies: + uglify-js "^2.6" + + har-validator@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" + dependencies: + chalk "^1.1.1" + commander "^2.9.0" + is-my-json-valid "^2.12.4" + pinkie-promise "^2.0.0" + + has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + + has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + + hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + + hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + + hosted-git-info@^2.1.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" + + http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + + imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + + inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + + inherits@2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + + invariant@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + + invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + + is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + + is-buffer@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" + + is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + + is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + + is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + + is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + + is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + + is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + + is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + + is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + + is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + + is-my-json-valid@^2.12.4: + version "2.16.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + + is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + + is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + + is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + + is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + + is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + + is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + + is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + + is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + + isarray@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + + isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + + isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + + isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + + istanbul-lib-coverage@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" + + istanbul-lib-hook@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz#dd6607f03076578fe7d6f2a630cf143b49bacddc" + dependencies: + append-transform "^0.4.0" + + istanbul-lib-instrument@^1.7.3: + version "1.7.4" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.4.tgz#e9fd920e4767f3d19edc765e2d6b3f5ccbd0eea8" + dependencies: + babel-generator "^6.18.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + babylon "^6.17.4" + istanbul-lib-coverage "^1.1.1" + semver "^5.3.0" + + istanbul-lib-report@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#f0e55f56655ffa34222080b7a0cd4760e1405fc9" + dependencies: + istanbul-lib-coverage "^1.1.1" + mkdirp "^0.5.1" + path-parse "^1.0.5" + supports-color "^3.1.2" + + istanbul-lib-source-maps@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz#a6fe1acba8ce08eebc638e572e294d267008aa0c" + dependencies: + debug "^2.6.3" + istanbul-lib-coverage "^1.1.1" + mkdirp "^0.5.1" + rimraf "^2.6.1" + source-map "^0.5.3" + + istanbul-reports@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.1.tgz#042be5c89e175bc3f86523caab29c014e77fee4e" + dependencies: + handlebars "^4.0.3" + + iterall@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.1.tgz#f7f0af11e9a04ec6426260f5019d9fcca4d50214" + + js-tokens@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + + js-yaml@3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" + dependencies: + argparse "^1.0.7" + esprima "^2.6.0" + + jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + + jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + + json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + + json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + + json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + + jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + + jsprim@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918" + dependencies: + assert-plus "1.0.0" + extsprintf "1.0.2" + json-schema "0.2.3" + verror "1.3.6" + + kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + + kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + + lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + + lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + + lcov-parse@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" + + load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + + load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + + locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + + lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + + lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + + lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + + lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + + lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + + lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + + lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + + lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + + lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + + lodash@^4.17.4, lodash@^4.2.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + + log-driver@1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" + + longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + + loose-envify@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + + lru-cache@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + + md5-hex@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" + dependencies: + md5-o-matic "^0.1.1" + + md5-o-matic@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" + + mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + + merge-source-map@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" + dependencies: + source-map "^0.5.6" + + micromatch@^2.3.11: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + + mime-db@~1.29.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878" + + mime-types@^2.1.12, mime-types@~2.1.7: + version "2.1.16" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.16.tgz#2b858a52e5ecd516db897ac2be87487830698e23" + dependencies: + mime-db "~1.29.0" + + mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + + minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + + minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + + minimist@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + + minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + + mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + + mocha@^3.4.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.4.2.tgz#d0ef4d332126dbf18d0d640c9b382dd48be97594" + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.6.0" + diff "3.2.0" + escape-string-regexp "1.0.5" + glob "7.1.1" + growl "1.9.2" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + + ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + + ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + + normalize-package-data@^2.3.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + + normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + + npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + + number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + + nyc@^11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.0.3.tgz#0c28bc669a851621709bf7a08503034bee3812b6" + dependencies: + archy "^1.0.0" + arrify "^1.0.1" + caching-transform "^1.0.0" + convert-source-map "^1.3.0" + debug-log "^1.0.1" + default-require-extensions "^1.0.0" + find-cache-dir "^0.1.1" + find-up "^2.1.0" + foreground-child "^1.5.3" + glob "^7.0.6" + istanbul-lib-coverage "^1.1.1" + istanbul-lib-hook "^1.0.7" + istanbul-lib-instrument "^1.7.3" + istanbul-lib-report "^1.1.1" + istanbul-lib-source-maps "^1.2.1" + istanbul-reports "^1.1.1" + md5-hex "^1.2.0" + merge-source-map "^1.0.2" + micromatch "^2.3.11" + mkdirp "^0.5.0" + resolve-from "^2.0.0" + rimraf "^2.5.4" + signal-exit "^3.0.1" + spawn-wrap "^1.3.7" + test-exclude "^4.1.1" + yargs "^8.0.1" + yargs-parser "^5.0.0" + + oauth-sign@~0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + + object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + + object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + + once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + + optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + + os-homedir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + + os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + + p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + + p-limit@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" + + p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + + parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + + parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + + path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + + path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + + path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + + path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + + path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + + path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + + path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + + pathval@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" + + pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + + pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + + pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + + pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + + preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + + pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + + punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + + qs@~6.3.0: + version "6.3.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" + + randomatic@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + + read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + + read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + + read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + + read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + + reflect-metadata@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.10.tgz#b4f83704416acad89988c9b15635d47e03b9344a" + + regenerator-runtime@^0.10.0: + version "0.10.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" + + regex-cache@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" + dependencies: + is-equal-shallow "^0.1.3" + is-primitive "^2.0.0" + + remove-trailing-separator@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz#69b062d978727ad14dc6b56ba4ab772fd8d70511" + + repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + + repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + + repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + + request@2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + + require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + + require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + + resolve-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + + right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + + rimraf@^2.3.3, rimraf@^2.5.4, rimraf@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" + dependencies: + glob "^7.0.5" + + "semver@2 || 3 || 4 || 5", semver@^5.3.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + + set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + + shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + + shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + + signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + + slide@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + + sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + + source-map-support@^0.4.15: + version "0.4.15" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" + dependencies: + source-map "^0.5.6" + + source-map@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + + source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + + spawn-wrap@^1.3.7: + version "1.3.8" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.8.tgz#fa2a79b990cbb0bb0018dca6748d88367b19ec31" + dependencies: + foreground-child "^1.5.6" + mkdirp "^0.5.0" + os-homedir "^1.0.1" + rimraf "^2.3.3" + signal-exit "^3.0.2" + which "^1.2.4" + + spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + + spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + + spdx-license-ids@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" + + sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + + sshpk@^1.7.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + + string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + + string-width@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + + stringstream@~0.0.4: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + + strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + + strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + + strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + + strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + + strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + + supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + dependencies: + has-flag "^1.0.0" + + supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + + supports-color@^3.1.2: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + + test-exclude@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" + dependencies: + arrify "^1.0.1" + micromatch "^2.3.11" + object-assign "^4.1.0" + read-pkg-up "^1.0.1" + require-main-filename "^1.0.1" + + to-fast-properties@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + + tough-cookie@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" + dependencies: + punycode "^1.4.1" + + trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + + tunnel-agent@~0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + + tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + + type-detect@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-3.0.0.tgz#46d0cc8553abb7b13a352b0d6dea2fd58f2d9b55" + + type-detect@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea" + + typescript@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.2.tgz#f8395f85d459276067c988aa41837a8f82870844" + + uglify-js@^2.6: + version "2.8.29" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + + uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + + uuid@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" + + validate-npm-package-license@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" + + verror@1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" + dependencies: + extsprintf "1.0.2" + + which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + + which@^1.2.4, which@^1.2.9: + version "1.2.14" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" + dependencies: + isexe "^2.0.0" + + window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + + wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + + wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + + wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + + wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + + write-file-atomic@^1.1.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + + xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + + y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + + yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + + yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + dependencies: + camelcase "^3.0.0" + + yargs-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" + dependencies: + camelcase "^4.1.0" + + yargs@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0" + + yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" + +Trace: + Error: getaddrinfo ENOTFOUND registry.yarnpkg.com registry.yarnpkg.com:443 + at errnoException (dns.js:50:10) + at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26) diff --git a/yarn.lock b/yarn.lock index 1011f27..b05f2b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,21 +3,25 @@ "@types/chai@^4.0.0": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.5.tgz#b6e250e281b47e0192e236619e9b1afe62fd345c" + version "4.0.10" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.10.tgz#0eb222c7353adde8e0980bea04165d4d3b6afef3" -"@types/graphql@^0.11.6": - version "0.11.6" - resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.11.6.tgz#5063e6f7adb66f746a5c73d1ddb3ed3d1361f0a1" +"@types/graphql@^0.11.7": + version "0.11.7" + resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.11.7.tgz#da39a2f7c74e793e32e2bb7b3b68da1691532dd5" "@types/lodash@^4.14.65": - version "4.14.85" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.85.tgz#a16fbf942422f6eca5622b6910492c496c35069b" + version "4.14.91" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.91.tgz#794611b28056d16b5436059c6d800b39d573cd3a" "@types/mocha@^2.2.41": version "2.2.44" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.44.tgz#1d4a798e53f35212fd5ad4d04050620171cd5b5e" +"@types/sinon@^4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.1.2.tgz#9085db9cc3288b0f12daceee20a26c4afd9c2dcd" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -303,8 +307,8 @@ commander@2.9.0: graceful-readlink ">= 1.0.0" commander@^2.9.0: - version "2.12.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.1.tgz#468635c4168d06145b9323356d1da84d14ac4a7a" + version "2.12.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" commondir@^1.0.1: version "1.0.1" @@ -319,8 +323,8 @@ convert-source-map@^1.3.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" core-js@^2.4.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" + version "2.5.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" core-util-is@1.0.2: version "1.0.2" @@ -415,6 +419,10 @@ diff@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" +diff@^3.1.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" + ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" @@ -473,10 +481,14 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" -extsprintf@1.3.0, extsprintf@^1.2.0: +extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -541,6 +553,12 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" +formatio@1.2.0, formatio@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb" + dependencies: + samsam "1.x" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -620,9 +638,9 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2: version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" -graphql@^0.11.7: - version "0.11.7" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.7.tgz#e5abaa9cb7b7cccb84e9f0836bf4370d268750c6" +graphql@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.12.0.tgz#a62576995f67f7a94a02f3e57e91d752bae70055" dependencies: iterall "1.1.3" @@ -659,6 +677,10 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" @@ -812,6 +834,10 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + isarray@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -925,6 +951,10 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +just-extend@^1.1.26: + version "1.1.27" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" + kind-of@^3.0.2: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -999,6 +1029,10 @@ lodash.create@3.1.1: lodash._basecreate "^3.0.0" lodash._isiterateecall "^3.0.0" +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -1023,6 +1057,14 @@ log-driver@1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" +lolex@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" + +lolex@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.1.tgz#3d2319894471ea0950ef64692ead2a5318cff362" + longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" @@ -1139,6 +1181,16 @@ ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" +nise@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.2.0.tgz#079d6cadbbcb12ba30e38f1c999f36ad4d6baa53" + dependencies: + formatio "^1.2.0" + just-extend "^1.1.26" + lolex "^1.6.0" + path-to-regexp "^1.7.0" + text-encoding "^0.6.4" + normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" @@ -1287,6 +1339,12 @@ path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -1362,8 +1420,8 @@ reflect-metadata@^0.1.10: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.10.tgz#b4f83704416acad89988c9b15635d47e03b9344a" regenerator-runtime@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1" + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" regex-cache@^0.4.2: version "0.4.4" @@ -1438,6 +1496,10 @@ rimraf@^2.3.3, rimraf@^2.5.4, rimraf@^2.6.1: dependencies: glob "^7.0.5" +samsam@1.x: + version "1.3.0" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" + "semver@2 || 3 || 4 || 5", semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -1460,6 +1522,18 @@ signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" +sinon@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.1.3.tgz#fc599eda47ed9f1a694ce774b94ab44260bd7ac5" + dependencies: + diff "^3.1.0" + formatio "1.2.0" + lodash.get "^4.4.2" + lolex "^2.2.0" + nise "^1.2.0" + supports-color "^4.4.0" + type-detect "^4.0.5" + slide@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -1586,6 +1660,12 @@ supports-color@^3.1.2: dependencies: has-flag "^1.0.0" +supports-color@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + test-exclude@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" @@ -1596,6 +1676,10 @@ test-exclude@^4.1.1: read-pkg-up "^1.0.1" require-main-filename "^1.0.1" +text-encoding@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -1618,13 +1702,13 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" -type-detect@^4.0.0: +type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.5.tgz#d70e5bc81db6de2a381bcaca0c6e0cbdc7635de2" typescript@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.1.tgz#ef39cdea27abac0b500242d6726ab90e0c846631" + version "2.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" uglify-js@^2.6: version "2.8.29"