Skip to content

Commit

Permalink
Fix definitions, interfaces, types and tests isssues
Browse files Browse the repository at this point in the history
  • Loading branch information
MichalLytek committed Sep 2, 2018
1 parent ac65c7a commit a4b2289
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 60 deletions.
7 changes: 7 additions & 0 deletions @types/graphql-query-complexity/graphql.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Complexity } from "graphql-query-complexity";

declare module "graphql/type/definition" {
export interface GraphQLFieldConfig<TSource, TContext, TArgs = { [argName: string]: any }> {
complexity?: Complexity;
}
}
80 changes: 50 additions & 30 deletions @types/graphql-query-complexity/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,55 @@

declare module "graphql-query-complexity" {
import {QueryComplexityOptions} from 'graphql-query-complexity/dist/QueryComplexity';
import QueryComplexity from 'graphql-query-complexity/dist/QueryComplexity';
import { ValidationContext } from 'graphql';
type returnType = (context: ValidationContext) => QueryComplexity ;
export default function createQueryComplexityValidator(options: QueryComplexityOptions): returnType;
import { ValidationContext } from "graphql";
import QueryComplexity, {
QueryComplexityOptions,
} from "graphql-query-complexity/dist/QueryComplexity";

export type ComplexityResolver = (args: any, complexity: number) => number;

export type Complexity = number | ComplexityResolver;

export default function createQueryComplexityValidator(
options: QueryComplexityOptions,
): (context: ValidationContext) => QueryComplexity;
}

declare module "graphql-query-complexity/dist/QueryComplexity" {
import { ValidationContext, FragmentDefinitionNode, OperationDefinitionNode, FieldNode, InlineFragmentNode } from 'graphql';
import { GraphQLUnionType, GraphQLObjectType, GraphQLInterfaceType, GraphQLError } from 'graphql';
export interface QueryComplexityOptions {
maximumComplexity: number;
variables?: Object;
onComplete?: (complexity: number) => void;
createError?: (max: number, actual: number) => GraphQLError;
}
export default class QueryComplexity {
context: ValidationContext;
complexity: number;
options: QueryComplexityOptions;
fragments: {
[name: string]: FragmentDefinitionNode;
};
OperationDefinition: Object;
constructor(context: ValidationContext, options: QueryComplexityOptions);
onOperationDefinitionEnter(operation: OperationDefinitionNode): void;
onOperationDefinitionLeave(): GraphQLError | undefined;
nodeComplexity(node: FieldNode | FragmentDefinitionNode | InlineFragmentNode | OperationDefinitionNode, typeDef: GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType, complexity?: number): number;
createError(): GraphQLError;
getDefaultComplexity(args: Object, childScore: number): number;
}
import {
ValidationContext,
FragmentDefinitionNode,
OperationDefinitionNode,
FieldNode,
InlineFragmentNode,
GraphQLUnionType,
GraphQLObjectType,
GraphQLInterfaceType,
GraphQLError,
} from "graphql";

}
export interface QueryComplexityOptions {
maximumComplexity: number;
variables?: Object;
onComplete?: (complexity: number) => void;
createError?: (max: number, actual: number) => GraphQLError;
}

export default class QueryComplexity {
context: ValidationContext;
complexity: number;
options: QueryComplexityOptions;
fragments: {
[name: string]: FragmentDefinitionNode;
};
OperationDefinition: Object;
constructor(context: ValidationContext, options: QueryComplexityOptions);
onOperationDefinitionEnter(operation: OperationDefinitionNode): void;
onOperationDefinitionLeave(): GraphQLError | undefined;
nodeComplexity(
node: FieldNode | FragmentDefinitionNode | InlineFragmentNode | OperationDefinitionNode,
typeDef: GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType,
complexity?: number,
): number;
createError(): GraphQLError;
getDefaultComplexity(args: Object, childScore: number): number;
}
}
2 changes: 2 additions & 0 deletions src/decorators/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function Field(
schemaName: options.name || propertyKey,
getType,
typeOptions,
complexity: options.complexity,
target: prototype.constructor,
description: options.description,
deprecationReason: options.deprecationReason,
Expand All @@ -51,6 +52,7 @@ export function Field(
schemaName: options.name || propertyKey,
target: prototype.constructor,
handler: isResolverMethod ? (prototype as any)[propertyKey] : undefined,
complexity: options.complexity,
});
}
};
Expand Down
1 change: 1 addition & 0 deletions src/decorators/FieldResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export function FieldResolver(
handler: (prototype as any)[propertyKey],
getType,
typeOptions,
complexity: options.complexity,
description: options.description,
deprecationReason: options.deprecationReason,
});
Expand Down
12 changes: 9 additions & 3 deletions src/decorators/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { GraphQLScalarType } from "graphql";
import { ValidatorOptions } from "class-validator";
import { Complexity } from "graphql-query-complexity";

