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: {}, }, ]; }