Skip to content

Commit

Permalink
separate files
Browse files Browse the repository at this point in the history
  • Loading branch information
maticzav committed Jul 15, 2018
1 parent b728e35 commit cd5e722
Show file tree
Hide file tree
Showing 9 changed files with 507 additions and 467 deletions.
180 changes: 180 additions & 0 deletions src/applicator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import {
GraphQLObjectType,
GraphQLFieldResolver,
GraphQLField,
GraphQLSchema,
defaultFieldResolver,
} from 'graphql'
import { IResolverOptions, IResolvers } from 'graphql-tools'
import {
IMiddlewareFunction,
IMiddlewareResolver,
IMiddlewareFieldMap,
IApplyOptions,
IMiddleware,
} from './types'
import {
isMiddlewareFunction,
isGraphQLObjectType,
isMiddlewareResolver,
isMiddlewareWithFragment,
} from './utils'

// Applicator

function wrapResolverInMiddleware<TSource, TContext, TArgs>(
resolver: GraphQLFieldResolver<any, any, any>,
middleware: IMiddlewareResolver<TSource, TContext, TArgs>,
): GraphQLFieldResolver<any, any, any> {
return (parent, args, ctx, info) =>
middleware(
(_parent = parent, _args = args, _ctx = ctx, _info = info) =>
resolver(_parent, _args, _ctx, _info),
parent,
args,
ctx,
info,
)
}

function applyMiddlewareToField<TSource, TContext, TArgs>(
field: GraphQLField<any, any, any>,
options: IApplyOptions,
middleware: IMiddlewareFunction<TSource, TContext, TArgs>,
): IResolverOptions {
if (isMiddlewareWithFragment(middleware) && field.resolve) {
return {
fragment: middleware.fragment,
resolve: wrapResolverInMiddleware(field.resolve, middleware.resolve),
}
} else if (isMiddlewareWithFragment(middleware) && field.subscribe) {
return {
fragment: middleware.fragment,
subscribe: wrapResolverInMiddleware(field.subscribe, middleware.resolve),
}
} else if (isMiddlewareResolver(middleware) && field.resolve) {
return { resolve: wrapResolverInMiddleware(field.resolve, middleware) }
} else if (isMiddlewareResolver(middleware) && field.subscribe) {
return { subscribe: wrapResolverInMiddleware(field.subscribe, middleware) }
} else if (
isMiddlewareWithFragment(middleware) &&
!options.onlyDeclaredResolvers
) {
return {
fragment: middleware.fragment,
resolve: wrapResolverInMiddleware(
defaultFieldResolver,
middleware.resolve,
),
}
} else if (
isMiddlewareResolver(middleware) &&
!options.onlyDeclaredResolvers
) {
return {
resolve: wrapResolverInMiddleware(defaultFieldResolver, middleware),
}
} else {
return { resolve: defaultFieldResolver }
}
}

function applyMiddlewareToType<TSource, TContext, TArgs>(
type: GraphQLObjectType,
options: IApplyOptions,
middleware:
| IMiddlewareFunction<TSource, TContext, TArgs>
| IMiddlewareFieldMap<TSource, TContext, TArgs>,
): IResolvers {
const fieldMap = type.getFields()

if (isMiddlewareFunction(middleware)) {
const resolvers = Object.keys(fieldMap).reduce(
(resolvers, field) => ({
...resolvers,
[field]: applyMiddlewareToField(
fieldMap[field],
options,
middleware as IMiddlewareFunction<TSource, TContext, TArgs>,
),
}),
{},
)

return resolvers
} else {
const resolvers = Object.keys(middleware).reduce(
(resolvers, field) => ({
...resolvers,
[field]: applyMiddlewareToField(
fieldMap[field],
options,
middleware[field],
),
}),
{},
)

return resolvers
}
}

function applyMiddlewareToSchema<TSource, TContext, TArgs>(
schema: GraphQLSchema,
options: IApplyOptions,
middleware: IMiddlewareFunction<TSource, TContext, TArgs>,
): IResolvers {
const typeMap = schema.getTypeMap()

const resolvers = Object.keys(typeMap)
.filter(type => isGraphQLObjectType(typeMap[type]))
.reduce(
(resolvers, type) => ({
...resolvers,
[type]: applyMiddlewareToType(
typeMap[type] as GraphQLObjectType,
options,
middleware,
),
}),
{},
)

return resolvers
}

// Generator

export function generateResolverFromSchemaAndMiddleware<
TSource,
TContext,
TArgs
>(
schema: GraphQLSchema,
options: IApplyOptions,
middleware: IMiddleware<TSource, TContext, TArgs>,
): IResolvers {
if (isMiddlewareFunction(middleware)) {
return applyMiddlewareToSchema(
schema,
options,
middleware as IMiddlewareFunction<TSource, TContext, TArgs>,
)
} else {
const typeMap = schema.getTypeMap()

const resolvers = Object.keys(middleware).reduce(
(resolvers, type) => ({
...resolvers,
[type]: applyMiddlewareToType(
typeMap[type] as GraphQLObjectType,
options,
middleware[type],
),
}),
{},
)

return resolvers
}
}
8 changes: 8 additions & 0 deletions src/constructors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { MiddlewareGenerator } from './generator'
import { IMiddlewareGenerator, IMiddlewareGeneratorConstructor } from './types'

export function middleware<TSource = any, TContext = any, TArgs = any>(
generator: IMiddlewareGeneratorConstructor<TSource, TContext, TArgs>,
): IMiddlewareGenerator<TSource, TContext, TArgs> {
return new MiddlewareGenerator(generator)
}
23 changes: 23 additions & 0 deletions src/fragments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { FragmentReplacement } from './types'
import { IResolvers } from 'graphql-tools/dist/Interfaces'

export function extractFragmentReplacements(
resolvers: IResolvers,
): FragmentReplacement[] {
const fragmentReplacements: FragmentReplacement[] = []

for (const typeName in resolvers) {
const fieldResolvers: any = resolvers[typeName]
for (const fieldName in fieldResolvers) {
const fieldResolver = fieldResolvers[fieldName]
if (typeof fieldResolver === 'object' && fieldResolver.fragment) {
fragmentReplacements.push({
field: fieldName,
fragment: fieldResolver.fragment,
})
}
}
}

return fragmentReplacements
}
21 changes: 21 additions & 0 deletions src/generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {
IMiddlewareGeneratorConstructor,
IMiddleware,
IMiddlewareGenerator,
} from './types'
import { GraphQLSchema } from 'graphql'

export class MiddlewareGenerator<TSource, TContext, TArgs>
implements IMiddlewareGenerator<TSource, TContext, TArgs> {
private generator: IMiddlewareGeneratorConstructor<TSource, TContext, TArgs>

constructor(
generator: IMiddlewareGeneratorConstructor<TSource, TContext, TArgs>,
) {
this.generator = generator
}

generate(schema: GraphQLSchema): IMiddleware<TSource, TContext, TArgs> {
return this.generator(schema)
}
}
Loading

0 comments on commit cd5e722

Please sign in to comment.