Skip to content

Commit

Permalink
Added basic implementation for MichalLytek#124
Browse files Browse the repository at this point in the history
  • Loading branch information
Wessel van der Veen committed Oct 6, 2018
1 parent 5c00d31 commit 85b3f47
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 43 deletions.
27 changes: 27 additions & 0 deletions src/decorators/Metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { getMetadataStorage } from "../metadata/getMetadataStorage";
import { MethodAndPropDecorator } from "./types";

export interface Metadata {
[index: string]: any;
}

export function Metadata(data: Metadata): ClassDecorator | MethodAndPropDecorator | any {
return (
targetOrPrototype: Function | Object,
propertyKey?: string | symbol,
descriptor?: any,
): void => {
if (typeof targetOrPrototype === "function") {
getMetadataStorage().collectAdditionalObjectTypeMetadata({
target: targetOrPrototype,
data,
});
} else if (propertyKey !== undefined) {
getMetadataStorage().collectAdditionalFieldMetadata({
name: propertyKey,
target: targetOrPrototype.constructor,
data,
});
}
};
}
1 change: 1 addition & 0 deletions src/metadata/definitions/class-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export interface ClassMetadata {
fields?: FieldMetadata[];
description?: string;
interfaceClasses?: Function[];
metadata?: any;
}
1 change: 1 addition & 0 deletions src/metadata/definitions/field-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export interface FieldMetadata {
params?: ParamMetadata[];
roles?: any[];
middlewares?: Array<Middleware<any>>;
metadata?: any;
}
1 change: 1 addition & 0 deletions src/metadata/definitions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from "./middleware-metadata";
export * from "./param-metadata";
export * from "./resolver-metadata";
export * from "./union-metadata";
export * from "./metadata";
5 changes: 5 additions & 0 deletions src/metadata/definitions/metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface Metadata {
data: any;
target: Function;
name?: string | symbol;
}
71 changes: 59 additions & 12 deletions src/metadata/metadata-storage.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import { NoExplicitTypeError } from "../errors";
import { ClassType } from "../interfaces";
import {
ResolverMetadata,
ClassMetadata,
FieldMetadata,
ParamMetadata,
FieldResolverMetadata,
AuthorizedMetadata,
BaseResolverMetadata,
ClassMetadata,
EnumMetadata,
UnionMetadata,
UnionMetadataWithSymbol,
FieldMetadata,
FieldResolverMetadata,
Metadata,
MiddlewareMetadata,
ParamMetadata,
ResolverClassMetadata,
ResolverMetadata,
SubscriptionResolverMetadata,
MiddlewareMetadata,
UnionMetadata,
UnionMetadataWithSymbol,
} from "./definitions";
import { ClassType } from "../interfaces";
import { NoExplicitTypeError } from "../errors";
import {
mapSuperResolverHandlers,
ensureReflectMetadataExists,
mapMiddlewareMetadataToArray,
mapSuperFieldResolverHandlers,
ensureReflectMetadataExists,
mapSuperResolverHandlers,
} from "./utils";

export class MetadataStorage {
Expand All @@ -28,6 +29,8 @@ export class MetadataStorage {
subscriptions: SubscriptionResolverMetadata[] = [];
fieldResolvers: FieldResolverMetadata[] = [];
objectTypes: ClassMetadata[] = [];
additionalObjectTypeMetadata: Metadata[] = [];
additionalFieldMetadata: Array<Metadata & { name: string | Symbol }> = [];
inputTypes: ClassMetadata[] = [];
argumentTypes: ClassMetadata[] = [];
interfaceTypes: ClassMetadata[] = [];
Expand All @@ -47,33 +50,43 @@ export class MetadataStorage {
collectQueryHandlerMetadata(definition: ResolverMetadata) {
this.queries.push(definition);
}

collectMutationHandlerMetadata(definition: ResolverMetadata) {
this.mutations.push(definition);
}

collectSubscriptionHandlerMetadata(definition: SubscriptionResolverMetadata) {
this.subscriptions.push(definition);
}

collectFieldResolverMetadata(definition: FieldResolverMetadata) {
this.fieldResolvers.push(definition);
}

collectObjectMetadata(definition: ClassMetadata) {
this.objectTypes.push(definition);
}

collectInputMetadata(definition: ClassMetadata) {
this.inputTypes.push(definition);
}

collectArgsMetadata(definition: ClassMetadata) {
this.argumentTypes.push(definition);
}

collectInterfaceMetadata(definition: ClassMetadata) {
this.interfaceTypes.push(definition);
}

collectAuthorizedFieldMetadata(definition: AuthorizedMetadata) {
this.authorizedFields.push(definition);
}

collectEnumMetadata(definition: EnumMetadata) {
this.enums.push(definition);
}

collectUnionMetadata(definition: UnionMetadata) {
const unionSymbol = Symbol(definition.name);
this.unions.push({
Expand All @@ -82,16 +95,27 @@ export class MetadataStorage {
});
return unionSymbol;
}

collectMiddlewareMetadata(definition: MiddlewareMetadata) {
this.middlewares.push(definition);
}

collectResolverClassMetadata(definition: ResolverClassMetadata) {
this.resolverClasses.push(definition);
}

collectClassFieldMetadata(definition: FieldMetadata) {
this.fields.push(definition);
}

collectAdditionalFieldMetadata(definition: Metadata & { name: string | symbol }) {
this.additionalFieldMetadata.push(definition);
}

collectAdditionalObjectTypeMetadata(definition: Metadata) {
this.additionalObjectTypeMetadata.push(definition);
}

collectHandlerParamMetadata(definition: ParamMetadata) {
this.params.push(definition);
}
Expand Down Expand Up @@ -145,7 +169,9 @@ export class MetadataStorage {
middleware => middleware.target === field.target && middleware.fieldName === field.name,
),
);
field.metadata = this.findAdditionalFieldMetadata(field.target, field.name);
});
def.metadata = this.findAdditionalObjectTypeMetadata(def.target);
def.fields = fields;
});
}
Expand Down Expand Up @@ -251,4 +277,25 @@ export class MetadataStorage {
}
return authorizedField.roles;
}

