addSchemaLevelResolveFunction.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. Object.defineProperty(exports, "__esModule", { value: true });
  2. var graphql_1 = require("graphql");
  3. // wraps all resolve functions of query, mutation or subscription fields
  4. // with the provided function to simulate a root schema level resolve funciton
  5. function addSchemaLevelResolveFunction(schema, fn) {
  6. // TODO test that schema is a schema, fn is a function
  7. var rootTypes = [
  8. schema.getQueryType(),
  9. schema.getMutationType(),
  10. schema.getSubscriptionType(),
  11. ].filter(function (x) { return !!x; });
  12. rootTypes.forEach(function (type) {
  13. // XXX this should run at most once per request to simulate a true root resolver
  14. // for graphql-js this is an approximation that works with queries but not mutations
  15. var rootResolveFn = runAtMostOncePerRequest(fn);
  16. var fields = type.getFields();
  17. Object.keys(fields).forEach(function (fieldName) {
  18. // XXX if the type is a subscription, a same query AST will be ran multiple times so we
  19. // deactivate here the runOnce if it's a subscription. This may not be optimal though...
  20. if (type === schema.getSubscriptionType()) {
  21. fields[fieldName].resolve = wrapResolver(fields[fieldName].resolve, fn);
  22. }
  23. else {
  24. fields[fieldName].resolve = wrapResolver(fields[fieldName].resolve, rootResolveFn);
  25. }
  26. });
  27. });
  28. }
  29. // XXX badly named function. this doesn't really wrap, it just chains resolvers...
  30. function wrapResolver(innerResolver, outerResolver) {
  31. return function (obj, args, ctx, info) {
  32. return Promise.resolve(outerResolver(obj, args, ctx, info)).then(function (root) {
  33. if (innerResolver) {
  34. return innerResolver(root, args, ctx, info);
  35. }
  36. return graphql_1.defaultFieldResolver(root, args, ctx, info);
  37. });
  38. };
  39. }
  40. // XXX this function only works for resolvers
  41. // XXX very hacky way to remember if the function
  42. // already ran for this request. This will only work
  43. // if people don't actually cache the operation.
  44. // if they do cache the operation, they will have to
  45. // manually remove the __runAtMostOnce before every request.
  46. function runAtMostOncePerRequest(fn) {
  47. var value;
  48. var randomNumber = Math.random();
  49. return function (root, args, ctx, info) {
  50. if (!info.operation['__runAtMostOnce']) {
  51. info.operation['__runAtMostOnce'] = {};
  52. }
  53. if (!info.operation['__runAtMostOnce'][randomNumber]) {
  54. info.operation['__runAtMostOnce'][randomNumber] = true;
  55. value = fn(root, args, ctx, info);
  56. }
  57. return value;
  58. };
  59. }
  60. exports.default = addSchemaLevelResolveFunction;
  61. //# sourceMappingURL=addSchemaLevelResolveFunction.js.map