babel-plugin-redux-state-compose
Version:
compose redux State type
173 lines (129 loc) • 5.66 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _path = require('path');
var _babelTypes = require('babel-types');
var t = _interopRequireWildcard(_babelTypes);
var _babelPluginSyntaxFlow = require('babel-plugin-syntax-flow');
var _babelPluginSyntaxFlow2 = _interopRequireDefault(_babelPluginSyntaxFlow);
var _babelFileLoader = require('babel-file-loader');
var _babelAddFlowComments = require('babel-add-flow-comments');
var _babelExplodeModule = require('babel-explode-module');
var _babelExplodeModule2 = _interopRequireDefault(_babelExplodeModule);
var _uppercamelcase = require('uppercamelcase');
var _uppercamelcase2 = _interopRequireDefault(_uppercamelcase);
var _util = require('./util');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
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); } }
var STATE = 'State';
function getStateName(path) {
var parentPath = (0, _path.normalize)((0, _path.dirname)(path)).split('/');
return parentPath[parentPath.length - 1] + STATE;
}
function isExport(path, target) {
var _explodeModule = (0, _babelExplodeModule2.default)(path.node),
ex = _explodeModule.exports;
if (ex.length === 0) {
return false;
}
return ex.some(function (v) {
return v.external === target;
});
}
function haveStateType(path) {
return isExport(path, STATE);
}
// export type State = { app: AppState }
var createStateDeclaration = function createStateDeclaration(states) {
var stateTypes = states.map(function (v) {
return t.objectTypeProperty(t.identifier(v.name.replace(STATE, '')), t.genericTypeAnnotation(t.identifier(v.name)));
});
return t.exportNamedDeclaration(t.typeAlias(t.identifier(STATE), null, t.objectTypeAnnotation(stateTypes, null, null)), [], null);
};
// import type {State as AppState} from './App/reducer'
var createNewImportStateDeclaration = function createNewImportStateDeclaration(source) {
if (!source) {
return null;
}
var specifiers = [t.importSpecifier(t.identifier(getStateName(source)), t.identifier(STATE))];
var newImportStateDeclaration = t.importDeclaration(specifiers, t.stringLiteral(source)
// $FlowFixMe
);newImportStateDeclaration.importKind = 'type';
return newImportStateDeclaration;
};
exports.default = function () {
return {
inherits: _babelPluginSyntaxFlow2.default,
visitor: {
Program: {
// eslint-disable-next-line
exit: function exit(path, _ref) {
var file = _ref.file,
input = _ref.opts.input;
if (!input) {
return false;
}
var from = file.opts.filename;
var importPath = (0, _util.getImportPath)(from, input);
try {
var _loadFileSync = (0, _babelFileLoader.loadFileSync)(input),
loadPath = _loadFileSync.path;
if (!haveStateType(loadPath)) {
return false;
}
} catch (err) {
if (err.code !== 'ENOENT') {
throw err;
}
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = path.get('body')[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var item = _step.value;
if (t.isImportDeclaration(item) && item.node.source.value === importPath) {
item.remove();
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return false;
}
var exploded = (0, _babelExplodeModule2.default)(path.node);
var thisImports = exploded.imports.length > 0 ? exploded.imports.map(function (v) {
return v.source;
}) : [];
// import type
var typeDeclarations = Array.from(new Set([].concat(_toConsumableArray(thisImports), [importPath]))).sort().map(createNewImportStateDeclaration
// すでにあるimport typeを取得
);var stateNames = exploded.imports.filter(function (v) {
return v.kind === 'type';
}).map(function (v) {
return v.local;
}
// 重複を除去
);var states = Array.from(new Set([].concat(_toConsumableArray(stateNames), [(0, _uppercamelcase2.default)(getStateName(importPath))]).sort())).map(function (v) {
return t.identifier(v);
});
path.node.body = [].concat(_toConsumableArray(typeDeclarations), [t.noop(), createStateDeclaration(states)]);
(0, _babelAddFlowComments.removeFlowComment)(file.ast.comments);
path.addComment('leading', ' @flow', true);
}
}
}
};
};