Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add extension field to types and fields #172

Merged
merged 1 commit into from
Mar 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
69 changes: 67 additions & 2 deletions src/EnumTypeComposer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,20 @@ import { defineEnumValues, defineEnumValuesToConfig } from './utils/configToDefi
import { graphqlVersion } from './utils/graphqlVersion';
import type { TypeAsString } from './TypeMapper';
import type { SchemaComposer } from './SchemaComposer';
import type { Extensions } from './TypeComposer';

export type EnumTypeComposerDefinition = TypeAsString | GraphQLEnumTypeConfig | GraphQLEnumType;
export type EnumTypeComposerDefinition = TypeAsString | ComposeEnumTypeConfig | GraphQLEnumType;

export type ComposeEnumTypeConfig = GraphQLEnumTypeConfig & {
+extensions?: Extensions,
};

export type GraphQLEnumTypeExtended = GraphQLEnumType & {
_gqcExtensions?: Extensions,
};

export class EnumTypeComposer {
gqType: GraphQLEnumType;
gqType: GraphQLEnumTypeExtended;

static schemaComposer: SchemaComposer<any>;

Expand Down Expand Up @@ -65,6 +74,7 @@ export class EnumTypeComposer {
...(typeDef: any),
});
ETC = new this.schemaComposer.EnumTypeComposer(type);
ETC.gqType._gqcExtensions = typeDef.extensions || {};
} else {
throw new Error('You should provide GraphQLEnumTypeConfig or string with enum name or SDL');
}
Expand Down Expand Up @@ -258,6 +268,61 @@ export class EnumTypeComposer {
return this;
}

// -----------------------------------------------
// Extensions methods
// -----------------------------------------------

getExtensions(): Extensions {
if (!this.gqType._gqcExtensions) {
return {};
} else {
return this.gqType._gqcExtensions;
}
}

setExtensions(extensions: Extensions): EnumTypeComposer {
this.gqType._gqcExtensions = extensions;
return this;
}

extendExtensions(extensions: Extensions): EnumTypeComposer {
const current = this.getExtensions();
this.setExtensions({
...current,
...extensions,
});
return this;
}

clearExtensions(): EnumTypeComposer {
this.setExtensions({});
return this;
}

getExtension(extensionName: string): ?any {
const extensions = this.getExtensions();
return extensions[extensionName];
}

hasExtension(extensionName: string): boolean {
const extensions = this.getExtensions();
return extensionName in extensions;
}

setExtension(extensionName: string, value: any): EnumTypeComposer {
this.extendExtensions({
[extensionName]: value,
});
return this;
}

removeExtension(extensionName: string): EnumTypeComposer {
const extensions = { ...this.getExtensions() };
delete extensions[extensionName];
this.setExtensions(extensions);
return this;
}

// -----------------------------------------------
// Type methods
// -----------------------------------------------
Expand Down
145 changes: 142 additions & 3 deletions src/InputTypeComposer.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
/* @flow strict */
/* eslint-disable no-use-before-define */

