graphql#GraphQLUnionType TypeScript Examples
The following examples show how to use
graphql#GraphQLUnionType.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Utils.ts From graphql-ts-client with MIT License | 6 votes |
export function targetTypeOf(type: GraphQLType): GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType | undefined {
if (type instanceof GraphQLNonNull) {
return targetTypeOf(type.ofType);
}
if (type instanceof GraphQLList) {
return targetTypeOf(type.ofType);
}
if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType || type instanceof GraphQLUnionType) {
return type;
}
return undefined;
}
Example #2
Source File: unionType.ts From genql with MIT License | 6 votes |
unionType = (type: GraphQLUnionType, _: RenderContext) => {
const types = type.getTypes()
const typeObj: FieldMap<string> = types.reduce<FieldMap<string>>((r, t) => {
r[`on_${t.name}`] = { type: t.name }
return r
}, {})
const commonInterfaces = uniq(flatten(types.map((x) => x.getInterfaces())))
commonInterfaces.forEach((t) => {
typeObj[`on_${t.name}`] = { type: t.name }
})
typeObj.__typename = { type: 'String' }
return typeObj
}
Example #3
Source File: Generator.ts From graphql-ts-client with MIT License | 6 votes |
protected createFetcheWriter(
modelType: GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType,
ctx: FetcherContext,
stream: WriteStream,
config: GeneratorConfig
): FetcherWriter {
return new FetcherWriter(
modelType,
ctx,
stream,
config
);
}
Example #4
Source File: unionType.ts From genql with MIT License | 6 votes |
unionType = (type: GraphQLUnionType, ctx: RenderContext) => {
let types = type.getTypes()
if (ctx.config?.sortProperties) {
types = types.sort()
}
const fieldStrings = types.map((t) => `on_${t.name}?:${requestTypeName(t)}`)
const commonInterfaces = uniq(flatten(types.map((x) => x.getInterfaces())))
fieldStrings.push(
...commonInterfaces.map((type) => {
return `on_${type.name}?: ${requestTypeName(type)}`
}),
)
fieldStrings.push('__typename?: boolean | number')
ctx.addCodeBlock(
`${typeComment(type)}export interface ${requestTypeName(
type,
)}{\n${fieldStrings.map((x) => ' ' + x).join(',\n')}\n}`,
)
}
Example #5
Source File: CommonTypesWriter.ts From graphql-ts-client with MIT License | 6 votes |
private writeImplementionType() {
const t = this.text.bind(this);
t(IMPLEMENTANTION_TYPE_COMMENT);
t("export type ImplementationType<T> = ");
this.enter("BLANK", true);
for (const [type, castTypes] of this.inheritanceInfo.downcastTypeMap) {
t("T extends '");
t(type.name)
t("' ? ");
this.enter("BLANK")
if (!(type instanceof GraphQLUnionType)) {
t("'");
t(type.name);
t("'");
}
for (const castType of castTypes) {
this.separator(" | ");
t("ImplementationType<'");
t(castType.name);
t("'>");
}
this.leave();
t(" :\n");
}
t("T\n");
this.leave();
t(";");
}
Example #6
Source File: types.ts From tql with MIT License | 6 votes |
printField = (field: GraphQLField<any, any, any>): string => {
const { args } = field;
const isList = listType(field.type);
const isNonNull = field.type instanceof GraphQLNonNull;
const type = outputType(field.type);
const printVariables = () => {
return args.length > 0
? `(variables: { ${args.map(printVariable).join(", ")} })`
: "";
};
if (type instanceof GraphQLScalarType) {
return (
`${args.length > 0 ? "" : "readonly"} ${field.name}${printVariables()}: ${
isList ? `ReadonlyArray<${toPrimitive(type)}>` : `${toPrimitive(type)}`
}` + (isNonNull ? "" : " | null")
);
} else if (type instanceof GraphQLEnumType) {
return (
`${args.length > 0 ? "" : "readonly"} ${field.name}${printVariables()}: ${
isList ? `ReadonlyArray<${type.name}>` : `${type.name}`
}` + (isNonNull ? "" : " | null")
);
} else if (
type instanceof GraphQLInterfaceType ||
type instanceof GraphQLUnionType ||
type instanceof GraphQLObjectType
) {
return (
`${args.length > 0 ? "" : "readonly"} ${field.name}${printVariables()}: ${
isList ? `ReadonlyArray<I${type.name}>` : `I${type.name}`
}` + (isNonNull ? "" : " | null")
);
} else {
throw new Error("Unable to print field.");
}
}
Example #7
Source File: schema.ts From squid with GNU General Public License v3.0 | 6 votes |
function addUnion(model: Model, type: GraphQLUnionType): void {
if (model[type.name]) return
let variants: string[] = []
model[type.name] = {
kind: 'union',
variants,
description: type.description || undefined
}
type.getTypes().forEach(obj => {
if (isEntityType(obj)) {
throw new Error(`union ${type.name} has entity ${obj.name} as a variant. Entities in union types are not supported`)
}
addEntityOrJsonObjectOrInterface(model, obj)
variants.push(obj.name)
})
}
Example #8
Source File: serializeToJSON.ts From amplify-codegen with Apache License 2.0 | 6 votes |
function serializeUnionType(type: GraphQLUnionType) {
const { name, description } = type;
const types = type.getTypes();
return {
kind: 'UnionType',
name,
description,
types: types.map(type => ({
name: type.name,
description: type.description,
})),
};
}
Example #9
Source File: GraphQLStateGenerator.d.ts From graphql-ts-client with MIT License | 5 votes |
protected createFetcheWriter(modelType: GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType, ctx: FetcherContext, stream: WriteStream, config: GeneratorConfig): GraphQLStateFetcherWriter;
Example #10
Source File: visitor.ts From proto2graphql with MIT License | 5 votes |
function visitOneOf(oneOf: protobuf.OneOf, context: Context) {
const unionType = new GraphQLUnionType({
name: fullTypeName(oneOf),
types: () => oneOf.fieldsArray.map(field => visitFieldType(field, context))
});
setType(unionType, context);
return unionType;
}
Example #11
Source File: FetcherWriter.d.ts From graphql-ts-client with MIT License | 5 votes |
protected importedNamesForSuperType(superType: GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType): string[];
Example #12
Source File: schema.ts From squid with GNU General Public License v3.0 | 4 votes |
function addEntityOrJsonObjectOrInterface(model: Model, type: GraphQLObjectType | GraphQLInterfaceType): void {
if (model[type.name]) return
let kind: 'entity' | 'object' | 'interface' = isEntityType(type)
? 'entity'
: type instanceof GraphQLInterfaceType ? 'interface' : 'object'
let properties: Record<string, Prop> = {}
let interfaces: string[] = []
let indexes: Index[] = type instanceof GraphQLObjectType ? checkEntityIndexes(type) : []
let description = type.description || undefined
switch(kind) {
case 'entity':
model[type.name] = {kind, properties, description, interfaces, indexes}
break
case 'object':
model[type.name] = {kind, properties, description, interfaces}
break
case 'interface':
model[type.name] = {kind, properties, description}
break
default:
throw unexpectedCase(kind)
}
let fields = type.getFields()
if (kind == 'entity') {
if (fields.id == null) {
properties.id = {
type: {kind: 'scalar', name: 'ID'},
nullable: false
}
} else {
let correctIdType = fields.id.type instanceof GraphQLNonNull
&& fields.id.type.ofType instanceof GraphQLScalarType
&& fields.id.type.ofType.name === 'ID'
if (!correctIdType) {
throw unsupportedFieldTypeError(type.name + '.id')
}
}
}
for (let key in fields) {
let f: GraphQLField<any, any> = fields[key]
handleFulltextDirective(model, type, f)
let propName = `${type.name}.${f.name}`
let fieldType = f.type
let nullable = true
let description = f.description || undefined
let derivedFrom = checkDerivedFrom(type, f)
let index = checkFieldIndex(type, f)
let unique = index?.unique || false
if (index) {
indexes.push(index)
}
if (fieldType instanceof GraphQLNonNull) {
nullable = false
fieldType = fieldType.ofType
}
let list = unwrapList(fieldType)
fieldType = list.item
if (fieldType instanceof GraphQLScalarType) {
properties[key] = {
type: wrapWithList(list.nulls, {
kind: 'scalar',
name: fieldType.name
}),
nullable,
description
}
} else if (fieldType instanceof GraphQLEnumType) {
addEnum(model, fieldType)
properties[key] = {
type: wrapWithList(list.nulls, {
kind: 'enum',
name: fieldType.name
}),
nullable,
description
}
} else if (fieldType instanceof GraphQLUnionType) {
addUnion(model, fieldType)
properties[key] = {
type: wrapWithList(list.nulls, {
kind: 'union',
name: fieldType.name
}),
nullable,
description
}
} else if (fieldType instanceof GraphQLObjectType) {
if (isEntityType(fieldType)) {
switch(list.nulls.length) {
case 0:
if (derivedFrom) {
if (!nullable) {
throw new SchemaError(`Property ${propName} must be nullable`)
}
properties[key] = {
type: {
kind: 'lookup',
entity: fieldType.name,
field: derivedFrom.field
},
nullable,
description
}
} else {
if (unique && nullable) {
throw new SchemaError(`Unique property ${propName} must be non-nullable`)
}
properties[key] = {
type: {
kind: 'fk',
foreignEntity: fieldType.name
},
nullable,
unique,
description
}
}
break
case 1:
if (derivedFrom == null) {
throw new SchemaError(`@derivedFrom directive is required on ${propName} declaration`)
}
properties[key] = {
type: {
kind: 'list-lookup',
entity: fieldType.name,
field: derivedFrom.field
},
nullable: false,
description
}
break
default:
throw unsupportedFieldTypeError(propName)
}
} else {
addEntityOrJsonObjectOrInterface(model, fieldType)
properties[key] = {
type: wrapWithList(list.nulls, {
kind: 'object',
name: fieldType.name
}),
nullable,
description
}
}
} else {
throw unsupportedFieldTypeError(propName)
}
}
if (kind != 'interface') {
type.getInterfaces().forEach(i => {
addEntityOrJsonObjectOrInterface(model, i)
interfaces.push(i.name)
})
}
}
Example #13
Source File: selectors.ts From tql with MIT License | 4 votes |
transform = (
ast: DocumentNode,
schema: GraphQLSchema
): ASTVisitor => {
// const Field = imp("Field@timkendall@tql");
// const Argument = imp("Argument@timkendall@tql");
// const Variable = imp("Variable@timkendall@tql");
// const InlineFragment = imp("InlineFragment@timkendall@tql");
return {
[Kind.DIRECTIVE_DEFINITION]: () => null,
[Kind.SCALAR_TYPE_DEFINITION]: () => null,
[Kind.ENUM_TYPE_DEFINITION]: (node) => {
return null;
},
[Kind.ENUM_VALUE_DEFINITION]: (node) => {
return null;
},
[Kind.INPUT_OBJECT_TYPE_DEFINITION]: (def) => {
return null;
},
[Kind.OBJECT_TYPE_DEFINITION]: (node) => {
const typename = node.name.value;
const type = schema.getType(typename);
invariant(
type instanceof GraphQLObjectType,
`Type "${typename}" was not instance of expected class GraphQLObjectType.`
);
const fields = Object.values(type.getFields());
return code`
${/* selector interface */ ""}
interface I${type.name}Selector {
readonly __typename: () => Field<"__typename">
${fields.map(printSignature).join("\n")}
}
${/* selector object */ ""}
const ${typename}Selector: I${typename}Selector = {
__typename: () => field("__typename"),
${fields.map(printMethod).join("\n")}
}
${/* select fn */ ""}
export const ${toLower(
typename
)} = <T extends ReadonlyArray<Selection>>(select: (t: I${typename}Selector) => T) => new SelectionBuilder<ISchema, "${type}", T>(SCHEMA as any, "${typename}", select(${typename}Selector))
`;
},
[Kind.INTERFACE_TYPE_DEFINITION]: (node) => {
const typename = node.name.value;
const type = schema.getType(typename);
invariant(
type instanceof GraphQLInterfaceType,
`Type "${typename}" was not instance of expected class GraphQLInterfaceType.`
);
// @note Get all implementors of this union
const implementations = schema
.getPossibleTypes(type)
.map((type) => type.name);
const fields = Object.values(type.getFields());
return code`
${/* selector interface */ ""}
interface I${type.name}Selector {
readonly __typename: () => Field<"__typename">
${fields.map(printSignature).join("\n")}
readonly on: <T extends ReadonlyArray<Selection>, F extends ${implementations
.map((name) => `"${name}"`)
.join(" | ")}>(
type: F,
select: (t: ${printConditionalSelectorArg(
implementations.map((name) => name)
)}) => T
) => InlineFragment<NamedType<F>, SelectionSet<T>>
}
${/* selector object */ ""}
const ${typename}Selector: I${typename}Selector = {
__typename: () => field("__typename"),
${fields.map(printMethod).join("\n")}
on: (
type,
select,
) => {
switch(type) {
${implementations
.map(
(name) => `
case "${name}": {
return inlineFragment(
namedType("${name}"),
selectionSet(select(${name}Selector as Parameters<typeof select>[0])),
)
}
`
)
.join("\n")}
default:
throw new TypeConditionError({
selectedType: type,
abstractType: "${type.name}",
})
}
},
}
${/* select fn */ ""}
export const ${toLower(
typename
)} = <T extends ReadonlyArray<Selection>>(select: (t: I${typename}Selector) => T) => new SelectionBuilder<ISchema, "${type}", T>(SCHEMA as any, "${typename}", select(${typename}Selector))
`;
},
[Kind.UNION_TYPE_DEFINITION]: (node) => {
const typename = node.name.value;
const type = schema.getType(typename);
invariant(
type instanceof GraphQLUnionType,
`Type "${typename}" was not instance of expected class GraphQLUnionType.`
);
// @note Get all implementors of this union
const implementations = schema
.getPossibleTypes(type)
.map((type) => type.name);
return code`
${/* selector interface */ ""}
interface I${type.name}Selector {
readonly __typename: () => Field<"__typename">
readonly on: <T extends ReadonlyArray<Selection>, F extends ${implementations
.map((name) => `"${name}"`)
.join(" | ")}>(
type: F,
select: (t: ${printConditionalSelectorArg(
implementations.map((name) => name)
)}) => T
) => InlineFragment<NamedType<F>, SelectionSet<T>>
}
${/* selector object */ ""}
const ${typename}Selector: I${typename}Selector = {
__typename: () => field("__typename"),
on: (
type,
select,
) => {
switch(type) {
${implementations
.map(
(name) => `
case "${name}": {
return inlineFragment(
namedType("${name}"),
selectionSet(select(${name}Selector as Parameters<typeof select>[0])),
)
}
`
)
.join("\n")}
default:
throw new TypeConditionError({
selectedType: type,
abstractType: "${type.name}",
})
}
},
}
${/* select fn */ ""}
export const ${toLower(
typename
)} = <T extends ReadonlyArray<Selection>>(select: (t: I${typename}Selector) => T) => new SelectionBuilder<ISchema, "${type}", T>(SCHEMA as any, "${typename}", select(${typename}Selector))
`;
},
[Kind.SCHEMA_DEFINITION]: (node) => {
return null;
},
};
}
Example #14
Source File: generateSchema.ts From davinci with MIT License | 4 votes |
generateGQLSchema = ({
type,
parentType,
key,
schemas = {},
isInput = false,
operationType,
resolverMetadata,
partial,
transformMetadata = _.identity
}: IGenerateGQLSchemaArgs) => {
// grab meta infos
// maybe it's a decorated class, let's try to get the fields metadata
const parentFieldsMetadata: IFieldDecoratorMetadata[] = parentType?.prototype
? getFieldsMetadata(parentType.prototype.constructor, isInput, operationType, resolverMetadata)
: [];
const meta = _fp.find({ key }, parentFieldsMetadata) || ({} as IFieldDecoratorMetadata);
const metadata = transformMetadata(meta, { isInput, type, parentType, schemas });
const isRequired = !partial && metadata.opts?.required;
// it's a primitive type, simple case
if ([String, Number, Boolean, Date, Object].includes(type)) {
const gqlType = scalarDict[type.name.toLowerCase()];
const schema = isRequired ? new GraphQLNonNull(gqlType) : gqlType;
return { schema, schemas };
}
// it's an array => recursively call makeSchema on the first array element
if (Array.isArray(type)) {
const gqlSchema = generateGQLSchema({
type: type[0],
parentType,
schemas,
key,
isInput,
operationType,
resolverMetadata,
partial,
transformMetadata
});
const gqlType = new GraphQLList(gqlSchema.schema);
const schema = isRequired ? new GraphQLNonNull(gqlType) : gqlType;
return { schema, schemas: _.merge(schemas, gqlSchema.schemas) };
}
// it's a complex type => create nested types
if (typeof type === 'function' || typeof type === 'object') {
const suffix = isInput
? _.compact([partial && 'Partial', _.upperFirst(operationType || ''), 'Input']).join('')
: '';
const typeMetadata = Reflector.getMetadata('davinci:graphql:types', type) || {};
const name = `${typeMetadata.name || type.name || key}${suffix}`;
// existing type, let's return it
if (schemas[name]) {
return { schema: schemas[name], schemas };
}
if (type instanceof UnionType) {
const types = Array.isArray(type.types)
? type.types.map(
t =>
generateGQLSchema({
type: t,
parentType,
schemas,
key,
isInput,
operationType,
resolverMetadata,
partial,
transformMetadata
}).schema
)
: type.types;
const unionTypeConfig = {
..._.omit(metadata.opts, ['type']),
name,
types,
resolveType: type.resolveType
};
schemas[name] = isRequired
? new GraphQLNonNull(new GraphQLUnionType(unionTypeConfig))
: new GraphQLUnionType(unionTypeConfig);
} else {
const objTypeConfig: any = {
...metadata.opts,
name,
// eslint-disable-next-line no-use-before-define
fields: createObjectFields({
parentType: type,
schemas,
isInput,
operationType,
resolverMetadata,
partial,
transformMetadata
})
};
const ObjectType = isInput ? GraphQLInputObjectType : GraphQLObjectType;
schemas[name] = isRequired
? new GraphQLNonNull(new ObjectType(objTypeConfig))
: new ObjectType(objTypeConfig);
}
return { schema: schemas[name], schemas };
}
return null;
}
Example #15
Source File: buildObjectType.ts From payload with MIT License | 4 votes |
function buildObjectType(name: string, fields: Field[], parentName: string, baseFields: BaseFields = {}): GraphQLType {
const recursiveBuildObjectType = buildObjectType.bind(this);
const fieldToSchemaMap = {
number: (field: NumberField) => ({ type: withNullableType(field, GraphQLFloat) }),
text: (field: TextField) => ({ type: withNullableType(field, GraphQLString) }),
email: (field: EmailField) => ({ type: withNullableType(field, EmailAddressResolver) }),
textarea: (field: TextareaField) => ({ type: withNullableType(field, GraphQLString) }),
code: (field: CodeField) => ({ type: withNullableType(field, GraphQLString) }),
date: (field: DateField) => ({ type: withNullableType(field, DateTimeResolver) }),
point: (field: PointField) => ({ type: withNullableType(field, new GraphQLList(GraphQLFloat)) }),
richText: (field: RichTextField) => ({
type: withNullableType(field, GraphQLJSON),
async resolve(parent, args, context) {
if (args.depth > 0) {
await createRichTextRelationshipPromise({
req: context.req,
siblingDoc: parent,
depth: args.depth,
field,
showHiddenFields: false,
});
}
return parent[field.name];
},
args: {
depth: {
type: GraphQLInt,
},
},
}),
upload: (field: UploadField) => {
const { relationTo, label } = field;
const uploadName = combineParentName(parentName, label === false ? toWords(field.name, true) : label);
// If the relationshipType is undefined at this point,
// it can be assumed that this blockType can have a relationship
// to itself. Therefore, we set the relationshipType equal to the blockType
// that is currently being created.
const type = this.collections[relationTo].graphQL.type || newlyCreatedBlockType;
const uploadArgs = {} as LocaleInputType;
if (this.config.localization) {
uploadArgs.locale = {
type: this.types.localeInputType,
};
uploadArgs.fallbackLocale = {
type: this.types.fallbackLocaleInputType,
};
}
const relatedCollectionSlug = field.relationTo;
const relatedCollection = this.collections[relatedCollectionSlug];
const { find } = this.operations.collections;
const upload = {
args: uploadArgs,
type,
extensions: { complexity: 20 },
async resolve(parent, args, context) {
const value = parent[field.name];
const locale = args.locale || context.req.locale;
const fallbackLocale = args.fallbackLocale || context.req.fallbackLocale;
let id = value;
if (id) {
id = id.toString();
const relatedDocumentQuery = {
collection: relatedCollection,
where: {
...(args.where || {}),
_id: {
equals: id,
},
},
res: context.res,
req: {
...context.req,
locale,
fallbackLocale,
},
depth: 0,
pagination: false,
};
const relatedDocument = await find(relatedDocumentQuery);
if (relatedDocument.docs[0]) return relatedDocument.docs[0];
return null;
}
return null;
},
};
const whereFields = this.collections[relationTo].config.fields;
upload.args.where = {
type: this.buildWhereInputType(
uploadName,
whereFields,
uploadName,
),
};
return upload;
},
radio: (field: RadioField) => ({
type: withNullableType(
field,
new GraphQLEnumType({
name: combineParentName(parentName, field.name),
values: formatOptions(field),
}),
),
}),
checkbox: (field: CheckboxField) => ({ type: withNullableType(field, GraphQLBoolean) }),
select: (field: SelectField) => {
const fullName = combineParentName(parentName, field.name);
let type: GraphQLType = new GraphQLEnumType({
name: fullName,
values: formatOptions(field),
});
type = field.hasMany ? new GraphQLList(type) : type;
type = withNullableType(field, type);
return { type };
},
relationship: (field: RelationshipField) => {
const { relationTo, label } = field;
const isRelatedToManyCollections = Array.isArray(relationTo);
const hasManyValues = field.hasMany;
const relationshipName = combineParentName(parentName, label === false ? toWords(field.name, true) : label);
let type;
let relationToType = null;
if (Array.isArray(relationTo)) {
relationToType = new GraphQLEnumType({
name: `${relationshipName}_RelationTo`,
values: relationTo.reduce((relations, relation) => ({
...relations,
[formatName(relation)]: {
value: relation,
},
}), {}),
});
const types = relationTo.map((relation) => this.collections[relation].graphQL.type);
type = new GraphQLObjectType({
name: `${relationshipName}_Relationship`,
fields: {
relationTo: {
type: relationToType,
},
value: {
type: new GraphQLUnionType({
name: relationshipName,
types,
async resolveType(data, { req: { payload } }) {
return payload.collections[data.collection].graphQL.type.name;
},
}),
},
},
});
} else {
({ type } = this.collections[relationTo as string].graphQL);
}
// If the relationshipType is undefined at this point,
// it can be assumed that this blockType can have a relationship
// to itself. Therefore, we set the relationshipType equal to the blockType
// that is currently being created.
type = type || newlyCreatedBlockType;
const relationshipArgs: {
locale?: unknown
fallbackLocale?: unknown
where?: unknown
page?: unknown
limit?: unknown
} = {};
if (this.config.localization) {
relationshipArgs.locale = {
type: this.types.localeInputType,
};
relationshipArgs.fallbackLocale = {
type: this.types.fallbackLocaleInputType,
};
}
const {
collections,
operations: {
collections: {
find,
},
},
} = this;
const relationship = {
args: relationshipArgs,
type: hasManyValues ? new GraphQLList(type) : type,
extensions: { complexity: 10 },
async resolve(parent, args, context) {
const value = parent[field.name];
const locale = args.locale || context.req.locale;
const fallbackLocale = args.fallbackLocale || context.req.fallbackLocale;
let relatedCollectionSlug = field.relationTo;
if (hasManyValues) {
const results = [];
const resultPromises = [];
const createPopulationPromise = async (relatedDoc, i) => {
let id = relatedDoc;
let collectionSlug = field.relationTo;
if (isRelatedToManyCollections) {
collectionSlug = relatedDoc.relationTo;
id = relatedDoc.value;
}
const result = await find({
collection: collections[collectionSlug as string],
where: {
...(args.where || {}),
_id: {
equals: id,
},
},
res: context.res,
req: {
...context.req,
locale,
fallbackLocale,
},
depth: 0,
pagination: false,
});
if (result.docs.length === 1) {
if (isRelatedToManyCollections) {
results[i] = {
relationTo: collectionSlug,
value: {
...result.docs[0],
collection: collectionSlug,
},
};
} else {
[results[i]] = result.docs;
}
}
};
if (value) {
value.forEach((relatedDoc, i) => {
resultPromises.push(createPopulationPromise(relatedDoc, i));
});
}
await Promise.all(resultPromises);
return results;
}
let id = value;
if (isRelatedToManyCollections && value) {
id = value.value;
relatedCollectionSlug = value.relationTo;
}
if (id) {
id = id.toString();
const relatedDocumentQuery = {
collection: collections[relatedCollectionSlug as string],
where: {
...(args.where || {}),
id: {
equals: id,
},
},
...context,
depth: 0,
};
if (args.page) relatedDocumentQuery.paginate.page = args.page;
if (args.limit) relatedDocumentQuery.paginate.limit = args.limit;
const relatedDocument = await find(relatedDocumentQuery);
if (relatedDocument.docs[0]) {
if (isRelatedToManyCollections) {
return {
relationTo: relatedCollectionSlug,
value: {
...relatedDocument.docs[0],
collection: relatedCollectionSlug,
},
};
}
return relatedDocument.docs[0];
}
return null;
}
return null;
},
};
if (hasManyValues) {
relationship.args.page = { type: GraphQLInt };
relationship.args.limit = { type: GraphQLInt };
}
if (Array.isArray(relationTo)) {
const relatedCollectionFields = relationTo.reduce((allFields, relation) => [
...allFields,
...collections[relation].config.fields,
], []);
relationship.args.where = {
type: this.buildWhereInputType(
relationshipName,
relatedCollectionFields,
relationshipName,
),
};
} else {
const whereFields = this.collections[relationTo].config.fields;
relationship.args.where = {
type: this.buildWhereInputType(
relationshipName,
whereFields,
relationshipName,
),
};
}
return relationship;
},
array: (field: ArrayField) => {
const fullName = combineParentName(parentName, field.label === false ? toWords(field.name, true) : field.label);
let type = recursiveBuildObjectType(fullName, field.fields, fullName);
type = new GraphQLList(withNullableType(field, type));
return { type };
},
group: (field: GroupField) => {
const fullName = combineParentName(parentName, field.label === false ? toWords(field.name, true) : field.label);
const type = recursiveBuildObjectType(fullName, field.fields, fullName);
return { type };
},
blocks: (field: BlockField) => {
const blockTypes = field.blocks.map((block) => {
this.buildBlockType(block);
return this.types.blockTypes[block.slug];
});
const fullName = combineParentName(parentName, field.label === false ? toWords(field.name, true) : field.label);
const type = new GraphQLList(new GraphQLUnionType({
name: fullName,
types: blockTypes,
resolveType: (data) => this.types.blockTypes[data.blockType].name,
}));
return { type };
},
row: (field) => field.fields.reduce((subFieldSchema, subField) => {
const buildSchemaType = fieldToSchemaMap[subField.type];
if (!fieldIsPresentationalOnly(subField) && buildSchemaType) {
return {
...subFieldSchema,
[formatName(subField.name)]: buildSchemaType(subField),
};
}
return subFieldSchema;
}, {}),
};
const objectSchema = {
name,
fields: () => fields.reduce((schema, field) => {
if (!fieldIsPresentationalOnly(field) && !field.hidden) {
const fieldSchema = fieldToSchemaMap[field.type];
if (fieldSchema) {
if (fieldAffectsData(field)) {
return {
...schema,
[formatName(field.name)]: fieldSchema(field),
};
}
return {
...schema,
...fieldSchema(field),
};
}
}
return schema;
}, baseFields),
};
const newlyCreatedBlockType = new GraphQLObjectType(objectSchema);
return newlyCreatedBlockType;
}
Example #16
Source File: Generator.ts From graphql-ts-client with MIT License | 4 votes |
async generate() {
const schema = await this.loadSchema();
validateConfigAndSchema(this.config, schema);
await this.rmdirIfNecessary();
await this.mkdirIfNecessary();
const inheritanceInfo = new InheritanceInfo(schema);
const fetcherTypes: Array<GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType> = [];
const connections = new Map<GraphQLType, Connection>();
const edgeTypes = new Set<GraphQLType>();
const inputTypes: GraphQLInputObjectType[] = [];
const enumTypes: GraphQLEnumType[] = [];
const typeMap = schema.getTypeMap();
for (const typeName in typeMap) {
if (!typeName.startsWith("__")) {
const type = typeMap[typeName]!;
if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) {
const tuple = connectionTypeTuple(type);
if (tuple !== undefined) {
connections.set(tuple[0], {
edgeType: tuple[1],
nodeType: tuple[2]
});
edgeTypes.add(tuple[1]);
}
}
if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType || type instanceof GraphQLUnionType) {
fetcherTypes.push(type);
} else if (type instanceof GraphQLInputObjectType) {
inputTypes.push(type);
} else if (type instanceof GraphQLEnumType) {
enumTypes.push(type);
}
}
}
const configuredIdFieldMap = this.config.idFieldMap ?? {};
const entityTypes = new Set<GraphQLType>();
const embeddedTypes = new Set<GraphQLType>();
const idFieldMap = new Map<GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType, GraphQLField<any, any>>();
const triggerableTypes = new Set<GraphQLType>();
const typesWithParameterizedField = new Set<GraphQLObjectType | GraphQLInterfaceType>();
for (const fetcherType of fetcherTypes) {
if (connections.has(fetcherType) || edgeTypes.has(fetcherType)) {
continue;
}
if (fetcherType instanceof GraphQLObjectType || fetcherType instanceof GraphQLInterfaceType) {
const fieldMap = fetcherType.getFields();
if (fetcherType.name === "Query") {
if (Object.keys(fieldMap).length !== 0) {
triggerableTypes.add(fetcherType);
}
} else {
let idFieldName = configuredIdFieldMap[fetcherType.name];
if (idFieldName === undefined) {
let configuredUpcastType: GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType | undefined = undefined;
inheritanceInfo.visitUpcastTypesRecursively(fetcherType, upcastType => {
const newIdFieldName = configuredIdFieldMap[upcastType.name];
if (idFieldName === undefined) {
configuredUpcastType = upcastType;
idFieldName = newIdFieldName;
} else if (idFieldName !== newIdFieldName) {
throw new Error(
`Conflict id property configuration: ${configuredUpcastType!.name}.${idFieldName} and ${fetcherType.name}.${newIdFieldName}`
);
}
});
}
const idField = fieldMap[idFieldName ?? "id"];
if (idField !== undefined && idField !== null) {
idFieldMap.set(fetcherType, idField);
entityTypes.add(fetcherType);
if (Object.keys(fieldMap).length !== 1) {
triggerableTypes.add(fetcherType);
}
} else {
embeddedTypes.add(fetcherType);
}
}
for (const fieldName in fieldMap) {
const args = fieldMap[fieldName].args;
if (args.length !== 0) {
typesWithParameterizedField.add(fetcherType);
break;
}
}
}
}
const ctx: FetcherContext = {
schema,
inheritanceInfo,
fetcherTypes,
entityTypes,
embeddedTypes,
connections,
edgeTypes,
triggerableTypes,
idFieldMap,
typesWithParameterizedField
};
const promises: Promise<any>[] = [];
if (fetcherTypes.length !== 0) {
await this.mkdirIfNecessary("fetchers");
promises.push(this.generateFetcherTypes(ctx));
}
if (inputTypes.length !== 0) {
await this.mkdirIfNecessary("inputs");
promises.push(this.generateInputTypes(inputTypes));
}
if (enumTypes.length !== 0) {
await this.mkdirIfNecessary("enums");
promises.push(this.generateEnumTypes(enumTypes));
}
promises.push(this.generateCommonTypes(schema, inheritanceInfo));
this.generateServices(ctx, promises);
promises.push(this.writeIndex(schema));
await Promise.all(promises);
}
Example #17
Source File: getFields.test.ts From amplify-codegen with Apache License 2.0 | 4 votes |
describe('getField', () => {
const nestedType = new GraphQLObjectType({
name: 'NestedObject',
fields: () => ({
level: { type: GraphQLInt },
subObj: { type: nestedType },
}),
});
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
foo: { type: GraphQLInt },
nested: { type: nestedType },
},
}),
});
it('should support simple scalar', () => {
const queries = schema.getQueryType().getFields();
expect(getFields(queries.foo, schema, 3, { useExternalFragmentForS3Object: false })).toEqual({
name: 'foo',
fields: [],
fragments: [],
hasBody: false,
});
expect(getFragment).not.toHaveBeenCalled();
});
it('it should recursively resolve fields up to max depth', () => {
const queries = schema.getQueryType().getFields();
expect(getFields(queries.nested, schema, 2, { useExternalFragmentForS3Object: false })).toEqual({
name: 'nested',
fields: [
{
name: 'level',
fields: [],
fragments: [],
hasBody: false,
},
{
name: 'subObj',
fields: [
{
name: 'level',
fields: [],
fragments: [],
hasBody: false,
},
],
fragments: [],
hasBody: true,
},
],
fragments: [],
hasBody: true,
});
});
it('should not return anything for complex type when the depth is < 1', () => {
const queries = schema.getQueryType().getFields();
expect(getFields(queries.nested, schema, 0, { useExternalFragmentForS3Object: false })).toBeUndefined();
});
describe('When type is an Interface', () => {
beforeEach(() => {
jest.resetAllMocks();
});
const shapeInterfaceType = new GraphQLInterfaceType({
name: 'Entity',
fields: {
name: { type: GraphQLString },
},
});
const rectangleType = new GraphQLObjectType({
name: 'Rectangle',
fields: {
name: { type: GraphQLString },
length: { type: GraphQLInt },
width: { type: GraphQLInt },
},
interfaces: () => [shapeInterfaceType],
});
const circleType = new GraphQLObjectType({
name: 'Circle',
fields: {
name: { type: GraphQLString },
radius: { type: GraphQLInt },
},
interfaces: () => [shapeInterfaceType],
});
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
shapeInterface: { type: shapeInterfaceType },
},
}),
types: [circleType, rectangleType],
});
it('interface - should return fragments of all the implementations', () => {
const maxDepth = 2;
const getPossibleTypeSpy = jest.spyOn(schema, 'getPossibleTypes');
getFields(schema.getQueryType().getFields().shapeInterface, schema, maxDepth, { useExternalFragmentForS3Object: false });
expect(getPossibleTypeSpy).toHaveBeenCalled();
expect(getFragment).toHaveBeenCalled();
const commonField = {
name: 'name',
fragments: [],
hasBody: false,
fields: [],
};
expect(getFragment.mock.calls[0][0]).toEqual(circleType);
expect(getFragment.mock.calls[0][1]).toEqual(schema);
expect(getFragment.mock.calls[0][2]).toEqual(maxDepth);
expect(getFragment.mock.calls[0][3]).toEqual([commonField]);
expect(getFragment.mock.calls[1][0]).toEqual(rectangleType);
expect(getFragment.mock.calls[1][1]).toEqual(schema);
expect(getFragment.mock.calls[1][2]).toEqual(maxDepth);
expect(getFragment.mock.calls[1][3]).toEqual([commonField]);
});
});
describe('When type is an union', () => {
beforeEach(() => {
jest.resetAllMocks();
});
const rectangleType = new GraphQLObjectType({
name: 'Rectangle',
fields: {
length: { type: GraphQLInt },
width: { type: GraphQLInt },
},
});
const circleType = new GraphQLObjectType({
name: 'Circle',
fields: {
radius: { type: GraphQLInt },
},
});
const shapeResultUnion = new GraphQLUnionType({
name: 'ShapeResultUnion',
types: [circleType, rectangleType],
});
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
shapeResult: { type: shapeResultUnion },
},
}),
});
it('union - should return fragments of all the types', () => {
const maxDepth = 2;
const getPossibleTypeSpy = jest.spyOn(schema, 'getPossibleTypes');
getFields(schema.getQueryType().getFields().shapeResult, schema, maxDepth, { useExternalFragmentForS3Object: false });
expect(getPossibleTypeSpy).toHaveBeenCalled();
expect(getFragment).toHaveBeenCalled();
const commonField = []; // unions don't have to have common field
expect(getFragment.mock.calls[0][0]).toEqual(circleType);
expect(getFragment.mock.calls[0][1]).toEqual(schema);
expect(getFragment.mock.calls[0][2]).toEqual(maxDepth);
expect(getFragment.mock.calls[0][3]).toEqual(commonField);
expect(getFragment.mock.calls[1][0]).toEqual(rectangleType);
expect(getFragment.mock.calls[1][1]).toEqual(schema);
expect(getFragment.mock.calls[1][2]).toEqual(maxDepth);
expect(getFragment.mock.calls[1][3]).toEqual(commonField);
});
});
describe('aggregateItems should generate two additional levels', () => {
beforeEach(() => {
jest.resetAllMocks();
});
const aggregateScalarResult = new GraphQLObjectType({
name: 'SearchableAggregateScalarResult',
fields: {
value: { type: GraphQLFloat },
},
});
const aggregateBucketResultItem = new GraphQLObjectType({
name: 'SearchableAggregateBucketResultItem',
fields: {
key: { type: GraphQLString },
doc_count: { type: GraphQLInt },
},
});
const aggregateBucketResult = new GraphQLObjectType({
name: 'SearchableAggregateBucketResult',
fields: {
buckets: { type: aggregateBucketResultItem },
},
});
const aggregateResult = new GraphQLUnionType({
name: 'SearchableAggregateGenericResult',
types: [aggregateScalarResult, aggregateBucketResult],
});
const aggregateItemsObject = new GraphQLObjectType({
name: 'SearchableAggregateResult',
fields: {
name: { type: GraphQLString },
result: { type: aggregateResult },
},
});
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
aggregateItems: { type: aggregateItemsObject },
},
}),
});
it('aggregateItems property should traverse two additional levels to generate required fields with default depth 2', () => {
const maxDepth = 2;
const getPossibleTypeSpy = jest.spyOn(schema, 'getPossibleTypes');
getFields(schema.getQueryType().getFields().aggregateItems, schema, maxDepth, { useExternalFragmentForS3Object: false });
expect(getPossibleTypeSpy).toHaveBeenCalled();
expect(getFragment).toHaveBeenCalled();
const commonField = []; // unions don't have to have common field
expect(getFragment.mock.calls[0][0]).toEqual(aggregateScalarResult);
expect(getFragment.mock.calls[0][1]).toEqual(schema);
expect(getFragment.mock.calls[0][2]).toEqual(maxDepth - 1);
expect(getFragment.mock.calls[0][3]).toEqual(commonField);
expect(getFragment.mock.calls[1][0]).toEqual(aggregateBucketResult);
expect(getFragment.mock.calls[1][1]).toEqual(schema);
expect(getFragment.mock.calls[1][2]).toEqual(maxDepth - 1);
expect(getFragment.mock.calls[1][3]).toEqual(commonField);
});
});
});
Example #18
Source File: index.ts From graphql-mesh with MIT License | 4 votes |
transformSchema(schema: GraphQLSchema, rawSource: SubschemaConfig) {
const federationConfig: FederationConfig<any> = {};
rawSource.merge = {};
if (this.config?.types) {
const queryType = schema.getQueryType();
const queryTypeFields = queryType.getFields();
for (const type of this.config.types) {
rawSource.merge[type.name] = {};
const fields: FederationFieldsConfig = {};
if (type.config?.fields) {
for (const field of type.config.fields) {
fields[field.name] = field.config;
rawSource.merge[type.name].fields = rawSource.merge[type.name].fields || {};
rawSource.merge[type.name].fields[field.name] = rawSource.merge[type.name].fields[field.name] || {};
if (field.config.requires) {
rawSource.merge[type.name].fields[field.name].computed = true;
rawSource.merge[type.name].fields[field.name].selectionSet = `{ ${field.config.requires} }`;
}
}
}
// If a field is a key field, it should be GraphQLID
if (type.config?.keyFields) {
rawSource.merge[type.name].selectionSet = `{ ${type.config.keyFields.join(' ')} }`;
for (const fieldName of type.config.keyFields) {
const objectType = schema.getType(type.name) as GraphQLObjectType;
if (objectType) {
const existingType = objectType.getFields()[fieldName].type;
objectType.getFields()[fieldName].type = isNonNullType(existingType)
? new GraphQLNonNull(GraphQLID)
: GraphQLID;
}
}
}
let resolveReference: MergedTypeResolver<any>;
if (type.config?.resolveReference) {
const resolveReferenceConfig = type.config.resolveReference;
if (typeof resolveReferenceConfig === 'string') {
const fn$ = loadFromModuleExportExpression<any>(resolveReferenceConfig, {
cwd: this.baseDir,
defaultExportName: 'default',
importFn: this.importFn,
});
resolveReference = (...args: any[]) => fn$.then(fn => fn(...args));
} else if (typeof resolveReferenceConfig === 'function') {
resolveReference = resolveReferenceConfig;
} else {
const queryField = queryTypeFields[resolveReferenceConfig.queryFieldName];
const keyArg = resolveReferenceConfig.keyArg || queryField.args[0].name;
const keyField = type.config.keyFields[0];
const isBatch = isListType(queryField.args.find(arg => arg.name === keyArg));
resolveReference = async (root, context, info) => {
const result = await context[this.apiName].Query[queryField.name]({
root,
...(isBatch
? {
key: root[keyField],
argsFromKeys: (keys: string[]) => ({
[keyArg]: keys,
}),
}
: {
args: {
[keyArg]: root[keyField],
},
}),
context,
info,
});
return {
...root,
...result,
};
};
}
rawSource.merge[type.name].resolve = resolveReference;
}
federationConfig[type.name] = {
...type.config,
resolveReference,
fields,
};
}
}
const entityTypes = Object.fromEntries(
Object.entries(federationConfig)
.filter(([, { keyFields }]) => keyFields?.length)
.map(([objectName]) => {
const type = schema.getType(objectName);
if (!isObjectType(type)) {
throw new Error(`Type "${objectName}" is not an object type and can't have a key directive`);
}
return [objectName, type];
})
);
const hasEntities = !!Object.keys(entityTypes).length;
const sdlWithFederationDirectives = addFederationAnnotations(printSchemaWithDirectives(schema), federationConfig);
const schemaWithFederationQueryType = mapSchema(schema, {
[MapperKind.QUERY]: type => {
const config = type.toConfig();
return new GraphQLObjectType({
...config,
fields: {
...config.fields,
...(hasEntities && {
_entities: entitiesField,
_service: {
...serviceField,
resolve: () => ({ sdl: sdlWithFederationDirectives }),
},
}),
},
});
},
});
const schemaWithUnionType = mapSchema(schemaWithFederationQueryType, {
[MapperKind.UNION_TYPE]: type => {
if (type.name === EntityType.name) {
return new GraphQLUnionType({
...EntityType.toConfig(),
types: Object.values(entityTypes),
});
}
return type;
},
});
// Not using transformSchema since it will remove resolveReference
Object.entries(federationConfig).forEach(([objectName, currentFederationConfig]) => {
if (currentFederationConfig.resolveReference) {
const type = schemaWithUnionType.getType(objectName);
if (!isObjectType(type)) {
throw new Error(`Type "${objectName}" is not an object type and can't have a resolveReference function`);
}
type.resolveObject = currentFederationConfig.resolveReference;
}
});
return schemaWithUnionType;
}
Example #19
Source File: generateSchema.test.ts From davinci with MIT License | 4 votes |
describe('schema generation', () => {
describe('#generateGQLSchema', () => {
it('supports primitive types', () => {
class Customer {
@field()
firstname: string;
@field()
age: number;
@field()
isActive: boolean;
@field()
date: Date
@field()
blob: Object
@field({ type: String })
something() {}
}
const { schema } = generateGQLSchema({ type: Customer });
should(schema)
.have.property('name')
.equal('Customer');
const fields = schema.getFields();
should(Object.keys(fields)).be.deepEqual(['firstname', 'age', 'isActive', 'date', 'blob', 'something']);
should(fields.firstname.type).be.equal(GraphQLString);
should(fields.age.type).be.equal(GraphQLFloat);
should(fields.isActive.type).be.equal(GraphQLBoolean);
should(fields.date.type).be.equal(GraphQLDateTime);
should(fields.blob.type).be.equal(GraphQLJSON);
should(fields.something.type).be.equal(GraphQLString);
});
it('supports nested classes', () => {
class CustomerBirth {
@field()
place: string;
}
class Customer {
@field()
birth: CustomerBirth;
}
const { schemas } = generateGQLSchema({ type: Customer });
should(schemas)
.have.property('Customer')
.instanceOf(GraphQLObjectType);
// @ts-ignore
const { birth } = schemas.Customer.getFields();
should(birth.type).be.instanceOf(GraphQLObjectType);
// @ts-ignore
const { place } = schemas.CustomerBirth.getFields();
should(place.type).be.equal(GraphQLString);
});
it('should pass fields defined as function as resolve', () => {
class Customer {
@field({ type: String })
something(parent, args, context, info) {
return { parent, args, context, info };
}
@field({ type: [Number] })
somethingArray(parent, args, context, info) {
return { parent, args, context, info };
}
}
const { schema } = generateGQLSchema({ type: Customer });
should(schema).be.instanceOf(GraphQLObjectType);
// @ts-ignore
const { something, somethingArray } = schema.getFields();
should(something.type).be.equal(GraphQLString);
should(something.resolve).be.equal(Customer.prototype.something);
should(somethingArray.type).be.instanceOf(GraphQLList);
should(somethingArray.type.ofType).be.equal(GraphQLFloat);
should(somethingArray.resolve).be.equal(Customer.prototype.somethingArray);
});
it('should create an external resolver', () => {
class Book {}
class Author {
@field()
title: string;
}
// @ts-ignore
class AuthorController {
@fieldResolver(Book, 'authors', [Author])
getBookAuthors() {}
}
const { schema } = generateGQLSchema({ type: Book });
should(schema).be.instanceOf(GraphQLObjectType);
// @ts-ignore
const { authors } = schema.getFields();
should(authors.type).be.instanceOf(GraphQLList);
should(authors.type.ofType).be.instanceOf(GraphQLObjectType);
should(authors.resolve).be.type('function');
});
it('supports arrays', () => {
class CustomerPhone {
@field()
number: string;
}
class Customer {
@field({ type: [CustomerPhone] })
phones: CustomerPhone[];
@field({ type: [String] })
tags: string[];
}
const schemas: any = generateGQLSchema({ type: Customer }).schemas;
should(Object.keys(schemas.Customer.getFields())).be.deepEqual(['phones', 'tags']);
should(Object.keys(schemas.CustomerPhone.getFields())).be.deepEqual(['number']);
const { tags, phones } = schemas.Customer.getFields();
should(tags.type)
.be.instanceOf(GraphQLList)
.have.property('ofType')
.equal(GraphQLString);
should(phones.type)
.be.instanceOf(GraphQLList)
.have.property('ofType')
.equal(schemas.CustomerPhone);
});
it('supports union types', () => {
class Cat {
@field()
breed: string;
}
class Human {
@field()
phone: string;
}
const resolveType = () => 'Human';
const Animal = new UnionType('Animal', [Cat, Human], resolveType);
const schemas: any = generateGQLSchema({ type: Animal }).schemas;
should(Object.keys(schemas)).be.deepEqual(['Cat', 'Human', 'Animal']);
const types = schemas.Animal.getTypes();
should(types[0].name).be.equal('Cat')
should(types[1].name).be.equal('Human')
should(types).have.length(2);
should(schemas.Animal).be.instanceOf(GraphQLUnionType);
});
it('if transformMetadata is supplied, it should transform the metadata', () => {
class Customer {
@field()
firstname: string;
}
const transformMetadata = (metadata, { type: t, parentType }) => {
const type = _fp.get('opts.type', metadata) || t;
if (type === String && parentType.name !== 'Query') {
class Query {
@field()
EQ: string;
}
return _fp.set('opts.type', Query, metadata);
}
return metadata;
};
const schemas: any = generateGQLSchema({ type: Customer, transformMetadata }).schemas;
const fields = schemas.Customer.getFields();
should(fields.firstname.type).be.instanceOf(GraphQLObjectType);
should(fields.firstname.type.getFields()).have.property('EQ');
});
});
});