@lcap/asl
Version:
NetEase Application Specific Language
682 lines (643 loc) • 22 kB
text/typescript
import { firstUpperCase } from '../utils';
import pluralize = require('pluralize');
import { kebabCase } from 'lodash';
import { Entity, EntityProperty } from '..';
import { dataTypesMap } from './dataTypes';
import Schema from './Schema';
export const ENTITY_STRUCTURE_PREFIX = [
'Sort', 'PageOf', 'ApiReturnOfPageOf',
'ApiReturnOf', 'ApiReturnOflong', 'ScopeOf',
];
export const ENTITY_INTERFACE_PREFIX = [
'get', 'delete', 'count', 'update', 'create',
'getAll', 'import', 'export',
];
interface Parameter {
name: string,
in: string,
required: boolean,
schema: Schema,
entityFieldId?: string,
[name: string]: any,
}
type Parameters = { [name: string]: Parameter };
const resolverNormal = {
ast: {
type: 'MemberExpression',
object: {
type: 'Identifier',
name: 'data',
},
property: {
type: 'Identifier',
name: 'Data',
},
},
code: 'data.Data',
};
const resolverPageOf = {
ast: {
type: 'MemberExpression',
object: {
type: 'MemberExpression',
object: {
type: 'Identifier',
name: 'data',
},
property: {
type: 'Identifier',
name: 'Data',
},
},
property: {
type: 'Identifier',
name: 'content',
},
},
code: 'data.Data.content',
};
/**
* 获取实体相关的所有数据结构的名称
* @param entityName 实体名称
*/
export const getEntityStructureNames = (entityName: string) =>
ENTITY_STRUCTURE_PREFIX.map((key) => `${key}${firstUpperCase(entityName)}`);
/**
* 获取实体相关的所有数据结构
* @param entity 实体
*/
export function getEntityStructures(entity: Entity) {
const service = entity.dataNode.service;
return [
{
name: `Sort${firstUpperCase(entity.name)}`,
type: 'object',
propertyList: [
{
level: 'property',
name: 'empty',
description: '',
$ref: '#/basicTypes/Boolean',
},
{
level: 'property',
name: 'sorted',
description: '',
$ref: '#/basicTypes/Boolean',
},
{
level: 'property',
name: 'unsorted',
description: '',
$ref: '#/basicTypes/Boolean',
},
],
},
{
name: `PageOf${firstUpperCase(entity.name)}`,
type: 'object',
propertyList: [
{
level: 'property',
name: 'content',
description: '',
$ref: `#/${service.id}/${entity.id}`,
isArray: true,
},
{
level: 'property',
name: 'empty',
description: '',
$ref: '#/basicTypes/Boolean',
},
{
level: 'property',
name: 'first',
description: '',
$ref: '#/basicTypes/Boolean',
},
{
level: 'property',
name: 'last',
description: '',
$ref: '#/basicTypes/Boolean',
},
{
level: 'property',
name: 'number',
description: '',
$ref: '#/basicTypes/Integer',
},
{
level: 'property',
name: 'numberOfElements',
description: '',
$ref: '#/basicTypes/Integer',
},
{
level: 'property',
name: 'size',
description: '',
$ref: '#/basicTypes/Integer',
},
{
level: 'property',
name: 'totalElements',
description: '',
$ref: '#/basicTypes/Integer',
},
{
level: 'property',
name: 'totalPages',
description: '',
$ref: '#/basicTypes/Integer',
},
],
},
{
name: `ApiReturnOfPageOf${firstUpperCase(entity.name)}`,
type: 'object',
propertyList: [
{
level: 'property',
name: 'Code',
description: '',
$ref: '#/basicTypes/Integer',
},
{
level: 'property',
name: 'Data',
description: '',
$ref: `PageOf${firstUpperCase(entity.name)}`, //
},
{
level: 'property',
name: 'Message',
description: '',
type: 'string',
format: '',
$ref: '#/basicTypes/String',
},
],
structureRef: `PageOf${firstUpperCase(entity.name)}`,
},
{
name: `ApiReturnOf${firstUpperCase(entity.name)}`,
type: 'object',
propertyList: [
{
level: 'property',
name: 'Code',
description: '',
$ref: '#/basicTypes/Integer',
},
{
level: 'property',
name: 'Data',
description: '',
$ref: `#/${service.id}/${entity.id}`,
},
{
level: 'property',
name: 'Message',
description: '',
$ref: '#/basicTypes/String',
},
],
},
{
name: `ApiReturnOflong${firstUpperCase(entity.name)}`,
type: 'object',
propertyList: [
{
level: 'property',
name: 'Code',
description: '',
$ref: '#/basicTypes/Integer',
},
{
level: 'property',
name: 'Data',
description: '',
$ref: '#/basicTypes/Decimal',
},
{
level: 'property',
name: 'Message',
description: '',
$ref: '#/basicTypes/String',
},
],
},
{
name: `ScopeOf${firstUpperCase(entity.name)}`,
type: 'object',
propertyList: [
{
level: 'property',
name: 'item',
$ref: `#/${service.id}/${entity.id}`,
},
{
level: 'property',
name: 'value',
$ref: '#/basicTypes/String',
},
{
level: 'property',
name: 'rowIndex',
$ref: '#/basicTypes/Integer',
},
{
level: 'property',
name: 'columnIndex',
$ref: '#/basicTypes/Integer',
},
{
level: 'property',
name: 'index',
$ref: '#/basicTypes/Integer',
},
],
},
];
}
/**
* 获取实体相关的所有 GET 接口请求参数
* @param entity 实体
*/
export function getEntityGetAllQueryParams(entity: Entity) {
const parameters: Parameters = {};
if (!entity)
return parameters;
function addJDLQueryParam(property: EntityProperty, operator: string, type?: string) {
const name = `${property.name}.${operator}`;
const schema = dataTypesMap[property.$ref];
const parameter = {
name,
in: 'query',
required: false,
schema: Object.assign({}, schema),
entityFieldId: property.id,
};
if (type === 'array')
parameter.schema = { type: 'array', items: Object.assign({}, schema) };
else if (type === 'boolean')
parameter.schema = { type: 'boolean', format: '' };
parameters[name] = parameter;
}
parameters.page = {
name: 'page',
in: 'query',
required: false,
schema: { type: 'integer', format: 'int' },
};
parameters.size = {
name: 'size',
in: 'query',
required: false,
schema: { type: 'integer', format: 'int' },
};
parameters.sort = {
name: 'sort',
in: 'query',
required: false,
schema: {
type: 'array',
items: { type: 'string', format: '' },
},
};
entity.propertyList.forEach((property) => {
if (!property.$ref) {
console.error('property.$ref undefined', entity.name, property.name);
return;
}
const schema = dataTypesMap[property.$ref];
if (!property.$ref.startsWith('#/basicTypes/') && schema.type !== 'enum') {
// 这里有枚举和非枚举的问题
property = new EntityProperty({
name: property.name + 'Id',
$ref: '#/basicTypes/Long',
});
}
addJDLQueryParam(property, 'equals');
addJDLQueryParam(property, 'notEquals');
addJDLQueryParam(property, 'in', 'array');
addJDLQueryParam(property, 'notIn', 'array');
addJDLQueryParam(property, 'specified', 'boolean');
if (
property.$ref === '#/basicTypes/Integer'
|| property.$ref === '#/basicTypes/Long'
|| property.$ref === '#/basicTypes/Decimal'
) {
addJDLQueryParam(property, 'greaterThan');
addJDLQueryParam(property, 'greaterThanOrEqual');
addJDLQueryParam(property, 'lessThan');
addJDLQueryParam(property, 'lessThanOrEqual');
}
if (
property.$ref === '#/basicTypes/Date'
|| property.$ref === '#/basicTypes/Time'
|| property.$ref === '#/basicTypes/DateTime'
) {
addJDLQueryParam(property, 'greaterThan');
addJDLQueryParam(property, 'greaterThanOrEqual');
addJDLQueryParam(property, 'lessThan');
addJDLQueryParam(property, 'lessThanOrEqual');
}
if (
property.$ref === '#/basicTypes/String'
|| property.$ref === '#/basicTypes/Text'
) {
addJDLQueryParam(property, 'contains');
addJDLQueryParam(property, 'doesNotContain');
}
});
return parameters;
}
/**
* 获取实体相关的所有导出请求参数
* @param entity 实体
*/
function getEntityExportQueryParams(entity: Entity) {
const parameters = getEntityGetAllQueryParams(entity);
parameters.fields = {
name: 'fields',
in: 'query',
required: false,
schema: dataTypesMap['#/basicTypes/String'],
};
return parameters;
}
/**
* 获取实体某个属性相关的所有接口参数
* @param property 实体属性
* @param dataTypesMap
*/
export function getEntityPropertyParams(property: EntityProperty) {
const parameters: Parameters = {};
if (!property)
return parameters;
function addJDLQueryParam(
property: EntityProperty,
operator: string, type?: string,
) {
const name = `${property.name}.${operator}`;
const schema = dataTypesMap[property.$ref];
const parameter: Parameter = {
name,
in: 'query',
required: false,
schema: Object.assign({}, schema),
entityFieldId: property.id,
};
if (type === 'array')
parameter.schema = { type: 'array', items: Object.assign({}, schema) };
else if (type === 'boolean')
parameter.schema = { type: 'boolean', format: '' };
parameters[name] = parameter;
}
if (!property.$ref) {
console.error('property.$ref undefined', property.name);
return;
}
const schema = dataTypesMap[property.$ref];
if (!property.$ref.startsWith('#/basicTypes/') && schema.type !== 'enum') {
// 这里有枚举和非枚举的问题
property = new EntityProperty({
name: property.name + 'Id',
$ref: '#/basicTypes/Long',
});
}
addJDLQueryParam(property, 'equals');
addJDLQueryParam(property, 'notEquals');
addJDLQueryParam(property, 'in', 'array');
addJDLQueryParam(property, 'notIn', 'array');
addJDLQueryParam(property, 'specified', 'boolean');
if (property.$ref === '#/basicTypes/Integer' || property.$ref === '#/basicTypes/Long' || property.$ref === '#/basicTypes/Decimal') {
addJDLQueryParam(property, 'greaterThan');
addJDLQueryParam(property, 'greaterThanOrEqual');
addJDLQueryParam(property, 'lessThan');
addJDLQueryParam(property, 'lessThanOrEqual');
}
if (property.$ref === '#/basicTypes/Date' || property.$ref === '#/basicTypes/Time' || property.$ref === '#/basicTypes/DateTime') {
addJDLQueryParam(property, 'greaterThan');
addJDLQueryParam(property, 'greaterThanOrEqual');
addJDLQueryParam(property, 'lessThan');
addJDLQueryParam(property, 'lessThanOrEqual');
}
if (property.$ref === '#/basicTypes/String' || property.$ref === '#/basicTypes/Text') {
addJDLQueryParam(property, 'contains');
addJDLQueryParam(property, 'doesNotContain');
}
return parameters;
}
/**
* 获取实体相关的所有接口
* @param entity 实体
*/
export function getEntityInterfaces(entity: Entity) {
const pluralized = pluralize(entity.name);
const service = entity.dataNode.service;
return [
{
data: {
name: `getAll${firstUpperCase(pluralized)}`,
method: 'GET',
path: `/api/${kebabCase(pluralized)}`,
description: `getAll${firstUpperCase(pluralized)}`,
parameters: JSON.stringify(getEntityGetAllQueryParams(entity)),
responses: JSON.stringify({
200: {
description: '',
content: {
'application/json': {
schema: {
$ref: `<#/ApiReturnOfPageOf${firstUpperCase(entity.name)}>`,
},
},
},
},
}),
},
resolver: resolverPageOf,
},
{
data: {
name: `get${firstUpperCase(entity.name)}`,
method: 'GET',
path: `/api/${kebabCase(pluralized)}/{id}`,
description: `get${firstUpperCase(entity.name)}`,
parameters: JSON.stringify({
id: {
name: 'id',
in: 'path',
required: true,
schema: { type: 'integer', format: 'long' },
},
}),
responses: JSON.stringify({
200: {
description: '',
content: {
'application/json': {
schema: {
$ref: `<#/ApiReturnOf${firstUpperCase(entity.name)}>`,
},
},
},
},
}),
},
resolver: resolverNormal,
},
{
data: {
name: `create${firstUpperCase(entity.name)}`,
method: 'POST',
path: `/api/${kebabCase(pluralized)}`,
description: `create${firstUpperCase(entity.name)}`,
parameters: '{}',
requestBody: JSON.stringify({
description: '',
content: {
'application/json': {
schema: {
$ref: `#/${service.id}/${entity.id}`,
},
},
},
}),
responses: JSON.stringify({
200: {
description: '',
content: {
'application/json': {
schema: {
$ref: `<#/ApiReturnOf${firstUpperCase(entity.name)}>`,
},
},
},
},
}),
},
resolver: {},
},
{
data: {
name: `delete${firstUpperCase(entity.name)}`,
method: 'DELETE',
path: `/api/${kebabCase(pluralized)}/{id}`,
description: `delete${firstUpperCase(entity.name)}`,
parameters: JSON.stringify({
id: {
name: 'id',
in: 'path',
required: true,
schema: { type: 'integer', format: 'long' },
},
}),
responses: '{}',
},
resolver: {},
},
{
data: {
name: `update${firstUpperCase(entity.name)}`,
method: 'PUT',
path: `/api/${kebabCase(pluralized)}`,
description: `update${firstUpperCase(entity.name)}`,
parameters: '{}',
requestBody: JSON.stringify({
description: '',
content: {
'application/json': {
schema: {
$ref: `#/${service.id}/${entity.id}`,
},
},
},
}),
responses: JSON.stringify({
200: {
description: '',
content: {
'application/json': {
schema: {
$ref: `<#/ApiReturnOf${firstUpperCase(entity.name)}>`,
},
},
},
},
}),
},
resolver: {},
},
{
data: {
name: `count${firstUpperCase(entity.name)}`,
method: 'GET',
path: `/api/${kebabCase(pluralized)}/count`,
description: `count${firstUpperCase(entity.name)}`,
parameters: JSON.stringify(getEntityGetAllQueryParams(entity)),
responses: JSON.stringify({
200: {
description: '',
content: {
'application/json': {
schema: {
$ref: `<#/ApiReturnOflong${firstUpperCase(entity.name)}>`,
},
},
},
},
}),
},
resolver: {},
},
{
data: {
name: `import${firstUpperCase(entity.name)}`,
method: 'POST',
path: `/api/${kebabCase(pluralized)}/import`,
description: `import${firstUpperCase(entity.name)}`,
parameters: '{}',
responses: JSON.stringify({
200: {
description: '',
content: {
'application/json': {
schema: {
$ref: `<#/ApiReturnOflong${firstUpperCase(entity.name)}>`,
},
},
},
},
}),
},
resolver: {},
},
{
data: {
name: `export${firstUpperCase(entity.name)}`,
method: 'GET',
path: `/api/${kebabCase(pluralized)}/export`,
description: `export${firstUpperCase(entity.name)}`,
parameters: JSON.stringify(getEntityExportQueryParams(entity)),
responses: JSON.stringify({
200: {
description: '',
content: {
'application/json': {
schema: {
$ref: `<#/ApiReturnOflong${firstUpperCase(entity.name)}>`,
},
},
},
},
}),
},
resolver: {},
},
];
}