import { GraphQLResolveInfo , GraphQLArgument , GraphQLField , getNamedType , GraphQLType , } from 'graphql' ; import { GraphQLUpload } from 'apollo-upload-server' ; import { IMiddlewareFunction } from 'graphql-middleware' ; type Maybe < T > = T | null ; param info function getResolverField ( info ) { const { fieldName , parentType } = info ; const typeFields = parentType . getFields ( ) ; return typeFields [ fieldName ] ; } param field function getFieldArguments < TSource , TContext , TArgs > ( field ) { return field . args ; } param f param xs function filterMap < T , U > ( f , xs ) { return xs . reduce ( ( acc , x ) => { const res = f ( x ) ; if ( res !== null ) { return [ res , ... acc ] ; } else { return acc ; } } , [ ] ) ; } param args param arg function getArgumentValue ( args , arg ) { return args [ arg . name ] ; } param f param info param args export function filterMapFieldArguments < T > ( f , info , args ) { const field = getResolverField ( info ) ; const fieldArguments = getFieldArguments ( field ) ; const fWithArguments = arg => f ( arg , getArgumentValue ( args , arg ) ) ; return filterMap ( fWithArguments , fieldArguments ) ; } param type param x export function isGraphQLArgumentType ( type , argument ) { return getNamedType ( argument . type ) . name === getNamedType ( type ) . name ; } export interface IUpload { stream : string ; filename : string ; mimetype : string ; encoding : string ; } interface IUploadArgument { argumentName : string ; upload : Promise < IUpload > | Promise < IUpload > [ ] ; } interface IProcessedUploadArgument < T > { argumentName : string ; upload : T | T [ ] ; } declare type IUploadHandler < T > = ( upload : IUpload ) => Promise < T > ; interface IConfig < T > { uploadHandler : IUploadHandler < T > ; } param def param value export function uploadTypeIdentifier ( def , value ) { if ( isGraphQLArgumentType ( GraphQLUpload , def ) ) { return { argumentName : def . name , upload : value , } ; } else { return null ; } } param args param info function extractUploadArguments ( args , info ) { return filterMapFieldArguments ( uploadTypeIdentifier , info , args ) ; } param arr export function normaliseArguments < T > ( args ) { return args . reduce ( ( acc , val ) => { return { ... acc , [ val . argumentName ] : val . upload , } ; } , { } ) ; } param uploadHandler export function processor < T > ( uploadHandler ) { return function ( { argumentName , upload , } ) : Maybe < Promise < IProcessedUploadArgument < T > > > { if ( Array . isArray ( upload ) ) { const uploads = upload . reduce ( ( acc , file ) => { if ( file !== undefined && file !== null && file . then ) { return [ ... acc , file . then ( uploadHandler ) ] ; } else { return acc ; } } , [ ] ) ; return Promise . all ( uploads ) . then ( res => ( { argumentName : argumentName , upload : res , } ) ) ; } else if ( upload !== undefined && upload !== null && upload . then ) { return upload . then ( uploadHandler ) . then ( res => ( { argumentName : argumentName , upload : res , } ) ) ; } else { return null ; } } ; } param config export function upload < T > ( { uploadHandler } ) { return async ( resolve , parent , args , ctx , info ) => { const uploadArguments = extractUploadArguments ( args , info ) ; const uploads = filterMap ( processor ( uploadHandler ) , uploadArguments ) ; const uploaded = await Promise . all ( uploads ) ; const argsUploaded = normaliseArguments ( uploaded ) ; const argsWithUploads = { ... args , ... argsUploaded } ; return resolve ( parent , argsWithUploads , ctx , info ) ; } ; }