All files / lib/graphQl resolvers.js

18.75% Statements 12/64
0% Branches 0/30
0% Functions 0/20
21.05% Lines 12/57
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114  1x   1x     1x 1x   1x                               1x           1x           1x                   1x                                   1x                                                         1x               1x                      
'use strict'
const resolvers = module.exports = { }
 
const _ = {
  assign: require('lodash.assign')
}
const rerouter = require('../rerouter.js')
const jsonApi = require('../..')
 
resolvers.search = (resourceConfig, attribute, parent, args, req, ast) => {
  let path
  // If we don't have a JSON:API resource, go get it
  if (!parent) {
    path = jsonApi._apiConfig.pathPrefix + resourceConfig.resource
    return resolvers.rerouteTo('GET', path, { }, req, ast)
  }
  // Simple attributes can be plucked from the JSON:API resource
  if (!resourceConfig.attributes[attribute]._settings) {
    return parent.attributes[attribute]
  }
  // Related resources need to be requested via the related link
  path = parent.relationships[attribute].links.related
  return resolvers.rerouteTo('GET', path, { }, req, ast)
}
 
resolvers.create = (resourceConfig, parent, args, req, ast) => {
  const path = jsonApi._apiConfig.pathPrefix + resourceConfig.resource
  const data = resolvers.generateResourceFromArgs(args, resourceConfig)
  return resolvers.rerouteTo('POST', path, { data }, req, ast)
}
 
resolvers.update = (resourceConfig, parent, args, req, ast) => {
  const path = `${jsonApi._apiConfig.pathPrefix + resourceConfig.resource}/${args[resourceConfig.resource].id}`
  const data = resolvers.generateResourceFromArgs(args, resourceConfig)
  return resolvers.rerouteTo('PATCH', path, { data }, req, ast)
}
 
resolvers.delete = (resourceConfig, parent, args, req, ast) => {
  const path = `${jsonApi._apiConfig.pathPrefix + resourceConfig.resource}/${args.id}`
  let resource
  return resolvers.rerouteTo('GET', path, { }, req, ast)
    .then(originalResource => {
      resource = originalResource
      return resolvers.rerouteTo('DELETE', path, { }, req, ast)
    }).then(() => resource)
}
 
resolvers.rerouteTo = (method, path, args, req, ast) => new Promise((resolve, reject) => {
  rerouter.route({
    method,
    uri: path,
    params: _.assign({
      fields: resolvers.generateFieldsQueryFromAst(ast),
      filter: resolvers.generateFilterQueryFromAst(ast)
    }, args),
    originalRequest: {
      headers: req.headers || { },
      cookies: req.cookies || { }
    }
  }, (err, json) => {
    if (err) return reject(err.errors.map(e => e.detail))
    resolve(json.data)
  })
})
 
resolvers.generateResourceFromArgs = (args, resourceConfig) => {
  if ((Object.keys(args).length === 1) && (args[resourceConfig.resource])) {
    args = args[resourceConfig.resource]
  }
 
  const data = {
    type: resourceConfig.resource,
    attributes: { },
    relationships: { }
  }
 
  Object.keys(resourceConfig.attributes).forEach(attribute => {
    const joiSchema = resourceConfig.attributes[attribute]
    if (!args[attribute]) return
    if (!joiSchema._settings) {
      data.attributes[attribute] = args[attribute]
    } else {
      data.relationships[attribute] = {
        data: args[attribute]
      };
      [].concat(data.relationships[attribute].data).forEach(relation => {
        relation.type = (joiSchema._settings.__one || joiSchema._settings.__many)[0]
      })
    }
  })
 
  return data
}
 
resolvers.generateFieldsQueryFromAst = ast => {
  const arrays = (ast.fieldASTs || []).map(fieldAST => fieldAST.selectionSet.selections || [ ])
  const combined = [].concat.apply([], arrays)
  let fields = combined.map(thing => (thing.name || { }).value).filter(a => a)
  fields = fields.join(',')
  return fields
}
 
resolvers.generateFilterQueryFromAst = ast => {
  const arrays = (ast.fieldNodes || []).map(function (fieldAST) {
    return fieldAST.arguments || [ ]
  })
  const combined = [].concat.apply([], arrays)
  const filter = { }
  combined.forEach(thing => {
    filter[thing.name.value] = thing.value.value
  })
  return filter
}