mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-03 16:07:24 +00:00
208 lines
5.0 KiB
TypeScript
208 lines
5.0 KiB
TypeScript
import PropTypes from 'prop-types';
|
|
import { isValidElement } from 'react';
|
|
import { isElement } from '@ali/lowcode-utils';
|
|
import { PropConfig } from '@ali/lowcode-types';
|
|
|
|
export const primitiveTypes = [
|
|
'string',
|
|
'number',
|
|
'array',
|
|
'bool',
|
|
'func',
|
|
'object',
|
|
'node',
|
|
'element',
|
|
'symbol',
|
|
'any',
|
|
];
|
|
|
|
function makeRequired(propType: any, lowcodeType: string | object) {
|
|
function lowcodeCheckTypeIsRequired(...rest: any[]) {
|
|
return propType.isRequired(...rest);
|
|
}
|
|
if (typeof lowcodeType === 'string') {
|
|
lowcodeType = {
|
|
type: lowcodeType,
|
|
};
|
|
}
|
|
lowcodeCheckTypeIsRequired.lowcodeType = {
|
|
...lowcodeType,
|
|
isRequired: true,
|
|
};
|
|
return lowcodeCheckTypeIsRequired;
|
|
}
|
|
|
|
function define(propType: any = PropTypes.any, lowcodeType: string | object = {}) {
|
|
if (!propType._inner && propType.name !== 'lowcodeCheckType') {
|
|
propType.lowcodeType = lowcodeType;
|
|
}
|
|
function lowcodeCheckType(...rest: any[]) {
|
|
return propType(...rest);
|
|
}
|
|
lowcodeCheckType.lowcodeType = lowcodeType;
|
|
lowcodeCheckType.isRequired = makeRequired(propType, lowcodeType);
|
|
return lowcodeCheckType;
|
|
}
|
|
|
|
const LowcodeTypes: any = {
|
|
...PropTypes,
|
|
define,
|
|
};
|
|
|
|
(window as any).PropTypes = LowcodeTypes;
|
|
(window as any).React.PropTypes = LowcodeTypes;
|
|
|
|
// override primitive type chechers
|
|
primitiveTypes.forEach(type => {
|
|
const propType = (PropTypes as any)[type];
|
|
if (!propType) {
|
|
return;
|
|
}
|
|
propType._inner = true;
|
|
LowcodeTypes[type] = define(propType, type);
|
|
});
|
|
|
|
// You can ensure that your prop is limited to specific values by treating
|
|
// it as an enum.
|
|
LowcodeTypes.oneOf = (list: any[]) => {
|
|
return define(PropTypes.oneOf(list), {
|
|
type: 'oneOf',
|
|
value: list,
|
|
});
|
|
};
|
|
|
|
// An array of a certain type
|
|
LowcodeTypes.arrayOf = (type: any) => {
|
|
return define(PropTypes.arrayOf(type), {
|
|
type: 'arrayOf',
|
|
value: type.lowcodeType || 'any',
|
|
});
|
|
};
|
|
|
|
// An object with property values of a certain type
|
|
LowcodeTypes.objectOf = (type: any) => {
|
|
return define(PropTypes.objectOf(type), {
|
|
type: 'objectOf',
|
|
value: type.lowcodeType || 'any',
|
|
});
|
|
};
|
|
|
|
// An object that could be one of many types
|
|
LowcodeTypes.oneOfType = (types: any[]) => {
|
|
const itemTypes = types.map(type => type.lowcodeType || 'any');
|
|
return define(PropTypes.oneOfType(types), {
|
|
type: 'oneOfType',
|
|
value: itemTypes,
|
|
});
|
|
};
|
|
|
|
// An object with warnings on extra properties
|
|
LowcodeTypes.exact = (typesMap: any) => {
|
|
const configs = Object.keys(typesMap).map(key => {
|
|
return {
|
|
name: key,
|
|
propType: typesMap[key].lowcodeType || 'any',
|
|
};
|
|
});
|
|
return define(PropTypes.exact(typesMap), {
|
|
type: 'exact',
|
|
value: configs,
|
|
});
|
|
};
|
|
|
|
// An object taking on a particular shape
|
|
LowcodeTypes.shape = (typesMap: any) => {
|
|
const configs = Object.keys(typesMap).map(key => {
|
|
return {
|
|
name: key,
|
|
propType: typesMap[key].lowcodeType || 'any',
|
|
};
|
|
});
|
|
return define(PropTypes.shape(typesMap), {
|
|
type: 'shape',
|
|
value: configs,
|
|
});
|
|
};
|
|
|
|
const BasicTypes = ['string', 'number', 'object'];
|
|
export function parseProps(component: any): PropConfig[] {
|
|
if (!component) {
|
|
return [];
|
|
}
|
|
const propTypes = component.propTypes || ({} as any);
|
|
const defaultProps = component.defaultProps || ({} as any);
|
|
const result: any = {};
|
|
if (!propTypes) return [];
|
|
Object.keys(propTypes).forEach(key => {
|
|
const propTypeItem = propTypes[key];
|
|
const defaultValue = defaultProps[key];
|
|
const lowcodeType = propTypeItem.lowcodeType;
|
|
if (lowcodeType) {
|
|
result[key] = {
|
|
name: key,
|
|
propType: lowcodeType,
|
|
};
|
|
if (defaultValue != null) {
|
|
result[key].defaultValue = defaultValue;
|
|
}
|
|
return;
|
|
}
|
|
|
|
let i = primitiveTypes.length;
|
|
while (i-- > 0) {
|
|
const k = primitiveTypes[i];
|
|
if ((LowcodeTypes as any)[k] === propTypeItem) {
|
|
result[key] = {
|
|
name: key,
|
|
propType: k,
|
|
};
|
|
if (defaultValue != null) {
|
|
result[key].defaultValue = defaultValue;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
result[key] = {
|
|
name: key,
|
|
propType: 'any',
|
|
};
|
|
if (defaultValue != null) {
|
|
result[key].defaultValue = defaultValue;
|
|
}
|
|
});
|
|
|
|
Object.keys(defaultProps).forEach(key => {
|
|
if (result[key]) return;
|
|
const defaultValue = defaultProps[key];
|
|
let type: string = typeof defaultValue;
|
|
if (type === 'boolean') {
|
|
type = 'bool';
|
|
} else if (type === 'function') {
|
|
type = 'func';
|
|
} else if (type === 'object' && Array.isArray(defaultValue)) {
|
|
type = 'array';
|
|
} else if (defaultValue && isValidElement(defaultValue)) {
|
|
type = 'node';
|
|
} else if (defaultValue && isElement(defaultValue)) {
|
|
type = 'element';
|
|
} else if (!BasicTypes.includes(type)) {
|
|
type = 'any';
|
|
}
|
|
|
|
result[key] = {
|
|
name: key,
|
|
propType: type || 'any',
|
|
defaultValue,
|
|
};
|
|
});
|
|
|
|
return Object.keys(result).map(key => result[key]);
|
|
}
|
|
|
|
export function parseMetadata(component: any): any {
|
|
return {
|
|
props: parseProps(component),
|
|
...component.componentMetadata,
|
|
};
|
|
}
|