all files / semantic-graphql/src/graphql/ getGraphqlPolymorphicScalarType.js

23.33% Statements 7/30
0% Branches 0/8
0% Functions 0/1
31.82% Lines 7/22
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                                                                            
const { GraphQLScalarType } = require('graphql');
const ArrayKeyedMap = require('../ArrayKeyedMap');
const getIriLocalName = require('../utils/getIriLocalName');
const { graphqlScalarTypes, graphqlScalarMethods } = require('../scalars');
 
const memory = new ArrayKeyedMap();
 
function getGraphqlPolymorphicScalarType(g, ranges) {
  if (memory.has(ranges)) return memory.get(ranges);
 
  // Polymorphic range: not cached, so we create it
  // NOTE: The current implementation uses the ordered ranges to pick the prefered type when
  // multiple types are available. (typically float and integer, string and id, etc...)
  const localNames = ranges.map(range => getIriLocalName(range));
  const scalarTypes = localNames.map(localName => graphqlScalarTypes[localName]);
 
  if (scalarTypes.some(type => !type)) throw new Error(`Validate much? ranges: ${ranges}`);
 
  const scalarMethods = scalarTypes.map(type => graphqlScalarMethods.get(type));
 
  // No exception thrown here, GraphQL takes care of it
  const coerce = value => {
    const correctMethods = scalarMethods.filter(({ isOfType }) => isOfType(value));
 
    if (!correctMethods.length) return null;
 
    return correctMethods[0].coerce(value); // Favors precedence in graphqlScalarMethods
  };
 
  const type = new GraphQLScalarType({
    name: `Polymorphic_scalar_${localNames.join('_')}`,
    serialize: coerce,
    parseValue: coerce,
    parseLiteral: ast => scalarMethods
      .map(({ parseLiteral }) => parseLiteral(ast))
      .filter(value => value !== null)[0] || null, // TODO: use find
  });
 
  memory.set(ranges, type);
 
  return type;
}
 
module.exports = getGraphqlPolymorphicScalarType;