source: node_modules/react-immutable-proptypes/src/ImmutablePropTypes.js

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 11.0 KB
Line 
1/**
2 * This is a straight rip-off of the React.js ReactPropTypes.js proptype validators,
3 * modified to make it possible to validate Immutable.js data.
4 * ImmutableTypes.listOf is patterned after React.PropTypes.arrayOf, but for Immutable.List
5 * ImmutableTypes.shape is based on React.PropTypes.shape, but for any Immutable.Iterable
6 */
7var Immutable = require('immutable');
8
9var ANONYMOUS = '<<anonymous>>';
10
11var ImmutablePropTypes;
12
13if (process.env.NODE_ENV !== 'production') {
14 ImmutablePropTypes = {
15 listOf: createListOfTypeChecker,
16 mapOf: createMapOfTypeChecker,
17 orderedMapOf: createOrderedMapOfTypeChecker,
18 setOf: createSetOfTypeChecker,
19 orderedSetOf: createOrderedSetOfTypeChecker,
20 stackOf: createStackOfTypeChecker,
21 iterableOf: createIterableOfTypeChecker,
22 recordOf: createRecordOfTypeChecker,
23 shape: createShapeChecker,
24 contains: createShapeChecker,
25 mapContains: createMapContainsChecker,
26 orderedMapContains: createOrderedMapContainsChecker,
27 // Primitive Types
28 list: createImmutableTypeChecker('List', Immutable.List.isList),
29 map: createImmutableTypeChecker('Map', Immutable.Map.isMap),
30 orderedMap: createImmutableTypeChecker('OrderedMap', Immutable.OrderedMap.isOrderedMap),
31 set: createImmutableTypeChecker('Set', Immutable.Set.isSet),
32 orderedSet: createImmutableTypeChecker('OrderedSet', Immutable.OrderedSet.isOrderedSet),
33 stack: createImmutableTypeChecker('Stack', Immutable.Stack.isStack),
34 seq: createImmutableTypeChecker('Seq', Immutable.Seq.isSeq),
35 record: createImmutableTypeChecker('Record', function(isRecord) { return isRecord instanceof Immutable.Record; }),
36 iterable: createImmutableTypeChecker('Iterable', Immutable.Iterable.isIterable)
37 };
38} else {
39 var productionTypeChecker = function() {
40 invariant(
41 false,
42 'ImmutablePropTypes type checking code is stripped in production.'
43 );
44 };
45 productionTypeChecker.isRequired = productionTypeChecker;
46 var getProductionTypeChecker = function () { return productionTypeChecker };
47
48 ImmutablePropTypes = {
49 listOf: getProductionTypeChecker,
50 mapOf: getProductionTypeChecker,
51 orderedMapOf: getProductionTypeChecker,
52 setOf: getProductionTypeChecker,
53 orderedSetOf: getProductionTypeChecker,
54 stackOf: getProductionTypeChecker,
55 iterableOf: getProductionTypeChecker,
56 recordOf: getProductionTypeChecker,
57 shape: getProductionTypeChecker,
58 contains: getProductionTypeChecker,
59 mapContains: getProductionTypeChecker,
60 orderedMapContains: getProductionTypeChecker,
61 // Primitive Types
62 list: productionTypeChecker,
63 map: productionTypeChecker,
64 orderedMap: productionTypeChecker,
65 set: productionTypeChecker,
66 orderedSet: productionTypeChecker,
67 stack: productionTypeChecker,
68 seq: productionTypeChecker,
69 record: productionTypeChecker,
70 iterable: productionTypeChecker
71 };
72}
73
74ImmutablePropTypes.iterable.indexed = createIterableSubclassTypeChecker('Indexed', Immutable.Iterable.isIndexed);
75ImmutablePropTypes.iterable.keyed = createIterableSubclassTypeChecker('Keyed', Immutable.Iterable.isKeyed);
76
77function getPropType(propValue) {
78 var propType = typeof propValue;
79 if (Array.isArray(propValue)) {
80 return 'array';
81 }
82 if (propValue instanceof RegExp) {
83 // Old webkits (at least until Android 4.0) return 'function' rather than
84 // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
85 // passes PropTypes.object.
86 return 'object';
87 }
88 if (propValue instanceof Immutable.Iterable) {
89 return 'Immutable.' + propValue.toSource().split(' ')[0];
90 }
91 return propType;
92}
93
94function createChainableTypeChecker(validate) {
95 function checkType(isRequired, props, propName, componentName, location, propFullName, ...rest) {
96 propFullName = propFullName || propName;
97 componentName = componentName || ANONYMOUS;
98 if (props[propName] == null) {
99 var locationName = location;
100 if (isRequired) {
101 return new Error(
102 `Required ${locationName} \`${propFullName}\` was not specified in ` +
103 `\`${componentName}\`.`
104 );
105 }
106 } else {
107 return validate(props, propName, componentName, location, propFullName, ...rest);
108 }
109 }
110
111 var chainedCheckType = checkType.bind(null, false);
112 chainedCheckType.isRequired = checkType.bind(null, true);
113
114 return chainedCheckType;
115}
116
117function createImmutableTypeChecker(immutableClassName, immutableClassTypeValidator) {
118 function validate(props, propName, componentName, location, propFullName) {
119 var propValue = props[propName];
120 if(!immutableClassTypeValidator(propValue)) {
121 var propType = getPropType(propValue);
122 return new Error(
123 `Invalid ${location} \`${propFullName}\` of type \`${propType}\` ` +
124 `supplied to \`${componentName}\`, expected \`${immutableClassName}\`.`
125 );
126 }
127 return null;
128 }
129 return createChainableTypeChecker(validate);
130}
131
132function createIterableSubclassTypeChecker(subclassName, validator) {
133 return createImmutableTypeChecker(`Iterable.${subclassName}`, (propValue) =>
134 Immutable.Iterable.isIterable(propValue) && validator(propValue)
135 );
136}
137
138function createIterableTypeChecker(typeChecker, immutableClassName, immutableClassTypeValidator) {
139
140 function validate(props, propName, componentName, location, propFullName, ...rest) {
141 var propValue = props[propName];
142 if (!immutableClassTypeValidator(propValue)) {
143 var locationName = location;
144 var propType = getPropType(propValue);
145 return new Error(
146 `Invalid ${locationName} \`${propFullName}\` of type ` +
147 `\`${propType}\` supplied to \`${componentName}\`, expected an Immutable.js ${immutableClassName}.`
148 );
149 }
150
151 if (typeof typeChecker !== 'function') {
152 return new Error(
153 `Invalid typeChecker supplied to \`${componentName}\` ` +
154 `for propType \`${propFullName}\`, expected a function.`
155 );
156 }
157
158 var propValues = propValue.valueSeq().toArray();
159 for (var i = 0, len = propValues.length; i < len; i++) {
160 var error = typeChecker(propValues, i, componentName, location, `${propFullName}[${i}]`, ...rest);
161 if (error instanceof Error) {
162 return error;
163 }
164 }
165 }
166 return createChainableTypeChecker(validate);
167}
168
169function createKeysTypeChecker(typeChecker) {
170
171 function validate(props, propName, componentName, location, propFullName, ...rest) {
172 var propValue = props[propName];
173 if (typeof typeChecker !== 'function') {
174 return new Error(
175 `Invalid keysTypeChecker (optional second argument) supplied to \`${componentName}\` ` +
176 `for propType \`${propFullName}\`, expected a function.`
177 );
178 }
179
180 var keys = propValue.keySeq().toArray();
181 for (var i = 0, len = keys.length; i < len; i++) {
182 var error = typeChecker(keys, i, componentName, location, `${propFullName} -> key(${keys[i]})`, ...rest);
183 if (error instanceof Error) {
184 return error;
185 }
186 }
187 }
188 return createChainableTypeChecker(validate);
189}
190
191function createListOfTypeChecker(typeChecker) {
192 return createIterableTypeChecker(typeChecker, 'List', Immutable.List.isList);
193}
194
195function createMapOfTypeCheckerFactory(valuesTypeChecker, keysTypeChecker, immutableClassName, immutableClassTypeValidator) {
196 function validate(...args) {
197 return createIterableTypeChecker(valuesTypeChecker, immutableClassName, immutableClassTypeValidator)(...args)
198 || keysTypeChecker && createKeysTypeChecker(keysTypeChecker)(...args)
199 }
200
201 return createChainableTypeChecker(validate);
202}
203
204function createMapOfTypeChecker(valuesTypeChecker, keysTypeChecker) {
205 return createMapOfTypeCheckerFactory(valuesTypeChecker, keysTypeChecker, 'Map', Immutable.Map.isMap);
206}
207
208function createOrderedMapOfTypeChecker(valuesTypeChecker, keysTypeChecker) {
209 return createMapOfTypeCheckerFactory(valuesTypeChecker, keysTypeChecker, 'OrderedMap', Immutable.OrderedMap.isOrderedMap);
210}
211
212function createSetOfTypeChecker(typeChecker) {
213 return createIterableTypeChecker(typeChecker, 'Set', Immutable.Set.isSet);
214}
215
216function createOrderedSetOfTypeChecker(typeChecker) {
217 return createIterableTypeChecker(typeChecker, 'OrderedSet', Immutable.OrderedSet.isOrderedSet);
218}
219
220function createStackOfTypeChecker(typeChecker) {
221 return createIterableTypeChecker(typeChecker, 'Stack', Immutable.Stack.isStack);
222}
223
224function createIterableOfTypeChecker(typeChecker) {
225 return createIterableTypeChecker(typeChecker, 'Iterable', Immutable.Iterable.isIterable);
226}
227
228function createRecordOfTypeChecker(recordKeys) {
229 function validate(props, propName, componentName, location, propFullName, ...rest) {
230 var propValue = props[propName];
231 if (!(propValue instanceof Immutable.Record)) {
232 var propType = getPropType(propValue);
233 var locationName = location;
234 return new Error(
235 `Invalid ${locationName} \`${propFullName}\` of type \`${propType}\` ` +
236 `supplied to \`${componentName}\`, expected an Immutable.js Record.`
237 );
238 }
239 for (var key in recordKeys) {
240 var checker = recordKeys[key];
241 if (!checker) {
242 continue;
243 }
244 var mutablePropValue = propValue.toObject();
245 var error = checker(mutablePropValue, key, componentName, location, `${propFullName}.${key}`, ...rest);
246 if (error) {
247 return error;
248 }
249 }
250 }
251 return createChainableTypeChecker(validate);
252}
253
254// there is some irony in the fact that shapeTypes is a standard hash and not an immutable collection
255function createShapeTypeChecker(shapeTypes, immutableClassName = 'Iterable', immutableClassTypeValidator = Immutable.Iterable.isIterable) {
256 function validate(props, propName, componentName, location, propFullName, ...rest) {
257 var propValue = props[propName];
258 if (!immutableClassTypeValidator(propValue)) {
259 var propType = getPropType(propValue);
260 var locationName = location;
261 return new Error(
262 `Invalid ${locationName} \`${propFullName}\` of type \`${propType}\` ` +
263 `supplied to \`${componentName}\`, expected an Immutable.js ${immutableClassName}.`
264 );
265 }
266 var mutablePropValue = propValue.toObject();
267 for (var key in shapeTypes) {
268 var checker = shapeTypes[key];
269 if (!checker) {
270 continue;
271 }
272 var error = checker(mutablePropValue, key, componentName, location, `${propFullName}.${key}`, ...rest);
273 if (error) {
274 return error;
275 }
276 }
277 }
278 return createChainableTypeChecker(validate);
279}
280
281function createShapeChecker(shapeTypes) {
282 return createShapeTypeChecker(shapeTypes);
283}
284
285function createMapContainsChecker(shapeTypes) {
286 return createShapeTypeChecker(shapeTypes, 'Map', Immutable.Map.isMap);
287}
288
289function createOrderedMapContainsChecker(shapeTypes) {
290 return createShapeTypeChecker(shapeTypes, 'OrderedMap', Immutable.OrderedMap.isOrderedMap);
291}
292
293module.exports = ImmutablePropTypes;
Note: See TracBrowser for help on using the repository browser.