Socket
Socket
Sign inDemoInstall

@playlyfe/babel-plugin-flow-react-proptypes

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@playlyfe/babel-plugin-flow-react-proptypes - npm Package Compare versions

Comparing version 3.4.3-patch.1 to 13.0.1-patch.1

340

lib/convertToPropTypes.js

@@ -19,2 +19,74 @@ 'use strict';

function mapGenericToRealType(node, typeParamMapping) {
if (node.type === 'GenericTypeAnnotation' && node.id.type === 'Identifier') {
return typeParamMapping[node.id.name] || node;
} else if (node.type === 'NullableTypeAnnotation') {
var realTypeAnnotation = mapGenericToRealType(node.typeAnnotation, typeParamMapping);
var newNode = Object.assign({}, node, {
typeAnnotation: realTypeAnnotation
});
return newNode;
} else if (node.type === 'UnionTypeAnnotation') {
var realTypes = node.types.map(function (n) {
return mapGenericToRealType(n, typeParamMapping);
});
var _newNode = Object.assign({}, node, {
types: realTypes
});
return _newNode;
} else if (node.type === 'ObjectTypeProperty') {
var realValue = mapGenericToRealType(node.value, typeParamMapping);
var _newNode2 = Object.assign({}, node, {
value: realValue
});
return _newNode2;
} else if (node.type === 'ObjectTypeAnnotation') {
var realProperties = node.properties.map(function (p) {
return mapGenericToRealType(p, typeParamMapping);
});
var _newNode3 = Object.assign({}, node, {
properties: realProperties
});
return _newNode3;
}
return node;
}
function convertGenericToPropTypes(node, typeParamMapping, importedTypes, internalTypes) {
if (node.type === 'GenericTypeAnnotation' && node.id.type === 'Identifier' && !node.typeParameters) {
return convertToPropTypes(typeParamMapping[node.id.name], importedTypes, internalTypes);
} else if (node.type === 'GenericTypeAnnotation' && node.typeParameters) {
var realTypeParameters = node.typeParameters.params.map(function (p) {
return mapGenericToRealType(p, typeParamMapping);
});
return internalTypes[node.id.name](realTypeParameters);
} else if (node.type === 'ArrayTypeAnnotation') {
var realElementType = mapGenericToRealType(node.elementType, typeParamMapping);
var realNode = Object.assign({}, node, {
elementType: realElementType
});
return convertToPropTypes(realNode, importedTypes, internalTypes);
} else if (node.type === 'NullableTypeAnnotation') {
var result = convertGenericToPropTypes(node.typeAnnotation, typeParamMapping, importedTypes, internalTypes);
result.optional = true;
return result;
} else if (node.type === 'UnionTypeAnnotation') {
var types = node.types.map(function (n) {
return mapGenericToRealType(n, typeParamMapping);
});
var _realNode = Object.assign({}, node, {
types: types
});
return convertToPropTypes(_realNode, importedTypes, internalTypes);
} else if (node.type === 'ObjectTypeAnnotation') {
var properties = node.properties.map(function (n) {
return mapGenericToRealType(n, typeParamMapping);
});
var _realNode2 = Object.assign({}, node, {
properties: properties
});
return convertToPropTypes(_realNode2, importedTypes, internalTypes);
}
}
function convertToPropTypes(node, importedTypes, internalTypes) {

@@ -24,2 +96,18 @@ (0, _util.$debug)('convertToPropTypes', node);

if (node.type === 'TypeAlias' && node.typeParameters) {
return function (types) {
var typeParams = node.typeParameters.params.map(function (t) {
return t.name;
});
var typeParamMapping = {};
for (var i = 0; i < typeParams.length; i++) {
typeParamMapping[typeParams[i]] = types[i];
}
// console.log(node.right, typeParamMapping);
return convertGenericToPropTypes(node.right, typeParamMapping, importedTypes, internalTypes);
};
} else if (node.right) {
node = node.right;
}
if (node.type === 'ObjectTypeAnnotation') {

@@ -34,3 +122,5 @@ var properties = [];

var result = convertToPropTypes(subnode, importedTypes, internalTypes);
if (subnode.leadingComments && subnode.leadingComments.length) {
result.leadingComments = subnode.leadingComments;
}
if (Array.isArray(result)) {

@@ -83,114 +173,162 @@ result.forEach(function (prop) {

return _properties;
} else if (node.type === 'FunctionTypeAnnotation') resultPropType = { type: 'func' };else if (node.type === 'AnyTypeAnnotation') resultPropType = { type: 'any' };else if (node.type === 'ExistentialTypeParam') resultPropType = { type: 'any' };else if (node.type === 'MixedTypeAnnotation') resultPropType = { type: 'any' };else if (node.type === 'TypeofTypeAnnotation') resultPropType = { type: 'any' };else if (node.type === 'NumberTypeAnnotation') resultPropType = { type: 'number' };else if (node.type === 'StringTypeAnnotation') resultPropType = { type: 'string' };else if (node.type === 'BooleanTypeAnnotation') resultPropType = { type: 'bool' };else if (node.type === 'VoidTypeAnnotation') resultPropType = { type: 'void' };else if (node.type === 'TupleTypeAnnotation') resultPropType = { type: 'arrayOf', of: { type: 'any' } };else if (node.type === 'NullableTypeAnnotation') {
resultPropType = convertToPropTypes(node.typeAnnotation, importedTypes, internalTypes);
resultPropType.optional = true;
} else if (node.type === 'IntersectionTypeAnnotation') {
var _ref;
} else if (node.type === 'FunctionTypeAnnotation') resultPropType = { type: 'func' };else if (node.type === 'AnyTypeAnnotation') resultPropType = { type: 'any' };
// babylon6 Node Name
else if (node.type === 'ExistentialTypeParam') resultPropType = { type: 'any' };
// babylon7 Node Name
else if (node.type === 'ExistsTypeAnnotation') resultPropType = { type: 'any' };else if (node.type === 'MixedTypeAnnotation') resultPropType = { type: 'any' };else if (node.type === 'TypeofTypeAnnotation') resultPropType = { type: 'any' };else if (node.type === 'NumberTypeAnnotation') resultPropType = { type: 'number' };else if (node.type === 'StringTypeAnnotation') resultPropType = { type: 'string' };else if (node.type === 'BooleanTypeAnnotation') resultPropType = { type: 'bool' };else if (node.type === 'VoidTypeAnnotation') resultPropType = { type: 'void' };else if (node.type === 'TupleTypeAnnotation') resultPropType = { type: 'arrayOf', of: { type: 'any' } };else if (node.type === 'NullableTypeAnnotation') {
resultPropType = convertToPropTypes(node.typeAnnotation, importedTypes, internalTypes);
resultPropType.optional = true;
} else if (node.type === 'IntersectionTypeAnnotation') {
var _ref;
var objectTypeAnnotations = node.types.filter(function (annotation) {
return annotation.type === 'ObjectTypeAnnotation' || annotation.type === 'GenericTypeAnnotation';
});
var objectTypeAnnotations = node.types.filter(function (annotation) {
return annotation.type === 'ObjectTypeAnnotation' || annotation.type === 'GenericTypeAnnotation';
});
var propTypes = objectTypeAnnotations.map(function (node) {
return convertToPropTypes(node, importedTypes, internalTypes);
});
var shapes = propTypes.filter(function (propType) {
return propType.type === 'shape';
});
var propTypes = objectTypeAnnotations.map(function (node) {
return convertToPropTypes(node, importedTypes, internalTypes);
});
var shapes = propTypes.filter(function (propType) {
return propType.type === 'shape';
});
var requiresRuntimeMerge = propTypes.filter(function (propType) {
return propType.type === 'raw' || propType.type === 'shape-intersect-runtime';
});
var mergedProperties = (_ref = []).concat.apply(_ref, _toConsumableArray(shapes.map(function (propType) {
return propType.properties;
})));
var requiresRuntimeMerge = propTypes.filter(function (propType) {
return propType.type === 'raw' || propType.type === 'shape-intersect-runtime';
});
var mergedProperties = (_ref = []).concat.apply(_ref, _toConsumableArray(shapes.map(function (propType) {
return propType.properties;
})));
if (mergedProperties.length === 0 && requiresRuntimeMerge.length === 0) {
resultPropType = { type: 'any' };
} else if (requiresRuntimeMerge.length === 0) {
resultPropType = { 'type': 'shape', properties: mergedProperties };
} else {
// TODO: properties may be a misnomer - that probably means a list of object
// property specifications
resultPropType = { 'type': 'shape-intersect-runtime', properties: propTypes };
}
}
// Exact
else if (node.type === 'GenericTypeAnnotation' && node.id.name === '$Exact') {
resultPropType = {
type: 'exact',
properties: convertToPropTypes(node.typeParameters.params[0], importedTypes, internalTypes)
};
} else if (node.type === 'GenericTypeAnnotation' || node.type === 'ArrayTypeAnnotation') {
if (node.type === 'ArrayTypeAnnotation' || node.id.name === 'Array') {
var arrayType = void 0;
if (node.type === 'ArrayTypeAnnotation') {
arrayType = node.elementType;
if (mergedProperties.length === 0 && requiresRuntimeMerge.length === 0) {
resultPropType = { type: 'any' };
} else if (requiresRuntimeMerge.length === 0) {
resultPropType = { 'type': 'shape', properties: mergedProperties };
} else {
arrayType = node.typeParameters.params[0];
// TODO: properties may be a misnomer - that probably means a list of object
// property specifications
resultPropType = { 'type': 'shape-intersect-runtime', properties: propTypes };
}
if (arrayType.type === 'GenericTypeAnnotation' && arrayType.id.type === 'QualifiedTypeIdentifier' && arrayType.id.qualification.name === 'React' && arrayType.id.id.name === 'Element') {
resultPropType = { type: 'node' };
} else {
resultPropType = { type: 'arrayOf', of: convertToPropTypes(arrayType, importedTypes, internalTypes) };
}
} else if (node.id && node.id.name && internalTypes[node.id.name]) {
resultPropType = Object.assign({}, internalTypes[node.id.name]);
} else if (node.id && node.id.name && importedTypes[node.id.name]) {
resultPropType = { type: 'raw', value: importedTypes[node.id.name] };
} else if (node.id.name === 'Object') {
resultPropType = { type: 'object' };
} else if (node.id.name === 'Function') {
resultPropType = { type: 'func' };
} else {
resultPropType = { type: 'possible-class', value: node.id };
}
} else if (node.type === 'UnionTypeAnnotation') {
var types = node.types;
// https://github.com/brigand/babel-plugin-flow-react-proptypes/issues/147
else if (node.type === 'GenericTypeAnnotation' && node.id.type === 'QualifiedTypeIdentifier' && node.id.qualification && node.id.qualification.name === 'React' && node.id.id && node.id.id.name === 'ElementProps') {
var tp = node.typeParameters && node.typeParameters.params;
if (!tp || tp.length !== 1) {
throw new TypeError('babel-plugin-flow-react-proptypes expected React.ElementProps to have one type parameter');
}
if (tp[0].type === 'StringLiteralTypeAnnotation') {
resultPropType = {
type: 'object',
properties: []
};
} else if (tp[0].type === 'TypeofTypeAnnotation') {
var argument = tp[0].argument;
var id = argument.id;
if (id.type !== 'Identifier') {
throw new TypeError('babel-plugin-flow-react-proptypes expected React.ElementProps<typeof OneIdentifier>, but found some other type parameter');
}
var name = id.name;
var typesWithoutNulls = types.filter(function (t) {
return t.type !== 'NullLiteralTypeAnnotation';
});
resultPropType = {
type: 'reference',
propertyPath: [name, 'propTypes']
};
} else {
throw new TypeError('babel-plugin-flow-react-proptypes expected React.ElementProps to either be e.g. React.ElementProps<\'div\'> or React.ElementProps<typeof SomeComponent> ');
}
}
// Exact
else if (node.type === 'GenericTypeAnnotation' && node.id.name === '$Exact') {
resultPropType = {
type: 'exact',
properties: convertToPropTypes(node.typeParameters.params[0], importedTypes, internalTypes)
};
} else if (node.type === 'GenericTypeAnnotation' || node.type === 'ArrayTypeAnnotation') {
if (node.type === 'ArrayTypeAnnotation' || node.id.name === 'Array') {
var arrayType = void 0;
if (node.type === 'ArrayTypeAnnotation') {
arrayType = node.elementType;
} else if (!node.typeParameters) {
resultPropType = { type: 'array' };
arrayType = null;
} else {
arrayType = node.typeParameters.params[0];
}
if (arrayType && arrayType.type === 'GenericTypeAnnotation' && arrayType.id.type === 'QualifiedTypeIdentifier' && arrayType.id.qualification.name === 'React' && (arrayType.id.id.name === 'Element' || arrayType.id.id.name === 'Node')) {
resultPropType = { type: 'node' };
} else if (arrayType) {
resultPropType = { type: 'arrayOf', of: convertToPropTypes(arrayType, importedTypes, internalTypes) };
}
} else if (node.type === 'GenericTypeAnnotation' && node.id.type === 'QualifiedTypeIdentifier' && node.id.qualification.name === 'React' && (node.id.id.name === 'Element' || node.id.id.name === 'Node')) {
resultPropType = { type: 'node' };
} else if (node.type === 'GenericTypeAnnotation' && node.typeParameters && typeof internalTypes[node.id.name] === 'function') {
resultPropType = Object.assign({}, internalTypes[node.id.name](node.typeParameters.params));
} else if (node.id && node.id.name && internalTypes[node.id.name]) {
resultPropType = Object.assign({}, internalTypes[node.id.name]);
} else if (node.id && node.id.name && importedTypes[node.id.name]) {
resultPropType = { type: 'raw', value: importedTypes[node.id.name] };
} else if (node.id.name === 'Object') {
resultPropType = { type: 'object' };
} else if (node.id.name === 'Function') {
resultPropType = { type: 'func' };
} else {
resultPropType = { type: 'possible-class', value: node.id };
}
} else if (node.type === 'UnionTypeAnnotation') {
var _node = node,
types = _node.types;
// If a NullLiteralTypeAnnotation we know that this union type is not required.
var optional = typesWithoutNulls.length !== types.length;
// e.g. null | string
// 'foo' | null
if (typesWithoutNulls.length === 1) {
resultPropType = convertToPropTypes(typesWithoutNulls[0], importedTypes, internalTypes);
resultPropType.optional = optional;
} else if (typesWithoutNulls.every(function (t) {
return (/Literal/.test(t.type)
);
})) {
// e.g. 'hello' | 5
resultPropType = {
type: 'oneOf',
optional: optional,
options: typesWithoutNulls.map(function (_ref2) {
var value = _ref2.value;
return value;
})
};
} else {
// e.g. string | number
resultPropType = {
type: 'oneOfType',
optional: optional,
options: typesWithoutNulls.map(function (node) {
return convertToPropTypes(node, importedTypes, internalTypes);
})
};
}
} else if (node.type in {
'StringLiteralTypeAnnotation': 0,
'NumericLiteralTypeAnnotation': 0,
'BooleanLiteralTypeAnnotation': 0,
'NullLiteralTypeAnnotation': 0
}) {
resultPropType = { type: 'oneOf', options: [node.value] };
}
var typesWithoutNulls = types.filter(function (t) {
return t.type !== 'NullLiteralTypeAnnotation' && t.type !== 'VoidTypeAnnotation';
});
// If a NullLiteralTypeAnnotation we know that this union type is not required.
var optional = typesWithoutNulls.length !== types.length;
// e.g. null | string
// 'foo' | null
if (typesWithoutNulls.length === 1) {
resultPropType = convertToPropTypes(typesWithoutNulls[0], importedTypes, internalTypes);
resultPropType.optional = optional;
} else if (typesWithoutNulls.every(function (t) {
return (/Literal/.test(t.type)
);
})) {
// e.g. 'hello' | 5
resultPropType = {
type: 'oneOf',
optional: optional,
options: typesWithoutNulls.map(function (_ref2) {
var value = _ref2.value;
return value;
})
};
} else {
// e.g. string | number
resultPropType = {
type: 'oneOfType',
optional: optional,
options: typesWithoutNulls.map(function (node) {
return convertToPropTypes(node, importedTypes, internalTypes);
})
};
}
} else if (node.type in {
'StringLiteralTypeAnnotation': 0,
// Babylon6
'NumericLiteralTypeAnnotation': 0,
// Babylon7
'NumberLiteralTypeAnnotation': 0,
'BooleanLiteralTypeAnnotation': 0,
'NullLiteralTypeAnnotation': 0
}) {
var _value = node.value;
// babylon7 does not provide value for NullLiteralTypeAnnotation
if (node.type === 'NullLiteralTypeAnnotation') {
_value = true;
}
resultPropType = { type: 'oneOf', options: [_value] };
}
if (resultPropType) {

@@ -197,0 +335,0 @@ return resultPropType;

@@ -18,5 +18,14 @@ 'use strict';

var importedTypes = {};
var exportedTypes = {};
var suppress = false;
var omitRuntimeTypeExport = false;
var SUPPRESS_STRING = 'no babel-plugin-flow-react-proptypes';
// The template to use for the dead code elimination check
// if it passes, the prop types will be removed
// currently the 'deadCode' option is off by default, but this may change
var DEFAULT_DCE = 'process.env.NODE_ENV === \'production\'';
// General control flow:

@@ -45,18 +54,34 @@ // Parse flow type annotations in index.js

var getFunctionalComponentTypeProps = function getFunctionalComponentTypeProps(path) {
// Check if this looks like a stateless react component with PropType reference:
var firstParam = path.node.params[0];
var typeAnnotation = firstParam && firstParam.typeAnnotation && firstParam.typeAnnotation.typeAnnotation;
module.exports = function flowReactPropTypes(babel) {
var t = babel.types;
if (!typeAnnotation) {
(0, _util.$debug)('Found stateless component without type definition');
return;
var opts = {};
var _templateCache = {};
function getDcePredicate() {
// opts.deadCode could be a boolean (true for DEFAULT_DCE), or a string to be
// used as a template
// if it's falsy, then just return node without any wrapper
if (!opts.deadCode) return null;
// cache the template since it's going to be used a lot
var templateCode = typeof opts.deadCode === 'string' ? opts.deadCode : DEFAULT_DCE;
if (!_templateCache[templateCode]) {
_templateCache[templateCode] = babel.template(templateCode);
}
// return a ternary
var predicate = _templateCache[templateCode]({}).expression;
return predicate;
}
return getPropsForTypeAnnotation(typeAnnotation);
};
function wrapInDceCheck(node) {
var predicate = getDcePredicate(node);
if (!predicate) return node;
module.exports = function flowReactPropTypes(babel) {
var t = babel.types;
var conditional = t.conditionalExpression(predicate, t.nullLiteral(), node);
return conditional;
}
var isFunctionalReactComponent = function isFunctionalReactComponent(path) {

@@ -77,2 +102,51 @@ if ((path.type === 'ArrowFunctionExpression' || path.type === 'FunctionExpression') && !path.parent.id) {

/**
* Adds propTypes or contextTypes annotations to code
*
* Extracts some shared logic from `annotate`.
*
* @param path
* @param name
* @param attribute - target member name ('propTypes' or 'contextTypes')
* @param typesOrVar - propsOrVar / contextOrVar value
*/
var addAnnotationsToAST = function addAnnotationsToAST(path, name, attribute, typesOrVar) {
var attachPropTypesAST = void 0;
// if type was exported, use the declared variable
var valueNode = null;
if (typeof typesOrVar === 'string') {
valueNode = t.identifier(typesOrVar);
var inner = t.assignmentExpression('=', t.memberExpression(t.identifier(name), t.identifier(attribute)), valueNode);
if (attribute === 'propTypes') {
inner = wrapInDceCheck(inner);
}
attachPropTypesAST = t.expressionStatement(inner);
}
// type was not exported, generate
else {
var propTypesAST = (0, _makePropTypesAst.makePropTypesAstForPropTypesAssignment)(typesOrVar);
valueNode = propTypesAST;
if (attribute === 'propTypes') {
valueNode = wrapInDceCheck(valueNode);
}
if (propTypesAST == null) {
return;
}
attachPropTypesAST = t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier(name), t.identifier(attribute)), valueNode));
}
if (opts.useStatic && (path.type === 'ClassDeclaration' || path.type === 'ClassExpression')) {
var newNode = t.classProperty(t.identifier(attribute), valueNode);
newNode.static = true;
path.node.body.body.push(newNode);
} else {
path.insertAfter(attachPropTypesAST);
}
};
/**
* Called when visiting a node.

@@ -85,27 +159,31 @@ *

* @param path
* @param props
* @param propsOrVar - props or exported props variable reference
* @param contextOrVar - context or exported context variable reference
*/
var annotate = function annotate(path, props) {
var annotate = function annotate(path, propsOrVar) {
var contextOrVar = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var name = void 0;
var targetPath = void 0;
if (path.type === 'ArrowFunctionExpression' || path.type === 'FunctionExpression') {
if (opts.useStatic && (path.type === 'ClassDeclaration' || path.type === 'ClassExpression')) {
targetPath = path;
} else if (path.type === 'ArrowFunctionExpression' || path.type === 'FunctionExpression') {
name = path.parent.id.name;
var basePath = path.parentPath.parentPath;
targetPath = t.isExportDeclaration(basePath.parent) ? basePath.parentPath : basePath;
} else {
} else if (path.node.id) {
name = path.node.id.name;
targetPath = ['Program', 'BlockStatement'].indexOf(path.parent.type) >= 0 ? path : path.parentPath;
} else {
throw new Error('babel-plugin-flow-react-proptypes attempted to add propTypes to a function/class with no name');
}
if (!props) {
throw new Error('Did not find type annotation for ' + name);
if (propsOrVar) {
addAnnotationsToAST(targetPath, name, 'propTypes', propsOrVar);
}
var propTypesAST = (0, _makePropTypesAst.makePropTypesAstForPropTypesAssignment)(props);
if (propTypesAST == null) {
return;
if (contextOrVar) {
addAnnotationsToAST(targetPath, name, 'contextTypes', contextOrVar);
}
var attachPropTypesAST = t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier(name), t.identifier('propTypes')), propTypesAST));
targetPath.insertAfter(attachPropTypesAST);
};

@@ -117,3 +195,3 @@

* Determines if a function is a functional react component and
* inserts the proptypes AST via `annotate`.
* inserts the proptypes and contexttypes AST via `annotate`.
*

@@ -126,6 +204,29 @@ * @param path

}
var props = getFunctionalComponentTypeProps(path);
if (props) {
annotate(path, props);
// Check if this looks like a stateless react component with PropType reference:
var firstParam = path.node.params[0];
var typeAnnotation = firstParam && firstParam.typeAnnotation && firstParam.typeAnnotation.typeAnnotation;
// Check if the component has context annotations
var secondParam = path.node.params[1];
var contextAnnotation = secondParam && secondParam.typeAnnotation && secondParam.typeAnnotation.typeAnnotation;
var propsOrVar = null;
if (!typeAnnotation) {
(0, _util.$debug)('Found stateless component without type definition');
} else {
propsOrVar = typeAnnotation.id && exportedTypes[typeAnnotation.id.name] ? exportedTypes[typeAnnotation.id.name] : getPropsForTypeAnnotation(typeAnnotation);
}
var contextOrVar = void 0;
if (contextAnnotation) {
contextOrVar = contextAnnotation.id && exportedTypes[contextAnnotation.id.name] ? exportedTypes[contextAnnotation.id.name] : getPropsForTypeAnnotation(contextAnnotation);
} else {
contextOrVar = null;
}
if (propsOrVar) {
annotate(path, propsOrVar, contextOrVar);
}
};

@@ -136,7 +237,10 @@

Program: function Program(path, _ref) {
var opts = _ref.opts;
var _opts = _ref.opts;
opts = _opts;
internalTypes = {};
importedTypes = {};
exportedTypes = {};
suppress = false;
omitRuntimeTypeExport = opts.omitRuntimeTypeExport || false;
var directives = path.node.directives;

@@ -160,5 +264,3 @@ if (directives && directives.length) {

(0, _util.$debug)('TypeAlias found');
var right = path.node.right;
var typeAliasName = path.node.id.name;

@@ -169,6 +271,11 @@ if (!typeAliasName) {

var propTypes = convertNodeToPropTypes(right);
var propTypes = convertNodeToPropTypes(path.node);
internalTypes[typeAliasName] = propTypes;
},
ClassDeclaration: function ClassDeclaration(path) {
"ClassExpression|ClassDeclaration": function ClassExpressionClassDeclaration(path) {
if (!opts.useStatic && path.node.type === 'ClassExpression') return;
if (path.node.BPFRP_HIT_FOR_CLASS_ANNOTATION) return;
path.node.BPFRP_HIT_FOR_CLASS_ANNOTATION = true;
if (suppress) return;

@@ -186,17 +293,59 @@ var superClass = path.node.superClass;

// And have type as property annotations or Component<void, Props, void>
var propTypes = null,
contextTypes = null;
// And have type as property annotations
path.node.body.body.forEach(function (bodyNode) {
if (bodyNode && bodyNode.key.name === 'props' && bodyNode.typeAnnotation) {
var props = getPropsForTypeAnnotation(bodyNode.typeAnnotation.typeAnnotation);
return annotate(path, props);
var annotation = bodyNode.typeAnnotation.typeAnnotation;
var props = getPropsForTypeAnnotation(annotation);
if (!props) {
throw new TypeError('Couldn\'t process \`class { props: This }`');
}
propTypes = props;
return;
}
if (bodyNode && bodyNode.key.name === 'context' && bodyNode.typeAnnotation) {
var _annotation = bodyNode.typeAnnotation.typeAnnotation;
var context = getPropsForTypeAnnotation(_annotation);
if (!context) {
throw new TypeError('Couldn\'t process \`class { context: This }`');
}
contextTypes = context;
}
});
// super type parameter
var secondSuperParam = path.node.superTypeParameters && path.node.superTypeParameters.params[1];
// or Component<void, Props, Context>
var secondSuperParam = getPropsTypeParam(path.node);
if (secondSuperParam && secondSuperParam.type === 'GenericTypeAnnotation') {
var typeAliasName = secondSuperParam.id.name;
var props = internalTypes[typeAliasName];
return annotate(path, props);
if (typeAliasName === 'Object') return;
var props = internalTypes[typeAliasName] || importedTypes[typeAliasName];
if (!props) {
throw new TypeError('Couldn\'t find type "' + typeAliasName + '"');
}
propTypes = props;
}
if (secondSuperParam && secondSuperParam.type === 'ObjectTypeAnnotation') {
propTypes = (0, _convertToPropTypes2.default)(secondSuperParam, importedTypes, internalTypes);
}
var thirdSuperParam = getContextTypeParam(path.node);
if (thirdSuperParam && thirdSuperParam.type === 'GenericTypeAnnotation') {
var _typeAliasName = thirdSuperParam.id.name;
if (_typeAliasName === 'Object') return;
var _props = internalTypes[_typeAliasName] || importedTypes[_typeAliasName];
if (!_props) {
throw new TypeError('Couldn\'t find type "' + _typeAliasName + '"');
}
contextTypes = _props;
}
annotate(path, propTypes, contextTypes);
},

@@ -244,5 +393,22 @@ FunctionExpression: function FunctionExpression(path) {

var exportAst = t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('Object'), t.identifier('defineProperty')), [t.identifier('exports'), t.stringLiteral((0, _util.getExportNameForType)(name)), t.objectExpression([t.objectProperty(t.identifier('value'), propTypesAst), t.objectProperty(t.identifier('configurable'), t.booleanLiteral(true))])]));
var conditionalExportsAst = t.ifStatement(t.binaryExpression('!==', t.unaryExpression('typeof', t.identifier('exports')), t.stringLiteral('undefined')), exportAst);
path.insertAfter(conditionalExportsAst);
// create a variable for reuse
var exportedName = (0, _util.getExportNameForType)(name);
exportedTypes[name] = exportedName;
var variableDeclarationAst = t.variableDeclaration('var', [t.variableDeclarator(t.identifier(exportedName), wrapInDceCheck(propTypesAst))]);
path.insertBefore(variableDeclarationAst);
if (!omitRuntimeTypeExport) {
// add the variable to the exports
var exportAst = t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('Object'), t.identifier('defineProperty')), [t.identifier('exports'), t.stringLiteral((0, _util.getExportNameForType)(name)), t.objectExpression([t.objectProperty(t.identifier('value'), t.identifier(exportedName)), t.objectProperty(t.identifier('configurable'), t.booleanLiteral(true))])]));
var exportsDefinedCondition = t.binaryExpression('!==', t.unaryExpression('typeof', t.identifier('exports')), t.stringLiteral('undefined'));
var ifCond = exportsDefinedCondition;
if (opts.deadCode) {
var dceConditional = t.unaryExpression('!', getDcePredicate());
ifCond = t.logicalExpression('&&', dceConditional, ifCond);
}
var conditionalExportsAst = t.ifStatement(ifCond, exportAst);
path.insertAfter(conditionalExportsAst);
}
},

@@ -271,2 +437,10 @@ ImportDeclaration: function ImportDeclaration(path) {

importedTypes[typeName] = (0, _util.getExportNameForType)(typeName);
// https://github.com/brigand/babel-plugin-flow-react-proptypes/issues/129
if (node.source.value === 'react' && typeName === 'ComponentType') {
var ast = t.variableDeclaration('var', [t.variableDeclarator(t.identifier((0, _util.getExportNameForType)(typeName)), t.memberExpression(t.callExpression(t.identifier('require'), [t.stringLiteral('prop-types')]), t.identifier('func')))]);
path.insertAfter(ast);
return;
}
var variableDeclarationAst = t.variableDeclaration('var', [t.variableDeclarator(

@@ -316,2 +490,26 @@ // TODO: use local import name?

};
};
};
function getPropsTypeParam(node) {
if (!node) return null;
if (!node.superTypeParameters) return null;
var superTypes = node.superTypeParameters;
if (superTypes.params.length === 2) {
return superTypes.params[0];
} else if (superTypes.params.length === 3) {
return superTypes.params[0];
} else if (superTypes.params.length === 1) {
return superTypes.params[0];
}
return null;
}
function getContextTypeParam(node) {
if (!node) return null;
if (!node.superTypeParameters) return null;
var superTypes = node.superTypeParameters;
if (superTypes.params.length === 3) {
return superTypes.params[2];
}
return null;
}

@@ -29,2 +29,4 @@ 'use strict';

var anyTemplate = (0, _babelTemplate2.default)('\n(props, propName, componentName) => {\n if (!Object.prototype.hasOwnProperty.call(props, propName)) {\n throw new Error(`Prop \\`${propName}\\` has type \'any\' or \'mixed\', but was not provided to \\`${componentName}\\`. Pass undefined or any other value.`);\n }\n}\n');
/**

@@ -43,11 +45,14 @@ * Top-level function to generate prop-types AST.

function makePropTypesAstForPropTypesAssignment(propTypeData) {
var node = null;
if (propTypeData.type === 'shape-intersect-runtime') {
// For top-level usage, e.g. Foo.proptype, return
// an expression returning an object.
return makeObjectMergeAstForShapeIntersectRuntime(propTypeData);
node = makeObjectMergeAstForShapeIntersectRuntime(propTypeData);
} else if (propTypeData.type === 'shape') {
return makeObjectAstForShape(propTypeData);
node = makeObjectAstForShape(propTypeData);
} else if (propTypeData.type === 'raw') {
return makeObjectAstForRaw(propTypeData);
node = makeObjectAstForRaw(propTypeData);
}
return node;
};

@@ -164,5 +169,10 @@

var key = _ref.key,
value = _ref.value;
value = _ref.value,
leadingComments = _ref.leadingComments;
return t.objectProperty(t.identifier(key), makePropType(value));
var node = t.objectProperty(t.identifier(key), makePropType(value));
if (leadingComments) {
node.leadingComments = leadingComments;
}
return node;
});

@@ -241,4 +251,12 @@ return t.objectExpression(rootProperties);

if (method === 'any' || method === 'string' || method === 'number' || method === 'bool' || method === 'object' || method === 'array' || method === 'func' || method === 'node') {
if (method === 'string' || method === 'number' || method === 'bool' || method === 'object' || method === 'array' || method === 'func' || method === 'node') {
node = t.memberExpression(node, t.identifier(method));
} else if (method === 'any') {
markFullExpressionAsRequired = false;
if (data.isRequired) {
node = anyTemplate().expression;
} else {
node = t.memberExpression(node, t.identifier(method));
}
} else if (method === 'raw') {

@@ -263,5 +281,10 @@ markFullExpressionAsRequired = false;

var key = _ref2.key,
value = _ref2.value;
value = _ref2.value,
leadingComments = _ref2.leadingComments;
return t.objectProperty(t.identifier(key), makePropType(value));
var node = t.objectProperty(t.identifier(key), makePropType(value));
if (leadingComments) {
node.leadingComments = leadingComments;
}
return node;
});

@@ -289,2 +312,9 @@ if (isExact || data.isExact) {

}))]);
} else if (method === 'reference') {
var pp = data.propertyPath.slice();
var valueNode = t.identifier(pp.shift());
while (pp.length) {
valueNode = t.memberExpression(valueNode, t.identifier(pp.shift()));
}
node = t.callExpression(t.memberExpression(node, t.identifier('shape')), [valueNode]);
} else if (method === 'void') {

@@ -291,0 +321,0 @@ markFullExpressionAsRequired = false;

{
"name": "@playlyfe/babel-plugin-flow-react-proptypes",
"version": "3.4.3-patch.1",
"version": "13.0.1-patch.1",
"description": "converts flow types to react proptypes",

@@ -9,3 +9,3 @@ "main": "lib/index.js",

"test": "npm run build && jest --coverage",
"build": "babel src/ --out-dir lib/ --ignore src/__tests__ --presets es2015,stage-1,react",
"build": "cross-env BABEL_ENV=production babel src/ --out-dir lib/ --ignore src/__tests__ --presets es2015,stage-1,react",
"predeploy": "npm run build && npm run lint",

@@ -44,11 +44,15 @@ "prepublish": "npm run build && npm run lint",

"babel-preset-react": "^6.24.1",
"babel-preset-react-native": "^4.0.0",
"babel-preset-stage-1": "^6.24.1",
"chalk": "^1.1.3",
"coveralls": "^2.13.1",
"cross-env": "^5.0.5",
"eslint": "^4.0.0",
"eslint-plugin-react": "^7.0.1",
"jest": "^20.0.4",
"jest-environment-node-debug": "^2.0.0",
"prettier": "^1.4.4",
"react": "^15.5.4",
"react-test-renderer": "^15.5.4"
"react-test-renderer": "^15.5.4",
"uglify-js": "^3.2.2"
},

@@ -55,0 +59,0 @@ "dependencies": {

@@ -119,2 +119,3 @@ A babel plugin to generate React PropTypes definitions from Flow type declarations.

};
exports.default = Foo;

@@ -137,3 +138,3 @@ ```

Also install the prop-types package. This is required for React `>=15.5.0`. For earlier React versions
you can use version `0.21.0` of this plugin, which doesn't use the prop-types pacakge.
you can use version `0.21.0` of this plugin, which doesn't use the prop-types package.

@@ -166,2 +167,40 @@ ```sh

## useStatic
When combining it with some plugins, such as react-transform (also used by react-native in development mode), the way we normally add `propTypes` doesn't work. You can enable the `useStatic` option to cause us to generate code like:
```js
class C extends Component<Props> {
static propTypes = { x: require('prop-types').string }
}
```
Add the option to your babel config.
```json
{
"presets": ["..."],
"plugins": [["flow-react-proptypes", { "useStatic": true }]]
}
```
## deadCode
The deadCode option (disabled by default) adds a predicate to the code allowing both your propTypes definitions and potentially the
entire 'prop-types' package to be excluded in certain builds. Unlike specifying this plugin in the development env, mentioned above,
this also works for packages published to npm.
```json
"plugins": [["flow-react-proptypes", { "deadCode": true }]]
```
The value of `true` is short for `process.env.NODE_ENV === 'production'`. You can alternatively pass any JavaScript expression. If the expression
returns a truthy value, then the propTypes will be removed. This works because e.g. webpack will subsitute the value of `process.env.NODE_ENV` with `'production'`, resulting in the condition being `'production' === 'production'`, and then a minifer sees that the code we're generating can't be executed, and strips it, and the `require('prop-types')` code out of the final bundle.
Example of specifying a custom expression:
```json
"plugins": [["flow-react-proptypes", { "deadCode": "__PROD__" }]]
```
## Suppression

@@ -174,3 +213,3 @@ This plugin isn't perfect. You can disable it for an entire file with this directive (including quotes):

Specifically for react-native you can disable this for files in `node_modules` with the `ignoreNodeModules` config option.
Specifically for react-native you can disable this for files in `node_modules` with the `ignoreNodeModules` config option. In react-native, you'll also want the `useStatic` option.

@@ -180,3 +219,3 @@ ```json

"presets": ["..."],
"plugins": [["flow-react-proptypes", {"ignoreNodeModules": true}]]
"plugins": [["flow-react-proptypes", { "ignoreNodeModules": true }]]
}

@@ -193,2 +232,28 @@ ```

## Minimizing production bundle size
In production, omitting props and minimizing bundle size can be done with the additon of two things:
1. Add the [transform-react-remove-prop-types](https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types) plugin
2. Omit exported types to allow for dead code pruning
There are cases where a library wishes to `export type` making types available in `*.js.flow` shadow files,
but these may have no other purpose during runtime. If you wish to omit the corresponding export of
the generated flow types, using this option with the
[transform-react-remove-prop-types](https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types)
plugin will allow for the smallest production bundle size.
An example snippet from a `.babelrc`:
```json
"production": {
"plugins": [
["transform-react-remove-prop-types", {
"mode": "wrap",
"plugins": [
["babel-plugin-flow-react-proptypes", {"omitRuntimeTypeExport": true}],
"babel-plugin-transform-flow-strip-types",
]
}]
]
}
```
## Custom generator function

@@ -211,2 +276,1 @@ ```js

const FooPropTypes = toPropTypes((t: FooProps) => t);
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc