mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-01 22:10:27 +00:00
183 lines
5.9 KiB
TypeScript
183 lines
5.9 KiB
TypeScript
import lg from '@ali/vu-logger';
|
|
import { ComponentClass, ComponentType } from 'react';
|
|
import Prototype from './prototype';
|
|
import { designer } from '../editor';
|
|
|
|
function basename(name: string) {
|
|
return name ? (/[^\/]+$/.exec(name) || [''])[0] : '';
|
|
}
|
|
|
|
function getCamelName(name: string) {
|
|
const words = basename(name)
|
|
.replace(/^((vc)-)?(.+)/, '$3')
|
|
.split('-');
|
|
return words.reduce((s, word) => s + word[0].toUpperCase() + word.substring(1), '');
|
|
}
|
|
|
|
export interface ComponentProtoBundle {
|
|
// @ali/vc-xxx
|
|
name: string;
|
|
componentName?: string;
|
|
category?: string;
|
|
module: Prototype | Prototype[];
|
|
}
|
|
|
|
export interface ComponentViewBundle {
|
|
// @ali/vc-xxx
|
|
name: string;
|
|
// alias to property name
|
|
componentName?: string;
|
|
category?: string;
|
|
module: ComponentType<any>;
|
|
}
|
|
|
|
export default class Bundle {
|
|
static createPrototype = Prototype.create;
|
|
static addGlobalPropsReducer = Prototype.addGlobalPropsReducer;
|
|
static addGlobalPropsConfigure = Prototype.addGlobalPropsConfigure;
|
|
static addGlobalExtraActions = Prototype.addGlobalExtraActions;
|
|
static removeGlobalPropsConfigure = Prototype.removeGlobalPropsConfigure;
|
|
static overridePropsConfigure = Prototype.overridePropsConfigure;
|
|
static create(protos: ComponentProtoBundle[], views?: ComponentViewBundle[]) {
|
|
return new Bundle(protos, views);
|
|
}
|
|
|
|
private viewsMap: { [componentName: string]: ComponentType } = {};
|
|
private registry: { [componentName: string]: Prototype } = {};
|
|
private prototypeList: Prototype[] = [];
|
|
|
|
constructor(protos?: ComponentProtoBundle[], views?: ComponentViewBundle[]) {
|
|
// 注册 prototypeView 视图
|
|
if (views && Array.isArray(views)) {
|
|
this.recursivelyRegisterViews(views);
|
|
}
|
|
protos?.forEach((item) => {
|
|
const prototype = item.module;
|
|
if (prototype instanceof Prototype) {
|
|
this.revisePrototype(item, prototype);
|
|
const componentName = item.componentName || prototype.getComponentName()!;
|
|
const matchedView = this.viewsMap[componentName] || null;
|
|
if (!prototype.getView() && matchedView) {
|
|
prototype.setView(matchedView);
|
|
}
|
|
this.registerPrototype(prototype);
|
|
} else if (Array.isArray(prototype)) {
|
|
this.recursivelyRegisterPrototypes(prototype, item);
|
|
}
|
|
});
|
|
}
|
|
|
|
getFromMeta(componentName: string): Prototype {
|
|
if (this.registry[componentName]) {
|
|
return this.registry[componentName];
|
|
}
|
|
const meta = designer.getComponentMeta(componentName);
|
|
const prototype = Prototype.create(meta);
|
|
this.prototypeList.push(prototype);
|
|
this.registry[componentName] = prototype;
|
|
return prototype;
|
|
}
|
|
|
|
removeComponentBundle(componentName: string) {
|
|
const cIndex = this.prototypeList.findIndex((proto) => proto.getComponentName() === componentName);
|
|
delete this.registry[componentName];
|
|
this.prototypeList.splice(cIndex, 1);
|
|
}
|
|
|
|
getList() {
|
|
return this.prototypeList;
|
|
}
|
|
|
|
get(componentName: string) {
|
|
return this.registry[componentName];
|
|
}
|
|
|
|
replacePrototype(componentName: string, cp: Prototype) {
|
|
const view: any = this.get(componentName).getView();
|
|
this.removeComponentBundle(componentName);
|
|
this.registry[cp.getComponentName()!] = cp;
|
|
this.prototypeList.push(cp);
|
|
cp.setView(view);
|
|
}
|
|
|
|
/**
|
|
* TODO dirty fix
|
|
*/
|
|
addComponentBundle(bundles: any) {
|
|
/**
|
|
* Normal Component bundle: [ Prototype, PrototypeView ]
|
|
* Component without Prototype.js: [ View ]
|
|
*/
|
|
if (bundles.length >= 2) {
|
|
const prototype = bundles[0];
|
|
const prototypeView = bundles[1];
|
|
prototype.setView(prototypeView);
|
|
this.registerPrototype(prototype);
|
|
}
|
|
}
|
|
|
|
private recursivelyRegisterViews(list: any[], viewName?: string): void {
|
|
list.forEach((item: any) => {
|
|
if (Array.isArray(item.module)) {
|
|
return this.recursivelyRegisterViews(item.module, item.name);
|
|
} else if (Array.isArray(item)) {
|
|
return this.recursivelyRegisterViews(item, viewName);
|
|
}
|
|
let viewDetail: ComponentClass;
|
|
if (item.module && typeof item.module === 'function') {
|
|
viewDetail = item.module;
|
|
} else {
|
|
viewDetail = item;
|
|
}
|
|
if (!viewDetail.displayName) {
|
|
lg.log('ERROR_NO_PROTOTYPE_VIEW');
|
|
lg.error('WARNING: the package without displayName is', item);
|
|
viewDetail.displayName = getCamelName(viewName || item.name);
|
|
}
|
|
(viewDetail as any)._packageName_ = viewName || item.name;
|
|
this.viewsMap[viewDetail.displayName] = viewDetail;
|
|
});
|
|
}
|
|
|
|
private recursivelyRegisterPrototypes(list: any[], cp: ComponentProtoBundle) {
|
|
const propList: ComponentProtoBundle[] = list;
|
|
propList.forEach((proto: ComponentProtoBundle, index: number) => {
|
|
if (Array.isArray(proto)) {
|
|
this.recursivelyRegisterPrototypes(proto, cp);
|
|
return;
|
|
}
|
|
if (proto instanceof Prototype) {
|
|
const componentName = proto.getComponentName()!;
|
|
if (!proto.getView() && this.viewsMap[componentName]) {
|
|
proto.setView(this.viewsMap[componentName]);
|
|
}
|
|
if (cp.name && !proto.getPackageName()) {
|
|
proto.setPackageName(cp.name);
|
|
}
|
|
this.registerPrototype(proto);
|
|
}
|
|
});
|
|
}
|
|
|
|
private revisePrototype(item: ComponentProtoBundle, prototype: Prototype) {
|
|
if (item.category) {
|
|
prototype.setCategory(item.category);
|
|
}
|
|
if (item.name && !prototype.getPackageName()) {
|
|
prototype.setPackageName(item.name);
|
|
}
|
|
}
|
|
|
|
private registerPrototype(prototype: Prototype) {
|
|
const componentName = prototype.getComponentName()!;
|
|
if (this.registry[componentName]) {
|
|
lg.warn('WARN: override prototype', prototype, componentName);
|
|
const idx = this.prototypeList.findIndex((proto) => componentName === proto.getComponentName());
|
|
this.prototypeList[idx] = prototype;
|
|
} else {
|
|
this.prototypeList.push(prototype);
|
|
}
|
|
this.registry[componentName] = prototype;
|
|
}
|
|
}
|