import { ResolverFilterData, ClassType, ComplexityResolver } from "../interfaces";
import { ResolverFilterData, ClassType } from "../interfaces";

export type TypeValue = ClassType | GraphQLScalarType | Function | object | symbol;
export type ReturnTypeFuncValue = TypeValue | [TypeValue];
Expand All @@ -17,7 +18,6 @@ export type SubscriptionFilterFunc = (

export interface DecoratorTypeOptions {
nullable?: boolean;
complexity?: number | ComplexityResolver;
}
export interface TypeOptions extends DecoratorTypeOptions {
array?: boolean;
Expand All @@ -31,11 +31,17 @@ export interface DepreciationOptions {
export interface ValidateOptions {
validate?: boolean | ValidatorOptions;
}
export interface ComplexityOptions {
complexity?: Complexity;
}
export interface SchemaNameOptions {
name?: string;
}
export type BasicOptions = DecoratorTypeOptions & DescriptionOptions;
export type AdvancedOptions = BasicOptions & DepreciationOptions & SchemaNameOptions;
export type AdvancedOptions = BasicOptions &
DepreciationOptions &
SchemaNameOptions &
ComplexityOptions;

export interface EnumConfig {
name: string;
Expand Down
1 change: 1 addition & 0 deletions src/helpers/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ export function getHandlerInfo(
returnTypeOptions: typeOptions,
description: options.description,
deprecationReason: options.deprecationReason,
complexity: options.complexity,
};
}
11 changes: 0 additions & 11 deletions src/interfaces/ComplexityTypes.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ export * from "./Publisher";
export * from "./ResolverData";
export * from "./ResolverFilterData";
export * from "./ResolverInterface";
export * from "./ComplexityTypes";
3 changes: 3 additions & 0 deletions src/metadata/definitions/field-metadata.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Complexity } from "graphql-query-complexity";

import { ParamMetadata } from "./param-metadata";
import { TypeValueThunk, TypeOptions } from "../../decorators/types";
import { Middleware } from "../../interfaces/Middleware";
Expand All @@ -10,6 +12,7 @@ export interface FieldMetadata {
typeOptions: TypeOptions;
description: string | undefined;
deprecationReason: string | undefined;
complexity: Complexity | undefined;
params?: ParamMetadata[];
roles?: any[];
middlewares?: Array<Middleware<any>>;
Expand Down
3 changes: 3 additions & 0 deletions src/metadata/definitions/resolver-metadata.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Complexity } from "graphql-query-complexity";

import {
TypeValueThunk,
TypeOptions,
Expand All @@ -12,6 +14,7 @@ export interface BaseResolverMetadata {
schemaName: string;
target: Function;
handler: Function | undefined;
complexity: Complexity | undefined;
resolverClassMetadata?: ResolverClassMetadata;
params?: ParamMetadata[];
roles?: any[];
Expand Down
1 change: 1 addition & 0 deletions src/metadata/metadata-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ export class MetadataStorage {
typeOptions: def.typeOptions!,
deprecationReason: def.deprecationReason,
description: def.description,
complexity: def.complexity,
roles: def.roles!,
middlewares: def.middlewares!,
params: def.params!,
Expand Down
10 changes: 5 additions & 5 deletions src/schema/schema-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
} from "../resolvers/create";
import { BuildContext, BuildContextOptions } from "./build-context";
import { UnionResolveTypeError, GeneratingSchemaError } from "../errors";
import { ResolverFilterData, ComplexityGraphQLFieldConfigMap } from "../interfaces";
import { ResolverFilterData } from "../interfaces";
import { getFieldMetadataFromInputType, getFieldMetadataFromObjectType } from "./utils";

interface ObjectTypeInfo {
Expand Down Expand Up @@ -216,7 +216,7 @@ export abstract class SchemaGenerator {
return interfaces;
},
fields: () => {
let fields = objectType.fields!.reduce<ComplexityGraphQLFieldConfigMap<any, any>>(
let fields = objectType.fields!.reduce<GraphQLFieldConfigMap<any, any>>(
(fieldsMap, field) => {
const fieldResolverMetadata = getMetadataStorage().fieldResolvers.find(
resolver =>
Expand All @@ -227,7 +227,7 @@ export abstract class SchemaGenerator {
);
fieldsMap[field.schemaName] = {
type: this.getGraphQLOutputType(field.name, field.getType(), field.typeOptions),
complexity: field.typeOptions.complexity || 1,
complexity: field.complexity || 1,
args: this.generateHandlerArgs(field.params!),
resolve: fieldResolverMetadata
? createAdvancedFieldResolver(fieldResolverMetadata)
Expand Down Expand Up @@ -344,7 +344,7 @@ export abstract class SchemaGenerator {
private static generateHandlerFields<T = any, U = any>(
handlers: ResolverMetadata[],
): GraphQLFieldConfigMap<T, U> {
return handlers.reduce<ComplexityGraphQLFieldConfigMap<T, U>>((fields, handler) => {
return handlers.reduce<GraphQLFieldConfigMap<T, U>>((fields, handler) => {
// omit emitting abstract resolver fields
if (handler.resolverClassMetadata && handler.resolverClassMetadata.isAbstract) {
return fields;
Expand All @@ -359,7 +359,7 @@ export abstract class SchemaGenerator {
resolve: createHandlerResolver(handler),
description: handler.description,
deprecationReason: handler.deprecationReason,
complexity: handler.returnTypeOptions.complexity,
complexity: handler.complexity,
};
return fields;
}, {});
Expand Down
17 changes: 7 additions & 10 deletions tests/functional/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
import { getMetadataStorage } from "../../src/metadata/getMetadataStorage";
import { getSchemaInfo } from "../helpers/getSchemaInfo";
import { ObjectType, Field, Query, Resolver } from "../../src";
import { FieldMetadata } from "../../src/metadata/definitions";

describe("Fields - schema", () => {
let schemaIntrospection: IntrospectionSchema;
Expand Down Expand Up @@ -87,15 +86,6 @@ describe("Fields - schema", () => {
return (fieldType.type as IntrospectionNonNullTypeRef).ofType! as IntrospectionNamedTypeRef;
}

it("should add complexity to the metadata storage", async () => {
const metadatStorage = getMetadataStorage();
const sampleObj = metadatStorage.objectTypes.find(it => it.name === "SampleObject")!;
const complexField = (sampleObj.fields as FieldMetadata[]).find(
it => it.name === "complexField",
);
expect((complexField as FieldMetadata).typeOptions.complexity).toBe(10);
});

// tests
it("should generate schema without errors", async () => {
expect(schemaIntrospection).toBeDefined();
Expand Down Expand Up @@ -282,4 +272,11 @@ describe("Fields - schema", () => {
expect(overwrittenNameFieldType.kind).toEqual(TypeKind.SCALAR);
expect(overwrittenNameFieldType.name).toEqual("String");
});

it("should add complexity info to the metadata storage", async () => {
const metadataStorage = getMetadataStorage();
const sampleObj = metadataStorage.objectTypes.find(it => it.name === "SampleObject")!;
const complexField = sampleObj.fields!.find(it => it.name === "complexField")!;
expect(complexField.complexity).toBe(10);
});
});

0 comments on commit a4b2289

Please sign in to comment.