Skip to content

Commit

Permalink
fix: small flowtype definition improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
nodkz committed Feb 13, 2018
1 parent 5abdb88 commit a34f04e
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 46 deletions.
55 changes: 36 additions & 19 deletions src/resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import type {
import { typeByPath } from './typeByPath';
import type { ProjectionType } from './projection';
import type { GenericMap } from './utils/definitions';
import type { InputTypeComposer } from './inputTypeComposer';
import type { InputTypeComposer, ComposeInputFieldConfig } from './inputTypeComposer';
import type { EnumTypeComposer } from './enumTypeComposer';
import type { SchemaComposer } from './schemaComposer';

Expand Down Expand Up @@ -64,19 +64,27 @@ export type ResolverFilterArgConfig<TSource, TContext> = {
filterTypeNameFallback?: string,
};

export type ResolverSortArgFn = (resolveParams: ResolveParams<any, any>) => mixed;
export type ResolverSortArgFn<TSource, TContext> = (
resolveParams: ResolveParams<TSource, TContext>
) => mixed;

export type ResolverSortArgConfig = {
export type ResolverSortArgConfig<TSource, TContext> = {
name: string,
sortTypeNameFallback?: string,
// value also can be an `Object`, but flow does not understande union with object and function
// see https://github.com/facebook/flow/issues/1948
value: ResolverSortArgFn | string | number | boolean | Array<any> | GenericMap<any>,
value:
| ResolverSortArgFn<TSource, TContext>
| string
| number
| boolean
| Array<any>
| GenericMap<any>,
deprecationReason?: ?string,
description?: ?string,
};

export type ResolverOpts<TSource, TContext> = {
export type ResolverOpts<TSource, TContext> = {|
type?: ComposeOutputType<TContext>,
resolve?: ResolverRpCb<TSource, TContext>,
args?: ComposeFieldConfigArgumentMap,
Expand All @@ -85,7 +93,7 @@ export type ResolverOpts<TSource, TContext> = {
kind?: ResolverKinds,
description?: string,
parent?: Resolver<TSource, TContext>,
};
|};

export type ResolverWrapCb<TSource, TContext> = (
newResolver: Resolver<TSource, TContext>,
Expand All @@ -103,17 +111,20 @@ export type ResolverWrapArgsCb = (
prevArgs: GraphQLFieldConfigArgumentMap
) => ComposeFieldConfigArgumentMap;

export type ResolverWrapTypeCb = (prevType: GraphQLOutputType) => ComposeOutputType<any>;
export type ResolverWrapTypeCb<TContext> = (
prevType: GraphQLOutputType
) => ComposeOutputType<TContext>;

export type ResolveDebugOpts = {
showHidden?: boolean,
depth?: number,
colors?: boolean,
};

export class Resolver<TSource = any, TContext = any> {
export class Resolver<TSource, TContext> {
static schemaComposer: SchemaComposer<TContext>;

/* :: context: TContext */
type: GraphQLOutputType;
args: GraphQLFieldConfigArgumentMap;
resolve: ResolverRpCb<TSource, TContext>;
Expand Down Expand Up @@ -340,7 +351,7 @@ export class Resolver<TSource = any, TContext = any> {
/* eslint-disable */
resolve(
resolveParams: ResolveParams<TSource, TContext> | $Shape<ResolveParams<TSource, TContext>>
): Promise<any> {
): Promise<mixed> {
return Promise.resolve();
}
/* eslint-enable */
Expand Down Expand Up @@ -435,23 +446,26 @@ export class Resolver<TSource = any, TContext = any> {
return typeByPath(this, path);
}

clone(opts: ResolverOpts<TSource, TContext> = {}): Resolver<TSource, TContext> {
clone(opts: $Shape<ResolverOpts<TSource, TContext>> = {}): Resolver<TSource, TContext> {
const oldOpts = {};

const self: any = this;
const self: Resolver<TSource, TContext> = this;
for (const key in self) {
if (self.hasOwnProperty(key)) {
// $FlowFixMe
oldOpts[key] = self[key];
}
}
oldOpts.displayName = undefined;
oldOpts.args = { ...this.args };
return new this.constructor.schemaComposer.Resolver({ ...oldOpts, ...opts });
oldOpts.args = ({ ...this.args }: GraphQLFieldConfigArgumentMap);
return new this.constructor.schemaComposer.Resolver(
(({ ...oldOpts, ...opts }: any): ResolverOpts<TSource, TContext>)
);
}

wrap(
cb: ?ResolverWrapCb<TSource, TContext>,
newResolverOpts: ?ResolverOpts<TSource, TContext> = {}
newResolverOpts: ?$Shape<ResolverOpts<TSource, TContext>> = {}
): Resolver<TSource, TContext> {
const prevResolver: Resolver<TSource, TContext> = this;
const newResolver = this.clone({
Expand Down Expand Up @@ -501,7 +515,10 @@ export class Resolver<TSource = any, TContext = any> {
});
}

wrapType(cb: ResolverWrapTypeCb, wrapperName: string = 'wrapType'): Resolver<TSource, TContext> {
wrapType(
cb: ResolverWrapTypeCb<TContext>,
wrapperName: string = 'wrapType'
): Resolver<TSource, TContext> {
return this.wrap(
(newResolver, prevResolver) => {
const prevType = prevResolver.getType();
Expand Down Expand Up @@ -561,9 +578,9 @@ export class Resolver<TSource = any, TContext = any> {

filterITC.setField(
opts.name,
({
(({
...only(opts, ['name', 'type', 'defaultValue', 'description']),
}: any)
}: any): ComposeInputFieldConfig)
);

const resolveNext = resolver.getResolve();
Expand All @@ -584,7 +601,7 @@ export class Resolver<TSource = any, TContext = any> {
return resolver;
}

addSortArg(opts: ResolverSortArgConfig): Resolver<TSource, TContext> {
addSortArg(opts: ResolverSortArgConfig<TSource, TContext>): Resolver<TSource, TContext> {
if (!opts.name) {
throw new Error('For Resolver.addSortArg the `opts.name` is required.');
}
Expand Down Expand Up @@ -683,7 +700,7 @@ export class Resolver<TSource = any, TContext = any> {
return util.inspect(this.toDebugStructure(false), { depth: 20, colors }).replace(/\\n/g, '\n');
}

setDisplayName(name: string): this {
setDisplayName(name: string): Resolver<TSource, TContext> {
this.displayName = name;
return this;
}
Expand Down
2 changes: 1 addition & 1 deletion src/schemaComposer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { InputTypeComposer as _InputTypeComposer } from './inputTypeComposer';
import { EnumTypeComposer as _EnumTypeComposer } from './enumTypeComposer';
import { Resolver as _Resolver } from './resolver';

export class SchemaComposer<TContext = any> extends TypeStorage<
export class SchemaComposer<TContext> extends TypeStorage<
_TypeComposer<TContext> | _InputTypeComposer | GraphQLNamedType
> {
typeMapper: TypeMapper<TContext>;
Expand Down
34 changes: 19 additions & 15 deletions src/typeComposer.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ import type { SchemaComposer } from './schemaComposer';

export type GetRecordIdFn<TSource, TContext> = (
source: TSource,
args: ?mixed,
context: TContext
args?: ?mixed,
context?: TContext
) => string;

export type GraphQLObjectTypeExtended = GraphQLObjectType & {
export type GraphQLObjectTypeExtended<TSource, TContext> = GraphQLObjectType & {
_gqcInputTypeComposer?: InputTypeComposer,
_gqcResolvers?: Map<string, Resolver<any, any>>,
_gqcGetRecordIdFn?: GetRecordIdFn<any, any>,
_gqcRelations?: RelationThunkMap<any, any>,
_gqcResolvers?: Map<string, Resolver<TSource, TContext>>,
_gqcGetRecordIdFn?: GetRecordIdFn<TSource, TContext>,
_gqcRelations?: RelationThunkMap<TSource, TContext>,
description?: ?string,
};

Expand Down Expand Up @@ -149,8 +149,8 @@ export type RelationArgsMapper<TSource, TContext> = {
| GenericMap<any>,
};

export class TypeComposer<TContext = any> {
gqType: GraphQLObjectTypeExtended;
export class TypeComposer<TContext> {
gqType: GraphQLObjectTypeExtended<any, TContext>;
_fields: GraphQLFieldConfigMap<any, TContext>;
static schemaComposer: SchemaComposer<TContext>;

Expand Down Expand Up @@ -232,7 +232,7 @@ export class TypeComposer<TContext = any> {
*/
getFields(): ObjMap<any> {
if (!this._fields) {
const fields: Thunk<GraphQLFieldConfigMap<any, any>> = this.gqType._typeConfig.fields;
const fields: Thunk<GraphQLFieldConfigMap<any, TContext>> = this.gqType._typeConfig.fields;
this._fields = resolveMaybeThunk(fields) || {};
}

Expand All @@ -258,11 +258,11 @@ export class TypeComposer<TContext = any> {

this._fields = prepearedFields;
this.gqType._typeConfig.fields = () =>
resolveOutputConfigsAsThunk(
(resolveOutputConfigsAsThunk(
this.constructor.schemaComposer,
prepearedFields,
this.getTypeName()
);
): any);
delete this.gqType._fields; // clear builded fields in type
return this;
}
Expand Down Expand Up @@ -592,7 +592,7 @@ export class TypeComposer<TContext = any> {
// no problem, clone without resolveIdFn
}
this.getResolvers().forEach(resolver => {
const newResolver = resolver.clone(cloned);
const newResolver = resolver.clone();
cloned.addResolver(newResolver);
});

Expand Down Expand Up @@ -713,9 +713,11 @@ export class TypeComposer<TContext = any> {
}

addResolver(opts: Resolver<any, TContext> | ResolverOpts<any, TContext>): TypeComposer<TContext> {
let resolver;
let resolver: Resolver<any, TContext>;
if (!(opts instanceof this.constructor.schemaComposer.Resolver)) {
resolver = new this.constructor.schemaComposer.Resolver((opts: any));
resolver = new this.constructor.schemaComposer.Resolver(
((opts: any): ResolverOpts<any, TContext>)
);
} else {
resolver = opts;
}
Expand Down Expand Up @@ -836,7 +838,9 @@ export class TypeComposer<TContext = any> {
return typeByPath(this, path);
}

deprecateFields(fields: { [fieldName: string]: string } | string[] | string): this {
deprecateFields(
fields: { [fieldName: string]: string } | string[] | string
): TypeComposer<TContext> {
const existedFieldNames = this.getFieldNames();

if (typeof fields === 'string') {
Expand Down
6 changes: 3 additions & 3 deletions src/utils/__tests__/configAsThunk-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('typeAsThunk', () => {
description: 'Field5',
}),
};
const unwrapped = resolveOutputConfigsAsThunk(GQC, fieldMap);
const unwrapped: any = resolveOutputConfigsAsThunk(GQC, fieldMap);
expect(unwrapped.f0.type).toBe(GraphQLString);
expect(unwrapped.f0.description).toBe('Field0');
expect(unwrapped.f0._fieldAsThunk).toBeTruthy();
Expand Down Expand Up @@ -118,7 +118,7 @@ describe('typeAsThunk', () => {
description: 'Field4',
}),
};
const unwrapped = resolveOutputConfigsAsThunk(GQC, fieldMap);
const unwrapped: any = resolveOutputConfigsAsThunk(GQC, fieldMap);

expect(unwrapped.f3.type).toBe(GraphQLString);
expect(unwrapped.f3._fieldAsThunk).toBeTruthy();
Expand Down Expand Up @@ -149,7 +149,7 @@ describe('typeAsThunk', () => {
},
};
const unwrapped = resolveOutputConfigsAsThunk(GQC, fieldMap);
const { args } = unwrapped.f6;
const { args }: any = unwrapped.f6;
expect(args.a1.type).toBe(GraphQLString);
expect(args.a2.type).toBe(GraphQLString);
expect(args.a2.description).toBe('Desc');
Expand Down
20 changes: 13 additions & 7 deletions src/utils/configAsThunk.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@

import { isFunction, isObject } from './is';
import type { SchemaComposer } from '../schemaComposer';
import type { GraphQLFieldConfig } from '../graphql';
import type { ObjMap } from '../utils/definitions';

export type FieldMaps = {
export type FieldMap = {
[fieldName: string]: any,
__proto__: null,
};

export function resolveOutputConfigsAsThunk<T: FieldMaps>(
schema: SchemaComposer<any>,
fieldMap: T,
export type GraphQLFieldConfigMapExtended<TSource, TContext> = ObjMap<
GraphQLFieldConfig<TSource, TContext> & { _fieldAsThunk?: () => any, _typeAsThunk?: () => any }
>;

export function resolveOutputConfigsAsThunk<TContext>(
schema: SchemaComposer<TContext>,
fieldMap: FieldMap,
typeName?: string = ''
): T {
): GraphQLFieldConfigMapExtended<any, TContext> {
if (isObject(fieldMap)) {
Object.keys(fieldMap).forEach(name => {
if (isFunction(fieldMap[name])) {
Expand Down Expand Up @@ -48,7 +54,7 @@ export function resolveOutputConfigsAsThunk<T: FieldMaps>(
return fieldMap;
}

export function resolveInputConfigsAsThunk<T: FieldMaps>(
export function resolveInputConfigsAsThunk<T: FieldMap>(
schema: SchemaComposer<any>,
fieldMap: T,
typeName?: string
Expand Down Expand Up @@ -79,7 +85,7 @@ export function resolveInputConfigsAsThunk<T: FieldMaps>(
return fieldMap;
}

export function keepConfigsAsThunk<T: FieldMaps>(fieldMap: T): T {
export function keepConfigsAsThunk<T: FieldMap>(fieldMap: T): T {
if (isObject(fieldMap)) {
Object.keys(fieldMap).forEach(key => {
if (fieldMap[key]._fieldAsThunk) {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pluralize from './pluralize';
import type { Thunk } from './definitions';

export function resolveMaybeThunk<T>(thingOrThunk: Thunk<T>): T {
export function resolveMaybeThunk<+T>(thingOrThunk: Thunk<T>): T {
// eslint-disable-line
return typeof thingOrThunk === 'function' ? thingOrThunk() : thingOrThunk;
}
Expand Down

0 comments on commit a34f04e

Please sign in to comment.