1020 lines
52 KiB
JavaScript
1020 lines
52 KiB
JavaScript
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.analyzeDepedency = void 0;
|
||
const tslib_1 = require("tslib");
|
||
const assert_1 = tslib_1.__importDefault(require("assert"));
|
||
const path_1 = require("path");
|
||
const fs_1 = require("fs");
|
||
const ts = tslib_1.__importStar(require("typescript"));
|
||
const string_1 = require("../utils/string");
|
||
const env_1 = require("./env");
|
||
const fs_extra_1 = require("fs-extra");
|
||
const lodash_1 = require("lodash");
|
||
const { factory } = ts;
|
||
/**
|
||
* 构建项目依赖关系图
|
||
* @param cwd
|
||
* @returns
|
||
*/
|
||
function analyzeDepedency(cwd) {
|
||
const depGraph = {
|
||
nodes: {},
|
||
dependencies: {},
|
||
ascOrder: [],
|
||
};
|
||
function analyzeOne(dir, name) {
|
||
if (name) {
|
||
if (!depGraph.nodes[name]) {
|
||
depGraph.nodes[name] = 1;
|
||
depGraph.dependencies[name] = {};
|
||
}
|
||
}
|
||
let dependencies = [];
|
||
const depConfigTsFile = join(dir, 'src', 'configuration', 'dependency.ts');
|
||
if ((0, fs_1.existsSync)(depConfigTsFile)) {
|
||
// 这里依赖配置是ts文件,得翻译成js再读取
|
||
const result = ts.transpileModule((0, fs_1.readFileSync)(depConfigTsFile, 'utf-8'), { compilerOptions: { module: ts.ModuleKind.CommonJS } });
|
||
dependencies = eval(result.outputText);
|
||
}
|
||
else {
|
||
const depConfigJsFile = join(dir, 'lib', 'configuration', 'dependency.js');
|
||
if ((0, fs_1.existsSync)(depConfigJsFile)) {
|
||
dependencies = require(depConfigJsFile).default;
|
||
}
|
||
else {
|
||
// 没有依赖文件,直接返回
|
||
return;
|
||
}
|
||
}
|
||
dependencies.forEach((dep) => {
|
||
if (name) {
|
||
depGraph.dependencies[name][dep] = 1;
|
||
}
|
||
if (!depGraph.nodes[dep]) {
|
||
let dir2 = join(cwd, 'node_modules', dep);
|
||
if (!(0, fs_1.existsSync)(dir2)) {
|
||
dir2 = join(dir, 'node_modules', dep);
|
||
if (!(0, fs_1.existsSync)(dir2)) {
|
||
throw new Error(`找不到依赖包${dep}的安装位置,当前包是${dir}`);
|
||
}
|
||
}
|
||
analyzeOne(dir2, dep);
|
||
}
|
||
});
|
||
}
|
||
analyzeOne(cwd, '');
|
||
// 输出一个依赖关系从底向上的序列,类似于图中的反向遍历算法
|
||
do {
|
||
const deps = Object.keys(depGraph.nodes);
|
||
if (deps.length === 0) {
|
||
break;
|
||
}
|
||
const freeNodes = [];
|
||
for (const n of deps) {
|
||
if (Object.keys(depGraph.dependencies[n]).length === 0) {
|
||
freeNodes.push(n);
|
||
}
|
||
}
|
||
(0, assert_1.default)(freeNodes.length > 0, '依赖关系成环!');
|
||
freeNodes.forEach((n) => {
|
||
(0, lodash_1.unset)(depGraph.nodes, n);
|
||
(0, lodash_1.unset)(depGraph.dependencies, n);
|
||
for (const n2 in depGraph.dependencies) {
|
||
(0, lodash_1.unset)(depGraph.dependencies[n2], n);
|
||
}
|
||
depGraph.ascOrder.push(n);
|
||
});
|
||
} while (true);
|
||
return depGraph;
|
||
}
|
||
exports.analyzeDepedency = analyzeDepedency;
|
||
function join(...paths) {
|
||
const path = (0, path_1.join)(...paths);
|
||
return path.replaceAll('\\', '/');
|
||
}
|
||
function destructVariableDeclaration(vd) {
|
||
(0, assert_1.default)(ts.isIdentifier(vd.name));
|
||
(0, assert_1.default)(vd.name.text.startsWith('total'));
|
||
const on = (0, string_1.firstLetterLowerCase)(vd.name.text.slice(5));
|
||
const { initializer: nonNullExpression } = vd;
|
||
(0, assert_1.default)(ts.isNonNullExpression(nonNullExpression));
|
||
const { expression: callExpression } = nonNullExpression;
|
||
(0, assert_1.default)(ts.isCallExpression(callExpression));
|
||
(0, assert_1.default)(ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'mergeConcatMany');
|
||
(0, assert_1.default)(callExpression.arguments.length === 1);
|
||
const [arg] = callExpression.arguments;
|
||
(0, assert_1.default)(ts.isAsExpression(arg));
|
||
const { expression } = arg;
|
||
(0, assert_1.default)(ts.isArrayLiteralExpression(expression));
|
||
return {
|
||
on,
|
||
expression,
|
||
};
|
||
}
|
||
function outputPolyfillDts(dependencies, briefNames, sourceFile, printer, filename) {
|
||
let statements2 = [];
|
||
if (dependencies.length > 0) {
|
||
const { statements } = sourceFile;
|
||
(0, assert_1.default)(ts.isImportDeclaration(statements[5]) && ts.isModuleDeclaration(statements[6]));
|
||
const importStatements = [];
|
||
dependencies.forEach((dep, idx) => {
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("FeatureDict"), factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(briefNames[idx])}FeatureDict`))])), factory.createStringLiteral(`${dep}/es/features`), undefined), factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("AspectDict"), factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(briefNames[idx])}AspectDict`))])), factory.createStringLiteral(`${dep}/es/aspects`), undefined));
|
||
});
|
||
/**
|
||
* declare global {
|
||
const OakComponent: MakeOakComponent<
|
||
EntityDict,
|
||
BackendRuntimeContext,
|
||
FrontendRuntimeContext,
|
||
AspectDict & OgbAspectDict<EntityDict, BackendRuntimeContext>,
|
||
FeatureDict & OgbFeatureDict<EntityDict>
|
||
>;
|
||
const features: FeatureDict & OgbFeatureDict<EntityDict>;
|
||
}
|
||
*/
|
||
const stmt6 = statements[6];
|
||
const { body } = stmt6;
|
||
const [ocStmt, featuresStmt] = body.statements;
|
||
(0, assert_1.default)(ts.isVariableStatement(ocStmt) && ts.isVariableStatement(featuresStmt));
|
||
const [ocVd] = ocStmt.declarationList.declarations;
|
||
const [featuresVd] = featuresStmt.declarationList.declarations;
|
||
(0, assert_1.default)(ts.isVariableDeclaration(ocVd) && ts.isIdentifier(ocVd.name) && ocVd.name.text === 'OakComponent');
|
||
(0, assert_1.default)(ts.isVariableDeclaration(featuresVd) && ts.isIdentifier(featuresVd.name) && featuresVd.name.text === 'features');
|
||
const ocType = ocVd.type;
|
||
(0, assert_1.default)(ts.isTypeReferenceNode(ocType) && ocType.typeArguments?.length === 5);
|
||
const aspectTypeNode = ocType.typeArguments[3];
|
||
const featureTypeNode = ocType.typeArguments[4];
|
||
(0, assert_1.default)(ts.isTypeReferenceNode(aspectTypeNode) && ts.isTypeReferenceNode(featureTypeNode));
|
||
Object.assign(ocType, {
|
||
typeArguments: [
|
||
...ocType.typeArguments.slice(0, 3),
|
||
factory.createIntersectionTypeNode([
|
||
aspectTypeNode,
|
||
...briefNames.map((ele) => factory.createTypeReferenceNode(factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(ele)}AspectDict`), [
|
||
factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined)
|
||
]))
|
||
]),
|
||
factory.createIntersectionTypeNode([
|
||
featureTypeNode,
|
||
...briefNames.map((ele) => factory.createTypeReferenceNode(factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(ele)}FeatureDict`), [
|
||
factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined)
|
||
]))
|
||
])
|
||
]
|
||
});
|
||
const featureType = featuresVd.type;
|
||
(0, assert_1.default)(ts.isTypeReferenceNode(featureType));
|
||
Object.assign(featuresVd, {
|
||
type: factory.createIntersectionTypeNode([
|
||
featureType,
|
||
...briefNames.map((ele) => factory.createTypeReferenceNode(factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(ele)}FeatureDict`), [
|
||
factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined)
|
||
]))
|
||
])
|
||
});
|
||
statements2 = [
|
||
...statements.slice(0, 6),
|
||
...importStatements,
|
||
...statements.slice(6)
|
||
];
|
||
}
|
||
else {
|
||
statements2 = [...sourceFile.statements];
|
||
}
|
||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||
console.log(`构建${filename}文件成功`);
|
||
}
|
||
function outputDependentExceptions(dependencies, briefNames, sourceFile, printer, filename) {
|
||
let statements2 = [];
|
||
if (dependencies.length > 0) {
|
||
const { statements } = sourceFile;
|
||
(0, assert_1.default)(ts.isImportDeclaration(statements[2]) && ts.isFunctionDeclaration(statements[3]));
|
||
const importStatements = [];
|
||
dependencies.forEach((dep, idx) => {
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("makeException"), factory.createIdentifier(`make${(0, string_1.firstLetterUpperCase)(briefNames[idx])}Exception`))])), factory.createStringLiteral(dep), undefined));
|
||
});
|
||
const stmt3 = statements[3];
|
||
const funcStmt0 = stmt3.body?.statements[0];
|
||
(0, assert_1.default)(ts.isVariableStatement(funcStmt0));
|
||
const vd = funcStmt0.declarationList.declarations[0];
|
||
const { name, initializer } = vd;
|
||
(0, assert_1.default)(ts.isIdentifier(name) && name.text === 'e');
|
||
(0, assert_1.default)(ts.isCallExpression(initializer));
|
||
const callExpressions = briefNames.map(ele => factory.createCallExpression(factory.createIdentifier(`make${(0, string_1.firstLetterUpperCase)(ele)}Exception`), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)], [factory.createIdentifier("data")]));
|
||
const rightExpression = callExpressions.length === 1 ? callExpressions[0] :
|
||
callExpressions.length === 2 ? factory.createBinaryExpression(callExpressions[0], factory.createToken(ts.SyntaxKind.BarBarToken), callExpressions[1]) : callExpressions.slice(2).reduce((prev, next) => factory.createBinaryExpression(prev, factory.createToken(ts.SyntaxKind.BarBarToken), next), factory.createBinaryExpression(callExpressions[0], factory.createToken(ts.SyntaxKind.BarBarToken), callExpressions[1]));
|
||
Object.assign(vd, {
|
||
initializer: factory.createBinaryExpression(initializer, factory.createToken(ts.SyntaxKind.BarBarToken), rightExpression)
|
||
});
|
||
statements2 = [
|
||
...statements.slice(0, 3),
|
||
...importStatements,
|
||
...statements.slice(3)
|
||
];
|
||
}
|
||
else {
|
||
statements2 = [...sourceFile.statements];
|
||
}
|
||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||
console.log(`构建${filename}文件成功`);
|
||
}
|
||
function outputRuntimeCxt(dependencies, briefNames, sourceFile, printer, filename) {
|
||
let statements2 = [];
|
||
if (dependencies.length > 0) {
|
||
const { statements } = sourceFile;
|
||
const importStatements = [];
|
||
const stmt9 = statements[9];
|
||
const stmt10 = statements[10];
|
||
(0, assert_1.default)(ts.isTypeAliasDeclaration(stmt9) && ts.isIdentifier(stmt9.name) && stmt9.name.text === 'AAD');
|
||
(0, assert_1.default)(ts.isTypeAliasDeclaration(stmt10) && ts.isIdentifier(stmt10.name) && stmt10.name.text === 'AFD');
|
||
(0, assert_1.default)(ts.isImportDeclaration(statements[5]) && ts.isTypeAliasDeclaration(statements[6]));
|
||
const AADs = [];
|
||
const AFDs = [];
|
||
dependencies.forEach((dep, idx) => {
|
||
const featureName = `${(0, string_1.firstLetterUpperCase)(briefNames[idx])}FeatureDict`;
|
||
const aspectName = `${(0, string_1.firstLetterUpperCase)(briefNames[idx])}AspectDict`;
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([
|
||
factory.createImportSpecifier(false, factory.createIdentifier("FeatureDict"), factory.createIdentifier(featureName)),
|
||
factory.createImportSpecifier(false, factory.createIdentifier("AspectDict"), factory.createIdentifier(aspectName))
|
||
])), factory.createStringLiteral(dep), undefined));
|
||
AFDs.push(featureName);
|
||
AADs.push(aspectName);
|
||
});
|
||
{
|
||
const { type } = stmt9;
|
||
(0, assert_1.default)(ts.isTypeReferenceNode(type));
|
||
Object.assign(stmt9, {
|
||
type: factory.createIntersectionTypeNode([
|
||
type,
|
||
...AADs.map(ele => factory.createTypeReferenceNode(factory.createIdentifier(ele), [factory.createTypeReferenceNode('EntityDict')]))
|
||
])
|
||
});
|
||
}
|
||
{
|
||
const { type } = stmt10;
|
||
(0, assert_1.default)(ts.isIntersectionTypeNode(type));
|
||
const { types } = type;
|
||
Object.assign(type, {
|
||
types: [
|
||
...types,
|
||
...AFDs.map(ele => factory.createTypeReferenceNode(factory.createIdentifier(ele), [factory.createTypeReferenceNode('EntityDict')]))
|
||
]
|
||
});
|
||
}
|
||
statements2 = [
|
||
...statements.slice(0, 6),
|
||
...importStatements,
|
||
...statements.slice(6)
|
||
];
|
||
}
|
||
else {
|
||
statements2 = [
|
||
...sourceFile.statements
|
||
];
|
||
}
|
||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||
console.log(`构建${filename}文件成功`);
|
||
}
|
||
function outputContext(depGraph, sourceFile, printer, filename) {
|
||
// 目前只支持单向依赖,未来可以利用mixin来实现多类的继承
|
||
// assert(depGraph.roots.length <= 1);
|
||
let root = depGraph.ascOrder.length > 0 ? depGraph.ascOrder[depGraph.ascOrder.length - 1] : 'oak-frontend-base';
|
||
const { statements } = sourceFile;
|
||
const isBackend = filename.includes('BackendRuntimeContext');
|
||
const statements2 = [
|
||
factory.createImportDeclaration(undefined, factory.createImportClause(false, factory.createIdentifier(isBackend ? "BaseBackendRuntimeContext" : "BaseFrontendRuntimeContext"), undefined), factory.createStringLiteral(`${root}/${isBackend ? 'lib' : 'es'}/context/${isBackend ? 'BackendRuntimeContext' : 'FrontendRuntimeContext'}`), undefined),
|
||
...statements
|
||
];
|
||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||
console.log(`构建${filename}文件成功`);
|
||
}
|
||
/**
|
||
* 生成initialize.prod.ts
|
||
* @param cwd
|
||
* @param dependencies
|
||
* @param briefNames
|
||
* @param sourceFile
|
||
* @param printer
|
||
*/
|
||
function outputIntializeProd(cwd, dependencies, briefNames, sourceFile, printer, filename) {
|
||
const { statements } = sourceFile;
|
||
const objectDict = {};
|
||
// 所有的import
|
||
const importStatements = [];
|
||
dependencies.forEach((dep, idx) => {
|
||
const depDir = join(cwd, 'node_modules', dep);
|
||
if (!(0, fs_1.existsSync)(depDir)) {
|
||
throw new Error(`依赖模块${dep}未能找到相应的安装目录【${depDir}】`);
|
||
}
|
||
const esDir = join(depDir, 'es');
|
||
const libDir = join(depDir, 'lib');
|
||
const esDirExisted = (0, fs_1.existsSync)(esDir);
|
||
const libDirExisted = (0, fs_1.existsSync)(libDir);
|
||
if (!esDirExisted && !libDirExisted) {
|
||
throw new Error(`依赖模块${dep}中没有es或者lib目录`);
|
||
}
|
||
const destDir = esDirExisted ? esDir : libDir;
|
||
const destDirName = esDirExisted ? 'es' : 'lib';
|
||
const objectDirs = ['checkers'];
|
||
objectDirs.forEach((o) => {
|
||
if ((0, fs_1.existsSync)(join(destDir, o))) {
|
||
const variableName = `${briefNames[idx]}${(0, string_1.firstLetterUpperCase)(o)}`;
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, factory.createIdentifier(variableName), undefined), factory.createStringLiteral(join(dep, destDirName, o)), undefined));
|
||
if (objectDict[o]) {
|
||
objectDict[o].push(variableName);
|
||
}
|
||
else {
|
||
objectDict[o] = [variableName];
|
||
}
|
||
}
|
||
});
|
||
// common
|
||
if ((0, fs_1.existsSync)(join(destDir, 'configuration'))) {
|
||
const variableName = `${briefNames[idx]}Common`;
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, factory.createIdentifier(variableName), undefined), factory.createStringLiteral(join(dep, destDirName, 'configuration')), undefined));
|
||
if (objectDict.common) {
|
||
objectDict.common.push(variableName);
|
||
}
|
||
else {
|
||
objectDict.common = [variableName];
|
||
}
|
||
}
|
||
// render
|
||
if ((0, fs_1.existsSync)(join(destDir, 'configuration', 'render.js'))) {
|
||
const variableName = `${briefNames[idx]}Render`;
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, factory.createIdentifier(variableName), undefined), factory.createStringLiteral(join(dep, destDirName, 'configuration', 'render')), undefined));
|
||
if (objectDict.render) {
|
||
objectDict.render.push(variableName);
|
||
}
|
||
else {
|
||
objectDict.render = [variableName];
|
||
}
|
||
}
|
||
// features
|
||
if ((0, fs_1.existsSync)(join(destDir, 'features'))) {
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([
|
||
factory.createImportSpecifier(false, factory.createIdentifier("create"), factory.createIdentifier(`create${(0, string_1.firstLetterUpperCase)(briefNames[idx])}Features`)),
|
||
factory.createImportSpecifier(false, factory.createIdentifier("FeatureDict"), factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(briefNames[idx])}FeatureDict`))
|
||
])), factory.createStringLiteral(join(dep, destDirName, 'features')), undefined));
|
||
if (objectDict.features) {
|
||
objectDict.features.push(briefNames[idx]);
|
||
}
|
||
else {
|
||
objectDict.features = [briefNames[idx]];
|
||
}
|
||
}
|
||
});
|
||
const funcStmt = statements.find((stmt) => ts.isFunctionDeclaration(stmt) && stmt.modifiers?.find(modifier => modifier.kind === ts.SyntaxKind.ExportKeyword) && stmt.modifiers.find(modifier => modifier.kind === ts.SyntaxKind.DefaultKeyword));
|
||
(0, assert_1.default)(funcStmt);
|
||
const idx = statements.indexOf(funcStmt);
|
||
const statements2 = [
|
||
...statements.slice(0, idx),
|
||
...importStatements,
|
||
...statements.slice(idx)
|
||
];
|
||
const stmt0 = funcStmt.body?.statements[0];
|
||
(0, assert_1.default)(ts.isVariableStatement(stmt0));
|
||
let vdl = stmt0.declarationList;
|
||
vdl.declarations.forEach((declaration) => {
|
||
const { on, expression } = destructVariableDeclaration(declaration);
|
||
if (objectDict[on]) {
|
||
const { elements } = expression;
|
||
Object.assign(expression, {
|
||
elements: elements.concat(...objectDict[on].map(ele => factory.createIdentifier(ele)))
|
||
});
|
||
}
|
||
});
|
||
if (objectDict.features) {
|
||
const stmt1 = funcStmt.body?.statements[1];
|
||
(0, assert_1.default)(ts.isVariableStatement(stmt1));
|
||
const tfDec = stmt1.declarationList.declarations[0];
|
||
const { name, initializer } = tfDec;
|
||
(0, assert_1.default)(ts.isIdentifier(name) && name.text === 'totalFeatures');
|
||
(0, assert_1.default)(ts.isAsExpression(initializer));
|
||
const { type } = initializer;
|
||
(0, assert_1.default)(ts.isIntersectionTypeNode(type));
|
||
Object.assign(type, {
|
||
types: type.types.concat(objectDict.features.map(ele => factory.createTypeReferenceNode(`${(0, string_1.firstLetterUpperCase)(ele)}FeatureDict`, [
|
||
factory.createTypeReferenceNode('EntityDict')
|
||
])))
|
||
});
|
||
Object.assign(funcStmt.body, {
|
||
statements: [
|
||
...funcStmt.body.statements.slice(0, 4),
|
||
...objectDict.features.map((ele) => [
|
||
factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier(`${ele}Features`), undefined, undefined, factory.createCallExpression(factory.createIdentifier(`create${(0, string_1.firstLetterUpperCase)(ele)}Features`), undefined, [factory.createIdentifier("totalFeatures")]))], ts.NodeFlags.Const)),
|
||
factory.createExpressionStatement(factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("Object"), factory.createIdentifier("assign")), undefined, [
|
||
factory.createIdentifier("totalFeatures"),
|
||
factory.createIdentifier(`${ele}Features`)
|
||
]))
|
||
]).flat(),
|
||
...funcStmt.body.statements.slice(4),
|
||
]
|
||
});
|
||
}
|
||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||
console.log(`构建${filename}文件成功`);
|
||
}
|
||
/**
|
||
* 生成initialize.dev.ts
|
||
* @param cwd
|
||
* @param dependencies
|
||
* @param briefNames
|
||
* @param sourceFile
|
||
* @param printer
|
||
*/
|
||
function outputIntializeDev(cwd, dependencies, briefNames, sourceFile, printer, filename) {
|
||
const { statements } = sourceFile;
|
||
const objectDict = {};
|
||
// 所有的import
|
||
const importStatements = [];
|
||
dependencies.forEach((dep, idx) => {
|
||
const depDir = join(cwd, 'node_modules', dep);
|
||
if (!(0, fs_1.existsSync)(depDir)) {
|
||
throw new Error(`依赖模块${dep}未能找到相应的安装目录【${depDir}】`);
|
||
}
|
||
const esDir = join(depDir, 'es');
|
||
const libDir = join(depDir, 'lib');
|
||
const esDirExisted = (0, fs_1.existsSync)(esDir);
|
||
const libDirExisted = (0, fs_1.existsSync)(libDir);
|
||
if (!esDirExisted && !libDirExisted) {
|
||
throw new Error(`依赖模块${dep}中没有es或者lib目录`);
|
||
}
|
||
const destDir = esDirExisted ? esDir : libDir;
|
||
const destDirName = esDirExisted ? 'es' : 'lib';
|
||
const objectDirs = ['triggers', 'checkers', 'watchers', 'timers', 'data', 'aspects'];
|
||
objectDirs.forEach((o) => {
|
||
if ((0, fs_1.existsSync)(join(destDir, o))) {
|
||
const variableName = `${briefNames[idx]}${(0, string_1.firstLetterUpperCase)(o)}`;
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, factory.createIdentifier(variableName), undefined), factory.createStringLiteral(join(dep, destDirName, o)), undefined));
|
||
if (objectDict[o]) {
|
||
objectDict[o].push(variableName);
|
||
}
|
||
else {
|
||
objectDict[o] = [variableName];
|
||
}
|
||
}
|
||
});
|
||
// startRoutine
|
||
if ((0, fs_1.existsSync)(join(destDir, 'routines', 'start.js'))) {
|
||
const variableName = `${briefNames[idx]}StartRoutines`;
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, factory.createIdentifier(variableName), undefined), factory.createStringLiteral(join(dep, destDirName, 'routines/start')), undefined));
|
||
if (objectDict.startRoutines) {
|
||
objectDict.startRoutines.push(variableName);
|
||
}
|
||
else {
|
||
objectDict.startRoutines = [variableName];
|
||
}
|
||
}
|
||
// common
|
||
if ((0, fs_1.existsSync)(join(destDir, 'configuration'))) {
|
||
const variableName = `${briefNames[idx]}Common`;
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, factory.createIdentifier(variableName), undefined), factory.createStringLiteral(join(dep, destDirName, 'configuration')), undefined));
|
||
if (objectDict.common) {
|
||
objectDict.common.push(variableName);
|
||
}
|
||
else {
|
||
objectDict.common = [variableName];
|
||
}
|
||
}
|
||
// features
|
||
if ((0, fs_1.existsSync)(join(destDir, 'features'))) {
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([
|
||
factory.createImportSpecifier(false, factory.createIdentifier("create"), factory.createIdentifier(`create${(0, string_1.firstLetterUpperCase)(briefNames[idx])}Features`)),
|
||
factory.createImportSpecifier(false, factory.createIdentifier("FeatureDict"), factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(briefNames[idx])}FeatureDict`))
|
||
])), factory.createStringLiteral(join(dep, destDirName, 'features')), undefined));
|
||
if (objectDict.features) {
|
||
objectDict.features.push(briefNames[idx]);
|
||
}
|
||
else {
|
||
objectDict.features = [briefNames[idx]];
|
||
}
|
||
}
|
||
// ports
|
||
if ((0, fs_1.existsSync)(join(destDir, 'ports'))) {
|
||
const importVariableName = `${briefNames[idx]}Importations`;
|
||
const exportVariableName = `${briefNames[idx]}Exportations`;
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([
|
||
factory.createImportSpecifier(false, factory.createIdentifier("importations"), factory.createIdentifier(importVariableName)),
|
||
factory.createImportSpecifier(false, factory.createIdentifier("exportations"), factory.createIdentifier(exportVariableName))
|
||
])), factory.createStringLiteral(join(dep, destDirName, 'ports')), undefined));
|
||
if (objectDict.importations) {
|
||
objectDict.importations.push(importVariableName);
|
||
}
|
||
else {
|
||
objectDict.importations = [importVariableName];
|
||
}
|
||
if (objectDict.exportations) {
|
||
objectDict.exportations.push(exportVariableName);
|
||
}
|
||
else {
|
||
objectDict.exportations = [exportVariableName];
|
||
}
|
||
}
|
||
});
|
||
const funcStmt = statements.find((stmt) => ts.isFunctionDeclaration(stmt) && stmt.modifiers?.find(modifier => modifier.kind === ts.SyntaxKind.ExportKeyword) && stmt.modifiers.find(modifier => modifier.kind === ts.SyntaxKind.DefaultKeyword));
|
||
(0, assert_1.default)(funcStmt);
|
||
const idx = statements.indexOf(funcStmt);
|
||
const statements2 = [
|
||
...statements.slice(0, idx),
|
||
...importStatements,
|
||
...statements.slice(idx)
|
||
];
|
||
const stmt0 = funcStmt.body?.statements[0];
|
||
(0, assert_1.default)(ts.isVariableStatement(stmt0));
|
||
let vdl = stmt0.declarationList;
|
||
vdl.declarations.forEach((declaration) => {
|
||
const { on, expression } = destructVariableDeclaration(declaration);
|
||
if (objectDict[on]) {
|
||
const { elements } = expression;
|
||
Object.assign(expression, {
|
||
elements: elements.concat(...objectDict[on].map(ele => factory.createIdentifier(ele)))
|
||
});
|
||
}
|
||
});
|
||
if (objectDict.features) {
|
||
const stmt2 = funcStmt.body?.statements[2];
|
||
(0, assert_1.default)(ts.isVariableStatement(stmt2));
|
||
const tfDec = stmt2.declarationList.declarations[0];
|
||
const { name, initializer } = tfDec;
|
||
(0, assert_1.default)(ts.isIdentifier(name) && name.text === 'totalFeatures');
|
||
(0, assert_1.default)(ts.isAsExpression(initializer));
|
||
const { type } = initializer;
|
||
(0, assert_1.default)(ts.isIntersectionTypeNode(type));
|
||
Object.assign(type, {
|
||
types: type.types.concat(objectDict.features.map(ele => factory.createTypeReferenceNode(`${(0, string_1.firstLetterUpperCase)(ele)}FeatureDict`, [
|
||
factory.createTypeReferenceNode('EntityDict')
|
||
])))
|
||
});
|
||
Object.assign(funcStmt.body, {
|
||
statements: [
|
||
...funcStmt.body.statements.slice(0, 5),
|
||
...objectDict.features.map((ele) => [
|
||
factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier(`${ele}Features`), undefined, undefined, factory.createCallExpression(factory.createIdentifier(`create${(0, string_1.firstLetterUpperCase)(ele)}Features`), undefined, [factory.createIdentifier("totalFeatures")]))], ts.NodeFlags.Const)),
|
||
factory.createExpressionStatement(factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("Object"), factory.createIdentifier("assign")), undefined, [
|
||
factory.createIdentifier("totalFeatures"),
|
||
factory.createIdentifier(`${ele}Features`)
|
||
]))
|
||
]).flat(),
|
||
...funcStmt.body.statements.slice(5),
|
||
]
|
||
});
|
||
}
|
||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||
console.log(`构建${filename}文件成功`);
|
||
}
|
||
/**
|
||
* 根据依赖关系,输出features/index.ts
|
||
* @param cwd
|
||
* @param dependencies
|
||
* @param briefNames
|
||
* @param printer
|
||
* @param filename
|
||
*/
|
||
function outputFeatureIndex(dependencies, briefNames, sourceFile, printer, filename, isModule) {
|
||
const { statements } = sourceFile;
|
||
let statements2 = [];
|
||
if (dependencies.length > 0) {
|
||
const importStatements = [];
|
||
const fdNames = [];
|
||
const adNames = [];
|
||
dependencies.forEach((dep, idx) => {
|
||
const fdName = `${(0, string_1.firstLetterUpperCase)(briefNames[idx])}FeatureDict`;
|
||
const adName = `${(0, string_1.firstLetterUpperCase)(briefNames[idx])}AspectDict`;
|
||
// 导入FeatureDict和AspectDict
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([
|
||
factory.createImportSpecifier(false, factory.createIdentifier("FeatureDict"), factory.createIdentifier(fdName)),
|
||
factory.createImportSpecifier(false, factory.createIdentifier("AspectDict"), factory.createIdentifier(adName))
|
||
])), factory.createStringLiteral(dep), undefined));
|
||
fdNames.push(fdName);
|
||
adNames.push(adName);
|
||
});
|
||
// 导入自己的AspectDict:import { AspectDict } from '../aspects/AspectDict';
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("AspectDict"), factory.createIdentifier("ProjectAspectDict"))])), factory.createStringLiteral("../aspects/AspectDict"), undefined));
|
||
// 创建一个这样的type: type MergeAspectDict = ProjectAspectDict & GenernalAspectDict<EntityDict>;
|
||
// 除了ProjectAspectDict,还有其他的AspectDict,需要<EntityDict>参数
|
||
const adTypeDeclaration = factory.createTypeAliasDeclaration(undefined, factory.createIdentifier("MergeAspectDict"), undefined, factory.createIntersectionTypeNode([
|
||
factory.createTypeReferenceNode(factory.createIdentifier("ProjectAspectDict"), undefined),
|
||
...adNames.map(ad => {
|
||
return factory.createTypeReferenceNode(factory.createIdentifier(ad), [factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined)]);
|
||
})
|
||
]));
|
||
let i = 0;
|
||
while (true) {
|
||
const stmt = statements[i];
|
||
if (ts.isFunctionDeclaration(stmt)) {
|
||
break;
|
||
}
|
||
i++;
|
||
}
|
||
const stmt3 = statements[i - 1], stmt4 = statements[i];
|
||
(0, assert_1.default)(ts.isImportDeclaration(stmt3) && ts.isFunctionDeclaration(stmt4));
|
||
const { name, parameters } = stmt4;
|
||
(0, assert_1.default)(name && ts.isIdentifier(name) && name.text === 'create' && parameters.length === 1);
|
||
const [param] = parameters;
|
||
const { name: paramName, type } = param;
|
||
(0, assert_1.default)(ts.isIdentifier(paramName) && paramName.text === 'features' && ts.isTypeReferenceNode(type));
|
||
Object.assign(param, {
|
||
type: factory.createIntersectionTypeNode([
|
||
type,
|
||
...fdNames.map(ele => factory.createTypeReferenceNode(ele, [
|
||
factory.createTypeReferenceNode('EntityDict')
|
||
]))
|
||
])
|
||
});
|
||
statements2 = [
|
||
...statements.slice(0, i),
|
||
...importStatements,
|
||
adTypeDeclaration,
|
||
...statements.slice(i)
|
||
];
|
||
if (isModule) {
|
||
statements2.push(factory.createFunctionDeclaration([
|
||
factory.createToken(ts.SyntaxKind.ExportKeyword),
|
||
factory.createToken(ts.SyntaxKind.AsyncKeyword)
|
||
], undefined, factory.createIdentifier("initialize"), [
|
||
factory.createTypeParameterDeclaration(undefined, factory.createIdentifier("ED"), factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined), undefined)
|
||
], [
|
||
factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier("features"), undefined, factory.createIntersectionTypeNode([
|
||
factory.createTypeReferenceNode(factory.createIdentifier("FeatureDict"), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]),
|
||
factory.createTypeReferenceNode(factory.createIdentifier("BasicFeatures"), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]),
|
||
...briefNames.map((ele) => factory.createTypeReferenceNode(factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(ele)}FeatureDict`), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]))
|
||
]), undefined)
|
||
], undefined, factory.createBlock([], true)));
|
||
}
|
||
}
|
||
else {
|
||
statements2 = [...statements];
|
||
}
|
||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||
console.log(`构建${filename}文件成功`);
|
||
}
|
||
function outputIntializeFeatures(cwd, dependencies, briefNames, sourceFile, printer, filename) {
|
||
const { statements } = sourceFile;
|
||
const features = [];
|
||
// 所有的import
|
||
const importStatements = [];
|
||
// 如果有oak-general-business,需要AccessConfiguration,自动注入
|
||
if (dependencies.includes('oak-general-business')) {
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, factory.createIdentifier("accessConfiguration"), undefined), factory.createStringLiteral("@project/configuration/access"), undefined));
|
||
}
|
||
dependencies.forEach((dep, idx) => {
|
||
const depDir = join(cwd, 'node_modules', dep);
|
||
if (!(0, fs_1.existsSync)(depDir)) {
|
||
throw new Error(`依赖模块${dep}未能找到相应的安装目录【${depDir}】`);
|
||
}
|
||
const esDir = join(depDir, 'es');
|
||
const libDir = join(depDir, 'lib');
|
||
const esDirExisted = (0, fs_1.existsSync)(esDir);
|
||
const libDirExisted = (0, fs_1.existsSync)(libDir);
|
||
if (!esDirExisted && !libDirExisted) {
|
||
throw new Error(`依赖模块${dep}中没有es或者lib目录`);
|
||
}
|
||
const destDir = esDirExisted ? esDir : libDir;
|
||
const destDirName = esDirExisted ? 'es' : 'lib';
|
||
// features
|
||
if ((0, fs_1.existsSync)(join(destDir, 'features'))) {
|
||
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([
|
||
factory.createImportSpecifier(false, factory.createIdentifier("initialize"), factory.createIdentifier(`initialize${(0, string_1.firstLetterUpperCase)(briefNames[idx])}Features`)),
|
||
factory.createImportSpecifier(false, factory.createIdentifier("FeatureDict"), factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(briefNames[idx])}FeatureDict`))
|
||
])), factory.createStringLiteral(join(dep, destDirName, 'features')), undefined));
|
||
features.push(briefNames[idx]);
|
||
}
|
||
});
|
||
const funcStmt = statements.find((stmt) => ts.isFunctionDeclaration(stmt) && stmt.modifiers?.find(modifier => modifier.kind === ts.SyntaxKind.ExportKeyword) && stmt.modifiers.find(modifier => modifier.kind === ts.SyntaxKind.DefaultKeyword));
|
||
(0, assert_1.default)(funcStmt);
|
||
const idx = statements.indexOf(funcStmt);
|
||
const statements2 = [
|
||
...statements.slice(0, idx),
|
||
...importStatements,
|
||
...statements.slice(idx)
|
||
];
|
||
if (features.length > 0) {
|
||
(0, assert_1.default)(funcStmt.parameters.length === 1);
|
||
const [param] = funcStmt.parameters;
|
||
const { type } = param;
|
||
(0, assert_1.default)(ts.isIntersectionTypeNode(type));
|
||
Object.assign(type, {
|
||
types: type.types.concat(features.map(ele => factory.createTypeReferenceNode(`${(0, string_1.firstLetterUpperCase)(ele)}FeatureDict`, [
|
||
factory.createTypeReferenceNode('EntityDict')
|
||
])))
|
||
});
|
||
}
|
||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||
console.log(`构建${filename}文件成功`);
|
||
}
|
||
function injectDataIndexFile(dataIndexFile, briefNames, printer) {
|
||
const sourceFile = ts.createSourceFile('index.ts', (0, fs_1.readFileSync)(dataIndexFile, 'utf-8'), ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
||
const { statements } = sourceFile;
|
||
const importStatements = briefNames.map((ele) => factory.createImportDeclaration(undefined, factory.createImportClause(false, factory.createIdentifier(`${ele}Data`), undefined), factory.createStringLiteral(`./${ele}Data`), undefined));
|
||
/**
|
||
* 在文件末尾的这个位置上注入引用
|
||
export default {
|
||
relation: relations,
|
||
actionAuth,
|
||
relationAuth,
|
||
path,
|
||
i18n,
|
||
};
|
||
*/
|
||
const exportStmt = statements[statements.length - 1];
|
||
(0, assert_1.default)(ts.isExportAssignment(exportStmt));
|
||
const { expression } = exportStmt;
|
||
(0, assert_1.default)(ts.isObjectLiteralExpression(expression));
|
||
const { properties } = expression;
|
||
Object.assign(expression, {
|
||
properties: [
|
||
...properties,
|
||
...briefNames.map((ele) => factory.createSpreadAssignment(factory.createIdentifier(`${ele}Data`)))
|
||
]
|
||
});
|
||
const statements2 = [
|
||
...importStatements,
|
||
...statements,
|
||
];
|
||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||
(0, fs_1.writeFileSync)(dataIndexFile, result, { flag: 'w' });
|
||
console.log(`注入${dataIndexFile}文件成功,共注入了${briefNames.length}个初始化数据引用`);
|
||
}
|
||
/**
|
||
* 尝试将pages目录下的页面移到项目目录中。
|
||
* 目前简化处理,假设目录结构都是pages/namespace/entity结构,以entity目录作为单元,如果有就放弃,没有就移植
|
||
* @param cwdPageDir
|
||
* @param modulePageDir
|
||
*/
|
||
function tryCopyPages(cwdPageDir, modulePageDir) {
|
||
// 各个namespace处理
|
||
const nss = (0, fs_1.readdirSync)(modulePageDir);
|
||
nss.forEach((namespace) => {
|
||
const pages = (0, fs_1.readdirSync)(join(modulePageDir, namespace));
|
||
pages.forEach((page) => {
|
||
const destDir = join(cwdPageDir, namespace, page);
|
||
if (!(0, fs_1.existsSync)(destDir)) {
|
||
(0, fs_extra_1.mkdirSync)(destDir);
|
||
const srcDir = join(modulePageDir, namespace, page);
|
||
console.log(`拷贝${srcDir}到${destDir}下`);
|
||
(0, fs_extra_1.copySync)(srcDir, destDir, {
|
||
recursive: true,
|
||
});
|
||
}
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* 对各个依赖项目,可能有些文件需要被移植到项目目录下,逐步完善
|
||
* @param cwd
|
||
* @param dependencies
|
||
* @param briefNames
|
||
*/
|
||
function tryCopyModuleTemplateFiles(cwd, dependencies, briefNames, printer) {
|
||
const injectDataIndexFileDependencies = [];
|
||
const injectDataIndexFileBriefNames = [];
|
||
dependencies.forEach((dep, idx) => {
|
||
const moduleDir = join(cwd, 'node_modules', dep);
|
||
const moduleTemplateDir = join(moduleDir, 'template');
|
||
if ((0, fs_1.existsSync)(moduleTemplateDir)) {
|
||
// data.ts中规定的初始化数据,拷贝到data目录下,并注入到data/index.ts
|
||
const dataFile = join(moduleTemplateDir, 'data.ts');
|
||
if ((0, fs_1.existsSync)(dataFile)) {
|
||
const prjDataFile = join(cwd, 'src', 'data', `${briefNames[idx]}Data.ts`);
|
||
if (!(0, fs_1.existsSync)(prjDataFile)) {
|
||
console.log(`拷贝${dataFile}到${prjDataFile}中`);
|
||
(0, fs_extra_1.copySync)(dataFile, prjDataFile);
|
||
injectDataIndexFileDependencies.push(dep);
|
||
injectDataIndexFileBriefNames.push(briefNames[idx]);
|
||
}
|
||
}
|
||
// pages中设计的页面,拷贝到pages对应的目录下,考虑namespace
|
||
const pageDir = join(moduleTemplateDir, 'pages');
|
||
if ((0, fs_1.existsSync)(pageDir)) {
|
||
tryCopyPages(join(cwd, 'src', 'pages'), pageDir);
|
||
}
|
||
}
|
||
});
|
||
if (injectDataIndexFileBriefNames.length > 0) {
|
||
injectDataIndexFile(join(cwd, 'src', 'data', 'index.ts'), injectDataIndexFileBriefNames, printer);
|
||
}
|
||
}
|
||
/**
|
||
* 对于module类型的项目,在feature/index.ts中注入initialize函数
|
||
* @param cwd
|
||
* @param dependencies
|
||
* @param briefNames
|
||
*/
|
||
function injectInitializeToFeatureIndex(cwd, dependencies, briefNames, printer) {
|
||
const featureIndexFile = join(cwd, 'src', 'features', 'index.ts');
|
||
const sourceFile = ts.createSourceFile('index.ts', (0, fs_1.readFileSync)(featureIndexFile, 'utf-8'), ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
||
const { statements } = sourceFile;
|
||
const initializeStmt = statements.find((stmt) => ts.isFunctionDeclaration(stmt) && ts.isIdentifier(stmt.name) && stmt.name.text === 'initialize');
|
||
if (!initializeStmt) {
|
||
const statements2 = [
|
||
...(dependencies.map((dep, idx) => factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("FeatureDict"), factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(briefNames[idx])}FeatureDict`))])), factory.createStringLiteral(dep), undefined))),
|
||
...statements,
|
||
factory.createFunctionDeclaration([
|
||
factory.createToken(ts.SyntaxKind.ExportKeyword),
|
||
factory.createToken(ts.SyntaxKind.AsyncKeyword)
|
||
], undefined, factory.createIdentifier("initialize"), [
|
||
factory.createTypeParameterDeclaration(undefined, factory.createIdentifier("ED"), factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined), undefined)
|
||
], [
|
||
factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier("features"), undefined, factory.createIntersectionTypeNode([
|
||
factory.createTypeReferenceNode(factory.createIdentifier("FeatureDict"), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]),
|
||
factory.createTypeReferenceNode(factory.createIdentifier("BasicFeatures"), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]),
|
||
...briefNames.map((ele) => factory.createTypeReferenceNode(factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(ele)}FeatureDict`), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]))
|
||
]), undefined)
|
||
], undefined, factory.createBlock([], true))
|
||
];
|
||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||
(0, fs_1.writeFileSync)(featureIndexFile, result, { flag: 'w' });
|
||
console.log(`注入${featureIndexFile}文件成功,用户可以自己修正initialize函数的参数和逻辑`);
|
||
}
|
||
}
|
||
/**
|
||
* 本函数用于构建src/initialize.dev, src/initialize.prod, src/initializeFeatures, src/context/FrontendContext, src/contextBackendContext
|
||
* 这些和dependency相关的项目文件
|
||
*/
|
||
function buildDependency(rebuild) {
|
||
const cwd = process.cwd();
|
||
const webDir = join(cwd, 'web');
|
||
const isModule = !(0, fs_1.existsSync)(webDir); // 如果没有web目录,说明是module,不需要处理模块级别的文件注入
|
||
const depConfigFile = join(cwd, 'src', 'configuration', 'dependency.ts');
|
||
if (!(0, fs_1.existsSync)(depConfigFile)) {
|
||
console.error(`${depConfigFile}不存在,无法构建启动文件`);
|
||
}
|
||
const depGraph = analyzeDepedency(cwd);
|
||
// 依赖如果是树形关系,应当从底层的被依赖者开始初始化
|
||
const dependencies = depGraph.ascOrder;
|
||
const briefNames = dependencies.map((dep, idx) => `${dep.split('-').map(ele => ele[0]).join('')}${idx}`);
|
||
const templateFileList = [
|
||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.frontend.ts'),
|
||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.server.ts'),
|
||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'initializeFeatures.ts'),
|
||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'RuntimeCxt.ts'),
|
||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'DependentExceptions.ts'),
|
||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'polyfill.d.ts'),
|
||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'features/index.ts'),
|
||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'BackendRuntimeContext.ts'),
|
||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'FrontendRuntimeContext.ts')
|
||
];
|
||
const program = ts.createProgram(templateFileList, {});
|
||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
||
let output = true;
|
||
if (!isModule) {
|
||
const initDevFile = join(cwd, 'src', 'initialize.frontend.ts');
|
||
if ((0, fs_1.existsSync)(initDevFile)) {
|
||
let tips = `[${initDevFile}]文件已经存在`;
|
||
if (!rebuild) {
|
||
tips += ',忽略构建。';
|
||
output = false;
|
||
}
|
||
else {
|
||
tips += ',将重新构建';
|
||
}
|
||
console.log(tips);
|
||
}
|
||
if (output) {
|
||
outputIntializeDev(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[0]), printer, initDevFile);
|
||
}
|
||
output = true;
|
||
const initProdFile = join(cwd, 'src', 'initialize.server.ts');
|
||
if ((0, fs_1.existsSync)(initProdFile) && !rebuild) {
|
||
let tips = `[${initProdFile}]文件已经存在`;
|
||
if (!rebuild) {
|
||
tips += ',忽略构建。';
|
||
output = false;
|
||
}
|
||
else {
|
||
tips += ',将重新构建';
|
||
}
|
||
console.log(tips);
|
||
}
|
||
if (output) {
|
||
outputIntializeProd(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[1]), printer, initProdFile);
|
||
}
|
||
output = true;
|
||
const initFeaturesFile = join(cwd, 'src', 'initializeFeatures.ts');
|
||
if ((0, fs_1.existsSync)(initFeaturesFile) && !rebuild) {
|
||
let tips = `[${initFeaturesFile}]文件已经存在`;
|
||
if (!rebuild) {
|
||
tips += ',忽略构建。';
|
||
output = false;
|
||
}
|
||
else {
|
||
tips += ',将重新构建,注意如果自定义过初始化过程,需要重新输入';
|
||
}
|
||
console.log(tips);
|
||
}
|
||
if (output) {
|
||
outputIntializeFeatures(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[2]), printer, initFeaturesFile);
|
||
}
|
||
}
|
||
output = true;
|
||
const runtimeCxtFile = join(cwd, 'src', 'types', 'RuntimeCxt.ts');
|
||
if ((0, fs_1.existsSync)(runtimeCxtFile) && !rebuild) {
|
||
let tips = `[${runtimeCxtFile}]文件已经存在`;
|
||
if (!rebuild) {
|
||
tips += ',忽略构建。';
|
||
output = false;
|
||
}
|
||
else {
|
||
tips += ',将重新构建';
|
||
}
|
||
console.log(tips);
|
||
}
|
||
if (output) {
|
||
outputRuntimeCxt(dependencies, briefNames, program.getSourceFile(templateFileList[3]), printer, runtimeCxtFile);
|
||
}
|
||
output = true;
|
||
const dependentExceptionsFile = join(cwd, 'src', 'types', 'DependentExceptions.ts');
|
||
if ((0, fs_1.existsSync)(dependentExceptionsFile) && !rebuild) {
|
||
let tips = `[${dependentExceptionsFile}]文件已经存在`;
|
||
if (!rebuild) {
|
||
tips += ',忽略构建。';
|
||
output = false;
|
||
}
|
||
else {
|
||
tips += ',将重新构建';
|
||
}
|
||
console.log(tips);
|
||
}
|
||
if (output) {
|
||
outputDependentExceptions(dependencies, briefNames, program.getSourceFile(templateFileList[4]), printer, dependentExceptionsFile);
|
||
}
|
||
output = true;
|
||
const polyfillDtsFile = join(cwd, 'typings', 'polyfill.d.ts');
|
||
if ((0, fs_1.existsSync)(polyfillDtsFile) && !rebuild) {
|
||
let tips = `[${polyfillDtsFile}]文件已经存在`;
|
||
if (!rebuild) {
|
||
tips += ',忽略构建。';
|
||
output = false;
|
||
}
|
||
else {
|
||
tips += ',将重新构建';
|
||
}
|
||
console.log(tips);
|
||
}
|
||
if (output) {
|
||
outputPolyfillDts(dependencies, briefNames, program.getSourceFile(templateFileList[5]), printer, polyfillDtsFile);
|
||
}
|
||
output = true;
|
||
const featureIndexFile = join(cwd, 'src', 'features', 'index.ts');
|
||
if ((0, fs_1.existsSync)(featureIndexFile) && !rebuild) {
|
||
let tips = `[${featureIndexFile}]文件已经存在`;
|
||
if (!rebuild) {
|
||
tips += ',忽略构建。';
|
||
output = false;
|
||
}
|
||
else {
|
||
tips += ',将重新构建';
|
||
}
|
||
console.log(tips);
|
||
}
|
||
else {
|
||
outputFeatureIndex(dependencies, briefNames, program.getSourceFile(templateFileList[6]), printer, featureIndexFile, isModule);
|
||
}
|
||
output = true;
|
||
let contextFile = join(cwd, 'src', 'context', 'BackendRuntimeContext.ts');
|
||
if ((0, fs_1.existsSync)(contextFile) && !rebuild) {
|
||
let tips = `[${contextFile}]文件已经存在`;
|
||
if (!rebuild) {
|
||
tips += ',忽略构建。';
|
||
output = false;
|
||
}
|
||
else {
|
||
tips += ',将重新构建,注意如果自定义过上下文的其它方法或属性,需要重新输入';
|
||
}
|
||
console.log(tips);
|
||
}
|
||
if (output) {
|
||
outputContext(depGraph, program.getSourceFile(templateFileList[7]), printer, contextFile);
|
||
}
|
||
output = true;
|
||
contextFile = join(cwd, 'src', 'context', 'FrontendRuntimeContext.ts');
|
||
if ((0, fs_1.existsSync)(contextFile) && !rebuild) {
|
||
let tips = `[${contextFile}]文件已经存在`;
|
||
if (!rebuild) {
|
||
tips += ',忽略构建。';
|
||
output = false;
|
||
}
|
||
else {
|
||
tips += ',将重新构建,注意如果自定义过上下文的其它方法或属性,需要重新输入';
|
||
}
|
||
console.log(tips);
|
||
}
|
||
if (output) {
|
||
outputContext(depGraph, program.getSourceFile(templateFileList[8]), printer, contextFile);
|
||
}
|
||
// 把各个依赖项目的一些初始化的文件拷贝过去
|
||
if (!isModule) {
|
||
tryCopyModuleTemplateFiles(cwd, dependencies, briefNames, printer);
|
||
}
|
||
}
|
||
exports.default = buildDependency;
|