Last active
November 29, 2019 10:47
-
-
Save gabriel-dehan/fa64b997227758cef4080e25b7855ed3 to your computer and use it in GitHub Desktop.
Given a component, returns an object with data about all props (what's the type, is it required, what are the options)...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import checkPropTypes from 'check-prop-types'; | |
import pickBy from 'lodash/pickBy'; | |
const getPropsSchema = (component) => { | |
if (component.type.propTypes) { | |
return Object.keys(component.type.propTypes).map((propName) => resolvePropType(component.type.propTypes, propName)); | |
} | |
return []; | |
}; | |
// Because we can't access proptypes, we have to take a prop and run the validator to determine the type | |
const resolvePropType = (propTypes, name) => { | |
// Object of value types to be checked | |
const types = { | |
array: [], | |
string: '', | |
number: 0, | |
bool: true, | |
func: () => {}, | |
object: {}, | |
element: (<div></div>), | |
oneOf: "____", | |
}; | |
for (const typeName in types) { | |
// Get the validator | |
const propTypeValidator = pickBy(propTypes, (_, k) => k === name); | |
// Create objects with default values, for instance { type: '' }, { isLoading: true}, etc... | |
const defaultValueChecker = {}; | |
defaultValueChecker[name] = types[typeName]; | |
// Used to check if the field is required | |
const noValueChecker = {}; | |
noValueChecker[name] = null; | |
// Run the validator for a default value of the given type and with no value | |
const error = checkPropTypes(propTypeValidator, defaultValueChecker, '_', '_'); | |
const isRequiredError = checkPropTypes(propTypeValidator, noValueChecker, '_', '_'); | |
const isRequired = /marked as required/.test(isRequiredError); | |
// If we don't have an error we found the right type | |
if (!error) { | |
return { | |
name: name, | |
required: isRequired, | |
type: typeName, | |
}; | |
// If we have an error the type is not right OR it was a oneOf proptype so we try to extract the options | |
} else if (/one of/.test(error)) { | |
var oneOfArray = /expected one of (\[.*\])/.exec(error); | |
if (oneOfArray && oneOfArray[1]) { | |
const options = JSON.parse(oneOfArray[1]) || []; | |
return { | |
name: name, | |
required: isRequired, | |
type: options.length > 0 ? (typeof options[0]) : undefined, | |
options, | |
}; | |
} | |
} | |
} | |
return { | |
name: name, | |
type: undefined, | |
required: false, | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Result example