UNPKG

@ephys/graphql-joi-directives

Version:

Adds Joi-powered constraint directive for GraphQL

124 lines (121 loc) 4.25 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildJoiStrDirectiveTypedef = exports.buildJoiStrDirective = void 0; const graphql_1 = require("graphql"); const joi_1 = __importDefault(require("joi")); const _internal_1 = require("./_internal"); class JoiConstrainedString extends _internal_1.JoiConstrainedScalar { buildJoi(fieldName, args) { let schema = joi_1.default.string().label(fieldName); const min = args.min ?? 0; if (min === 0) { schema = schema.allow(''); } for (const argKey of Object.keys(args)) { const argVal = args[argKey]; switch (argKey) { case 'min': schema = schema.min(argVal); break; case 'max': schema = schema.max(argVal); break; case 'length': schema = schema.length(argVal); break; case 'trim': schema = schema.trim(argVal); break; case 'pattern': schema = schema.pattern(parseRegExp(argVal)); break; case 'creditCard': { if (argVal) { schema = schema.creditCard(); } break; } case 'case': schema = schema.case(argVal.toLowerCase()); break; case 'isoDate': { if (argVal) { schema = schema.isoDate(); } break; } case 'isoDuration': { if (argVal) { schema = schema.isoDuration(); } break; } case 'uuidV4': { if (argVal) { schema = schema.uuid({ version: 'uuidv4' }); } break; } default: throw new Error(`Unsupported argument ${argKey}.`); } } return schema; } } function buildJoiStrDirective(tag) { return _internal_1.buildJoiDirective(tag, graphql_1.GraphQLString, JoiConstrainedString); } exports.buildJoiStrDirective = buildJoiStrDirective; function parseRegExp(regExpStr) { if (typeof regExpStr !== 'string') { throw new TypeError('Invalid argument: not a string.'); } const start = regExpStr.indexOf('/'); const end = regExpStr.lastIndexOf('/'); if (start === -1 || start === end) { throw new TypeError('Invalid RegExp syntax, matcher should be surrounded with slashes.'); } const matcher = regExpStr.substring(start + 1, end); if (matcher === '') { throw new TypeError('Invalid RegExp syntax, empty matcher.'); } const options = regExpStr.substr(end + 1); return new RegExp(matcher, options); } function buildJoiStrDirectiveTypedef(directiveName) { return ` directive @${directiveName}( # requires a minimum length of {min} min: Int, # requires a maximum length of {max} max: Int, # requires a length of exactly {length} length: Int, # trims the string before validation trim: Boolean, # ensure the string matches the provided regexp. # example # | pattern: "/[a-zA-Z0-9]/i" pattern: String, # requires the string to match a credit card format creditCard: Boolean, # converts casing, can be 'UPPER' or 'LOWER' case: JoiDirectiveCaseEnum # format must be a valid ISO date isoDate: Boolean, # format must be a valid ISO duration isoDuration: Boolean, # email: EmailInput uuidV4: Boolean ) on INPUT_FIELD_DEFINITION | ARGUMENT_DEFINITION enum JoiDirectiveCaseEnum { UPPER LOWER } `; } exports.buildJoiStrDirectiveTypedef = buildJoiStrDirectiveTypedef;