From fa329d06405eb053923eaade0a9786ba6bf264ac Mon Sep 17 00:00:00 2001 From: Yordan Pavlov Date: Thu, 18 Apr 2024 12:07:46 +0300 Subject: [PATCH 1/4] [EDM] Generate OpenAPI (#3792) --- .../dirigible/modules/src/http/decorators.ts | 13 +- .../src/http/rs/resource-http-controller.ts | 4 +- .../dirigible/ide-entity/js/details.js | 1 - .../dirigible/ide-entity/js/editor.js | 22 +- .../dirigible/ide-entity/js/serializer.js | 2 - .../dirigible/ide-entity/views/details.html | 12 - .../template/generateUtils.js | 10 +- .../template/template.js | 14 +- .../api/api.openapi.template | 835 ++++++++++++++++++ .../template/template.js | 138 ++- .../data/application.schema.template | 4 +- 11 files changed, 1005 insertions(+), 50 deletions(-) create mode 100644 components/template/template-application-rest/src/main/resources/META-INF/dirigible/template-application-rest/api/api.openapi.template diff --git a/components/api/api-modules-javascript/src/main/resources/META-INF/dirigible/modules/src/http/decorators.ts b/components/api/api-modules-javascript/src/main/resources/META-INF/dirigible/modules/src/http/decorators.ts index 287e0539d1a..fbe38f9afa8 100644 --- a/components/api/api-modules-javascript/src/main/resources/META-INF/dirigible/modules/src/http/decorators.ts +++ b/components/api/api-modules-javascript/src/main/resources/META-INF/dirigible/modules/src/http/decorators.ts @@ -15,7 +15,7 @@ import * as rs from "sdk/http/rs" const router = rs.service(); let instance = null; -export function Controller(ctr: {new()}, context: ClassDecoratorContext): void { +export function Controller(ctr: { new() }, context: ClassDecoratorContext): void { instance = new ctr(); router.execute(); } @@ -29,15 +29,12 @@ export const Head = createRequestDecorator("head") export const Options = createRequestDecorator("options") function createRequestDecorator(httpMethod) { - return function (path: string): any { + return function (path: string, consumesMimeTypes: undefined | string | string[] = ['*/*'], producesMimeTypes: undefined | string | string[] = ['application/json']): any { return function (target, propertyKey, descriptor) { const handler = descriptor ? descriptor.value : target; - router[httpMethod]( - path, - (ctx, req, res) => { - handleRequest(req, res, ctx, handler); - } - ); + router.resource(path)[httpMethod]((ctx, req, res) => { + handleRequest(req, res, ctx, handler); + }).consumes(consumesMimeTypes).produces(producesMimeTypes); }; } } diff --git a/components/api/api-modules-javascript/src/main/resources/META-INF/dirigible/modules/src/http/rs/resource-http-controller.ts b/components/api/api-modules-javascript/src/main/resources/META-INF/dirigible/modules/src/http/rs/resource-http-controller.ts index c48d23708e4..3ded9392383 100644 --- a/components/api/api-modules-javascript/src/main/resources/META-INF/dirigible/modules/src/http/rs/resource-http-controller.ts +++ b/components/api/api-modules-javascript/src/main/resources/META-INF/dirigible/modules/src/http/rs/resource-http-controller.ts @@ -270,7 +270,7 @@ const catchErrorHandler = function (logctx, ctx, err, request, response) { const matchMediaType = function (request, producesMediaTypes, consumesMediaTypes) { let isProduceMatched = false; const acceptsMediaTypes = normalizeMediaTypeHeaderValue(request.getHeader('Accept')); - if (!acceptsMediaTypes || acceptsMediaTypes.indexOf('*/*') > -1) { //output media type is not restricted + if (!acceptsMediaTypes || acceptsMediaTypes.length === 0 || acceptsMediaTypes.indexOf('*/*') > -1) { //output media type is not restricted isProduceMatched = true; } else { let matchedProducesMIME; @@ -286,7 +286,7 @@ const matchMediaType = function (request, producesMediaTypes, consumesMediaTypes let isConsumeMatched = false; const contentTypeMediaTypes = normalizeMediaTypeHeaderValue(request.getContentType()); - if (!consumesMediaTypes || consumesMediaTypes.indexOf('*') > -1) { //input media type is not restricted + if (!consumesMediaTypes || consumesMediaTypes.length === 0 || consumesMediaTypes.indexOf('*/*') > -1) { //input media type is not restricted isConsumeMatched = true; } else { let matchedConsumesMIME; diff --git a/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/details.js b/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/details.js index 07e81d9fb6e..4c37bb3df5a 100644 --- a/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/details.js +++ b/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/details.js @@ -138,7 +138,6 @@ angular.module('edmDetails', ['ideUI', 'ideView']) dataName: $scope.dataParameters.dataName, dataCount: $scope.dataParameters.dataCount, dataQuery: $scope.dataParameters.dataQuery, - disableGeneration: $scope.dataParameters.disableGeneration, title: $scope.dataParameters.title, caption: $scope.dataParameters.caption, tooltip: $scope.dataParameters.tooltip, diff --git a/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/editor.js b/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/editor.js index b7892163c13..dff4d30e122 100644 --- a/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/editor.js +++ b/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/editor.js @@ -9,14 +9,14 @@ * SPDX-FileCopyrightText: Eclipse Dirigible contributors * SPDX-License-Identifier: EPL-2.0 */ -function _uuid () { +function _uuid() { function _p8(s) { - let p = (Math.random().toString(16) + "000000000").substr(2, 8); - return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p; - } - return _p8() + _p8(true) + _p8(true) + _p8(); + let p = (Math.random().toString(16) + "000000000").substr(2, 8); + return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p; + } + return _p8() + _p8(true) + _p8(true) + _p8(); } - + angular.module('ui.entity-data.modeler', ["ideUI", "ideView", "ideWorkspace", "ideGenerate", "ideTemplates"]) .controller('ModelerCtrl', function ($scope, messageHub, $window, workspaceApi, generateApi, templatesApi, ViewParameters) { let contents; @@ -303,7 +303,6 @@ angular.module('ui.entity-data.modeler', ["ideUI", "ideView", "ideWorkspace", "i cell.value.dataName = msg.data.dataName; cell.value.dataCount = msg.data.dataCount; cell.value.dataQuery = msg.data.dataQuery; - cell.value.disableGeneration = msg.data.disableGeneration; cell.value.title = msg.data.title; cell.value.caption = msg.data.caption; cell.value.tooltip = msg.data.tooltip; @@ -500,7 +499,7 @@ angular.module('ui.entity-data.modeler', ["ideUI", "ideView", "ideWorkspace", "i }, true ); - + function main(container, outline, toolbar, sidebar) { let ICON_ENTITY = 'sap-icon--header'; let ICON_PROPERTY = 'sap-icon--bullet-text'; @@ -584,9 +583,9 @@ angular.module('ui.entity-data.modeler', ["ideUI", "ideView", "ideWorkspace", "i $scope.graph.isCellMovable = function (cell) { return this.isSwimlane(cell); }; - - $scope.graph.model.createId = function(_cell) { - let id = _uuid(); + + $scope.graph.model.createId = function (_cell) { + let id = _uuid(); return this.prefix + id + this.postfix; }; @@ -983,7 +982,6 @@ angular.module('ui.entity-data.modeler', ["ideUI", "ideView", "ideWorkspace", "i dataName: cell.value.dataName, dataCount: cell.value.dataCount, dataQuery: cell.value.dataQuery, - disableGeneration: cell.value.disableGeneration, title: cell.value.title, caption: cell.value.caption, tooltip: cell.value.tooltip, diff --git a/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/serializer.js b/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/serializer.js index 7ae23957609..022201f1ed9 100644 --- a/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/serializer.js +++ b/components/ide/ide-ui-entity/src/main/resources/META-INF/dirigible/ide-entity/js/serializer.js @@ -27,12 +27,10 @@ function createModel(graph) { child.value.tooltip = child.value.tooltip ? child.value.tooltip : child.value.name; child.value.menuKey = child.value.menuKey ? child.value.menuKey : JSON.stringify(child.value.name).replace(/\W/g, '').toLowerCase(); child.value.menuLabel = child.value.menuLabel ? child.value.menuLabel : child.value.name; - child.value.disableGeneration = child.value.disableGeneration ? child.value.disableGeneration : "false"; let entityContent = ' -
-
-
- - - Skip generation - -
- diff --git a/components/ide/ide-ui-generate-service/src/main/resources/META-INF/dirigible/ide-generate-service/template/generateUtils.js b/components/ide/ide-ui-generate-service/src/main/resources/META-INF/dirigible/ide-generate-service/template/generateUtils.js index 3c45ba2d58c..fbab1db19c5 100644 --- a/components/ide/ide-ui-generate-service/src/main/resources/META-INF/dirigible/ide-generate-service/template/generateUtils.js +++ b/components/ide/ide-ui-generate-service/src/main/resources/META-INF/dirigible/ide-generate-service/template/generateUtils.js @@ -44,7 +44,9 @@ exports.generateGeneric = function (model, parameters, templateSources) { exports.generateFiles = function (model, parameters, templateSources) { let generatedFiles = []; - const models = model.entities.filter(e => e.type !== "REPORT" && e.type !== "FILTER" && e.disableGeneration !== "true"); + const models = model.entities.filter(e => e.type !== "REPORT" && e.type !== "FILTER"); + const apiModels = model.entities.filter(e => e.type !== "PROJECTION"); + const daoModels = model.entities.filter(e => e.type !== "PROJECTION"); const feedModels = model.entities.filter(e => e.feedUrl); const reportModels = model.entities.filter(e => e.type === "REPORT"); @@ -94,6 +96,12 @@ exports.generateFiles = function (model, parameters, templateSources) { case "models": generatedFiles = generatedFiles.concat(generateCollection(location, content, template, models, parameters)); break; + case "apiModels": + generatedFiles = generatedFiles.concat(generateCollection(location, content, template, apiModels, parameters)); + break; + case "daoModels": + generatedFiles = generatedFiles.concat(generateCollection(location, content, template, daoModels, parameters)); + break; case "reportModels": generatedFiles = generatedFiles.concat(generateCollection(location, content, template, reportModels, parameters)); break; diff --git a/components/template/template-application-dao/src/main/resources/META-INF/dirigible/template-application-dao/template/template.js b/components/template/template-application-dao/src/main/resources/META-INF/dirigible/template-application-dao/template/template.js index 8dbde13fe64..3baaa3f1faf 100644 --- a/components/template/template-application-dao/src/main/resources/META-INF/dirigible/template-application-dao/template/template.js +++ b/components/template/template-application-dao/src/main/resources/META-INF/dirigible/template-application-dao/template/template.js @@ -23,7 +23,13 @@ exports.getTemplate = function (parameters) { action: "generate", rename: "gen/dao/{{perspectiveName}}/{{name}}Repository.ts", engine: "velocity", - collection: "models" + collection: "daoModels" + }, { + location: "/template-application-dao/dao/entity.extensionpoint.template", + action: "generate", + rename: "gen/dao/{{perspectiveName}}/{{name}}.extensionpoint", + engine: "velocity", + collection: "daoModels" }, { location: "/template-application-dao/dao/reportEntity.ts.template", action: "generate", @@ -40,12 +46,6 @@ exports.getTemplate = function (parameters) { action: "generate", rename: "tsconfig.json", engine: "velocity" - }, { - location: "/template-application-dao/dao/entity.extensionpoint.template", - action: "generate", - rename: "gen/dao/{{perspectiveName}}/{{name}}.extensionpoint", - engine: "velocity", - collection: "models" }, { location: "/template-application-dao/dao/utils/EntityUtils.ts.template", action: "copy", diff --git a/components/template/template-application-rest/src/main/resources/META-INF/dirigible/template-application-rest/api/api.openapi.template b/components/template/template-application-rest/src/main/resources/META-INF/dirigible/template-application-rest/api/api.openapi.template new file mode 100644 index 00000000000..334fd217592 --- /dev/null +++ b/components/template/template-application-rest/src/main/resources/META-INF/dirigible/template-application-rest/api/api.openapi.template @@ -0,0 +1,835 @@ +openapi: 3.0.3 +info: +#if($openApiTitle) + title: $openApiTitle - OpenAPI 3.0 +#elseif($title) + title: $title - OpenAPI 3.0 +#else + title: OpenAPI 3.0 +#end +#if($openApiVersion) + version: $openApiVersion +#else + version: 1.0.0 +#end +#if($openApiDescription) + description: $openApiDescription +#elseif($description) + description: $description +#else + description: REST API generated from an EDM model +#end +#if($openApiTermsOfService) + termsOfService: $openApiTermsOfService +#end +#if($openApiContactEmail || $openApiContactUrl) + contact: + name: API Support + #if($openApiContactEmail) + email: $openApiContactEmail + #end + #if($openApiContactUrl) + url: $openApiContactUrl + #end +#end +#if($openApiLicenseName && $openApiLicenseUrl) + license: + name: $openApiLicenseName + url: $openApiLicenseUrl +#end +#if($openApiExternalDocsDescription && $openApiExternalDocsUrl) +externalDocs: + description: $openApiExternalDocsDescription + url: $openApiExternalDocsUrl +#else +externalDocs: + description: Find out more about Eclipse Dirigible + url: https://dirigible.io +#end +servers: + - url: /services/ts +tags: +#foreach($model in $models) + #if($model.type != "PROJECTION") + - name: $model.perspectiveName + #end +#end +paths: +#foreach($model in $models) + #if($model.type != "PROJECTION") + #set($hasStringProperty = "false") + #foreach($property in $model.properties) + #if($property.dataTypeJava == "string") + #set($hasStringProperty = "true") + #end + #end + /$projectName/gen/api/$model.perspectiveName/${model.name}Service.ts: + get: + summary: List $model.name + parameters: + - in: query + name: $limit + description: The number of records to be returned _(both `$limit` and `$offset` should be provided)_. + required: false + allowReserved: true + schema: + type: integer + allowEmptyValue: true + - in: query + name: $offset + description: The number of records to skip _(both `$limit` and `$offset` should be provided)_. + required: false + allowReserved: true + schema: + type: integer + allowEmptyValue: true + tags: + - $model.perspectiveName + responses: + 200: + description: Successful Request + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/$model.name' + 400: + description: Bad Request Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 403: + description: Forbidden Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 500: + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + post: + summary: Create $model.name + tags: + - $model.perspectiveName + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/$model.name' + required: true + responses: + 201: + description: Successful Request + content: + application/json: + schema: + $ref: '#/components/schemas/$model.name' + 400: + description: Bad Request Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 403: + description: Forbidden Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 500: + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /$projectName/gen/api/$model.perspectiveName/${model.name}Service.ts/{id}: + get: + summary: Get $model.name by Id + parameters: + - in: path + name: id + description: The Id of the entity. + required: true + schema: + type: string + tags: + - $model.perspectiveName + responses: + 200: + description: Successful Request + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/$model.name' + 404: + description: Entity Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 403: + description: Forbidden Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 500: + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + put: + summary: Update $model.name by Id + parameters: + - in: path + name: id + description: The Id of the entity. + required: true + schema: + type: string + tags: + - $model.perspectiveName + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/$model.name' + required: true + responses: + 200: + description: Successful Request + content: + application/json: + schema: + $ref: '#/components/schemas/$model.name' + 400: + description: Bad Request Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 404: + description: Entity Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 403: + description: Forbidden Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 500: + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + summary: Delete $model.name by Id + parameters: + - in: path + name: id + description: The Id of the entity. + required: true + schema: + type: string + tags: + - $model.perspectiveName + responses: + 204: + description: Successful Request + 404: + description: Entity Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 403: + description: Forbidden Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 500: + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /$projectName/gen/api/$model.perspectiveName/${model.name}Service.ts/count: + get: + summary: Count the number of $model.name + tags: + - $model.perspectiveName + responses: + 200: + description: Successful Request + content: + application/json: + schema: + type: integer + example: 100 + 403: + description: Forbidden Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 500: + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + post: + summary: Count the number of $model.name by ${model.name}FilterOptions + tags: + - $model.perspectiveName + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/${model.name}FilterOptions' + examples: + countWithMultipleCriteria: + summary: Count with multiple criteria + value: + $filter: + notEquals: + $model.properties[0].name: 33 + #if($hasStringProperty == "true") + contains: + #foreach($property in $model.properties) + #if($property.dataTypeJava == "string") + $property.name: "abcd" + #end + #end + #end + greaterThan: + $model.properties[0].name: 0 + lessThanOrEqual: + $model.properties[0].name: 100 + countWithEquals: + summary: Count with Equals + value: + $filter: + equals: + $model.properties[0].name: 0 + countWithNotEquals: + summary: Count with Not Equals + value: + $filter: + notEquals: + $model.properties[0].name: 0 + #if($hasStringProperty == "true") + countWithContains: + summary: Count with Contains + value: + $filter: + contains: + #foreach($property in $model.properties) + #if($property.dataTypeJava == "string") + $property.name: "abcd" + #end + #end + #end + countWithGreaterThan: + summary: Count with Greater Than + value: + $filter: + greaterThan: + $model.properties[0].name: 0 + countWithGreaterThanOrEqual: + summary: Count with Greater Than Or Equal + value: + $filter: + greaterThanOrEqual: + $model.properties[0].name: 0 + countWithLessThan: + summary: Count with Less Than + value: + $filter: + lessThan: + $model.properties[0].name: 0 + countWithLessThanOrEqual: + summary: Count with Less Than Or Equal + value: + $filter: + lessThanOrEqual: + $model.properties[0].name: 0 + required: true + responses: + 200: + description: Successful Request + content: + application/json: + schema: + type: integer + example: 100 + 403: + description: Forbidden Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 500: + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /$projectName/gen/api/$model.perspectiveName/${model.name}Service.ts/search: + post: + summary: Search ${model.name} by ${model.name}FilterOptions + tags: + - $model.perspectiveName + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/${model.name}FilterOptions' + examples: + searchWithMultipleCriteria: + summary: Search with multiple criteria + value: + $filter: + notEquals: + $model.properties[0].name: 33 + #if($hasStringProperty == "true") + contains: + #foreach($property in $model.properties) + #if($property.dataTypeJava == "string") + $property.name: "abcd" + #end + #end + #end + greaterThan: + $model.properties[0].name: 0 + lessThanOrEqual: + $model.properties[0].name: 100 + searchWithEquals: + summary: Search with Equals + value: + $filter: + equals: + $model.properties[0].name: 0 + searchWithNotEquals: + summary: Search with Not Equals + value: + $filter: + notEquals: + $model.properties[0].name: 0 + #if($hasStringProperty == "true") + searchWithContains: + summary: Search with Contains + value: + $filter: + contains: + #foreach($property in $model.properties) + #if($property.dataTypeJava == "string") + $property.name: "abcd" + #end + #end + #end + searchWithGreaterThan: + summary: Search with Greater Than + value: + $filter: + greaterThan: + $model.properties[0].name: 0 + searchWithGreaterThanOrEqual: + summary: Search with Greater Than Or Equal + value: + $filter: + greaterThanOrEqual: + $model.properties[0].name: 0 + searchWithLessThan: + summary: Search with Less Than + value: + $filter: + lessThan: + $model.properties[0].name: 0 + searchWithLessThanOrEqual: + summary: Search with Less Than Or Equal + value: + $filter: + lessThanOrEqual: + $model.properties[0].name: 0 + required: true + responses: + 200: + description: Successful Request + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/$model.name' + 403: + description: Forbidden Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + 500: + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + #end +#end +components: + schemas: +#foreach($model in $models) + #if($model.type != "PROJECTION") + #set($hasRequiredProperty = "false") + #foreach($property in $model.properties) + #if($property.isRequiredProperty) + #set($hasRequiredProperty = "true") + #end + #end + $model.name: + type: object + #if($hasRequiredProperty) + required: + #foreach($property in $model.properties) + #if($property.isRequiredProperty) + - ${property.name} + #end + #end + #end + properties: + #foreach($property in $model.properties) + $property.name: + #if($property.dataTypeJava == "short" || $property.dataTypeJava == "int") + type: integer + format: int32 + #if($property.isCalculatedProperty) + readOnly: true + #end + #elseif($property.dataTypeJava == "long") + type: integer + format: int64 + #if($property.isCalculatedProperty) + readOnly: true + #end + #elseif($property.dataTypeJava == "float") + type: number + format: float + #if($property.isCalculatedProperty) + readOnly: true + #end + #elseif($property.dataTypeJava == "double") + type: number + format: double + #if($property.isCalculatedProperty) + readOnly: true + #end + #elseif($property.dataTypeJava == "string") + type: string + minLength: 0 + maxLength: $property.dataLength + #if($property.widgetPattern) + pattern: $property.widgetPattern + #end + #if($property.isCalculatedProperty) + readOnly: true + #end + #elseif($property.dataTypeJava == "boolean") + type: boolean + #if($property.isCalculatedProperty) + readOnly: true + #end + #elseif($property.dataTypeJava == "null") + type: null + #if($property.isCalculatedProperty) + readOnly: true + #end + #end + #end + ${model.name}FilterOptions: + type: object + properties: + $filter: + type: object + properties: + equals: + type: object + properties: + #foreach($property in $model.properties) + $property.name: + oneOf: + #if($property.dataTypeJava == "short" || $property.dataTypeJava == "int") + - type: integer + format: int32 + - type: array + items: + type: integer + format: int32 + #elseif($property.dataTypeJava == "long") + - type: integer + format: int64 + - type: array + items: + type: integer + format: int64 + #elseif($property.dataTypeJava == "float") + - type: number + format: float + - type: array + items: + type: number + format: float + #elseif($property.dataTypeJava == "double") + - type: number + format: double + - type: array + items: + type: number + format: double + #elseif($property.dataTypeJava == "string") + - type: string + minLength: 0 + maxLength: $property.dataLength + #if($property.widgetPattern) + pattern: $property.widgetPattern + #end + - type: array + items: + type: string + format: double + minLength: 0 + maxLength: $property.dataLength + #if($property.widgetPattern) + pattern: $property.widgetPattern + #end + #elseif($property.dataTypeJava == "boolean") + - type: boolean + - type: array + items: + type: boolean + #elseif($property.dataTypeJava == "null") + - type: null + - type: array + items: + type: null + #end + #end + notEquals: + type: object + properties: + #foreach($property in $model.properties) + $property.name: + oneOf: + #if($property.dataTypeJava == "short" || $property.dataTypeJava == "int") + - type: integer + format: int32 + - type: array + items: + type: integer + format: int32 + #elseif($property.dataTypeJava == "long") + - type: integer + format: int64 + - type: array + items: + type: integer + format: int64 + #elseif($property.dataTypeJava == "float") + - type: number + format: float + - type: array + items: + type: number + format: float + #elseif($property.dataTypeJava == "double") + - type: number + format: double + - type: array + items: + type: number + format: double + #elseif($property.dataTypeJava == "string") + - type: string + minLength: 0 + maxLength: $property.dataLength + #if($property.widgetPattern) + pattern: $property.widgetPattern + #end + - type: array + items: + type: string + format: double + minLength: 0 + maxLength: $property.dataLength + #if($property.widgetPattern) + pattern: $property.widgetPattern + #end + #elseif($property.dataTypeJava == "boolean") + - type: boolean + - type: array + items: + type: boolean + #elseif($property.dataTypeJava == "null") + - type: null + - type: array + items: + type: null + #end + #end + contains: + type: object + properties: + #foreach($property in $model.properties) + $property.name: + #if($property.dataTypeJava == "string") + type: string + minLength: 0 + maxLength: $property.dataLength + #if($property.widgetPattern) + pattern: $property.widgetPattern + #end + #end + #end + greaterThan: + type: object + properties: + #foreach($property in $model.properties) + $property.name: + #if($property.dataTypeJava == "short" || $property.dataTypeJava == "int") + type: integer + format: int32 + #elseif($property.dataTypeJava == "long") + type: integer + format: int64 + #elseif($property.dataTypeJava == "float") + type: number + format: float + #elseif($property.dataTypeJava == "double") + type: number + format: double + #elseif($property.dataTypeJava == "string") + type: string + minLength: 0 + maxLength: $property.dataLength + #if($property.widgetPattern) + pattern: $property.widgetPattern + #end + #end + #end + greaterThanOrEqual: + type: object + properties: + #foreach($property in $model.properties) + $property.name: + #if($property.dataTypeJava == "short" || $property.dataTypeJava == "int") + type: integer + format: int32 + #elseif($property.dataTypeJava == "long") + type: integer + format: int64 + #elseif($property.dataTypeJava == "float") + type: number + format: float + #elseif($property.dataTypeJava == "double") + type: number + format: double + #elseif($property.dataTypeJava == "string") + type: string + minLength: 0 + maxLength: $property.dataLength + #if($property.widgetPattern) + pattern: $property.widgetPattern + #end + #end + #end + lessThan: + type: object + properties: + #foreach($property in $model.properties) + $property.name: + #if($property.dataTypeJava == "short" || $property.dataTypeJava == "int") + type: integer + format: int32 + #elseif($property.dataTypeJava == "long") + type: integer + format: int64 + #elseif($property.dataTypeJava == "float") + type: number + format: float + #elseif($property.dataTypeJava == "double") + type: number + format: double + #elseif($property.dataTypeJava == "string") + type: string + minLength: 0 + maxLength: $property.dataLength + #if($property.widgetPattern) + pattern: $property.widgetPattern + #end + #end + #end + lessThanOrEqual: + type: object + properties: + #foreach($property in $model.properties) + $property.name: + #if($property.dataTypeJava == "short" || $property.dataTypeJava == "int") + type: integer + format: int32 + #elseif($property.dataTypeJava == "long") + type: integer + format: int64 + #elseif($property.dataTypeJava == "float") + type: number + format: float + #elseif($property.dataTypeJava == "double") + type: number + format: double + #elseif($property.dataTypeJava == "string") + type: string + minLength: 0 + maxLength: $property.dataLength + #if($property.widgetPattern) + pattern: $property.widgetPattern + #end + #end + #end + $select: + type: array + example: [#foreach($property in $model.properties)"$property.name"#if($foreach.hasNext), #end#end] + items: + type: string + $sort: + - type: string + example: "#foreach($property in $model.properties)$property.name#if($foreach.hasNext),#end#end" + $order: + type: string + enum: ["asc", "desc"] + example: "asc" + $offset: + type: integer + example: 0 + $limit: + type: integer + example: 10 + #end +#end + Error: + type: object + properties: + code: + type: integer + message: + type: string \ No newline at end of file diff --git a/components/template/template-application-rest/src/main/resources/META-INF/dirigible/template-application-rest/template/template.js b/components/template/template-application-rest/src/main/resources/META-INF/dirigible/template-application-rest/template/template.js index 81d2585f434..2691aa6bfcb 100644 --- a/components/template/template-application-rest/src/main/resources/META-INF/dirigible/template-application-rest/template/template.js +++ b/components/template/template-application-rest/src/main/resources/META-INF/dirigible/template-application-rest/template/template.js @@ -29,12 +29,17 @@ exports.getTemplate = function (parameters) { location: "/template-application-rest/api/utils/ValidationError.ts.template", action: "copy", rename: "gen/api/utils/ValidationError.ts", + }, { + location: "/template-application-rest/api/api.openapi.template", + action: "generate", + rename: "gen/{{fileName}}.openapi", + engine: "velocity" }, { location: "/template-application-rest/api/entity.ts.template", action: "generate", rename: "gen/api/{{perspectiveName}}/{{name}}Service.ts", engine: "velocity", - collection: "models" + collection: "apiModels" }, { location: "/template-application-rest/api/reportEntity.ts.template", action: "generate", @@ -42,12 +47,12 @@ exports.getTemplate = function (parameters) { engine: "velocity", collection: "reportModels" }, { - location: "/template-application-dao/project.json.mjs", + location: "/template-application-rest/project.json.mjs", action: "generate", rename: "project.json", engine: "javascript" }, { - location: "/template-application-dao/tsconfig.json.template", + location: "/template-application-rest/tsconfig.json.template", action: "generate", rename: "tsconfig.json", engine: "velocity" @@ -56,6 +61,133 @@ exports.getTemplate = function (parameters) { let templateParameters = []; templateParameters = templateParameters.concat(daoTemplate.parameters); + templateParameters.push + + templateParameters.push({ + name: "addOpenApiInfo", + label: "OpenAPI Info (Optional)", + type: "checkbox", + }); + templateParameters.push({ + name: "openApiTitle", + label: "OpenAPI Title", + placeholder: "Enter API title, if not provided the application title is taken", + required: false, + ui: { + hide: { + property: "addOpenApiInfo", + value: false + } + } + }); + templateParameters.push({ + name: "openApiVersion", + label: "OpenAPI Version", + placeholder: "Enter API version, default value is 1.0.0", + required: false, + ui: { + hide: { + property: "addOpenApiInfo", + value: false + } + } + }); + templateParameters.push({ + name: "openApiDescription", + label: "OpenAPI Description", + placeholder: "Enter API description, if not provided the application description is taken", + required: false, + ui: { + hide: { + property: "addOpenApiInfo", + value: false + } + } + }); + templateParameters.push({ + name: "openApiTermsOfService", + label: "OpenAPI Terms Of Service", + placeholder: "Enter API terms of service", + required: false, + ui: { + hide: { + property: "addOpenApiInfo", + value: false + } + } + }); + templateParameters.push({ + name: "openApiContactEmail", + label: "OpenAPI Contact Email", + placeholder: "Enter API contact email", + required: false, + ui: { + hide: { + property: "addOpenApiInfo", + value: false + } + } + }); + templateParameters.push({ + name: "openApiContactUrl", + label: "OpenAPI Contact URL", + placeholder: "Enter API contact URL", + required: false, + ui: { + hide: { + property: "addOpenApiInfo", + value: false + } + } + }); + templateParameters.push({ + name: "openApiLicenseName", + label: "OpenAPI License Name", + placeholder: "Enter API license name", + required: false, + ui: { + hide: { + property: "addOpenApiInfo", + value: false + } + } + }); + templateParameters.push({ + name: "openApiLicenseUrl", + label: "OpenAPI License URL", + placeholder: "Enter API license URL", + required: false, + ui: { + hide: { + property: "addOpenApiInfo", + value: false + } + } + }); + templateParameters.push({ + name: "openApiExternalDocsDescription", + label: "OpenAPI External Docs Description", + placeholder: "Enter API external docs description", + required: false, + ui: { + hide: { + property: "addOpenApiInfo", + value: false + } + } + }); + templateParameters.push({ + name: "openApiExternalDocsUrl", + label: "OpenAPI External Docs URL", + placeholder: "Enter API external docs URL", + required: false, + ui: { + hide: { + property: "addOpenApiInfo", + value: false + } + } + }); return { name: "Application - REST", diff --git a/components/template/template-application-schema/src/main/resources/META-INF/dirigible/template-application-schema/data/application.schema.template b/components/template/template-application-schema/src/main/resources/META-INF/dirigible/template-application-schema/data/application.schema.template index 10d36f12706..0dec92cb0c1 100644 --- a/components/template/template-application-schema/src/main/resources/META-INF/dirigible/template-application-schema/data/application.schema.template +++ b/components/template/template-application-schema/src/main/resources/META-INF/dirigible/template-application-schema/data/application.schema.template @@ -1,6 +1,6 @@ #set ($foreignKeysCount = 0) #foreach ($model in $models) -#if($model.type != "REPORT" && $model.type != "FILTER") +#if($model.type != "REPORT" && $model.type != "FILTER" && $model.type != "PROJECTION") #foreach ($property in $model.properties) #if($property.relationshipEntityName) #set ($foreignKeysCount = $foreignKeysCount + 1) @@ -12,7 +12,7 @@ "schema": { "structures": [ #foreach ($model in $models) -#if($model.type != "REPORT" && $model.type != "FILTER" && $model.disableGeneration != "true") +#if($model.type != "REPORT" && $model.type != "FILTER" && $model.type != "PROJECTION") { "name": "${tablePrefix}${model.dataName}", "type": "TABLE", From cae56deca931e0b797b8c1a34c216dc6af4eb644 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 12:10:18 +0300 Subject: [PATCH 2/4] Bump com.ibm.icu:icu4j from 74.2 to 75.1 (#3798) Bumps [com.ibm.icu:icu4j](https://github.com/unicode-org/icu) from 74.2 to 75.1. - [Release notes](https://github.com/unicode-org/icu/releases) - [Commits](https://github.com/unicode-org/icu/commits) --- updated-dependencies: - dependency-name: com.ibm.icu:icu4j dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4ab87aa2998..14af5fd7550 100644 --- a/pom.xml +++ b/pom.xml @@ -184,7 +184,7 @@ 0.10.0-pre7 33.1.0-jre - 74.2 + 75.1 4.8.170 2.9.2 From 9ffb860b9d9e98181d1c25a03b753ec9b129b6d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 12:11:27 +0300 Subject: [PATCH 3/4] Bump software.amazon.awssdk:s3-transfer-manager from 2.25.28 to 2.25.32 (#3802) Bumps software.amazon.awssdk:s3-transfer-manager from 2.25.28 to 2.25.32. --- updated-dependencies: - dependency-name: software.amazon.awssdk:s3-transfer-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- components/api/api-s3/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/api/api-s3/pom.xml b/components/api/api-s3/pom.xml index 4c99ab0c054..c46aed67633 100644 --- a/components/api/api-s3/pom.xml +++ b/components/api/api-s3/pom.xml @@ -32,7 +32,7 @@ software.amazon.awssdk s3-transfer-manager - 2.25.28 + 2.25.32 From e91d8a2eb1d330b68e10aefddeac13805fff838d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 12:11:43 +0300 Subject: [PATCH 4/4] Bump com.amazonaws:aws-java-sdk-qldb from 1.12.698 to 1.12.703 (#3804) Bumps [com.amazonaws:aws-java-sdk-qldb](https://github.com/aws/aws-sdk-java) from 1.12.698 to 1.12.703. - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.698...1.12.703) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk-qldb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 14af5fd7550..02f9d1a515e 100644 --- a/pom.xml +++ b/pom.xml @@ -176,7 +176,7 @@ 2.3.1 - 1.12.698 + 1.12.703 0.7.7