From 1917b338d3a542f0e066e7bec7ee6321fa3bcf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Lytek?= Date: Thu, 4 Apr 2019 21:58:58 +0200 Subject: [PATCH] feat(nullable): add support for setting defaultNullable option wip: refactor name src --- src/helpers/types.ts | 13 ++++++++++--- src/schema/build-context.ts | 10 ++++++++++ src/schema/schema-generator.ts | 6 ++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/helpers/types.ts b/src/helpers/types.ts index 13713c423..8dc87d115 100644 --- a/src/helpers/types.ts +++ b/src/helpers/types.ts @@ -40,7 +40,8 @@ export function convertTypeIfScalar(type: any): GraphQLScalarType | undefined { export function wrapWithTypeOptions( typeOwnerName: string, type: T, - typeOptions: TypeOptions = {}, + typeOptions: TypeOptions, + nullableByDefault: boolean, ): T { if ( !typeOptions.array && @@ -61,7 +62,11 @@ export function wrapWithTypeOptions( let gqlType: GraphQLType = type; if (typeOptions.array) { - if (typeOptions.nullable === "items" || typeOptions.nullable === "itemsAndList") { + if ( + typeOptions.nullable === "items" || + typeOptions.nullable === "itemsAndList" || + (typeOptions.nullable === undefined && nullableByDefault === true) + ) { gqlType = new GraphQLList(gqlType); } else { gqlType = new GraphQLList(new GraphQLNonNull(gqlType)); @@ -69,7 +74,9 @@ export function wrapWithTypeOptions( } if ( typeOptions.defaultValue === undefined && - (!typeOptions.nullable || typeOptions.nullable === "items") + (typeOptions.nullable === false || + (typeOptions.nullable === undefined && nullableByDefault === false) || + typeOptions.nullable === "items") ) { gqlType = new GraphQLNonNull(gqlType); } diff --git a/src/schema/build-context.ts b/src/schema/build-context.ts index 4df39e863..a439efcbe 100644 --- a/src/schema/build-context.ts +++ b/src/schema/build-context.ts @@ -26,6 +26,10 @@ export interface BuildContextOptions { pubSub?: PubSubEngine | PubSubOptions; globalMiddlewares?: Array>; container?: ContainerType | ContainerGetter; + /** + * Default value for type decorators, like `@Field({ nullable: true })` + */ + nullableByDefault?: boolean; } export abstract class BuildContext { @@ -37,6 +41,7 @@ export abstract class BuildContext { static pubSub: PubSubEngine; static globalMiddlewares: Array>; static container: IOCContainer; + static nullableByDefault: boolean; /** * Set static fields with current building context data @@ -75,6 +80,10 @@ export abstract class BuildContext { } this.container = new IOCContainer(options.container); + + if (options.nullableByDefault !== undefined) { + this.nullableByDefault = options.nullableByDefault; + } } /** @@ -89,6 +98,7 @@ export abstract class BuildContext { this.pubSub = new PubSub(); this.globalMiddlewares = []; this.container = new IOCContainer(); + this.nullableByDefault = false; } } diff --git a/src/schema/schema-generator.ts b/src/schema/schema-generator.ts index 890a63e47..9c02be21c 100644 --- a/src/schema/schema-generator.ts +++ b/src/schema/schema-generator.ts @@ -543,7 +543,8 @@ export abstract class SchemaGenerator { throw new Error(`Cannot determine GraphQL output type for ${typeOwnerName}`!); } - return wrapWithTypeOptions(typeOwnerName, gqlType, typeOptions); + const { nullableByDefault } = BuildContext; + return wrapWithTypeOptions(typeOwnerName, gqlType, typeOptions, nullableByDefault); } private static getGraphQLInputType( @@ -569,6 +570,7 @@ export abstract class SchemaGenerator { throw new Error(`Cannot determine GraphQL input type for ${typeOwnerName}`!); } - return wrapWithTypeOptions(typeOwnerName, gqlType, typeOptions); + const { nullableByDefault } = BuildContext; + return wrapWithTypeOptions(typeOwnerName, gqlType, typeOptions, nullableByDefault); } }