UNPKG

graphql-input-string

Version:

A configurable custom input string type for GraphQL with sanitization and validation.

260 lines (216 loc) 6.58 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _graphql = require('graphql'); var _error = require('graphql/error'); var _language = require('graphql/language'); function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function coerceString(value) { if (typeof value === 'string') { return value; } return null; } // http://stackoverflow.com/a/7592235 var strToUpperCase = function strToUpperCase(str) { return str.toUpperCase(); }; var wordRegex = /(?:^|\s)\S/g; var sentenceRegex = /(?:^|\.\s)\S/g; var newlineRegex = /[\r\n]+/g; var newlineWithWSRegex = /\s*[\r\n]+\s*/g; var whitespace = /\s+/g; var collapseWS = function collapseWS(str) { return str.replace(whitespace, ' '); }; exports.default = function (_ref) { var capitalize = _ref.capitalize; var collapseWhitespace = _ref.collapseWhitespace; var description = _ref.description; var empty = _ref.empty; var error = _ref.error; var lowerCase = _ref.lowerCase; var max = _ref.max; var min = _ref.min; var name = _ref.name; var parse = _ref.parse; var pattern = _ref.pattern; var sanitize = _ref.sanitize; var singleline = _ref.singleline; var test = _ref.test; var trim = _ref.trim; var trimLeft = _ref.trimLeft; var trimRight = _ref.trimRight; var truncate = _ref.truncate; var upperCase = _ref.upperCase; var config = _objectWithoutProperties(_ref, ['capitalize', 'collapseWhitespace', 'description', 'empty', 'error', 'lowerCase', 'max', 'min', 'name', 'parse', 'pattern', 'sanitize', 'singleline', 'test', 'trim', 'trimLeft', 'trimRight', 'truncate', 'upperCase']); if (!name) { throw new Error('"name" is required'); } if (typeof pattern === 'string') { pattern = new RegExp(pattern); } if (typeof error !== 'function') { error = function error(_ref2) { var value = _ref2.value; var ast = _ref2.ast; var message = _ref2.message; var more = message ? ' ' + message + '.' : ''; throw new _error.GraphQLError('Invalid value ' + JSON.stringify(value) + '.' + more, ast ? [ast] : []); }; } if (!description && !test) { // Autogenerate a description if no test is present description = 'A string'; if (min && max) { description += ' between ' + min + ' and ' + max + ' characters'; } else if (min) { description += ' of at least ' + min + ' characters'; } else if (max) { description += ' at most ' + max + ' characters'; } if (pattern) { if (description.length > 'A string'.length) { description += ' and'; } description += ' that matches the pattern \'' + pattern + '\''; } if (trim || trimLeft || trimRight) { if (trim) { description += ' that is trimmed.'; } else { description += 'that is trimmed to the ' + (trimLeft ? 'left' : 'right') + '.'; } } else { description += '.'; } } var parseValue = function parseValue(value, ast) { value = coerceString(value); if (value == null) { return null; } // Sanitization Phase if (value) { if (trim) { value = value.trim(); } else { if (trimLeft) { value = value.trimLeft(); } if (trimRight) { value = value.trimRight(); } } if (value) { if (singleline) { value = value.replace(newlineRegex, ' '); } if (collapseWhitespace) { if (singleline) { value = value.replace(whitespace, ' '); } else { value = value.split(newlineWithWSRegex).map(collapseWS).join('\n'); } } if (truncate != null && value.length > truncate) { value = value.substring(0, truncate); } if (upperCase) { value = value.toUpperCase(); } else if (lowerCase) { value = value.toLowerCase(); } if (capitalize) { switch (capitalize) { case 'characters': value = value.toUpperCase(); break; case 'words': value = value.replace(wordRegex, strToUpperCase); break; case 'sentences': value = value.replace(sentenceRegex, strToUpperCase); break; case 'first': default: value = value[0].toUpperCase() + value.slice(1); break; } } } } if (sanitize) { value = sanitize(value); if (typeof value !== 'string') { return null; } } // Validation Phase if (!empty && !value) { return error({ type: 'empty', value: value, message: 'Expected non-empty string', ast: ast }); } if (min != null && value.length < min) { return error({ type: 'min', value: value, min: min, message: 'Expected minimum length "' + min + '"', ast: ast }); } if (max != null && value.length > max) { return error({ type: 'max', value: value, max: max, message: 'Expected maximum length "' + max + '"', ast: ast }); } if (pattern != null && !pattern.test(value)) { return error({ type: 'pattern', value: value, pattern: pattern, message: 'Unexpected pattern', ast: ast }); } if (test && !test(value)) { return error({ type: 'test', value: value, test: test, ast: ast }); } // Parse Phase if (parse) { return parse(value); } return value; }; return new _graphql.GraphQLScalarType(_extends({ name: name, serialize: coerceString, parseValue: parseValue, description: description, parseLiteral: function parseLiteral(ast) { var kind = ast.kind; var value = ast.value; if (kind === _language.Kind.STRING) { return parseValue(value, ast); } return null; } }, config)); }; module.exports = exports['default'];