private findAdditionalFieldMetadata(
target: Function,
fieldName: string,
): Metadata & { name: string | symbol } | undefined {
const metadata = this.additionalFieldMetadata.find(
val => val.target === target && val.name === fieldName,
);
if (!metadata) {
return;
}
return metadata.data;
}

private findAdditionalObjectTypeMetadata(target: Function): Metadata | undefined {
const metadata = this.additionalObjectTypeMetadata.find(val => val.target === target);
if (!metadata) {
return;
}
return metadata.data;
}
}
55 changes: 31 additions & 24 deletions src/schema/schema-generator.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,70 @@
import {
GraphQLSchema,
GraphQLObjectType,
GraphQLNamedType,
graphql,
GraphQLEnumType,
GraphQLEnumValueConfigMap,
GraphQLFieldConfigArgumentMap,
GraphQLFieldConfigMap,
GraphQLOutputType,
GraphQLInputFieldConfigMap,
GraphQLInputObjectType,
GraphQLFieldConfigArgumentMap,
GraphQLInputType,
GraphQLInputFieldConfigMap,
GraphQLInterfaceType,
graphql,
introspectionQuery,
GraphQLEnumType,
GraphQLEnumValueConfigMap,
GraphQLNamedType,
GraphQLObjectType,
GraphQLOutputType,
GraphQLSchema,
GraphQLUnionType,
introspectionQuery,
} from "graphql";
import { withFilter, ResolverFn } from "graphql-subscriptions";

import { getMetadataStorage } from "../metadata/getMetadataStorage";
import { ResolverFn, withFilter } from "graphql-subscriptions";
import { TypeOptions, TypeValue } from "../decorators/types";
import {
GeneratingSchemaError,
MissingSubscriptionTopicsError,
UnionResolveTypeError,
} from "../errors";
import { convertTypeIfScalar, getEnumValuesMap, wrapWithTypeOptions } from "../helpers/types";
import { ResolverFilterData, ResolverTopicData } from "../interfaces";
import {
ResolverMetadata,
ParamMetadata,
ClassMetadata,
ParamMetadata,
ResolverMetadata,
SubscriptionResolverMetadata,
} from "../metadata/definitions";
import { TypeOptions, TypeValue } from "../decorators/types";
import { wrapWithTypeOptions, convertTypeIfScalar, getEnumValuesMap } from "../helpers/types";

import { getMetadataStorage } from "../metadata/getMetadataStorage";
import {
createHandlerResolver,
createAdvancedFieldResolver,
createHandlerResolver,
createSimpleFieldResolver,
} from "../resolvers/create";
import { BuildContext, BuildContextOptions } from "./build-context";
import {
UnionResolveTypeError,
GeneratingSchemaError,
MissingSubscriptionTopicsError,
} from "../errors";
import { ResolverFilterData, ResolverTopicData } from "../interfaces";
import { getFieldMetadataFromInputType, getFieldMetadataFromObjectType } from "./utils";

interface ObjectTypeInfo {
target: Function;
type: GraphQLObjectType;
}

interface InputObjectTypeInfo {
target: Function;
type: GraphQLInputObjectType;
}

interface InterfaceTypeInfo {
target: Function;
type: GraphQLInterfaceType;
}

interface EnumTypeInfo {
enumObj: object;
type: GraphQLEnumType;
}

interface UnionTypeInfo {
unionSymbol: symbol;
type: GraphQLUnionType;
}

// tslint:disable-next-line:no-empty-interface
export interface SchemaGeneratorOptions extends BuildContextOptions {}

Expand Down Expand Up @@ -236,6 +241,7 @@ export abstract class SchemaGenerator {
: createSimpleFieldResolver(field),
description: field.description,
deprecationReason: field.deprecationReason,
...field.metadata,
};
return fieldsMap;
},
Expand Down Expand Up @@ -264,6 +270,7 @@ export abstract class SchemaGenerator {
}
return fields;
},
...objectType.metadata,
}),
};
});
Expand Down

0 comments on commit 85b3f47

Please sign in to comment.