routerBuilder适配新的目录结构,dependencyBuilder处理了data和page等和具体模块相关的初始化
This commit is contained in:
parent
6ae7235a5a
commit
c76ca84cd2
|
|
@ -8,6 +8,7 @@ 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 { factory } = ts;
|
||||
/**
|
||||
* 构建项目依赖关系图
|
||||
|
|
@ -94,6 +95,82 @@ function destructVariableDeclaration(vd) {
|
|||
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, {
|
||||
arguments: [
|
||||
...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),
|
||||
factory.createTypeReferenceNode(factory.createIdentifier("BackendRuntimeContext"), 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),
|
||||
factory.createTypeReferenceNode(factory.createIdentifier("BackendRuntimeContext"), 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) {
|
||||
|
|
@ -127,7 +204,7 @@ function outputDependentExceptions(dependencies, briefNames, sourceFile, printer
|
|||
}
|
||||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||||
console.log('构建types/DependentException.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
function outputRuntimeCxt(dependencies, briefNames, sourceFile, printer, filename) {
|
||||
let statements2 = [];
|
||||
|
|
@ -185,7 +262,7 @@ function outputRuntimeCxt(dependencies, briefNames, sourceFile, printer, filenam
|
|||
}
|
||||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||||
console.log('构建types/RuntimeCxt.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
function outputDependentContext(depGraph, printer, filename) {
|
||||
// 目前只支持单向依赖,未来可以利用mixin来实现多类的继承
|
||||
|
|
@ -199,7 +276,7 @@ function outputDependentContext(depGraph, printer, filename) {
|
|||
];
|
||||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements), ts.createSourceFile("someFileName.ts", "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS));
|
||||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||||
console.log('构建context/DependentContext.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
/**
|
||||
* 生成initialize.prod.ts
|
||||
|
|
@ -327,7 +404,7 @@ function outputIntializeProd(cwd, dependencies, briefNames, sourceFile, printer,
|
|||
}
|
||||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||||
console.log('构建initialize.prod.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
/**
|
||||
* 生成initialize.dev.ts
|
||||
|
|
@ -487,7 +564,7 @@ function outputIntializeDev(cwd, dependencies, briefNames, sourceFile, printer,
|
|||
}
|
||||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||||
console.log('构建initialize.dev.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
function outputIntializeFeatures(cwd, dependencies, briefNames, sourceFile, printer, filename) {
|
||||
const { statements } = sourceFile;
|
||||
|
|
@ -556,7 +633,111 @@ function outputIntializeFeatures(cwd, dependencies, briefNames, sourceFile, prin
|
|||
}
|
||||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||||
console.log('构建initializeFeatures.ts文件成功');
|
||||
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)) {
|
||||
const entitiesDir = join(moduleTemplateDir, 'entities');
|
||||
if ((0, fs_1.existsSync)(entitiesDir)) {
|
||||
// entities目录下的定义直接拷贝过去(如果尚不存在的话)
|
||||
const prjEntitiesDir = join(cwd, 'src', 'entities');
|
||||
const result = (0, fs_1.readdirSync)(entitiesDir);
|
||||
result.forEach((filename) => {
|
||||
if (!(0, fs_1.existsSync)(join(prjEntitiesDir, filename))) {
|
||||
console.log(`拷贝${join(entitiesDir, filename)}到${prjEntitiesDir}目录下`);
|
||||
(0, fs_extra_1.copySync)(join(entitiesDir, filename), join(prjEntitiesDir, filename));
|
||||
}
|
||||
});
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 本函数用于构建src/initialize.dev, src/initialize.prod, src/initializeFeatures, src/context/FrontendContext, src/contextBackendContext
|
||||
|
|
@ -577,7 +758,8 @@ function buildDependency(rebuild) {
|
|||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.prod.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', 'DependentExceptions.ts'),
|
||||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'polyfill.d.ts')
|
||||
];
|
||||
const program = ts.createProgram(templateFileList, {});
|
||||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
||||
|
|
@ -623,5 +805,14 @@ function buildDependency(rebuild) {
|
|||
else {
|
||||
outputDependentExceptions(dependencies, briefNames, program.getSourceFile(templateFileList[4]), printer, dependentExceptionsFile);
|
||||
}
|
||||
const polyfillDtsFile = join(cwd, 'typings', 'polyfill.d.ts');
|
||||
if ((0, fs_1.existsSync)(polyfillDtsFile) && !rebuild) {
|
||||
console.log(`[${polyfillDtsFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputPolyfillDts(dependencies, briefNames, program.getSourceFile(templateFileList[5]), printer, polyfillDtsFile);
|
||||
}
|
||||
// 把各个依赖项目的一些初始化的文件拷贝过去
|
||||
tryCopyModuleTemplateFiles(cwd, dependencies, briefNames, printer);
|
||||
}
|
||||
exports.default = buildDependency;
|
||||
|
|
|
|||
|
|
@ -161,8 +161,8 @@ function judgeUseOakRouterBuilder(statements) {
|
|||
return ts.isExpressionStatement(stmt) && ts.isStringLiteral(stmt.expression) && stmt.expression.text === 'use oak router builder';
|
||||
}
|
||||
function outputInWebAppDir(appDir) {
|
||||
const routerFileName = (0, path_1.join)(appDir, 'router', 'allRouters.ts');
|
||||
const templateFileName = (0, path_1.join)(appDir, '../../../..', 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'allRouters.ts');
|
||||
const routerFileName = (0, path_1.join)(appDir, 'routers', 'allRouters.ts');
|
||||
const templateFileName = (0, path_1.join)(appDir, '../../..', 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'allRouters.ts');
|
||||
const program = ts.createProgram([templateFileName], {
|
||||
removeComments: false,
|
||||
});
|
||||
|
|
@ -176,7 +176,7 @@ function outputInWebAppDir(appDir) {
|
|||
const declaration = statement.declarationList.declarations.find(declaration => ts.isIdentifier(declaration.name) && declaration.name.text === 'allRouters');
|
||||
if (declaration) {
|
||||
Object.assign(declaration, {
|
||||
initializer: makeWebAllRouters(namespaceDir, (0, path_1.join)(appDir, '../../../..'), (0, path_1.dirname)(routerFileName))
|
||||
initializer: makeWebAllRouters(namespaceDir, (0, path_1.join)(appDir, '../../..'), (0, path_1.dirname)(routerFileName))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -188,14 +188,7 @@ function outputInWebAppDir(appDir) {
|
|||
}
|
||||
function outputInWebDir(dir) {
|
||||
const srcAppDir = (0, path_1.join)(dir, 'src', 'app');
|
||||
const apps = (0, fs_extra_1.readdirSync)(srcAppDir);
|
||||
apps.forEach((app) => {
|
||||
const appDir = (0, path_1.join)(srcAppDir, app);
|
||||
const stat = (0, fs_extra_1.statSync)(appDir);
|
||||
if (stat.isDirectory()) {
|
||||
outputInWebAppDir(appDir);
|
||||
}
|
||||
});
|
||||
outputInWebAppDir(srcAppDir);
|
||||
}
|
||||
function watchDir(projectDir, startupDir, type) {
|
||||
const srcPageDir = (0, path_1.join)(projectDir, 'src', 'pages');
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import assert from 'assert';
|
||||
import { join as pathJoin } from 'path';
|
||||
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
||||
import { existsSync, readFileSync, writeFileSync, readdirSync } from 'fs';
|
||||
import * as ts from 'typescript';
|
||||
import { firstLetterLowerCase, firstLetterUpperCase } from '../utils/string';
|
||||
import { OAK_CLI_MODULE_NAME } from './env';
|
||||
import { copySync, mkdirSync } from 'fs-extra';
|
||||
const { factory } = ts;
|
||||
|
||||
type DepNode = {
|
||||
|
|
@ -113,6 +114,168 @@ function destructVariableDeclaration(vd: ts.VariableDeclaration) {
|
|||
};
|
||||
}
|
||||
|
||||
function outputPolyfillDts(
|
||||
dependencies: string[],
|
||||
briefNames: string[],
|
||||
sourceFile: ts.SourceFile,
|
||||
printer: ts.Printer,
|
||||
filename: string
|
||||
) {
|
||||
let statements2: ts.Statement[] = [];
|
||||
if (dependencies.length > 0) {
|
||||
const { statements } = sourceFile;
|
||||
assert(ts.isImportDeclaration(statements[5]) && ts.isModuleDeclaration(statements[6]));
|
||||
|
||||
const importStatements: ts.Statement[] = [];
|
||||
|
||||
dependencies.forEach(
|
||||
(dep, idx) => {
|
||||
importStatements.push(
|
||||
factory.createImportDeclaration(
|
||||
undefined,
|
||||
factory.createImportClause(
|
||||
false,
|
||||
undefined,
|
||||
factory.createNamedImports([factory.createImportSpecifier(
|
||||
false,
|
||||
factory.createIdentifier("FeatureDict"),
|
||||
factory.createIdentifier(`${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(`${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] as ts.ModuleDeclaration;
|
||||
const { body } = stmt6;
|
||||
const [ocStmt, featuresStmt] = (<ts.ModuleBlock>body).statements;
|
||||
assert(ts.isVariableStatement(ocStmt) && ts.isVariableStatement(featuresStmt));
|
||||
const [ocVd] = ocStmt.declarationList.declarations;
|
||||
const [featuresVd] = featuresStmt.declarationList.declarations;
|
||||
assert(ts.isVariableDeclaration(ocVd) && ts.isIdentifier(ocVd.name) && ocVd.name.text === 'OakComponent');
|
||||
assert(ts.isVariableDeclaration(featuresVd) && ts.isIdentifier(featuresVd.name) && featuresVd.name.text === 'features');
|
||||
|
||||
const ocType = ocVd.type!;
|
||||
assert(ts.isTypeReferenceNode(ocType) && ocType.typeArguments?.length === 5);
|
||||
const aspectTypeNode = ocType.typeArguments[3];
|
||||
const featureTypeNode = ocType.typeArguments[4];
|
||||
assert(ts.isTypeReferenceNode(aspectTypeNode) && ts.isTypeReferenceNode(featureTypeNode));
|
||||
Object.assign(ocType, {
|
||||
arguments: [
|
||||
...ocType.typeArguments.slice(0, 3),
|
||||
factory.createIntersectionTypeNode(
|
||||
[
|
||||
aspectTypeNode,
|
||||
...briefNames.map(
|
||||
(ele) => factory.createTypeReferenceNode(
|
||||
factory.createIdentifier(`${firstLetterUpperCase(ele)}AspectDict`),
|
||||
[
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("EntityDict"),
|
||||
undefined
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
),
|
||||
factory.createIntersectionTypeNode(
|
||||
[
|
||||
featureTypeNode,
|
||||
...briefNames.map(
|
||||
(ele) => factory.createTypeReferenceNode(
|
||||
factory.createIdentifier(`${firstLetterUpperCase(ele)}FeatureDict`),
|
||||
[
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("EntityDict"),
|
||||
undefined
|
||||
),
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("BackendRuntimeContext"),
|
||||
undefined
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
});
|
||||
|
||||
const featureType = featuresVd.type!;
|
||||
assert(ts.isTypeReferenceNode(featureType));
|
||||
Object.assign(featuresVd, {
|
||||
type: factory.createIntersectionTypeNode(
|
||||
[
|
||||
featureType,
|
||||
...briefNames.map(
|
||||
(ele) => factory.createTypeReferenceNode(
|
||||
factory.createIdentifier(`${firstLetterUpperCase(ele)}FeatureDict`),
|
||||
[
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("EntityDict"),
|
||||
undefined
|
||||
),
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("BackendRuntimeContext"),
|
||||
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);
|
||||
|
||||
writeFileSync(filename, result, { flag: 'w' });
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
|
||||
function outputDependentExceptions(
|
||||
dependencies: string[],
|
||||
briefNames: string[],
|
||||
|
|
@ -208,7 +371,7 @@ function outputDependentExceptions(
|
|||
sourceFile);
|
||||
|
||||
writeFileSync(filename, result, { flag: 'w' });
|
||||
console.log('构建types/DependentException.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
|
||||
function outputRuntimeCxt(
|
||||
|
|
@ -221,13 +384,13 @@ function outputRuntimeCxt(
|
|||
let statements2: ts.Statement[] = [];
|
||||
if (dependencies.length > 0) {
|
||||
const { statements } = sourceFile;
|
||||
|
||||
|
||||
const importStatements: ts.Statement[] = [];
|
||||
const stmt9 = statements[9];
|
||||
const stmt10 = statements[10];
|
||||
assert(ts.isTypeAliasDeclaration(stmt9) && ts.isIdentifier(stmt9.name) && stmt9.name.text === 'AAD');
|
||||
assert(ts.isTypeAliasDeclaration(stmt10) && ts.isIdentifier(stmt10.name) && stmt10.name.text === 'AFD')
|
||||
|
||||
|
||||
assert(ts.isImportDeclaration(statements[5]) && ts.isTypeAliasDeclaration(statements[6]));
|
||||
const AADs = [] as string[];
|
||||
const AFDs = [] as string[];
|
||||
|
|
@ -303,7 +466,7 @@ function outputRuntimeCxt(
|
|||
sourceFile);
|
||||
|
||||
writeFileSync(filename, result, { flag: 'w' });
|
||||
console.log('构建types/RuntimeCxt.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
|
||||
function outputDependentContext(depGraph: DepGraph, printer: ts.Printer, filename: string) {
|
||||
|
|
@ -339,7 +502,7 @@ function outputDependentContext(depGraph: DepGraph, printer: ts.Printer, filenam
|
|||
ts.createSourceFile("someFileName.ts", "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS));
|
||||
|
||||
writeFileSync(filename, result, { flag: 'w' });
|
||||
console.log('构建context/DependentContext.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -591,7 +754,7 @@ function outputIntializeProd(
|
|||
sourceFile);
|
||||
|
||||
writeFileSync(filename, result, { flag: 'w' });
|
||||
console.log('构建initialize.prod.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -909,7 +1072,7 @@ function outputIntializeDev(
|
|||
sourceFile);
|
||||
|
||||
writeFileSync(filename, result, { flag: 'w' });
|
||||
console.log('构建initialize.dev.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
|
||||
function outputIntializeFeatures(
|
||||
|
|
@ -1055,7 +1218,163 @@ function outputIntializeFeatures(
|
|||
sourceFile);
|
||||
|
||||
writeFileSync(filename, result, { flag: 'w' });
|
||||
console.log('构建initializeFeatures.ts文件成功');
|
||||
console.log(`构建${filename}文件成功`);
|
||||
}
|
||||
|
||||
|
||||
function injectDataIndexFile(
|
||||
dataIndexFile: string,
|
||||
briefNames: string[],
|
||||
printer: ts.Printer,
|
||||
) {
|
||||
const sourceFile = ts.createSourceFile('index.ts', readFileSync(dataIndexFile, 'utf-8'), ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
||||
|
||||
const { statements } = sourceFile;
|
||||
const importStatements: ts.Statement[] = 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];
|
||||
assert(ts.isExportAssignment(exportStmt));
|
||||
const { expression } = exportStmt;
|
||||
assert(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);
|
||||
|
||||
writeFileSync(dataIndexFile, result, { flag: 'w' });
|
||||
console.log(`注入${dataIndexFile}文件成功,共注入了${briefNames.length}个初始化数据引用`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试将pages目录下的页面移到项目目录中。
|
||||
* 目前简化处理,假设目录结构都是pages/namespace/entity结构,以entity目录作为单元,如果有就放弃,没有就移植
|
||||
* @param cwdPageDir
|
||||
* @param modulePageDir
|
||||
*/
|
||||
function tryCopyPages(
|
||||
cwdPageDir: string,
|
||||
modulePageDir: string,
|
||||
) {
|
||||
// 各个namespace处理
|
||||
const nss = readdirSync(modulePageDir);
|
||||
nss.forEach(
|
||||
(namespace) => {
|
||||
const pages = readdirSync(join(modulePageDir, namespace));
|
||||
|
||||
pages.forEach(
|
||||
(page) => {
|
||||
const destDir = join(cwdPageDir, namespace, page);
|
||||
if (!existsSync(destDir)) {
|
||||
mkdirSync(destDir);
|
||||
const srcDir = join(modulePageDir, namespace, page);
|
||||
console.log(`拷贝${srcDir}到${destDir}下`);
|
||||
copySync(srcDir, destDir, {
|
||||
recursive: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 对各个依赖项目,可能有些文件需要被移植到项目目录下,逐步完善
|
||||
* @param cwd
|
||||
* @param dependencies
|
||||
* @param briefNames
|
||||
*/
|
||||
function tryCopyModuleTemplateFiles(
|
||||
cwd: string,
|
||||
dependencies: string[],
|
||||
briefNames: string[],
|
||||
printer: ts.Printer
|
||||
) {
|
||||
const injectDataIndexFileDependencies: string[] = [];
|
||||
const injectDataIndexFileBriefNames: string[] = [];
|
||||
|
||||
dependencies.forEach(
|
||||
(dep, idx) => {
|
||||
const moduleDir = join(cwd, 'node_modules', dep);
|
||||
const moduleTemplateDir = join(moduleDir, 'template');
|
||||
if (existsSync(moduleTemplateDir)) {
|
||||
const entitiesDir = join(moduleTemplateDir, 'entities');
|
||||
if (existsSync(entitiesDir)) {
|
||||
// entities目录下的定义直接拷贝过去(如果尚不存在的话)
|
||||
const prjEntitiesDir = join(cwd, 'src', 'entities');
|
||||
const result = readdirSync(entitiesDir);
|
||||
result.forEach(
|
||||
(filename) => {
|
||||
if (!existsSync(join(prjEntitiesDir, filename))) {
|
||||
console.log(`拷贝${join(entitiesDir, filename)}到${prjEntitiesDir}目录下`);
|
||||
copySync(join(entitiesDir, filename), join(prjEntitiesDir, filename));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// data.ts中规定的初始化数据,拷贝到data目录下,并注入到data/index.ts
|
||||
const dataFile = join(moduleTemplateDir, 'data.ts');
|
||||
if (existsSync(dataFile)) {
|
||||
const prjDataFile = join(cwd, 'src', 'data', `${briefNames[idx]}Data.ts`);
|
||||
if (!existsSync(prjDataFile)) {
|
||||
console.log(`拷贝${dataFile}到${prjDataFile}中`);
|
||||
copySync(dataFile, prjDataFile);
|
||||
injectDataIndexFileDependencies.push(dep);
|
||||
injectDataIndexFileBriefNames.push(briefNames[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
// pages中设计的页面,拷贝到pages对应的目录下,考虑namespace
|
||||
const pageDir = join(moduleTemplateDir, 'pages');
|
||||
if (existsSync(pageDir)) {
|
||||
tryCopyPages(join(cwd, 'src', 'pages'), pageDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (injectDataIndexFileBriefNames.length > 0) {
|
||||
injectDataIndexFile(join(cwd, 'src', 'data', 'index.ts'), injectDataIndexFileBriefNames, printer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1083,7 +1402,8 @@ export default function buildDependency(rebuild?: boolean) {
|
|||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.prod.ts'),
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'initializeFeatures.ts'),
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'RuntimeCxt.ts'),
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'DependentExceptions.ts')
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'DependentExceptions.ts'),
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'polyfill.d.ts')
|
||||
];
|
||||
|
||||
const program = ts.createProgram(templateFileList, {});
|
||||
|
|
@ -1130,7 +1450,7 @@ export default function buildDependency(rebuild?: boolean) {
|
|||
else {
|
||||
outputRuntimeCxt(dependencies, briefNames, program.getSourceFile(templateFileList[3])!, printer, runtimeCxtFile);
|
||||
}
|
||||
|
||||
|
||||
const dependentExceptionsFile = join(cwd, 'src', 'types', 'DependentExceptions.ts');
|
||||
if (existsSync(dependentExceptionsFile) && !rebuild) {
|
||||
console.log(`[${dependentExceptionsFile}]文件已经存在,无需构建启动文件`);
|
||||
|
|
@ -1138,4 +1458,15 @@ export default function buildDependency(rebuild?: boolean) {
|
|||
else {
|
||||
outputDependentExceptions(dependencies, briefNames, program.getSourceFile(templateFileList[4])!, printer, dependentExceptionsFile);
|
||||
}
|
||||
|
||||
const polyfillDtsFile = join(cwd, 'typings', 'polyfill.d.ts');
|
||||
if (existsSync(polyfillDtsFile) && !rebuild) {
|
||||
console.log(`[${polyfillDtsFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputPolyfillDts(dependencies, briefNames, program.getSourceFile(templateFileList[5])!, printer, polyfillDtsFile);
|
||||
}
|
||||
|
||||
// 把各个依赖项目的一些初始化的文件拷贝过去
|
||||
tryCopyModuleTemplateFiles(cwd, dependencies, briefNames, printer);
|
||||
}
|
||||
|
|
@ -352,8 +352,8 @@ function judgeUseOakRouterBuilder(statements: ts.NodeArray<ts.Statement>) {
|
|||
}
|
||||
|
||||
function outputInWebAppDir(appDir: string) {
|
||||
const routerFileName = join(appDir, 'router', 'allRouters.ts');
|
||||
const templateFileName = join(appDir, '../../../..', 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'allRouters.ts');
|
||||
const routerFileName = join(appDir, 'routers', 'allRouters.ts');
|
||||
const templateFileName = join(appDir, '../../..', 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'allRouters.ts');
|
||||
const program = ts.createProgram([templateFileName], {
|
||||
removeComments: false,
|
||||
});
|
||||
|
|
@ -370,7 +370,7 @@ function outputInWebAppDir(appDir: string) {
|
|||
);
|
||||
if (declaration) {
|
||||
Object.assign(declaration, {
|
||||
initializer: makeWebAllRouters(namespaceDir, join(appDir, '../../../..'), dirname(routerFileName))
|
||||
initializer: makeWebAllRouters(namespaceDir, join(appDir, '../../..'), dirname(routerFileName))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -391,17 +391,7 @@ function outputInWebAppDir(appDir: string) {
|
|||
|
||||
function outputInWebDir(dir: string) {
|
||||
const srcAppDir = join(dir, 'src', 'app');
|
||||
const apps = readdirSync(srcAppDir);
|
||||
apps.forEach(
|
||||
(app) => {
|
||||
const appDir = join(srcAppDir, app);
|
||||
const stat = statSync(appDir);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
outputInWebAppDir(appDir);
|
||||
}
|
||||
}
|
||||
)
|
||||
outputInWebAppDir(srcAppDir);
|
||||
}
|
||||
|
||||
function watchDir(projectDir: string, startupDir: string, type: 'native' | 'web' | 'wechatMp') {
|
||||
|
|
|
|||
Loading…
Reference in New Issue