mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-12 03:01:16 +00:00
feat: support UIPaaS-Component code generator solution
This commit is contained in:
parent
82b6a01533
commit
1ca940c880
@ -559,8 +559,8 @@ codealike.json
|
|||||||
"registry": "https://registry.npm.xxx.com"
|
"registry": "https://registry.npm.xxx.com"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alilc/lowcode-code-generator": "^1.0.0-beta.16",
|
"@alilc/lowcode-code-generator": "^1.0.0",
|
||||||
"@alilc/lowcode-types": "^1.0.0-beta.21",
|
"@alilc/lowcode-types": "^1.0.0",
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -62,10 +62,10 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
private projectPostProcessors: ProjectPostProcessor[];
|
private projectPostProcessors: ProjectPostProcessor[];
|
||||||
|
|
||||||
/** 是否处于严格模式 */
|
/** 是否处于严格模式 */
|
||||||
public readonly inStrictMode: boolean;
|
readonly inStrictMode: boolean;
|
||||||
|
|
||||||
/** 一些额外的上下文数据 */
|
/** 一些额外的上下文数据 */
|
||||||
public readonly extraContextData: IContextData;
|
readonly extraContextData: IContextData;
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
template,
|
template,
|
||||||
@ -260,7 +260,10 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
let finalResult = projectRoot;
|
let finalResult = projectRoot;
|
||||||
for (const projectPostProcessor of this.projectPostProcessors) {
|
for (const projectPostProcessor of this.projectPostProcessors) {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
finalResult = await projectPostProcessor(finalResult, schema, originalSchema);
|
finalResult = await projectPostProcessor(finalResult, schema, originalSchema, {
|
||||||
|
template: this.template,
|
||||||
|
parseResult,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return finalResult;
|
return finalResult;
|
||||||
|
|||||||
@ -32,7 +32,7 @@ import {
|
|||||||
import { SUPPORT_SCHEMA_VERSION_LIST } from '../const';
|
import { SUPPORT_SCHEMA_VERSION_LIST } from '../const';
|
||||||
|
|
||||||
import { getErrorMessage } from '../utils/errors';
|
import { getErrorMessage } from '../utils/errors';
|
||||||
import { handleSubNodes } from '../utils/schema';
|
import { handleSubNodes, isValidContainerType } from '../utils/schema';
|
||||||
import { uniqueArray } from '../utils/common';
|
import { uniqueArray } from '../utils/common';
|
||||||
import { componentAnalyzer } from '../analyzer/componentAnalyzer';
|
import { componentAnalyzer } from '../analyzer/componentAnalyzer';
|
||||||
import { ensureValidClassName } from '../utils/validate';
|
import { ensureValidClassName } from '../utils/validate';
|
||||||
@ -141,7 +141,7 @@ export class SchemaParser implements ISchemaParser {
|
|||||||
if (schema.componentsTree.length > 0) {
|
if (schema.componentsTree.length > 0) {
|
||||||
const firstRoot: ContainerSchema = schema.componentsTree[0] as ContainerSchema;
|
const firstRoot: ContainerSchema = schema.componentsTree[0] as ContainerSchema;
|
||||||
|
|
||||||
if (!('fileName' in firstRoot) || !firstRoot.fileName) {
|
if (!firstRoot.fileName && !isValidContainerType(firstRoot)) {
|
||||||
// 整个 schema 描述一个容器,且无根节点定义
|
// 整个 schema 描述一个容器,且无根节点定义
|
||||||
const container: IContainerInfo = {
|
const container: IContainerInfo = {
|
||||||
...firstRoot,
|
...firstRoot,
|
||||||
@ -259,8 +259,7 @@ export class SchemaParser implements ISchemaParser {
|
|||||||
utils = schema.utils;
|
utils = schema.utils;
|
||||||
utilsDeps = schema.utils
|
utilsDeps = schema.utils
|
||||||
.filter(
|
.filter(
|
||||||
(u): u is { name: string; type: 'npm' | 'tnpm'; content: NpmInfo } =>
|
(u): u is { name: string; type: 'npm' | 'tnpm'; content: NpmInfo } => u.type !== 'function',
|
||||||
u.type !== 'function',
|
|
||||||
)
|
)
|
||||||
.map(
|
.map(
|
||||||
(u): IExternalDependency => ({
|
(u): IExternalDependency => ({
|
||||||
|
|||||||
@ -9,7 +9,7 @@ const PARSERS = ['css', 'scss', 'less', 'json', 'html', 'vue'];
|
|||||||
|
|
||||||
export interface ProcessorConfig {
|
export interface ProcessorConfig {
|
||||||
customFileTypeParser: Record<string, string>;
|
customFileTypeParser: Record<string, string>;
|
||||||
plugins?: Array<prettier.Plugin>;
|
plugins?: prettier.Plugin[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const factory: PostProcessorFactory<ProcessorConfig> = (config?: ProcessorConfig) => {
|
const factory: PostProcessorFactory<ProcessorConfig> = (config?: ProcessorConfig) => {
|
||||||
@ -33,6 +33,8 @@ const factory: PostProcessorFactory<ProcessorConfig> = (config?: ProcessorConfig
|
|||||||
return prettier.format(content, {
|
return prettier.format(content, {
|
||||||
parser,
|
parser,
|
||||||
plugins: [parserBabel, parserPostCss, parserHtml, ...(cfg.plugins || [])],
|
plugins: [parserBabel, parserPostCss, parserHtml, ...(cfg.plugins || [])],
|
||||||
|
singleQuote: true,
|
||||||
|
jsxSingleQuote: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -170,11 +170,17 @@ export interface IProjectBuilder {
|
|||||||
/** 项目级别的前置处理器 */
|
/** 项目级别的前置处理器 */
|
||||||
export type ProjectPreProcessor = (schema: ProjectSchema) => Promise<ProjectSchema> | ProjectSchema;
|
export type ProjectPreProcessor = (schema: ProjectSchema) => Promise<ProjectSchema> | ProjectSchema;
|
||||||
|
|
||||||
|
export interface ProjectPostProcessorOptions {
|
||||||
|
parseResult?: IParseResult;
|
||||||
|
template?: IProjectTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
/** 项目级别的后置处理器 */
|
/** 项目级别的后置处理器 */
|
||||||
export type ProjectPostProcessor = (
|
export type ProjectPostProcessor = (
|
||||||
result: ResultDir,
|
result: ResultDir,
|
||||||
schema: ProjectSchema,
|
schema: ProjectSchema,
|
||||||
originalSchema: ProjectSchema | string,
|
originalSchema: ProjectSchema | string,
|
||||||
|
options: ProjectPostProcessorOptions,
|
||||||
) => Promise<ResultDir> | ResultDir;
|
) => Promise<ResultDir> | ResultDir;
|
||||||
|
|
||||||
/** 模块级别的后置处理器的工厂方法 */
|
/** 模块级别的后置处理器的工厂方法 */
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import changeCase from 'change-case';
|
import changeCase from 'change-case';
|
||||||
import type { IProjectInfo } from '../types/intermediate';
|
import type { IProjectInfo } from '../types/intermediate';
|
||||||
|
|
||||||
export type DataSourceDependenciesConfig = {
|
export interface DataSourceDependenciesConfig {
|
||||||
/** 数据源引擎的版本 */
|
/** 数据源引擎的版本 */
|
||||||
engineVersion?: string;
|
engineVersion?: string;
|
||||||
/** 数据源引擎的包名 */
|
/** 数据源引擎的包名 */
|
||||||
@ -14,7 +14,7 @@ export type DataSourceDependenciesConfig = {
|
|||||||
handlersPackages?: {
|
handlersPackages?: {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
export function buildDataSourceDependencies(
|
export function buildDataSourceDependencies(
|
||||||
ir: IProjectInfo,
|
ir: IProjectInfo,
|
||||||
@ -22,13 +22,13 @@ export function buildDataSourceDependencies(
|
|||||||
): Record<string, string> {
|
): Record<string, string> {
|
||||||
return {
|
return {
|
||||||
// 数据源引擎的依赖包
|
// 数据源引擎的依赖包
|
||||||
[cfg.enginePackage || '@alilc/lowcode-datasource-engine']: cfg.engineVersion || 'latest',
|
[cfg.enginePackage || '@alilc/lowcode-datasource-engine']: cfg.engineVersion || '^1.0.0',
|
||||||
|
|
||||||
// 各种数据源的 handlers 的依赖包
|
// 各种数据源的 handlers 的依赖包
|
||||||
...(ir.dataSourcesTypes || []).reduce(
|
...(ir.dataSourcesTypes || []).reduce(
|
||||||
(acc, dsType) => ({
|
(acc, dsType) => ({
|
||||||
...acc,
|
...acc,
|
||||||
[getDataSourceHandlerPackageName(dsType)]: cfg.handlersVersion?.[dsType] || 'latest',
|
[getDataSourceHandlerPackageName(dsType)]: cfg.handlersVersion?.[dsType] || '^1.0.0',
|
||||||
}),
|
}),
|
||||||
{},
|
{},
|
||||||
),
|
),
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import * as schema from './schema';
|
|||||||
import * as version from './version';
|
import * as version from './version';
|
||||||
import * as scope from './Scope';
|
import * as scope from './Scope';
|
||||||
import * as expressionParser from './expressionParser';
|
import * as expressionParser from './expressionParser';
|
||||||
|
import * as dataSource from './dataSource';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
common,
|
common,
|
||||||
@ -25,4 +26,5 @@ export {
|
|||||||
version,
|
version,
|
||||||
scope,
|
scope,
|
||||||
expressionParser,
|
expressionParser,
|
||||||
|
dataSource,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -182,7 +182,7 @@ function generateSimpleNode(
|
|||||||
function linkPieces(pieces: CodePiece[]): string {
|
function linkPieces(pieces: CodePiece[]): string {
|
||||||
const tagsPieces = pieces.filter((p) => p.type === PIECE_TYPE.TAG);
|
const tagsPieces = pieces.filter((p) => p.type === PIECE_TYPE.TAG);
|
||||||
if (tagsPieces.length !== 1) {
|
if (tagsPieces.length !== 1) {
|
||||||
throw new CodeGeneratorError('One node only need one tag define');
|
throw new CodeGeneratorError('Only one tag definition required', tagsPieces);
|
||||||
}
|
}
|
||||||
const tagName = tagsPieces[0].value;
|
const tagName = tagsPieces[0].value;
|
||||||
|
|
||||||
@ -270,8 +270,7 @@ export function generateReactLoopCtrl(
|
|||||||
const loopDataExpr = pipe(
|
const loopDataExpr = pipe(
|
||||||
nodeItem.loop,
|
nodeItem.loop,
|
||||||
// 将 JSExpression 转换为 JS 表达式代码:
|
// 将 JSExpression 转换为 JS 表达式代码:
|
||||||
(expr) =>
|
(expr) => generateCompositeType(expr, scope, {
|
||||||
generateCompositeType(expr, scope, {
|
|
||||||
handlers: config?.handlers,
|
handlers: config?.handlers,
|
||||||
tolerateEvalErrors: false, // 这个内部不需要包 try catch, 下面会统一加的
|
tolerateEvalErrors: false, // 这个内部不需要包 try catch, 下面会统一加的
|
||||||
}),
|
}),
|
||||||
@ -391,8 +390,7 @@ export function createNodeGenerator(cfg: NodeGeneratorConfig = {}): NodeGenerato
|
|||||||
return `{${valueStr}}`;
|
return `{${valueStr}}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (nodeItem: NodeDataType, scope: IScope) =>
|
return (nodeItem: NodeDataType, scope: IScope) => unwrapJsExprQuoteInJsx(generateNode(nodeItem, scope));
|
||||||
unwrapJsExprQuoteInJsx(generateNode(nodeItem, scope));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultReactGeneratorConfig: NodeGeneratorConfig = {
|
const defaultReactGeneratorConfig: NodeGeneratorConfig = {
|
||||||
|
|||||||
@ -138,3 +138,11 @@ export function handleSubNodes<T>(
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isValidContainerType(schema: NodeSchema) {
|
||||||
|
return [
|
||||||
|
'Page',
|
||||||
|
'Component',
|
||||||
|
'Block',
|
||||||
|
].includes(schema.componentName);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user