import { GraphQLInputObjectType, GraphQLNonNull, GraphQLList, getNamedType } from './graphql';
import {
GraphQLInputObjectType,
GraphQLNonNull,
GraphQLList,
getNamedType,
isInputType,
} from './graphql';
import { resolveMaybeThunk, upperFirst } from './utils/misc';
import { deprecate } from './utils/debug';
import { isObject, isFunction, isString } from './utils/is';
import { resolveInputConfigMapAsThunk, resolveInputConfigAsThunk } from './utils/configAsThunk';
import { typeByPath } from './utils/typeByPath';
import type { Thunk, ObjMap } from './utils/definitions';
import type { ScalarTypeComposer } from './ScalarTypeComposer';
import type { EnumTypeComposer } from './EnumTypeComposer';
import { ScalarTypeComposer } from './ScalarTypeComposer';
import { EnumTypeComposer } from './EnumTypeComposer';
import type { TypeAsString } from './TypeMapper';
import type { SchemaComposer } from './SchemaComposer';
import type { Extensions } from './TypeComposer';
import type {
GraphQLInputFieldConfig,
GraphQLInputFieldConfigMap,
Expand All @@ -23,6 +30,7 @@ import { defineInputFieldMap, defineInputFieldMapToConfig } from './utils/config

export type GraphQLInputObjectTypeExtended = GraphQLInputObjectType & {
_gqcFields?: ComposeInputFieldConfigMap,
_gqcExtensions?: Extensions,
};

export type ComposeInputFieldConfigMap = ObjMap<ComposeInputFieldConfig>;
Expand All @@ -38,6 +46,7 @@ export type ComposeInputFieldConfigAsObject = {
description?: ?string,
astNode?: ?InputValueDefinitionNode,
[key: string]: any,
extensions?: Extensions,
};

export type ComposeInputType =
Expand All @@ -48,10 +57,21 @@ export type ComposeInputType =
| TypeAsString
| Array<ComposeInputType>;

export function isComposeInputType(type: mixed): boolean %checks {
return (
isInputType(type) ||
(Array.isArray(type) && isComposeInputType(type[0])) ||
type instanceof InputTypeComposer ||
type instanceof EnumTypeComposer ||
type instanceof ScalarTypeComposer
);
}

export type ComposeInputObjectTypeConfig = {
name: string,
fields: Thunk<ComposeInputFieldConfigMap>,
description?: ?string,
extensions?: Extensions,
};

export type InputTypeComposerDefinition =
Expand Down Expand Up @@ -114,6 +134,7 @@ export class InputTypeComposer {
});
ITC = new this.schemaComposer.InputTypeComposer(type);
if (isObject(typeDef.fields)) ITC.addFields(typeDef.fields);
ITC.gqType._gqcExtensions = typeDef.extensions || {};
} else {
throw new Error(
'You should provide InputObjectConfig or string with type name to InputTypeComposer.create(opts)'
Expand Down Expand Up @@ -424,6 +445,124 @@ export class InputTypeComposer {
);
}

// -----------------------------------------------
// Extensions methods
// -----------------------------------------------

getExtensions(): Extensions {
if (!this.gqType._gqcExtensions) {
return {};
} else {
return this.gqType._gqcExtensions;
}
}

setExtensions(extensions: Extensions): InputTypeComposer {
this.gqType._gqcExtensions = extensions;
return this;
}

extendExtensions(extensions: Extensions): InputTypeComposer {
const current = this.getExtensions();
this.setExtensions({
...current,
...extensions,
});
return this;
}

clearExtensions(): InputTypeComposer {
this.setExtensions({});
return this;
}

getExtension(extensionName: string): ?any {
const extensions = this.getExtensions();
return extensions[extensionName];
}

hasExtension(extensionName: string): boolean {
const extensions = this.getExtensions();
return extensionName in extensions;
}

setExtension(extensionName: string, value: any): InputTypeComposer {
this.extendExtensions({
[extensionName]: value,
});
return this;
}

removeExtension(extensionName: string): InputTypeComposer {
const extensions = { ...this.getExtensions() };
delete extensions[extensionName];
this.setExtensions(extensions);
return this;
}

getFieldExtensions(fieldName: string): Extensions {
const field = this.getField(fieldName);
if (
isObject(field) &&
!isFunction(field) &&
!Array.isArray(field) &&
!isComposeInputType(field) &&
// Flow is misbehaving so I have to add this
// it should be handled by the above isComposeInputType, but somehow is not
!(field instanceof GraphQLList) &&
!(field instanceof GraphQLNonNull)
) {
return (field: ComposeInputObjectTypeConfig).extensions || {};
} else {
return {};
}
}

setFieldExtensions(fieldName: string, extensions: Extensions): InputTypeComposer {
this.extendField(fieldName, {
extensions,
});
return this;
}

extendFieldExtensions(fieldName: string, extensions: Extensions): InputTypeComposer {
const current = this.getFieldExtensions(fieldName);
this.setFieldExtensions(fieldName, {
...current,
...extensions,
});
return this;
}

clearFieldExtensions(fieldName: string): InputTypeComposer {
this.setFieldExtensions(fieldName, {});
return this;
}

getFieldExtension(fieldName: string, extensionName: string): ?any {
const extensions = this.getFieldExtensions(fieldName);
return extensions[extensionName];
}

hasFieldExtension(fieldName: string, extensionName: string): boolean {
const extensions = this.getFieldExtensions(fieldName);
return extensionName in extensions;
}

setFieldExtension(fieldName: string, extensionName: string, value: any): InputTypeComposer {
this.extendFieldExtensions(fieldName, {
[extensionName]: value,
});
return this;
}

removeFieldExtension(fieldName: string, extensionName: string): InputTypeComposer {
const extensions = { ...this.getFieldExtensions(fieldName) };
delete extensions[extensionName];
this.setFieldExtensions(fieldName, extensions);
return this;
}

// -----------------------------------------------
// Misc methods
// -----------------------------------------------
Expand Down