mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-13 07:16:04 +00:00
203 lines
5.7 KiB
TypeScript
203 lines
5.7 KiB
TypeScript
/* eslint-disable @typescript-eslint/indent */
|
|
|
|
import {
|
|
IPublicTypeCompositeValue,
|
|
IPublicTypeJSExpression,
|
|
InterpretDataSourceConfig,
|
|
isJSExpression,
|
|
isJSFunction,
|
|
} from '@alilc/lowcode-types';
|
|
import changeCase from 'change-case';
|
|
|
|
import {
|
|
CLASS_DEFINE_CHUNK_NAME,
|
|
COMMON_CHUNK_NAME,
|
|
DEFAULT_LINK_AFTER,
|
|
} from '../../../const/generator';
|
|
import { Scope } from '../../../utils/Scope';
|
|
|
|
import {
|
|
BuilderComponentPlugin,
|
|
BuilderComponentPluginFactory,
|
|
ChunkType,
|
|
FileType,
|
|
ICodeStruct,
|
|
IScope,
|
|
} from '../../../types';
|
|
|
|
import { generateCompositeType } from '../../../utils/compositeType';
|
|
import { parseExpressionConvertThis2Context } from '../../../utils/expressionParser';
|
|
import { isValidContainerType } from '../../../utils/schema';
|
|
import { REACT_CHUNK_NAME } from './const';
|
|
|
|
export interface PluginConfig {
|
|
fileType?: string;
|
|
|
|
/**
|
|
* 数据源配置
|
|
*/
|
|
datasourceConfig?: {
|
|
/** 数据源引擎的版本 */
|
|
engineVersion?: string;
|
|
|
|
/** 数据源引擎的包名 */
|
|
enginePackage?: string;
|
|
|
|
/** 数据源 handlers 的版本 */
|
|
handlersVersion?: {
|
|
[key: string]: string;
|
|
};
|
|
|
|
/** 数据源 handlers 的包名 */
|
|
handlersPackages?: {
|
|
[key: string]: string;
|
|
};
|
|
};
|
|
}
|
|
|
|
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
|
const cfg = {
|
|
...config,
|
|
fileType: config?.fileType || FileType.JSX,
|
|
};
|
|
|
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
|
const next: ICodeStruct = {
|
|
...pre,
|
|
};
|
|
|
|
const scope = Scope.createRootScope();
|
|
const dataSourceConfig = isValidContainerType(pre.ir) ? pre.ir.dataSource : null;
|
|
const dataSourceItems: InterpretDataSourceConfig[] =
|
|
(dataSourceConfig && dataSourceConfig.list) || [];
|
|
const dataSourceEngineOptions = { runtimeConfig: true };
|
|
if (dataSourceItems.length > 0) {
|
|
const requestHandlersMap: Record<string, IPublicTypeJSExpression> = {};
|
|
|
|
dataSourceItems.forEach((ds) => {
|
|
const dsType = ds.type || 'fetch';
|
|
if (!(dsType in requestHandlersMap) && dsType !== 'custom') {
|
|
const handlerFactoryName = `__$$create${changeCase.pascal(dsType)}RequestHandler`;
|
|
|
|
requestHandlersMap[dsType] = {
|
|
type: 'JSExpression',
|
|
value:
|
|
handlerFactoryName + (dsType === 'urlParams' ? '(window.location.search)' : '()'),
|
|
};
|
|
|
|
const handlerFactoryExportName = `create${changeCase.pascal(dsType)}Handler`;
|
|
const handlerPkgName =
|
|
cfg.datasourceConfig?.handlersPackages?.[dsType] ||
|
|
`@alilc/lowcode-datasource-${changeCase.kebab(dsType)}-handler`;
|
|
|
|
next.chunks.push({
|
|
type: ChunkType.STRING,
|
|
fileType: FileType.JSX,
|
|
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
|
content: `
|
|
import { ${handlerFactoryExportName} as ${handlerFactoryName} } from '${handlerPkgName}';
|
|
`,
|
|
linkAfter: [],
|
|
});
|
|
}
|
|
});
|
|
|
|
Object.assign(dataSourceEngineOptions, { requestHandlersMap });
|
|
|
|
next.chunks.push({
|
|
type: ChunkType.STRING,
|
|
fileType: FileType.JSX,
|
|
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
|
content: `
|
|
import { create as __$$createDataSourceEngine } from '@alilc/lowcode-datasource-engine/runtime';
|
|
`,
|
|
linkAfter: [],
|
|
});
|
|
|
|
next.chunks.push({
|
|
type: ChunkType.STRING,
|
|
fileType: cfg.fileType,
|
|
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
|
content: `
|
|
_dataSourceConfig = this._defineDataSourceConfig();
|
|
_dataSourceEngine = __$$createDataSourceEngine(
|
|
this._dataSourceConfig,
|
|
this,
|
|
${generateCompositeType(dataSourceEngineOptions, scope)}
|
|
);
|
|
|
|
get dataSourceMap() {
|
|
return this._dataSourceEngine.dataSourceMap || {};
|
|
}
|
|
|
|
reloadDataSource = async () => {
|
|
await this._dataSourceEngine.reloadDataSource();
|
|
}
|
|
|
|
`,
|
|
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsVar]],
|
|
});
|
|
|
|
next.chunks.unshift({
|
|
type: ChunkType.STRING,
|
|
fileType: cfg.fileType,
|
|
name: REACT_CHUNK_NAME.ClassDidMountContent,
|
|
content: `
|
|
this._dataSourceEngine.reloadDataSource();
|
|
`,
|
|
linkAfter: [REACT_CHUNK_NAME.ClassDidMountStart],
|
|
});
|
|
|
|
next.chunks.push({
|
|
type: ChunkType.STRING,
|
|
fileType: cfg.fileType,
|
|
name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
|
content: `
|
|
_defineDataSourceConfig() {
|
|
const _this = this;
|
|
return (${generateCompositeType(
|
|
{
|
|
...dataSourceConfig,
|
|
list: [
|
|
...dataSourceItems.map((item) => ({
|
|
...item,
|
|
isInit: wrapAsFunction(item.isInit, scope),
|
|
options: wrapAsFunction(item.options, scope),
|
|
})),
|
|
],
|
|
},
|
|
scope,
|
|
{
|
|
handlers: {
|
|
function: (jsFunc) => parseExpressionConvertThis2Context(jsFunc.value, '_this'),
|
|
expression: (jsExpr) => parseExpressionConvertThis2Context(jsExpr.value, '_this'),
|
|
},
|
|
},
|
|
)});
|
|
}
|
|
`,
|
|
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
|
|
});
|
|
}
|
|
|
|
return next;
|
|
};
|
|
return plugin;
|
|
};
|
|
|
|
export default pluginFactory;
|
|
|
|
function wrapAsFunction(value: IPublicTypeCompositeValue, scope: IScope): IPublicTypeCompositeValue {
|
|
if (isJSExpression(value) || isJSFunction(value)) {
|
|
return {
|
|
type: 'JSExpression',
|
|
value: `function(){ return ((${value.value}))}`,
|
|
};
|
|
}
|
|
|
|
return {
|
|
type: 'JSExpression',
|
|
value: `function(){return((${generateCompositeType(value, scope)}))}`,
|
|
};
|
|
}
|