Skip to content

Commit

Permalink
feat: remove undocumented Thunk<FieldConfig> support due to Thunk<Typ…
Browse files Browse the repository at this point in the history
…eDefinition> stability in complex schemas and provide stronger & better DX

Closes #231
  • Loading branch information
nodkz committed Feb 15, 2020
1 parent 2dd83e3 commit 2b56ace
Show file tree
Hide file tree
Showing 11 changed files with 36 additions and 92 deletions.
10 changes: 3 additions & 7 deletions src/InputTypeComposer.d.ts
Expand Up @@ -34,13 +34,12 @@ export type InputTypeComposerAsObjectDefinition = {

export type InputTypeComposerFieldConfigMap = ObjMap<InputTypeComposerFieldConfig>;
export type InputTypeComposerFieldConfigMapDefinition = ObjMap<
Thunk<InputTypeComposerFieldConfigDefinition>
InputTypeComposerFieldConfigDefinition
>;

export type InputTypeComposerFieldConfigDefinition =
| InputTypeComposerFieldConfigAsObjectDefinition
| ComposeInputTypeDefinition
| ComposeInputType;
| Thunk<ComposeInputTypeDefinition>;

export type InputTypeComposerFieldConfigAsObjectDefinition = {
type: Thunk<ComposeInputTypeDefinition>;
Expand Down Expand Up @@ -101,10 +100,7 @@ export class InputTypeComposer<TContext = any> {

public setFields(fields: InputTypeComposerFieldConfigMapDefinition): this;

public setField(
fieldName: string,
fieldConfig: Thunk<InputTypeComposerFieldConfigDefinition | ComposeInputType>
): this;
public setField(fieldName: string, fieldConfig: InputTypeComposerFieldConfigDefinition): this;

/**
* Add new fields or replace existed in a GraphQL type
Expand Down
8 changes: 3 additions & 5 deletions src/InputTypeComposer.js
Expand Up @@ -52,13 +52,11 @@ export type InputTypeComposerAsObjectDefinition = {
};

export type InputTypeComposerFieldConfigMap = ObjMap<InputTypeComposerFieldConfig>;
export type InputTypeComposerFieldConfigMapDefinition = ObjMapReadOnly<
Thunk<InputTypeComposerFieldConfigDefinition>
>;
export type InputTypeComposerFieldConfigMapDefinition = ObjMapReadOnly<InputTypeComposerFieldConfigDefinition>;

export type InputTypeComposerFieldConfigDefinition =
| InputTypeComposerFieldConfigAsObjectDefinition
| ComposeInputTypeDefinition
| Thunk<ComposeInputTypeDefinition>
| $ReadOnly<ComposeInputType>;

export type InputTypeComposerFieldConfigAsObjectDefinition = {
Expand Down Expand Up @@ -222,7 +220,7 @@ export class InputTypeComposer<TContext> {

setField(
fieldName: string,
fieldConfig: Thunk<InputTypeComposerFieldConfigDefinition | $ReadOnly<ComposeInputType>>
fieldConfig: InputTypeComposerFieldConfigDefinition
): InputTypeComposer<TContext> {
this._gqcFields[fieldName] = this.schemaComposer.typeMapper.convertInputFieldConfig(
fieldConfig,
Expand Down
5 changes: 1 addition & 4 deletions src/InterfaceTypeComposer.d.ts
Expand Up @@ -121,10 +121,7 @@ export class InterfaceTypeComposer<TSource = any, TContext = any> {

public setField(
name: string,
fieldConfig: Thunk<
| ComposeOutputType<TContext>
| ObjectTypeComposerFieldConfigDefinition<TSource, TContext, ArgsMap>
>
fieldConfig: ObjectTypeComposerFieldConfigDefinition<TSource, TContext, ArgsMap>
): this;

/**
Expand Down
11 changes: 2 additions & 9 deletions src/InterfaceTypeComposer.js
Expand Up @@ -53,11 +53,7 @@ import {
} from './utils/typeHelpers';
import { defineFieldMap, convertObjectFieldMapToConfig } from './utils/configToDefine';
import { graphqlVersion } from './utils/graphqlVersion';
import type {
ComposeNamedInputType,
ComposeNamedOutputType,
ComposeOutputType,
} from './utils/typeHelpers';
import type { ComposeNamedInputType, ComposeNamedOutputType } from './utils/typeHelpers';
import { printInterface, type SchemaPrinterOptions } from './utils/schemaPrinter';
import { getInterfaceTypeDefinitionNode } from './utils/definitionNode';

Expand Down Expand Up @@ -253,10 +249,7 @@ export class InterfaceTypeComposer<TSource, TContext> {

setField(
fieldName: string,
fieldConfig: Thunk<
| $ReadOnly<ComposeOutputType<TContext>>
| ObjectTypeComposerFieldConfigDefinition<TSource, TContext, ArgsMap>
>
fieldConfig: ObjectTypeComposerFieldConfigDefinition<TSource, TContext, ArgsMap>
): InterfaceTypeComposer<TSource, TContext> {
this._gqcFields[fieldName] = this.schemaComposer.typeMapper.convertOutputFieldConfig(
fieldConfig
Expand Down
16 changes: 6 additions & 10 deletions src/ObjectTypeComposer.d.ts
Expand Up @@ -65,14 +65,13 @@ export type ObjectTypeComposerFieldConfigMap<TSource, TContext> = ObjMap<
ObjectTypeComposerFieldConfig<TSource, TContext>
>;
export type ObjectTypeComposerFieldConfigMapDefinition<TSource, TContext> = ObjMap<
Thunk<ObjectTypeComposerFieldConfigDefinition<TSource, TContext>>
ObjectTypeComposerFieldConfigDefinition<TSource, TContext>
>;

export type ObjectTypeComposerFieldConfigDefinition<TSource, TContext, TArgs = ArgsMap> =
| ObjectTypeComposerFieldConfigAsObjectDefinition<TSource, TContext, TArgs>
| ComposeOutputTypeDefinition<TContext>
| Resolver<any, TContext, any>
| ComposeOutputType<TContext>;
| Thunk<ComposeOutputTypeDefinition<TContext>>
| Resolver<any, TContext, any>;

export type ObjectTypeComposerFieldConfigAsObjectDefinition<TSource, TContext, TArgs = ArgsMap> = {
type: Thunk<ComposeOutputTypeDefinition<TContext> | Resolver<any, TContext, any>>;
Expand Down Expand Up @@ -106,7 +105,7 @@ export type ObjectTypeComposerArgumentConfigMap<TArgs = ArgsMap> = {
};

export type ObjectTypeComposerArgumentConfigMapDefinition<TArgs = ArgsMap> = {
[argName in keyof TArgs]: Thunk<ObjectTypeComposerArgumentConfigDefinition>;
[argName in keyof TArgs]: ObjectTypeComposerArgumentConfigDefinition;
};

export type ObjectTypeComposerArgumentConfigAsObjectDefinition = {
Expand All @@ -128,7 +127,7 @@ export type ObjectTypeComposerArgumentConfig = {

export type ObjectTypeComposerArgumentConfigDefinition =
| ObjectTypeComposerArgumentConfigAsObjectDefinition
| ComposeInputTypeDefinition;
| Thunk<ComposeInputTypeDefinition>;

// RELATION -----------------------------

Expand Down Expand Up @@ -231,10 +230,7 @@ export class ObjectTypeComposer<TSource = any, TContext = any> {

public setField<TArgs = ArgsMap>(
fieldName: string,
fieldConfig: Thunk<
| ComposeOutputType<TContext>
| ObjectTypeComposerFieldConfigDefinition<TSource, TContext, ArgsMap>
>
fieldConfig: ObjectTypeComposerFieldConfigDefinition<TSource, TContext, ArgsMap>
): this;

/**
Expand Down
16 changes: 6 additions & 10 deletions src/ObjectTypeComposer.js
Expand Up @@ -94,14 +94,13 @@ export type ObjectTypeComposerFieldConfigMap<TSource, TContext> = ObjMap<
ObjectTypeComposerFieldConfig<TSource, TContext>
>;
export type ObjectTypeComposerFieldConfigMapDefinition<TSource, TContext> = ObjMapReadOnly<
Thunk<ObjectTypeComposerFieldConfigDefinition<TSource, TContext>>
ObjectTypeComposerFieldConfigDefinition<TSource, TContext>
>;

export type ObjectTypeComposerFieldConfigDefinition<TSource, TContext, TArgs = ArgsMap> =
| ObjectTypeComposerFieldConfigAsObjectDefinition<TSource, TContext, TArgs>
| ComposeOutputTypeDefinition<TContext>
| $ReadOnly<Resolver<any, TContext, any>>
| $ReadOnly<ComposeOutputType<TContext>>;
| Thunk<ComposeOutputTypeDefinition<TContext>>
| $ReadOnly<Resolver<any, TContext, any>>;

export type ObjectTypeComposerFieldConfigAsObjectDefinition<TSource, TContext, TArgs = ArgsMap> = {
type: Thunk<ComposeOutputTypeDefinition<TContext> | $ReadOnly<Resolver<any, TContext, any>>>,
Expand Down Expand Up @@ -135,7 +134,7 @@ export type ObjectTypeComposerArgumentConfigMap<TArgs = ArgsMap> = {
};

export type ObjectTypeComposerArgumentConfigMapDefinition<TArgs = ArgsMap> = {
+[argName: $Keys<TArgs>]: Thunk<ObjectTypeComposerArgumentConfigDefinition>,
+[argName: $Keys<TArgs>]: ObjectTypeComposerArgumentConfigDefinition,
};

export type ObjectTypeComposerArgumentConfigAsObjectDefinition = {
Expand All @@ -157,7 +156,7 @@ export type ObjectTypeComposerArgumentConfig = {

export type ObjectTypeComposerArgumentConfigDefinition =
| ObjectTypeComposerArgumentConfigAsObjectDefinition
| ComposeInputTypeDefinition;
| Thunk<ComposeInputTypeDefinition>;

// RELATION -----------------------------

Expand Down Expand Up @@ -385,10 +384,7 @@ export class ObjectTypeComposer<TSource, TContext> {

setField(
fieldName: string,
fieldConfig: Thunk<
| $ReadOnly<ComposeOutputType<TContext>>
| ObjectTypeComposerFieldConfigDefinition<TSource, TContext, ArgsMap>
>
fieldConfig: ObjectTypeComposerFieldConfigDefinition<TSource, TContext, ArgsMap>
): ObjectTypeComposer<TSource, TContext> {
this._gqcFields[fieldName] = this.schemaComposer.typeMapper.convertOutputFieldConfig(
fieldConfig
Expand Down
8 changes: 3 additions & 5 deletions src/TypeMapper.d.ts
Expand Up @@ -78,9 +78,7 @@ declare class TypeMapper<TContext> {
): ComposeOutputType<TContext> | void;

public convertOutputFieldConfig<TSource>(
composeFC: Thunk<
ObjectTypeComposerFieldConfigDefinition<TSource, TContext> | Resolver<any, TContext>
>,
composeFC: ObjectTypeComposerFieldConfigDefinition<TSource, TContext> | Resolver<any, TContext>,
fieldName?: string,
typeName?: string
): ObjectTypeComposerFieldConfig<TSource, TContext>;
Expand All @@ -91,7 +89,7 @@ declare class TypeMapper<TContext> {
): ObjectTypeComposerFieldConfigMap<TSource, TContext>;

public convertArgConfig(
composeAC: Thunk<ObjectTypeComposerArgumentConfigDefinition>,
composeAC: ObjectTypeComposerArgumentConfigDefinition,
argName?: string,
fieldName?: string,
typeName?: string
Expand All @@ -110,7 +108,7 @@ declare class TypeMapper<TContext> {
): ComposeInputType | void;

public convertInputFieldConfig(
composeIFC: Thunk<InputTypeComposerFieldConfigDefinition>,
composeIFC: InputTypeComposerFieldConfigDefinition,
fieldName?: string,
typeName?: string
): InputTypeComposerFieldConfig;
Expand Down
31 changes: 4 additions & 27 deletions src/TypeMapper.js
Expand Up @@ -56,7 +56,6 @@ import {
} from './graphql';
import type { GraphQLType, GraphQLInputType } from './graphql';
import { GraphQLDate, GraphQLBuffer, GraphQLJSON, GraphQLJSONObject } from './type';
import { createThunkedObjectProxy } from './utils/createThunkedObjectProxy';

import type {
InputTypeComposerFieldConfigMap,
Expand Down Expand Up @@ -341,10 +340,9 @@ export class TypeMapper<TContext> {
}

convertOutputFieldConfig<TSource>(
composeFC: Thunk<
composeFC:
| ObjectTypeComposerFieldConfigDefinition<TSource, TContext>
| $ReadOnly<Resolver<any, TContext>>
>,
| $ReadOnly<Resolver<any, TContext>>,
fieldName?: string = '',
typeName?: string = ''
): ObjectTypeComposerFieldConfig<TSource, TContext> {
Expand All @@ -362,13 +360,6 @@ export class TypeMapper<TContext> {
};
}

// use proxy for evaluation on demand
if (isFunction(composeFC)) {
return (createThunkedObjectProxy(() =>
this.convertOutputFieldConfig(composeFC(), fieldName, typeName)
): any);
}

// convert type when its provided as composeIFC
const tcFromIFC = this.convertOutputTypeDefinition(composeFC, fieldName, typeName);
if (tcFromIFC) {
Expand Down Expand Up @@ -414,7 +405,7 @@ export class TypeMapper<TContext> {
}

convertArgConfig(
composeAC: Thunk<ObjectTypeComposerArgumentConfigDefinition>,
composeAC: ObjectTypeComposerArgumentConfigDefinition,
argName?: string = '',
fieldName?: string = '',
typeName?: string = ''
Expand All @@ -424,13 +415,6 @@ export class TypeMapper<TContext> {
throw new Error(`You provide empty argument config ${inspect(composeAC)}`);
}

// use proxy for evaluation on demand
if (isFunction(composeAC)) {
return (createThunkedObjectProxy(() =>
this.convertArgConfig(composeAC(), argName, fieldName, typeName)
): any);
}

// convert type when its provided as composeAC
const tcFromAC = this.convertInputTypeDefinition((composeAC: any));
if (tcFromAC) {
Expand Down Expand Up @@ -556,7 +540,7 @@ export class TypeMapper<TContext> {
}

convertInputFieldConfig(
composeIFC: Thunk<InputTypeComposerFieldConfigDefinition>,
composeIFC: InputTypeComposerFieldConfigDefinition,
fieldName?: string = '',
typeName?: string = ''
): InputTypeComposerFieldConfig {
Expand All @@ -565,13 +549,6 @@ export class TypeMapper<TContext> {
throw new Error(`You provide empty input field definition: ${inspect(composeIFC)}`);
}

// use proxy for evaluation on demand
if (isFunction(composeIFC)) {
return (createThunkedObjectProxy(() =>
this.convertInputFieldConfig(composeIFC(), fieldName, typeName)
): any);
}

// convert type when its provided as composeIFC
const tcFromIFC = this.convertInputTypeDefinition(composeIFC, fieldName, typeName);
if (tcFromIFC) {
Expand Down
11 changes: 3 additions & 8 deletions src/__tests__/ObjectTypeComposer-test.js
Expand Up @@ -133,17 +133,12 @@ describe('ObjectTypeComposer', () => {
}
});

it('accept fieldConfig as function', () => {
it('accept thunked type', () => {
tc.setFields({
input4: (): { type: string, args: { [key: string]: string }, resolve: Function } => ({
type: 'String',
args: { a: 'Int' },
resolve: () => 123,
}),
input4: () => 'String',
});
expect(tc.getField('input4').type).toBeInstanceOf(ThunkComposer);
expect(tc.getFieldType('input4')).toBe(GraphQLString);
expect(tc.getFieldArgType('input4', 'a')).toBe(GraphQLInt);
expect((tc.getField('input4'): any).resolve()).toBe(123);
});
});

Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/TypeMapper-test.js
Expand Up @@ -443,7 +443,7 @@ describe('TypeMapper', () => {
it('should pass unchanged thunk', () => {
const myTypeThunk = (): string => 'Int';
const fc: any = typeMapper.convertOutputFieldConfig(myTypeThunk);
expect(fc.type).toBeInstanceOf(ScalarTypeComposer);
expect(fc.type).toBeInstanceOf(ThunkComposer);
expect(fc.type.getType()).toBe(GraphQLInt);
});

Expand Down Expand Up @@ -923,7 +923,7 @@ describe('TypeMapper', () => {
it('should pass unchanged thunk', () => {
const myTypeThunk = (): string => 'Int';
const ac: any = typeMapper.convertArgConfig(myTypeThunk);
expect(ac.type).toBeInstanceOf(ScalarTypeComposer);
expect(ac.type).toBeInstanceOf(ThunkComposer);
expect(ac.type.getType()).toBe(GraphQLInt);
});

Expand Down
8 changes: 3 additions & 5 deletions src/__tests__/github_issues/231-test.js
Expand Up @@ -4,18 +4,16 @@ import { schemaComposer } from '../..';

describe('github issue #231: Cloning a resolver evaluates its configuration thunks', () => {
it('clone a resolver without evaluating its type and args thunks', async () => {
const aTypeThunk = jest.fn(() => 'String');
const aTypeThunk: any = jest.fn(() => 'String');

const aResolver = schemaComposer.createResolver({
name: aTypeThunk,
type: 'Boolean',
name: 'r1',
type: aTypeThunk,
args: {
anArg: aTypeThunk,
},
});

aResolver.clone();

expect(aTypeThunk).not.toBeCalled();
});
});

0 comments on commit 2b56ace

Please sign in to comment.