UNPKG

graphql-scalars

Version:

A collection of scalar types not included in base GraphQL.

70 lines (69 loc) 2.71 kB
import { GraphQLScalarType, Kind } from 'graphql'; import { createGraphQLError } from '../error.js'; const routingNumber = (rtn) => '' + rtn; const haveNineDigits = rtn => /^\d{9}$/.test(rtn); /** * Calculates checksum for MIRC format XXXXYYYYC where C is the check digit * * The checksum is position-weighted sum of each of the digits. So, given the * routing number `031001175`, which The last digit (5 in the example), is the * check digit. The calculation is given in terms of the eight first digits: * * 0 3 1 0 0 1 1 7 * x * 3 7 1 3 7 1 3 7 * ____________________________________ * 0 + 21 + 1 + 0 + 0 + 1 + 3 + 49 = 75 * ____________________________________ * 75 + 5 (check digit) = 80 (Must multiple of 10) */ const checksum = rtn => { const weight = [3, 7, 1]; const accumulator = (acc, curr) => acc + curr; const digits = rtn.split('').map(digit => Number.parseInt(digit, 10)); const checkDigit = digits.pop(); const sum = digits.map((digit, index) => digit * weight[index % 3]).reduce(accumulator, 0); return (sum + checkDigit) % 10 === 0; }; const validate = (value, ast) => { if (typeof value !== 'string' && !(typeof value === 'number' && Number.isInteger(value))) { throw createGraphQLError('must be integer or string', ast ? { nodes: ast } : undefined); } const rtn = routingNumber(value); if (!haveNineDigits(rtn)) { throw createGraphQLError('must have nine digits', ast ? { nodes: ast } : undefined); } if (!checksum(rtn)) { throw createGraphQLError("checksum doesn't match", ast ? { nodes: ast } : undefined); } return rtn; }; export const GraphQLRoutingNumberConfig = { name: 'RoutingNumber', description: 'In the US, an ABA routing transit number (`ABA RTN`) is a nine-digit ' + 'code to identify the financial institution.', specifiedByURL: 'https://en.wikipedia.org/wiki/ABA_routing_transit_number', serialize(value) { return validate(value); }, parseValue(value) { return validate(value); }, parseLiteral(ast) { if (ast.kind === Kind.INT || ast.kind === Kind.STRING) { return validate(ast.value, ast); } throw createGraphQLError(`ABA Routing Transit Number can only parse Integer or String but got '${ast.kind}'`, { nodes: ast, }); }, extensions: { codegenScalarType: 'string', jsonSchema: { title: 'RoutingNumber', type: 'string', pattern: /^\d{9}$/.source, }, }, }; export const GraphQLRoutingNumber = /*#__PURE__*/ new GraphQLScalarType(GraphQLRoutingNumberConfig);