routerBuilder适配新的目录结构,dependencyBuilder处理了data和page等和具体模块相关的初始化

This commit is contained in:
Xu Chang 2024-04-12 17:59:50 +08:00
parent 6ae7235a5a
commit c76ca84cd2
4 changed files with 548 additions and 43 deletions

View File

@ -8,6 +8,7 @@ const fs_1 = require("fs");
const ts = tslib_1.__importStar(require("typescript")); const ts = tslib_1.__importStar(require("typescript"));
const string_1 = require("../utils/string"); const string_1 = require("../utils/string");
const env_1 = require("./env"); const env_1 = require("./env");
const fs_extra_1 = require("fs-extra");
const { factory } = ts; const { factory } = ts;
/** /**
* 构建项目依赖关系图 * 构建项目依赖关系图
@ -94,6 +95,82 @@ function destructVariableDeclaration(vd) {
expression, 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) { function outputDependentExceptions(dependencies, briefNames, sourceFile, printer, filename) {
let statements2 = []; let statements2 = [];
if (dependencies.length > 0) { 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); const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' }); (0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
console.log('构建types/DependentException.ts文件成功'); console.log(`构建${filename}文件成功`);
} }
function outputRuntimeCxt(dependencies, briefNames, sourceFile, printer, filename) { function outputRuntimeCxt(dependencies, briefNames, sourceFile, printer, filename) {
let statements2 = []; let statements2 = [];
@ -185,7 +262,7 @@ function outputRuntimeCxt(dependencies, briefNames, sourceFile, printer, filenam
} }
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile); const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' }); (0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
console.log('构建types/RuntimeCxt.ts文件成功'); console.log(`构建${filename}文件成功`);
} }
function outputDependentContext(depGraph, printer, filename) { function outputDependentContext(depGraph, printer, filename) {
// 目前只支持单向依赖未来可以利用mixin来实现多类的继承 // 目前只支持单向依赖未来可以利用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)); 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' }); (0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
console.log('构建context/DependentContext.ts文件成功'); console.log(`构建${filename}文件成功`);
} }
/** /**
* 生成initialize.prod.ts * 生成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); const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' }); (0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
console.log('构建initialize.prod.ts文件成功'); console.log(`构建${filename}文件成功`);
} }
/** /**
* 生成initialize.dev.ts * 生成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); const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' }); (0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
console.log('构建initialize.dev.ts文件成功'); console.log(`构建${filename}文件成功`);
} }
function outputIntializeFeatures(cwd, dependencies, briefNames, sourceFile, printer, filename) { function outputIntializeFeatures(cwd, dependencies, briefNames, sourceFile, printer, filename) {
const { statements } = sourceFile; 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); const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' }); (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 * 本函数用于构建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', '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', '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', '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 program = ts.createProgram(templateFileList, {});
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
@ -623,5 +805,14 @@ function buildDependency(rebuild) {
else { else {
outputDependentExceptions(dependencies, briefNames, program.getSourceFile(templateFileList[4]), printer, dependentExceptionsFile); 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; exports.default = buildDependency;

View File

@ -161,8 +161,8 @@ function judgeUseOakRouterBuilder(statements) {
return ts.isExpressionStatement(stmt) && ts.isStringLiteral(stmt.expression) && stmt.expression.text === 'use oak router builder'; return ts.isExpressionStatement(stmt) && ts.isStringLiteral(stmt.expression) && stmt.expression.text === 'use oak router builder';
} }
function outputInWebAppDir(appDir) { function outputInWebAppDir(appDir) {
const routerFileName = (0, path_1.join)(appDir, 'router', '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 templateFileName = (0, path_1.join)(appDir, '../../..', 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'allRouters.ts');
const program = ts.createProgram([templateFileName], { const program = ts.createProgram([templateFileName], {
removeComments: false, removeComments: false,
}); });
@ -176,7 +176,7 @@ function outputInWebAppDir(appDir) {
const declaration = statement.declarationList.declarations.find(declaration => ts.isIdentifier(declaration.name) && declaration.name.text === 'allRouters'); const declaration = statement.declarationList.declarations.find(declaration => ts.isIdentifier(declaration.name) && declaration.name.text === 'allRouters');
if (declaration) { if (declaration) {
Object.assign(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) { function outputInWebDir(dir) {
const srcAppDir = (0, path_1.join)(dir, 'src', 'app'); const srcAppDir = (0, path_1.join)(dir, 'src', 'app');
const apps = (0, fs_extra_1.readdirSync)(srcAppDir); outputInWebAppDir(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);
}
});
} }
function watchDir(projectDir, startupDir, type) { function watchDir(projectDir, startupDir, type) {
const srcPageDir = (0, path_1.join)(projectDir, 'src', 'pages'); const srcPageDir = (0, path_1.join)(projectDir, 'src', 'pages');

View File

@ -1,9 +1,10 @@
import assert from 'assert'; import assert from 'assert';
import { join as pathJoin } from 'path'; 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 * as ts from 'typescript';
import { firstLetterLowerCase, firstLetterUpperCase } from '../utils/string'; import { firstLetterLowerCase, firstLetterUpperCase } from '../utils/string';
import { OAK_CLI_MODULE_NAME } from './env'; import { OAK_CLI_MODULE_NAME } from './env';
import { copySync, mkdirSync } from 'fs-extra';
const { factory } = ts; const { factory } = ts;
type DepNode = { 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( function outputDependentExceptions(
dependencies: string[], dependencies: string[],
briefNames: string[], briefNames: string[],
@ -208,7 +371,7 @@ function outputDependentExceptions(
sourceFile); sourceFile);
writeFileSync(filename, result, { flag: 'w' }); writeFileSync(filename, result, { flag: 'w' });
console.log('构建types/DependentException.ts文件成功'); console.log(`构建${filename}文件成功`);
} }
function outputRuntimeCxt( function outputRuntimeCxt(
@ -221,13 +384,13 @@ function outputRuntimeCxt(
let statements2: ts.Statement[] = []; let statements2: ts.Statement[] = [];
if (dependencies.length > 0) { if (dependencies.length > 0) {
const { statements } = sourceFile; const { statements } = sourceFile;
const importStatements: ts.Statement[] = []; const importStatements: ts.Statement[] = [];
const stmt9 = statements[9]; const stmt9 = statements[9];
const stmt10 = statements[10]; const stmt10 = statements[10];
assert(ts.isTypeAliasDeclaration(stmt9) && ts.isIdentifier(stmt9.name) && stmt9.name.text === 'AAD'); 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.isTypeAliasDeclaration(stmt10) && ts.isIdentifier(stmt10.name) && stmt10.name.text === 'AFD')
assert(ts.isImportDeclaration(statements[5]) && ts.isTypeAliasDeclaration(statements[6])); assert(ts.isImportDeclaration(statements[5]) && ts.isTypeAliasDeclaration(statements[6]));
const AADs = [] as string[]; const AADs = [] as string[];
const AFDs = [] as string[]; const AFDs = [] as string[];
@ -303,7 +466,7 @@ function outputRuntimeCxt(
sourceFile); sourceFile);
writeFileSync(filename, result, { flag: 'w' }); writeFileSync(filename, result, { flag: 'w' });
console.log('构建types/RuntimeCxt.ts文件成功'); console.log(`构建${filename}文件成功`);
} }
function outputDependentContext(depGraph: DepGraph, printer: ts.Printer, filename: string) { 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)); ts.createSourceFile("someFileName.ts", "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS));
writeFileSync(filename, result, { flag: 'w' }); writeFileSync(filename, result, { flag: 'w' });
console.log('构建context/DependentContext.ts文件成功'); console.log(`构建${filename}文件成功`);
} }
/** /**
@ -591,7 +754,7 @@ function outputIntializeProd(
sourceFile); sourceFile);
writeFileSync(filename, result, { flag: 'w' }); writeFileSync(filename, result, { flag: 'w' });
console.log('构建initialize.prod.ts文件成功'); console.log(`构建${filename}文件成功`);
} }
/** /**
@ -909,7 +1072,7 @@ function outputIntializeDev(
sourceFile); sourceFile);
writeFileSync(filename, result, { flag: 'w' }); writeFileSync(filename, result, { flag: 'w' });
console.log('构建initialize.dev.ts文件成功'); console.log(`构建${filename}文件成功`);
} }
function outputIntializeFeatures( function outputIntializeFeatures(
@ -1055,7 +1218,163 @@ function outputIntializeFeatures(
sourceFile); sourceFile);
writeFileSync(filename, result, { flag: 'w' }); 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', 'initialize.prod.ts'),
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'initializeFeatures.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', '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, {}); const program = ts.createProgram(templateFileList, {});
@ -1130,7 +1450,7 @@ export default function buildDependency(rebuild?: boolean) {
else { else {
outputRuntimeCxt(dependencies, briefNames, program.getSourceFile(templateFileList[3])!, printer, runtimeCxtFile); outputRuntimeCxt(dependencies, briefNames, program.getSourceFile(templateFileList[3])!, printer, runtimeCxtFile);
} }
const dependentExceptionsFile = join(cwd, 'src', 'types', 'DependentExceptions.ts'); const dependentExceptionsFile = join(cwd, 'src', 'types', 'DependentExceptions.ts');
if (existsSync(dependentExceptionsFile) && !rebuild) { if (existsSync(dependentExceptionsFile) && !rebuild) {
console.log(`[${dependentExceptionsFile}]文件已经存在,无需构建启动文件`); console.log(`[${dependentExceptionsFile}]文件已经存在,无需构建启动文件`);
@ -1138,4 +1458,15 @@ export default function buildDependency(rebuild?: boolean) {
else { else {
outputDependentExceptions(dependencies, briefNames, program.getSourceFile(templateFileList[4])!, printer, dependentExceptionsFile); 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);
} }

View File

@ -352,8 +352,8 @@ function judgeUseOakRouterBuilder(statements: ts.NodeArray<ts.Statement>) {
} }
function outputInWebAppDir(appDir: string) { function outputInWebAppDir(appDir: string) {
const routerFileName = join(appDir, 'router', 'allRouters.ts'); const routerFileName = join(appDir, 'routers', 'allRouters.ts');
const templateFileName = join(appDir, '../../../..', 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'allRouters.ts'); const templateFileName = join(appDir, '../../..', 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'allRouters.ts');
const program = ts.createProgram([templateFileName], { const program = ts.createProgram([templateFileName], {
removeComments: false, removeComments: false,
}); });
@ -370,7 +370,7 @@ function outputInWebAppDir(appDir: string) {
); );
if (declaration) { if (declaration) {
Object.assign(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) { function outputInWebDir(dir: string) {
const srcAppDir = join(dir, 'src', 'app'); const srcAppDir = join(dir, 'src', 'app');
const apps = readdirSync(srcAppDir); outputInWebAppDir(srcAppDir);
apps.forEach(
(app) => {
const appDir = join(srcAppDir, app);
const stat = statSync(appDir);
if (stat.isDirectory()) {
outputInWebAppDir(appDir);
}
}
)
} }
function watchDir(projectDir: string, startupDir: string, type: 'native' | 'web' | 'wechatMp') { function watchDir(projectDir: string, startupDir: string, type: 'native' | 'web' | 'wechatMp') {