-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[WIP] Rewrite internals + simplify decorators api
- Loading branch information
Showing
44 changed files
with
813 additions
and
569 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,52 @@ | ||
import {FieldConfig, FieldsMetadata} from "../metadata/FieldsMetadata"; | ||
import {invariant} from "../utils/core"; | ||
import * as _ from 'lodash'; | ||
import {GraphQLID} from "graphql"; | ||
import {GraphQLFieldResolver, GraphQLID} from "graphql"; | ||
import {ArgsType, FieldType} from "./typesInferention"; | ||
import {FieldsMetadata} from "../metadata/FieldsMetadata"; | ||
import {FieldConfig} from "../metadata/FieldConfig"; | ||
|
||
|
||
function patchField(target, propertyKey, partialConfig:Partial<FieldConfig>) { | ||
let fieldsMetadata:FieldsMetadata = FieldsMetadata.getOrCreateForClass(target.constructor); | ||
fieldsMetadata.patchConfig(propertyKey, partialConfig); | ||
function createDecorator(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}`) | ||
} | ||
} | ||
} | ||
|
||
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 id = ():PropertyDecorator => createDecorator(fieldConfig => fieldConfig.setType(GraphQLID)); | ||
|
||
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 field = (type:FieldType):PropertyDecorator => createDecorator(fieldConfig => { | ||
fieldConfig.setType(type); | ||
}); | ||
|
||
export const nonNull = ():PropertyDecorator => { | ||
return (target:Object, propertyKey:string) => patchField(target, propertyKey, {nonNull: true}) | ||
}; | ||
export const fieldThunk = (thunkType:() => (FieldType)):PropertyDecorator => createDecorator(fieldConfig => { | ||
fieldConfig.setTypeThunk(thunkType); | ||
}); | ||
|
||
export const nonNullItems = ():PropertyDecorator => { | ||
return (target:Object, propertyKey:string) => patchField(target, propertyKey, {nonNullItem: true}) | ||
}; | ||
export const nonNull = ():PropertyDecorator => createDecorator(fieldConfig => { | ||
fieldConfig.setNonNullConstraint() | ||
}); | ||
|
||
export const description = (description:string):PropertyDecorator => { | ||
return (target:Object, propertyKey:string) => patchField(target, propertyKey, {description}) | ||
}; | ||
export const nonNullItems = ():PropertyDecorator => createDecorator(fieldConfig => { | ||
fieldConfig.setNonNullItemsConstraint() | ||
}); | ||
export const description = (description:string):PropertyDecorator => createDecorator(fieldConfig => { | ||
fieldConfig.setDescription(description) | ||
}); | ||
|
||
export const args = (argsType:ArgsType):PropertyDecorator => { | ||
return (target:Object, propertyKey:string) => patchField(target, propertyKey, {args: argsType}) | ||
}; | ||
export const params = (argsType:ArgsType):PropertyDecorator => createDecorator(fieldConfig => { | ||
fieldConfig.setParamsType(argsType) | ||
}); | ||
|
||
export const resolve = (resolve:Function):PropertyDecorator => { | ||
return (target:Object, propertyKey:string) => patchField(target, propertyKey, {resolve}) | ||
}; | ||
export const resolve = <T>(resolve:GraphQLFieldResolver<any, any>):PropertyDecorator => createDecorator(fieldConfig => { | ||
fieldConfig.setResolver(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 list = (type:FieldType):PropertyDecorator => createDecorator(fieldConfig => { | ||
fieldConfig.setListType(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 | ||
}) | ||
} | ||
}; | ||
export const listThunk = (thunkType:() => FieldType):PropertyDecorator => createDecorator(fieldConfig => { | ||
fieldConfig.setListTypeThunk(thunkType) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
import {ObjectTypeMetadata, TypeConfig} from "../metadata/ObjectTypeMetadata"; | ||
import {TypeMetadata} from "../metadata/TypeMetadata"; | ||
import {TypeConfigParams} from "../metadata/TypeConfig"; | ||
|
||
export const type = (config:TypeConfig<any, any> = {}):ClassDecorator => { | ||
export const type = (config:TypeConfigParams<any, any> = {}):ClassDecorator => { | ||
return <TFunction extends Function>(klass:TFunction):TFunction => { | ||
let objectTypeMetadata = ObjectTypeMetadata.getOrCreateForClass(klass); | ||
let objectTypeMetadata = TypeMetadata.getOrCreateForClass(klass); | ||
objectTypeMetadata.setConfig(config); | ||
|
||
return klass; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,35 @@ | ||
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"; | ||
import {GraphQLFieldConfigArgumentMap, GraphQLType} from "graphql"; | ||
|
||
export type ArgsType = | ||
GraphQLInputObjectType | | ||
GraphQLFieldConfigArgumentMap | | ||
Type<any> | ||
|
||
export type FieldType = | ||
GraphQLType | | ||
Type<any> | | ||
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)}`) | ||
} | ||
// 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)}`) | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 "../metadata/TypeProxy"; | ||
|
||
|
||
export function createUnion(name:string, types:Thunk<Array<GraphQLObjectType|Function>>, resolveType):GraphQLUnionType { | ||
//TODO: rename to - unionType | ||
export function createUnion(name:string, types:Thunk<Array<GraphQLObjectType | Function>>, 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 | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import {GraphQLType} from "graphql"; | ||
import {TypeConfig, TypeConfigParams} from "./TypeConfig"; | ||
import {FieldConfig} from "./FieldConfig"; | ||
|
||
export abstract class AbstractMetadata<T extends FieldConfig = FieldConfig> { | ||
protected config:TypeConfig = new TypeConfig(); | ||
|
||
constructor(protected klass) { | ||
this.config.setName(this.klass.name); | ||
} | ||
|
||
setConfig(config:TypeConfigParams<any, any>) { | ||
this.config.setConfig(config); | ||
} | ||
|
||
abstract toGraphQLType():GraphQLType | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import {GraphQLFieldConfigArgumentMap, GraphQLType, Thunk} from "graphql"; | ||
import {FieldType} from "../decorators/typesInferention"; | ||
import * as _ from "lodash"; | ||
import {getMetadata} from "../utils/metadata"; | ||
import {resolveThunk} from "../utils/graphql"; | ||
import {ParamsMetadata} from "./ParamsMetadata"; | ||
|
||
export class ArgumentsTypeProxy { | ||
private _type:FieldType; | ||
private _typeThunk:Thunk<FieldType>; | ||
|
||
setType(type:FieldType) { | ||
this._type = type; | ||
} | ||
|
||
setTypeThunk(typeThunk:Thunk<FieldType>) { | ||
this._typeThunk = typeThunk; | ||
} | ||
|
||
toGraphQLType():GraphQLFieldConfigArgumentMap { | ||
let type:GraphQLType = (this._type || resolveThunk(this._typeThunk)) as GraphQLType; | ||
|
||
if (_.isFunction(type)) { | ||
let metadata = getMetadata(type as any) as ParamsMetadata; | ||
return metadata.toGraphQLArgumentMap(); | ||
} | ||
|
||
throw new Error(`Cannot infer type for ${JSON.stringify(type)}`) | ||
} | ||
} |
Oops, something went wrong.