|
|
"use strict";
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
|
value: true
|
|
|
});
|
|
|
exports.getValidFiles = exports.isValidHook = exports.genModels = exports.sort = exports.genExtraModels = exports.genImports = exports.getPath = exports.getName = void 0;
|
|
|
|
|
|
function _react() {
|
|
|
const data = _interopRequireDefault(require("react"));
|
|
|
|
|
|
_react = function _react() {
|
|
|
return data;
|
|
|
};
|
|
|
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
function _path() {
|
|
|
const data = _interopRequireDefault(require("path"));
|
|
|
|
|
|
_path = function _path() {
|
|
|
return data;
|
|
|
};
|
|
|
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
function _os() {
|
|
|
const data = require("os");
|
|
|
|
|
|
_os = function _os() {
|
|
|
return data;
|
|
|
};
|
|
|
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
function _fs() {
|
|
|
const data = require("fs");
|
|
|
|
|
|
_fs = function _fs() {
|
|
|
return data;
|
|
|
};
|
|
|
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
function _umi() {
|
|
|
const data = require("umi");
|
|
|
|
|
|
_umi = function _umi() {
|
|
|
return data;
|
|
|
};
|
|
|
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
|
|
const t = _umi().utils.t,
|
|
|
parser = _umi().utils.parser,
|
|
|
traverse = _umi().utils.traverse,
|
|
|
winPath = _umi().utils.winPath;
|
|
|
|
|
|
const getFileName = name => {
|
|
|
const fileName = _path().default.basename(name, _path().default.extname(name));
|
|
|
|
|
|
if (fileName.endsWith('.model') || fileName.endsWith('.models')) {
|
|
|
return fileName.split('.').slice(0, -1).join('.');
|
|
|
}
|
|
|
|
|
|
return fileName;
|
|
|
};
|
|
|
|
|
|
const getName = (absPath, absSrcPath) => {
|
|
|
const relativePath = _path().default.relative(absSrcPath, absPath); // model files with namespace
|
|
|
|
|
|
|
|
|
const dirList = _path().default.dirname(relativePath).split(_path().default.sep);
|
|
|
|
|
|
try {
|
|
|
const validDirs = dirList.filter(ele => !['src', 'page', 'pages', 'model', 'models'].includes(ele));
|
|
|
|
|
|
if (validDirs && validDirs.length) {
|
|
|
return `${validDirs.join('.')}.${getFileName(relativePath)}`;
|
|
|
}
|
|
|
|
|
|
return getFileName(relativePath);
|
|
|
} catch (e) {
|
|
|
return getFileName(relativePath);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
exports.getName = getName;
|
|
|
|
|
|
const getPath = absPath => {
|
|
|
const info = _path().default.parse(absPath);
|
|
|
|
|
|
return winPath(_path().default.join(info.dir, info.name).replace(/'/, "'"));
|
|
|
};
|
|
|
|
|
|
exports.getPath = getPath;
|
|
|
|
|
|
const genImports = imports => imports.map((ele, index) => `import model${index} from "${winPath(getPath(ele))}";`).join(_os().EOL);
|
|
|
|
|
|
exports.genImports = genImports;
|
|
|
|
|
|
const genExtraModels = (models = [], absSrcPath) => models.map(ele => {
|
|
|
if (typeof ele === 'string') {
|
|
|
return {
|
|
|
importPath: getPath(ele),
|
|
|
importName: _path().default.basename(ele).split('.')[0],
|
|
|
namespace: getName(ele, absSrcPath)
|
|
|
};
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
importPath: getPath(ele.absPath),
|
|
|
importName: _path().default.basename(ele.absPath).split('.')[0],
|
|
|
namespace: ele.namespace,
|
|
|
exportName: ele.exportName
|
|
|
};
|
|
|
});
|
|
|
|
|
|
exports.genExtraModels = genExtraModels;
|
|
|
|
|
|
const sort = ns => {
|
|
|
let final = [];
|
|
|
ns.forEach((item, index) => {
|
|
|
if (item.use && item.use.length) {
|
|
|
const itemGroup = [...item.use, item.namespace];
|
|
|
const cannotUse = [item.namespace];
|
|
|
|
|
|
for (let i = 0; i <= index; i += 1) {
|
|
|
if (ns[i].use.filter(v => cannotUse.includes(v)).length) {
|
|
|
if (!cannotUse.includes(ns[i].namespace)) {
|
|
|
cannotUse.push(ns[i].namespace);
|
|
|
i = -1;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const errorList = item.use.filter(v => cannotUse.includes(v));
|
|
|
|
|
|
if (errorList.length) {
|
|
|
throw Error(`Circular dependencies: ${item.namespace} can't use ${errorList.join(', ')}`);
|
|
|
}
|
|
|
|
|
|
const intersection = final.filter(v => itemGroup.includes(v));
|
|
|
|
|
|
if (intersection.length) {
|
|
|
// first intersection
|
|
|
const finalIndex = final.indexOf(intersection[0]); // replace with groupItem
|
|
|
|
|
|
final = final.slice(0, finalIndex).concat(itemGroup).concat(final.slice(finalIndex + 1));
|
|
|
} else {
|
|
|
final.push(...itemGroup);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!final.includes(item.namespace)) {
|
|
|
// first occurance append to the end
|
|
|
final.push(item.namespace);
|
|
|
}
|
|
|
});
|
|
|
return [...new Set(final)];
|
|
|
};
|
|
|
|
|
|
exports.sort = sort;
|
|
|
|
|
|
const genModels = (imports, absSrcPath) => {
|
|
|
const contents = imports.map(absPath => ({
|
|
|
namespace: getName(absPath, absSrcPath),
|
|
|
content: (0, _fs().readFileSync)(absPath).toString()
|
|
|
}));
|
|
|
const allUserModel = imports.map(absPath => getName(absPath, absSrcPath));
|
|
|
|
|
|
const checkDuplicates = list => new Set(list).size !== list.length;
|
|
|
|
|
|
const raw = contents.map((ele, index) => {
|
|
|
const ast = parser.parse(ele.content, {
|
|
|
sourceType: 'module',
|
|
|
plugins: ['jsx', 'typescript']
|
|
|
});
|
|
|
const use = [];
|
|
|
traverse.default(ast, {
|
|
|
enter(astPath) {
|
|
|
if (astPath.isIdentifier({
|
|
|
name: 'useModel'
|
|
|
})) {
|
|
|
try {
|
|
|
// string literal
|
|
|
const ns = astPath.parentPath.node.arguments[0].value;
|
|
|
|
|
|
if (allUserModel.includes(ns)) {
|
|
|
use.push(ns);
|
|
|
}
|
|
|
} catch (e) {// console.log(e)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
});
|
|
|
return {
|
|
|
namespace: ele.namespace,
|
|
|
use,
|
|
|
importName: `model${index}`
|
|
|
};
|
|
|
});
|
|
|
const models = sort(raw);
|
|
|
|
|
|
if (checkDuplicates(contents.map(ele => ele.namespace))) {
|
|
|
throw Error('umi: models 中包含重复的 namespace!');
|
|
|
}
|
|
|
|
|
|
return raw.sort((a, b) => models.indexOf(a.namespace) - models.indexOf(b.namespace));
|
|
|
};
|
|
|
|
|
|
exports.genModels = genModels;
|
|
|
|
|
|
const isValidHook = filePath => {
|
|
|
const isTS = _path().default.extname(filePath) === '.ts';
|
|
|
const isTSX = _path().default.extname(filePath) === '.tsx';
|
|
|
const content = (0, _fs().readFileSync)(filePath, {
|
|
|
encoding: 'utf-8'
|
|
|
}).toString();
|
|
|
const ast = parser.parse(content, {
|
|
|
sourceType: 'module',
|
|
|
plugins: [// .ts 不能加 jsx,因为里面可能有 `<Type>{}` 这种写法
|
|
|
// .tsx, .js, .jsx 可以加
|
|
|
isTS ? false : 'jsx', // 非 ts 不解析 typescript
|
|
|
isTS || isTSX ? 'typescript' : false, // 支持更多语法
|
|
|
'classProperties', 'dynamicImport', 'exportDefaultFrom', 'exportNamespaceFrom', 'functionBind', 'nullishCoalescingOperator', 'objectRestSpread', 'optionalChaining', 'decorators-legacy'].filter(Boolean)
|
|
|
});
|
|
|
let valid = false;
|
|
|
let identifierName = '';
|
|
|
traverse.default(ast, {
|
|
|
enter(p) {
|
|
|
if (p.isExportDefaultDeclaration()) {
|
|
|
const type = p.node.declaration.type;
|
|
|
|
|
|
try {
|
|
|
if (type === 'ArrowFunctionExpression' || type === 'FunctionDeclaration') {
|
|
|
valid = true;
|
|
|
} else if (type === 'Identifier') {
|
|
|
identifierName = p.node.declaration.name;
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error(e);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
try {
|
|
|
if (identifierName) {
|
|
|
ast.program.body.forEach(ele => {
|
|
|
if (ele.type === 'FunctionDeclaration') {
|
|
|
var _ele$id;
|
|
|
|
|
|
if (((_ele$id = ele.id) === null || _ele$id === void 0 ? void 0 : _ele$id.name) === identifierName) {
|
|
|
valid = true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (ele.type === 'VariableDeclaration') {
|
|
|
if (ele.declarations[0].id.name === identifierName && ele.declarations[0].init.type === 'ArrowFunctionExpression') {
|
|
|
valid = true;
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
} catch (e) {
|
|
|
valid = false;
|
|
|
}
|
|
|
|
|
|
return valid;
|
|
|
};
|
|
|
|
|
|
exports.isValidHook = isValidHook;
|
|
|
|
|
|
const getValidFiles = (files, modelsDir) => files.map(file => {
|
|
|
const filePath = _path().default.join(modelsDir, file);
|
|
|
|
|
|
const valid = isValidHook(filePath);
|
|
|
|
|
|
if (valid) {
|
|
|
return filePath;
|
|
|
}
|
|
|
|
|
|
return '';
|
|
|
}).filter(ele => !!ele);
|
|
|
|
|
|
exports.getValidFiles = getValidFiles; |