| 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;
}
});
}
|