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 115 | import { DocumentNode } from 'graphql'; import { graphql } from './graphql'; export function filter(doc: DocumentNode, data: any): any { const resolver = ( fieldName: string, root: any, args: any, context: any, info: any, ) => { return root[info.resultKey]; }; return graphql(resolver, doc, data); } // TODO: we should probably make check call propType and then throw, // rather than the other way round, to avoid constructing stack traces // for things like oneOf uses in React. At this stage I doubt many people // are using this like that, but in the future, who knows? export function check(doc: DocumentNode, data: any): void { const resolver = ( fieldName: string, root: any, args: any, context: any, info: any, ) => { if (!{}.hasOwnProperty.call(root, info.resultKey)) { throw new Error(`${info.resultKey} missing on ${root}`); } return root[info.resultKey]; }; graphql( resolver, doc, data, {}, {}, { fragmentMatcher: () => false, }, ); } // Lifted/adapted from // https://github.com/facebook/react/blob/master/src/isomorphic/classic/types/ReactPropTypes.js const ANONYMOUS = '<<anonymous>>'; function PropTypeError(message) { this.message = message; this.stack = ''; } // Make `instanceof Error` still work for returned errors. PropTypeError.prototype = Error.prototype; const reactPropTypeLocationNames = { prop: 'prop', context: 'context', childContext: 'child context', }; function createChainableTypeChecker(validate) { function checkType( isRequired, props, propName, componentName, location, propFullName, ) { componentName = componentName || ANONYMOUS; propFullName = propFullName || propName; if (props[propName] == null) { const locationName = reactPropTypeLocationNames[location]; if (isRequired) { if (props[propName] === null) { return new PropTypeError( `The ${locationName} \`${propFullName}\` is marked as required ` + `in \`${componentName}\`, but its value is \`null\`.`, ); } return new PropTypeError( `The ${locationName} \`${propFullName}\` is marked as required in ` + `\`${componentName}\`, but its value is \`undefined\`.`, ); } return null; } else { return validate(props, propName, componentName, location, propFullName); } } const chainedCheckType = checkType.bind(null, false); chainedCheckType.isRequired = checkType.bind(null, true); return chainedCheckType; } export function propType(doc) { return createChainableTypeChecker((props, propName) => { const prop = props[propName]; try { check(doc, prop); return null; } catch (e) { // Need a much better error. // Also we aren't checking for extra fields return e; } }); } |