100 lines
2.9 KiB
TypeScript

import { ProjectSchema, ResultFile, ResultDir } from '@ali/lowcode-types';
import {
BuilderComponentPlugin,
CodeGeneratorError,
ICodeChunk,
ICompiledModule,
IModuleBuilder,
IParseResult,
ISchemaParser,
PostProcessor,
} from '../types';
import { COMMON_SUB_MODULE_NAME } from '../const/generator';
import SchemaParser from '../parser/SchemaParser';
import ChunkBuilder from './ChunkBuilder';
import CodeBuilder from './CodeBuilder';
import { createResultFile, createResultDir, addFile } from '../utils/resultHelper';
export function createModuleBuilder(
options: {
plugins: BuilderComponentPlugin[];
postProcessors: PostProcessor[];
mainFileName?: string;
} = {
plugins: [],
postProcessors: [],
},
): IModuleBuilder {
const chunkGenerator = new ChunkBuilder(options.plugins);
const linker = new CodeBuilder();
const generateModule = async (input: unknown): Promise<ICompiledModule> => {
const moduleMainName = options.mainFileName || COMMON_SUB_MODULE_NAME;
if (chunkGenerator.getPlugins().length <= 0) {
throw new CodeGeneratorError('No plugins found. Component generation cannot work without any plugins!');
}
let files: ResultFile[] = [];
const { chunks } = await chunkGenerator.run(input);
chunks.forEach((fileChunkList) => {
const content = linker.link(fileChunkList);
const file = createResultFile(fileChunkList[0].subModule || moduleMainName, fileChunkList[0].fileType, content);
files.push(file);
});
if (options.postProcessors.length > 0) {
files = files.map((file) => {
let { content } = file;
const type = file.ext;
options.postProcessors.forEach((processer) => {
content = processer(content, type);
});
return createResultFile(file.name, type, content);
});
}
return {
files,
};
};
const generateModuleCode = async (schema: ProjectSchema | string): Promise<ResultDir> => {
// Init
const schemaParser: ISchemaParser = new SchemaParser();
const parseResult: IParseResult = schemaParser.parse(schema);
const containerInfo = parseResult.containers[0];
const { files } = await generateModule(containerInfo);
const dir = createResultDir(containerInfo.moduleName);
files.forEach((file) => addFile(dir, file));
return dir;
};
const linkCodeChunks = (chunks: Record<string, ICodeChunk[]>, fileName: string) => {
const files: ResultFile[] = [];
Object.keys(chunks).forEach((fileKey) => {
const fileChunkList = chunks[fileKey];
const content = linker.link(fileChunkList);
const file = createResultFile(fileChunkList[0].subModule || fileName, fileChunkList[0].fileType, content);
files.push(file);
});
return files;
};
return {
generateModule,
generateModuleCode,
linkCodeChunks,
addPlugin: chunkGenerator.addPlugin.bind(chunkGenerator),
};
}