flow-immutable-models
Version:
Generates model classes from Flow types using Immutable.js
118 lines (100 loc) • 5.97 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = fromJS;
var _getTypeAnnotationWithoutModelType = require('./getTypeAnnotationWithoutModelType');
var _getTypeAnnotationWithoutModelType2 = _interopRequireDefault(_getTypeAnnotationWithoutModelType);
var _typeToExpression = require('./typeToExpression');
var _typeToExpression2 = _interopRequireDefault(_typeToExpression);
var _withoutModelTypeSuffix = require('./withoutModelTypeSuffix');
var _flowTypes = require('./flowTypes');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function getParamTypeAnnotation(j, className, defaultValues) {
if (defaultValues) {
return j.typeAnnotation(j.genericTypeAnnotation(j.identifier(className + 'FromJSType'), null));
}
return j.typeAnnotation(j.genericTypeAnnotation(j.identifier(className + 'ModelType'), null));
}
function modelMapFn(j, nonModelType) {
return j.arrowFunctionExpression([j.identifier('item')], j.callExpression(j.memberExpression(j.identifier(nonModelType), j.identifier('fromJS')), [j.identifier('item')]));
}
function initializeArray(j, typeAlias, propExpression) {
var firstParamType = typeAlias.typeParameters.params[0];
var arrayType = firstParamType.type;
var createListExpression = j.callExpression(j.memberExpression(j.identifier('Immutable'), j.identifier('List')), [propExpression]);
var valueExpression = createListExpression;
if (arrayType === 'GenericTypeAnnotation') {
var modelType = firstParamType.id.name;
var nonModelType = (0, _withoutModelTypeSuffix.withoutModelTypeSuffix)(modelType);
if (nonModelType !== modelType) {
valueExpression = j.callExpression(j.memberExpression(createListExpression, j.identifier('map')), [modelMapFn(j, nonModelType)]);
}
}
return valueExpression;
}
function initializeObject(j, typeAlias, propExpression) {
var valueExpression = j.callExpression(j.memberExpression(j.identifier('Immutable'), j.identifier('Map')), [propExpression]);
var propIndexer = typeAlias.indexers[0];
var modelType = propIndexer && propIndexer.value.id && propIndexer.value.id.name;
var nonModelType = modelType && (0, _withoutModelTypeSuffix.withoutModelTypeSuffix)(modelType);
if (modelType !== nonModelType) {
valueExpression = j.callExpression(j.memberExpression(valueExpression, j.identifier('map')), [modelMapFn(j, nonModelType)]);
}
return valueExpression;
}
function fromJS(j, className, defaultValues, referenceProps) {
var jsonIdentifier = j.identifier('json');
var stateIdentifier = j.identifier('state');
var fromJSIdentifier = j.identifier('fromJS');
var paramTypeAnnotation = getParamTypeAnnotation(j, className, defaultValues);
var referenceInitializationStatements = referenceProps.filter(function (prop) {
var typeAlias = prop.value;
var isNullable = typeAlias.type === 'NullableTypeAnnotation';
var alias = isNullable ? typeAlias.typeAnnotation : typeAlias;
if ((0, _flowTypes.isImmutableType)(alias)) {
return false;
}
return (0, _flowTypes.isArray)(alias) || (0, _flowTypes.isObjectMap)(alias) || (0, _withoutModelTypeSuffix.endsWithModelType)(alias.id && alias.id.name);
}).map(function (prop) {
var valueExpression = void 0;
var typeAlias = prop.value;
var isNullable = typeAlias.type === 'NullableTypeAnnotation';
var alias = isNullable ? typeAlias.typeAnnotation : typeAlias;
var propExpression = j.memberExpression(j.identifier('state'), j.identifier(prop.key.name));
if ((0, _flowTypes.isArray)(alias)) {
valueExpression = initializeArray(j, alias, propExpression);
} else if ((0, _flowTypes.isObjectMap)(alias)) {
valueExpression = initializeObject(j, alias, propExpression);
} else {
var convertedProp = Object.assign({}, prop, {
value: (0, _getTypeAnnotationWithoutModelType2.default)(j, alias)
});
var typeExpression = (0, _typeToExpression2.default)(j, convertedProp.value.id);
valueExpression = j.callExpression(j.memberExpression(typeExpression, fromJSIdentifier), [propExpression]);
}
if (isNullable || prop.optional) {
valueExpression = j.conditionalExpression(propExpression, valueExpression, propExpression);
}
return j.expressionStatement(j.assignmentExpression('=', propExpression, valueExpression));
});
var assignExpressions = [];
var argumentArray = void 0;
if (defaultValues) {
argumentArray = [j.objectExpression([]), j.identifier('default' + className + 'Values'), j.identifier('json')];
} else {
argumentArray = [j.objectExpression([]), j.identifier('json')];
}
var stateObjectTypeAnnotation = j.typeAnnotation(j.genericTypeAnnotation(j.identifier('Object'), null));
var stateVariableIdentifier = Object.assign({}, j.identifier('state'), {
typeAnnotation: stateObjectTypeAnnotation
});
var stateVariable = j.variableDeclarator(stateVariableIdentifier, j.callExpression(j.memberExpression(j.identifier('Object'), j.identifier('assign')), argumentArray));
var assignExpression = j.variableDeclaration('const', [stateVariable]);
assignExpressions.push(assignExpression);
var param = Object.assign({}, jsonIdentifier, { typeAnnotation: paramTypeAnnotation });
var func = j.functionExpression(null, [param], j.blockStatement([].concat(assignExpressions, _toConsumableArray(referenceInitializationStatements), [j.returnStatement(j.newExpression(j.identifier('this'), [j.callExpression(j.memberExpression(j.identifier('Immutable'), j.identifier('Map')), [stateIdentifier])]))])));
func.returnType = j.typeAnnotation(j.genericTypeAnnotation(j.identifier(className), null));
return j.methodDefinition('method', fromJSIdentifier, func, true);
}