|
import {GraphQLObjectType,GraphQLScalarType} from 'graphql/type/definition'; |
|
|
|
function defaultResolveFn(source, args, { fieldName }) { |
|
var property = source[fieldName]; |
|
return typeof property === 'function' ? property.call(source) : property; |
|
} |
|
|
|
const wrapPromise = (next) => { |
|
return (obj, args, info) => { |
|
try { |
|
return Promise.resolve(next(obj, args, info)); |
|
} catch (e) { |
|
return Promise.reject(e); |
|
} |
|
} |
|
} |
|
|
|
const withLogging = (next) => { |
|
return (obj, args, info) => { |
|
console.log(`resolving: ${info.parentType.name}#${info.fieldName}`); |
|
return next(obj, args, info); |
|
} |
|
} |
|
|
|
const withRandomDelay = (max) => { |
|
return (next) => { |
|
return (obj, args, info) => { |
|
return new Promise((resolve, reject) => { |
|
setTimeout(() => { |
|
next(obj, args, info).then(resolve, reject); |
|
}, Math.floor(Math.random() * max)) |
|
}); |
|
} |
|
} |
|
} |
|
|
|
const withTiming = (next) => { |
|
return (obj, args, info) => { |
|
const start = new Date().getTime(); |
|
return Promise.resolve(next(obj, args, info)).then(res => { |
|
info.rootValue.response.timing.fields.push({ |
|
type: info.parentType.name, |
|
field: info.fieldName, |
|
args, |
|
duration: (new Date().getTime() - start) / 1000 |
|
}); |
|
return res; |
|
}); |
|
} |
|
} |
|
|
|
const schemaFieldsForEach = (schema, fn) => { |
|
Object.keys(schema.getTypeMap()) |
|
.filter(typeName => typeName.indexOf('__') !== 0) // remove schema fields... |
|
.map(typeName => schema.getType(typeName)) |
|
.filter(type => type instanceof GraphQLObjectType) // make sure its an object |
|
.forEach(type => { |
|
let fields = type.getFields(); |
|
Object.keys(fields).forEach(fieldName => { |
|
let field = fields[fieldName] |
|
fn(field, type); |
|
}); |
|
}); |
|
} |
|
|
|
schemaFieldsForEach(schema, (field, type) => { |
|
field.resolve = withTiming(withRandomDelay(1000)(withLogging(wrapPromise(field.resolve || defaultResolveFn)))); |
|
}); |