From c37790723f3b6641daf88c5271a3a51202e870c1 Mon Sep 17 00:00:00 2001 From: Kraust Date: Wed, 6 Aug 2025 19:10:38 -0400 Subject: [PATCH 1/5] Added cpp-oatpp-client. --- .gitignore | 6 + README.md | 1 + bin/configs/cpp-oatpp-client.yaml | 6 + docs/generators.md | 1 + docs/generators/cpp-oatpp-client.md | 272 +++++++ .../languages/CppOatppClientCodegen.java | 474 +++++++++++ .../org.openapitools.codegen.CodegenConfig | 1 + .../cpp-oatpp-client/README.mustache | 39 + .../cpp-oatpp-client/api-header.mustache | 50 ++ .../resources/cpp-oatpp-client/cmake.mustache | 38 + .../cpp-oatpp-client/licenseInfo.mustache | 11 + .../cpp-oatpp-client/main-api-client.mustache | 38 + .../cpp-oatpp-client/model-header.mustache | 61 ++ .../3_0/cpp-oatpp-client/petstore.yaml | 741 ++++++++++++++++++ .../cpp-oatpp/.openapi-generator-ignore | 23 + .../cpp-oatpp/.openapi-generator/FILES | 12 + .../cpp-oatpp/.openapi-generator/VERSION | 1 + .../client/petstore/cpp-oatpp/CMakeLists.txt | 36 + samples/client/petstore/cpp-oatpp/README.md | 39 + .../client/petstore/cpp-oatpp/api/PetApi.hpp | 116 +++ .../petstore/cpp-oatpp/api/StoreApi.hpp | 77 ++ .../client/petstore/cpp-oatpp/api/UserApi.hpp | 111 +++ .../petstore/cpp-oatpp/main-api-client.cpp | 56 ++ .../petstore/cpp-oatpp/model/ApiResponse.hpp | 53 ++ .../petstore/cpp-oatpp/model/Category.hpp | 51 ++ .../client/petstore/cpp-oatpp/model/Order.hpp | 59 ++ .../client/petstore/cpp-oatpp/model/Pet.hpp | 61 ++ .../client/petstore/cpp-oatpp/model/Tag.hpp | 51 ++ .../client/petstore/cpp-oatpp/model/User.hpp | 63 ++ website/i18n/en.json | 4 + 30 files changed, 2552 insertions(+) create mode 100644 bin/configs/cpp-oatpp-client.yaml create mode 100644 docs/generators/cpp-oatpp-client.md create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppOatppClientCodegen.java create mode 100644 modules/openapi-generator/src/main/resources/cpp-oatpp-client/README.mustache create mode 100644 modules/openapi-generator/src/main/resources/cpp-oatpp-client/api-header.mustache create mode 100644 modules/openapi-generator/src/main/resources/cpp-oatpp-client/cmake.mustache create mode 100644 modules/openapi-generator/src/main/resources/cpp-oatpp-client/licenseInfo.mustache create mode 100644 modules/openapi-generator/src/main/resources/cpp-oatpp-client/main-api-client.mustache create mode 100644 modules/openapi-generator/src/main/resources/cpp-oatpp-client/model-header.mustache create mode 100644 modules/openapi-generator/src/test/resources/3_0/cpp-oatpp-client/petstore.yaml create mode 100644 samples/client/petstore/cpp-oatpp/.openapi-generator-ignore create mode 100644 samples/client/petstore/cpp-oatpp/.openapi-generator/FILES create mode 100644 samples/client/petstore/cpp-oatpp/.openapi-generator/VERSION create mode 100644 samples/client/petstore/cpp-oatpp/CMakeLists.txt create mode 100644 samples/client/petstore/cpp-oatpp/README.md create mode 100644 samples/client/petstore/cpp-oatpp/api/PetApi.hpp create mode 100644 samples/client/petstore/cpp-oatpp/api/StoreApi.hpp create mode 100644 samples/client/petstore/cpp-oatpp/api/UserApi.hpp create mode 100644 samples/client/petstore/cpp-oatpp/main-api-client.cpp create mode 100644 samples/client/petstore/cpp-oatpp/model/ApiResponse.hpp create mode 100644 samples/client/petstore/cpp-oatpp/model/Category.hpp create mode 100644 samples/client/petstore/cpp-oatpp/model/Order.hpp create mode 100644 samples/client/petstore/cpp-oatpp/model/Pet.hpp create mode 100644 samples/client/petstore/cpp-oatpp/model/Tag.hpp create mode 100644 samples/client/petstore/cpp-oatpp/model/User.hpp diff --git a/.gitignore b/.gitignore index a2e29abe05bc..5c6df879f35d 100644 --- a/.gitignore +++ b/.gitignore @@ -92,6 +92,12 @@ samples/client/petstore/cpp-restsdk/client/cmake_install.cmake samples/client/petstore/cpp-restsdk/client/CppRestPetstoreClientConfig.cmake samples/client/petstore/cpp-restsdk/client/CMakeCache.txt +# cpp-oatpp +samples/client/petstore/cpp-oatpp/build +samples/client/petstore/cpp-oatpp/external +samples/server/petstore/cpp-oatpp/build +samples/server/petstore/cpp-oatpp/external + #Java/Android **/.gradle samples/client/petstore/java/hello.txt diff --git a/README.md b/README.md index e7af152c4336..c4c0e95a0429 100644 --- a/README.md +++ b/README.md @@ -1025,6 +1025,7 @@ Here is a list of template creators: * Apex: @asnelling * Bash: @bkryza * C: @PowerOfCreation @zhemant [:heart:](https://www.patreon.com/zhemant) + * C++ Oat++: @Kraust * C++ REST: @Danielku15 * C++ Tiny: @AndersSpringborg @kaareHH @michelealbano @mkakbas * C++ UE4: @Kahncode diff --git a/bin/configs/cpp-oatpp-client.yaml b/bin/configs/cpp-oatpp-client.yaml new file mode 100644 index 000000000000..eb8d3804a4ef --- /dev/null +++ b/bin/configs/cpp-oatpp-client.yaml @@ -0,0 +1,6 @@ +generatorName: cpp-oatpp-client +outputDir: samples/client/petstore/cpp-oatpp +inputSpec: modules/openapi-generator/src/test/resources/3_0/cpp-oatpp-client/petstore.yaml +templateDir: modules/openapi-generator/src/main/resources/cpp-oatpp-client +additionalProperties: + addExternalLibs: "true" diff --git a/docs/generators.md b/docs/generators.md index 009bb56b4bcd..ca295d97c5ad 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -12,6 +12,7 @@ The following generators are available: * [bash](generators/bash.md) * [c](generators/c.md) * [clojure](generators/clojure.md) +* [cpp-oatpp-client](generators/cpp-oatpp-client.md) * [cpp-qt-client](generators/cpp-qt-client.md) * [cpp-restsdk](generators/cpp-restsdk.md) * [cpp-tiny (beta)](generators/cpp-tiny.md) diff --git a/docs/generators/cpp-oatpp-client.md b/docs/generators/cpp-oatpp-client.md new file mode 100644 index 000000000000..370d816f12d8 --- /dev/null +++ b/docs/generators/cpp-oatpp-client.md @@ -0,0 +1,272 @@ +--- +title: Documentation for the cpp-oatpp-client Generator +--- + +## METADATA + +| Property | Value | Notes | +| -------- | ----- | ----- | +| generator name | cpp-oatpp-client | pass this to the generate command after -g | +| generator stability | STABLE | | +| generator type | CLIENT | | +| generator language | C++ | | +| generator default templating engine | mustache | | +| helpTxt | Generates a C++ client library (based on oat++). | | + +## CONFIG OPTIONS +These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details. + +| Option | Description | Values | Default | +| ------ | ----------- | ------ | ------- | +|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false| +|contentCompression|Enable Compressed Content Encoding for requests and responses| |false| +|cppNamespace|C++ namespace (convention: name::space::for::api).| |OpenAPI| +|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|
**false**
The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.
**true**
Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.
|true| +|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true| +|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|
**false**
No changes to the enum's are made, this is the default option.
**true**
With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.
|false| +|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|
**true**
The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.
**false**
The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.
|true| +|modelNamePrefix|Prefix that will be prepended to all model names.| |OAI| +|optionalProjectFile|Generate client.pri.| |true| +|packageName|C++ package (library) name.| |QtOpenAPIClient| +|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| +|reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| +|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| +|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| + +## IMPORT MAPPING + +| Type/Alias | Imports | +| ---------- | ------- | +|OAIHttpFileElement|#include "OAIHttpFileElement.h"| +|QJsonValue|#include <QJsonValue>| + + +## INSTANTIATION TYPES + +| Type/Alias | Instantiated By | +| ---------- | --------------- | + + +## LANGUAGE PRIMITIVES + + + +## RESERVED WORDS + + + +## FEATURE SET + + +### Client Modification Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|BasePath|✗|ToolingExtension +|Authorizations|✗|ToolingExtension +|UserAgent|✗|ToolingExtension +|MockServer|✗|ToolingExtension + +### Data Type Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|Custom|✗|OAS2,OAS3 +|Int32|✓|OAS2,OAS3 +|Int64|✓|OAS2,OAS3 +|Float|✓|OAS2,OAS3 +|Double|✓|OAS2,OAS3 +|Decimal|✓|ToolingExtension +|String|✓|OAS2,OAS3 +|Byte|✓|OAS2,OAS3 +|Binary|✓|OAS2,OAS3 +|Boolean|✓|OAS2,OAS3 +|Date|✓|OAS2,OAS3 +|DateTime|✓|OAS2,OAS3 +|Password|✓|OAS2,OAS3 +|File|✓|OAS2 +|Uuid|✗| +|Array|✓|OAS2,OAS3 +|Null|✗|OAS3 +|AnyType|✗|OAS2,OAS3 +|Object|✓|OAS2,OAS3 +|Maps|✓|ToolingExtension +|CollectionFormat|✓|OAS2 +|CollectionFormatMulti|✓|OAS2 +|Enum|✓|OAS2,OAS3 +|ArrayOfEnum|✓|ToolingExtension +|ArrayOfModel|✓|ToolingExtension +|ArrayOfCollectionOfPrimitives|✓|ToolingExtension +|ArrayOfCollectionOfModel|✓|ToolingExtension +|ArrayOfCollectionOfEnum|✓|ToolingExtension +|MapOfEnum|✓|ToolingExtension +|MapOfModel|✓|ToolingExtension +|MapOfCollectionOfPrimitives|✓|ToolingExtension +|MapOfCollectionOfModel|✓|ToolingExtension +|MapOfCollectionOfEnum|✓|ToolingExtension + +### Documentation Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|Readme|✓|ToolingExtension +|Model|✓|ToolingExtension +|Api|✓|ToolingExtension + +### Global Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|Host|✓|OAS2,OAS3 +|BasePath|✓|OAS2,OAS3 +|Info|✓|OAS2,OAS3 +|Schemes|✗|OAS2,OAS3 +|PartialSchemes|✓|OAS2,OAS3 +|Consumes|✓|OAS2 +|Produces|✓|OAS2 +|ExternalDocumentation|✓|OAS2,OAS3 +|Examples|✓|OAS2,OAS3 +|XMLStructureDefinitions|✗|OAS2,OAS3 +|MultiServer|✓|OAS3 +|ParameterizedServer|✓|OAS3 +|ParameterStyling|✓|OAS3 +|Callbacks|✗|OAS3 +|LinkObjects|✗|OAS3 + +### Parameter Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|Path|✓|OAS2,OAS3 +|Query|✓|OAS2,OAS3 +|Header|✓|OAS2,OAS3 +|Body|✓|OAS2 +|FormUnencoded|✓|OAS2 +|FormMultipart|✓|OAS2 +|Cookie|✓|OAS3 + +### Schema Support Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|Simple|✓|OAS2,OAS3 +|Composite|✓|OAS2,OAS3 +|Polymorphism|✓|OAS2,OAS3 +|Union|✗|OAS3 +|allOf|✗|OAS2,OAS3 +|anyOf|✗|OAS3 +|oneOf|✗|OAS3 +|not|✗|OAS3 + +### Security Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|BasicAuth|✓|OAS2,OAS3 +|ApiKey|✓|OAS2,OAS3 +|OpenIDConnect|✗|OAS3 +|BearerToken|✓|OAS3 +|OAuth2_Implicit|✓|OAS2,OAS3 +|OAuth2_Password|✓|OAS2,OAS3 +|OAuth2_ClientCredentials|✓|OAS2,OAS3 +|OAuth2_AuthorizationCode|✓|OAS2,OAS3 + +### Wire Format Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|JSON|✓|OAS2,OAS3 +|XML|✓|OAS2,OAS3 +|PROTOBUF|✗|ToolingExtension +|Custom|✗|OAS2,OAS3 diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppOatppClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppOatppClientCodegen.java new file mode 100644 index 000000000000..34dbdbef8d32 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppOatppClientCodegen.java @@ -0,0 +1,474 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.languages; + +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.servers.Server; +import org.apache.commons.lang3.StringUtils; +import org.openapitools.codegen.*; +import org.openapitools.codegen.meta.features.*; +import org.openapitools.codegen.model.ModelMap; +import org.openapitools.codegen.model.OperationMap; +import org.openapitools.codegen.model.OperationsMap; +import org.openapitools.codegen.utils.ModelUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.*; +import java.util.function.Predicate; + +import static org.openapitools.codegen.utils.StringUtils.underscore; + +public class CppOatppClientCodegen extends AbstractCppCodegen { + private final Logger LOGGER = LoggerFactory.getLogger(CppOatppClientCodegen.class); + + protected boolean isAddExternalLibs = true; + public static final String OPTIONAL_EXTERNAL_LIB = "addExternalLibs"; + public static final String OPTIONAL_EXTERNAL_LIB_DESC = "Add the Possibility to fetch and compile external Libraries needed by this Framework."; + protected final String PREFIX = ""; + + @Override + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + @Override + public String getName() { + return "cpp-oatpp-client"; + } + + @Override + public String getHelp() { + return "Generates a C++ API client (based on Oat++)"; + } + + public CppOatppClientCodegen() { + super(); + + // TODO: cpp-oatpp-client maintainer review + modifyFeatureSet(features -> features + .includeDocumentationFeatures(DocumentationFeature.Readme) + .securityFeatures(EnumSet.noneOf(SecurityFeature.class)) + .excludeGlobalFeatures( + GlobalFeature.XMLStructureDefinitions, + GlobalFeature.Callbacks, + GlobalFeature.LinkObjects, + GlobalFeature.ParameterStyling, + GlobalFeature.MultiServer) + .excludeSchemaSupportFeatures( + SchemaSupportFeature.Polymorphism) + .excludeParameterFeatures( + ParameterFeature.Cookie)); + + if (StringUtils.isEmpty(modelNamePrefix)) { + modelNamePrefix = PREFIX; + } + + apiPackage = "org.openapitools.client.api"; + modelPackage = "org.openapitools.client.model"; + + apiTemplateFiles.put("api-header.mustache", ".hpp"); + + modelTemplateFiles.put("model-header.mustache", ".hpp"); + + embeddedTemplateDir = templateDir = "cpp-oatpp-client"; + + cliOptions.clear(); + addSwitch(OPTIONAL_EXTERNAL_LIB, OPTIONAL_EXTERNAL_LIB_DESC, this.isAddExternalLibs); + addOption(RESERVED_WORD_PREFIX_OPTION, RESERVED_WORD_PREFIX_DESC, this.reservedWordPrefix); + addOption(VARIABLE_NAME_FIRST_CHARACTER_UPPERCASE_OPTION, + VARIABLE_NAME_FIRST_CHARACTER_UPPERCASE_DESC, + Boolean.toString(this.variableNameFirstCharacterUppercase)); + + setupSupportingFiles(); + + languageSpecificPrimitives = new HashSet<>( + Arrays.asList( + "oatpp::String", + "oatpp::Boolean", + "oatpp::Int32", + "oatpp::Int64", + "oatpp::Vector", + "oatpp::Fields", + "oatpp::UnorderedSet", + "oatpp::Object", + "oatpp::Float64", + "oatpp::Any" + )); + + typeMapping = new HashMap<>(); + typeMapping.put("date", "oatpp::String"); + typeMapping.put("DateTime", "oatpp::String"); + typeMapping.put("string", "oatpp::String"); + typeMapping.put("integer", "oatpp::Int32"); + typeMapping.put("long", "oatpp::Int64"); + typeMapping.put("boolean", "oatpp::Boolean"); + typeMapping.put("array", "oatpp::Vector"); + typeMapping.put("map", "oatpp::Fields"); + typeMapping.put("set", "oatpp::UnorderedSet"); + typeMapping.put("file", "oatpp::String"); + typeMapping.put("object", "oatpp::Object"); + typeMapping.put("binary", "oatpp::String"); + typeMapping.put("number", "oatpp::Float64"); + typeMapping.put("UUID", "oatpp::String"); + typeMapping.put("URI", "oatpp::String"); + typeMapping.put("ByteArray", "oatpp::String"); + typeMapping.put("AnyType", "oatpp::Any"); + + super.importMapping = new HashMap<>(); + } + + private void setupSupportingFiles() { + supportingFiles.clear(); + supportingFiles + .add(new SupportingFile("main-api-client.mustache", "", modelNamePrefix + "main-api-client.cpp")); + supportingFiles.add(new SupportingFile("cmake.mustache", "", "CMakeLists.txt")); + supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); + } + + @Override + public void processOpts() { + super.processOpts(); + if (additionalProperties.containsKey("modelNamePrefix")) { + additionalProperties().put("prefix", modelNamePrefix); + setupSupportingFiles(); + } + if (additionalProperties.containsKey(RESERVED_WORD_PREFIX_OPTION)) { + reservedWordPrefix = (String) additionalProperties.get(RESERVED_WORD_PREFIX_OPTION); + } + + additionalProperties.put("modelNamespaceDeclarations", modelPackage.split("\\.")); + additionalProperties.put("modelNamespace", modelPackage.replaceAll("\\.", "::")); + additionalProperties.put("apiNamespaceDeclarations", apiPackage.split("\\.")); + additionalProperties.put("apiNamespace", apiPackage.replaceAll("\\.", "::")); + additionalProperties.put(RESERVED_WORD_PREFIX_OPTION, reservedWordPrefix); + + if (additionalProperties.containsKey(OPTIONAL_EXTERNAL_LIB)) { + setAddExternalLibs(convertPropertyToBooleanAndWriteBack(OPTIONAL_EXTERNAL_LIB)); + } else { + additionalProperties.put(OPTIONAL_EXTERNAL_LIB, isAddExternalLibs); + } + } + + @Override + public String toModelImport(String name) { + if (importMapping.containsKey(name)) { + return importMapping.get(name); + } else { + return "#include \"" + name + ".hpp\""; + } + } + + @Override + public CodegenModel fromModel(String name, Schema model) { + CodegenModel codegenModel = super.fromModel(name, model); + + Set oldImports = codegenModel.imports; + codegenModel.imports = new HashSet<>(); + for (String imp : oldImports) { + String newImp = toModelImport(imp); + if (!newImp.isEmpty()) { + codegenModel.imports.add(newImp); + } + } + + if (!codegenModel.isEnum + && codegenModel.anyOf.size() > 1 + && codegenModel.anyOf.contains("std::string") + && !codegenModel.anyOf.contains("AnyType") + && codegenModel.interfaces.size() == 1) { + codegenModel.vendorExtensions.put("x-is-string-enum-container", true); + } + return codegenModel; + } + + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List servers) { + CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers); + + if (operation.getResponses() != null && !operation.getResponses().isEmpty()) { + ApiResponse apiResponse = findMethodResponse(operation.getResponses()); + + if (apiResponse != null) { + Schema response = ModelUtils.getSchemaFromResponse(openAPI, apiResponse); + if (response != null) { + CodegenProperty cm = fromProperty("response", response, false); + op.vendorExtensions.put("x-codegen-response", cm); + if ("HttpContent".equals(cm.dataType)) { + op.vendorExtensions.put("x-codegen-response-ishttpcontent", true); + } + } + } + } + + String pathForOatpp = path.replaceAll("\\{(.*?)}", "{$1}"); + op.vendorExtensions.put("x-codegen-oatpp-path", pathForOatpp); + + return op; + } + + @Override + public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List allModels) { + OperationMap operations = objs.getOperations(); + String classname = operations.getClassname(); + operations.put("classnameSnakeUpperCase", underscore(classname).toUpperCase(Locale.ROOT)); + operations.put("classnameSnakeLowerCase", underscore(classname).toLowerCase(Locale.ROOT)); + List operationList = operations.getOperation(); + for (CodegenOperation op : operationList) { + postProcessSingleOperation(operations, op); + } + + return objs; + } + + private void postProcessSingleOperation(OperationMap operations, CodegenOperation op) { + if (op.vendorExtensions == null) { + op.vendorExtensions = new HashMap<>(); + } + + if (op.bodyParam != null) { + if (op.bodyParam.vendorExtensions == null) { + op.bodyParam.vendorExtensions = new HashMap<>(); + } + + boolean isStringOrDate = op.bodyParam.isString || op.bodyParam.isDate; + op.bodyParam.vendorExtensions.put("x-codegen-oatpp-is-string-or-date", isStringOrDate); + } + + boolean consumeJson = false; + if (op.consumes != null) { + Predicate> isMediaTypeJson = consume -> (consume.get("mediaType") != null + && consume.get("mediaType").equals("application/json")); + consumeJson = op.consumes.stream().anyMatch(isMediaTypeJson); + } + op.vendorExtensions.put("x-codegen-oatpp-consumes-json", consumeJson); + + // Check if any one of the operations needs a model, then at API file level, at + // least one model has to be included. + Predicate importNotInImportMapping = hdr -> !importMapping.containsKey(hdr); + if (op.imports.stream().anyMatch(importNotInImportMapping)) { + operations.put("hasModelImport", true); + } + } + + /** + * postProcessSingleParam - Modifies a single parameter, adjusting generated + * data types for Header and Query parameters. + * + * @param param CodegenParameter to be modified. + */ + private static void postProcessSingleParam(CodegenParameter param) { + if (param.isQueryParam) { + param.dataType = "std::optional<" + param.dataType + ">"; + if (!param.isPrimitiveType) { + param.baseType = "std::optional<" + param.baseType + ">"; + } + } + } + + @Override + public String toModelFilename(String name) { + return toModelName(name); + } + + @Override + public String apiFilename(String templateName, String tag) { + return super.apiFilename(templateName, tag); + } + + @Override + public String toApiFilename(String name) { + return toApiName(name); + } + + /** + * Optional - type declaration. This is a String which is used by the + * templates to instantiate your types. There is typically special handling + * for different property types + * + * @return a string value used as the `dataType` field for model templates, + * `returnType` for api templates + */ + @Override + public String getTypeDeclaration(Schema p) { + String openAPIType = getSchemaType(p); + + if (ModelUtils.isArraySchema(p)) { + ArraySchema ap = (ArraySchema) p; + Schema inner = ap.getItems(); + if (languageSpecificPrimitives.contains(getSchemaType(inner))) { + return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">"; + } + return getSchemaType(p) + ">"; + } + if (ModelUtils.isMapSchema(p)) { + Schema inner = ModelUtils.getAdditionalProperties(p); + return getSchemaType(p) + ""; + } else if (ModelUtils.isByteArraySchema(p)) { + return "std::string"; + } + if (ModelUtils.isStringSchema(p) + || ModelUtils.isDateSchema(p) + || ModelUtils.isDateTimeSchema(p) || ModelUtils.isFileSchema(p) + || languageSpecificPrimitives.contains(openAPIType)) { + return toModelName(openAPIType); + } + + String namespace = (String)additionalProperties.get("modelNamespace"); + return namespace + "::" + openAPIType; + } + + @Override + public String toDefaultValue(Schema p) { + if (ModelUtils.isStringSchema(p)) { + if (p.getDefault() != null) { + return "\"" + p.getDefault().toString() + "\""; + } else { + return "\"\""; + } + } else if (ModelUtils.isBooleanSchema(p)) { + if (p.getDefault() != null) { + return p.getDefault().toString(); + } else { + return "false"; + } + } else if (ModelUtils.isDateSchema(p)) { + if (p.getDefault() != null) { + return "\"" + p.getDefault().toString() + "\""; + } else { + return "\"\""; + } + } else if (ModelUtils.isDateTimeSchema(p)) { + if (p.getDefault() != null) { + return "\"" + p.getDefault().toString() + "\""; + } else { + return "\"\""; + } + } else if (ModelUtils.isNumberSchema(p)) { + if (ModelUtils.isFloatSchema(p)) { // float + if (p.getDefault() != null) { + // We have to ensure that our default value has a decimal point, + // because in C++ the 'f' suffix is not valid on integer literals + // i.e. 374.0f is a valid float but 374 isn't. + String defaultStr = p.getDefault().toString(); + if (defaultStr.indexOf('.') < 0) { + return defaultStr + ".0f"; + } else { + return defaultStr + "f"; + } + } else { + return "0.0f"; + } + } else { // double + if (p.getDefault() != null) { + return p.getDefault().toString(); + } else { + return "0.0"; + } + } + } else if (ModelUtils.isIntegerSchema(p)) { + if (ModelUtils.isLongSchema(p)) { // long + if (p.getDefault() != null) { + return p.getDefault().toString() + "L"; + } else { + return "0L"; + } + } else { // integer + if (p.getDefault() != null) { + return p.getDefault().toString(); + } else { + return "0"; + } + } + } else if (ModelUtils.isByteArraySchema(p)) { + if (p.getDefault() != null) { + return "\"" + p.getDefault().toString() + "\""; + } else { + return "\"\""; + } + } else if (ModelUtils.isMapSchema(p)) { + String inner = getSchemaType(ModelUtils.getAdditionalProperties(p)); + return "std::map()"; + } else if (ModelUtils.isArraySchema(p)) { + ArraySchema ap = (ArraySchema) p; + String inner = getSchemaType(ap.getItems()); + if (!languageSpecificPrimitives.contains(inner)) { + inner = "std::shared_ptr<" + inner + ">"; + } + return "std::vector<" + inner + ">()"; + } else if (!StringUtils.isEmpty(p.get$ref())) { + return "std::make_shared<" + toModelName(ModelUtils.getSimpleRef(p.get$ref())) + ">()"; + } + + return "nullptr"; + } + + /** + * Location to write model files. You can use the modelPackage() as defined + * when the class is instantiated + */ + @Override + public String modelFileFolder() { + return (outputFolder + "/model").replace("/", File.separator); + } + + /** + * Location to write api files. You can use the apiPackage() as defined when + * the class is instantiated + */ + @Override + public String apiFileFolder() { + return (outputFolder + "/api").replace("/", File.separator); + } + + /** + * Optional - OpenAPI type conversion. This is used to map OpenAPI types in + * a `Schema` into either language specific types via `typeMapping` or + * into complex models if there is not a mapping. + * + * @return a string value of the type or complex model for this property + */ + @Override + public String getSchemaType(Schema p) { + String openAPIType = super.getSchemaType(p); + String type = null; + if (typeMapping.containsKey(openAPIType)) { + type = typeMapping.get(openAPIType); + } else { + type = openAPIType; + } + return toModelName(type); + } + + @Override + public String getTypeDeclaration(String str) { + return toModelName(str); + } + + /** + * Specify whether external libraries will be added during the generation + * + * @param value the value to be set + */ + public void setAddExternalLibs(boolean value) { + isAddExternalLibs = value; + } +} diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 1d48c0c0d66c..7764b2ed5a0e 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -14,6 +14,7 @@ org.openapitools.codegen.languages.ClojureClientCodegen org.openapitools.codegen.languages.ConfluenceWikiCodegen org.openapitools.codegen.languages.CppQtClientCodegen org.openapitools.codegen.languages.CppQtQHttpEngineServerCodegen +org.openapitools.codegen.languages.CppOatppClientCodegen org.openapitools.codegen.languages.CppOatppServerCodegen org.openapitools.codegen.languages.CppPistacheServerCodegen org.openapitools.codegen.languages.CppRestbedServerCodegen diff --git a/modules/openapi-generator/src/main/resources/cpp-oatpp-client/README.mustache b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/README.mustache new file mode 100644 index 000000000000..801776da4f0b --- /dev/null +++ b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/README.mustache @@ -0,0 +1,39 @@ +# REST API Client for {{appName}} + +## Overview +This API Client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. +It uses the [Oat++](https://github.com/oatpp/oatpp) Framework. + +## Files organization +The Oat++ C++ REST client generator creates two folders: +- `api`: This folder contains the handlers for each method specified in the OpenAPI definition. Every handler extracts +the path and parameters (if any) from the request issue them against the server. +- `model`: This folder contains the corresponding class for every object schema found in the OpenAPI specification. + +The main folder contains also a file with a main that can be used to issue REST requests through the client. +Of course, is you should customize this file based on your needs + +## Installation +First of all, you need to download and install the libraries listed [here](#libraries-required). + +Once the libraries are installed, in order to compile and run the client please follow the steps below: +```bash +mkdir build +cd build +cmake .. +make +``` + +Once compiled run the client: + +```bash +cd build +./api-client +``` + +## Libraries required +- [Oat++](https://oatpp.io/) + +## Namespaces +{{{apiPackage}}} +{{{modelPackage}}} diff --git a/modules/openapi-generator/src/main/resources/cpp-oatpp-client/api-header.mustache b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/api-header.mustache new file mode 100644 index 000000000000..a9fde1523b43 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/api-header.mustache @@ -0,0 +1,50 @@ +{{>licenseInfo}} +{{#operations}}/* + * {{classname}}.h + * + * {{description}} + */ + +#ifndef {{classname}}_H_ +#define {{classname}}_H_ + +{{{defaultInclude}}} + +#include "oatpp/web/client/ApiClient.hpp" +#include "oatpp/web/protocol/http/outgoing/MultipartBody.hpp" +#include "oatpp/core/macro/codegen.hpp" + +{{#imports}}{{{import}}} +{{/imports}} + +#include OATPP_CODEGEN_BEGIN(ApiClient) ///< Begin code-gen section + +namespace {{apiNamespace}} +{ + +class {{classname}} : public oatpp::web::client::ApiClient { +public: + + API_CLIENT_INIT({{classname}}) + + {{#operation}} + /// + /// {{summary}} + /// + /// + /// {{notes}} + /// + {{#allParams}} + {{#isPathParam}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/isPathParam}}{{#isQueryParam}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/isQueryParam}}{{#isBodyParam}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/isBodyParam}}{{#isHeaderParam}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/isHeaderParam}}{{#isFormParam}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/isFormParam}} + {{/allParams}} + API_CALL("{{httpMethod}}", "{{{vendorExtensions.x-codegen-oatpp-path}}}", {{operationIdSnakeCase}}{{#allParams}}{{#isPathParam}}, PATH({{#isModel}}{{modelNamespace}}::{{/isModel}}{{&dataType}}, {{paramName}}){{/isPathParam}}{{#isQueryParam}}, QUERY({{#isModel}}{{modelNamespace}}::{{/isModel}}{{&dataType}}, {{paramName}}){{/isQueryParam}}{{#isBodyParam}}, BODY_DTO({{#isModel}}oatpp::Object<{{#isModel}}{{modelNamespace}}::{{/isModel}}{{{dataType}}}>{{/isModel}}{{^isModel}}{{#isModel}}{{modelNamespace}}::{{/isModel}}{{{dataType}}}{{/isModel}}, {{paramName}}){{/isBodyParam}}{{#isHeaderParam}}, HEADER({{{dataType}}}, {{paramName}}, "{{paramName}}"){{/isHeaderParam}}{{/allParams}}{{#hasFormParams}}, BODY(std::shared_ptr, formData){{/hasFormParams}}) + {{/operation}} +}; + +#include OATPP_CODEGEN_END(ApiClient) ///< End code-gen section + +} // namespace {{apiNamespace}} + +#endif /* {{classname}}_H_ */ + +{{/operations}} diff --git a/modules/openapi-generator/src/main/resources/cpp-oatpp-client/cmake.mustache b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/cmake.mustache new file mode 100644 index 000000000000..5346e8e9470d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/cmake.mustache @@ -0,0 +1,38 @@ +cmake_minimum_required (VERSION 3.2) + +project(api-client) + +{{#addExternalLibs}} +include(ExternalProject) + +set(EXTERNAL_INSTALL_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/external) + +ExternalProject_Add(OATPP + GIT_REPOSITORY https://github.com/oatpp/oatpp.git + BUILD_IN_SOURCE true + GIT_TAG 1.3.1 + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION} +) + +include_directories(${EXTERNAL_INSTALL_LOCATION}/include/oatpp-1.3.0/oatpp) +{{/addExternalLibs}} + +include_directories(model) +include_directories(api) +include_directories(impl) + +file(GLOB SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/impl/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp +) + +add_executable(${PROJECT_NAME} ${SRCS}) +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) + +{{#addExternalLibs}}add_dependencies(${PROJECT_NAME} OATPP) +if(WIN32) +target_link_libraries(${PROJECT_NAME} ${EXTERNAL_INSTALL_LOCATION}/lib/oatpp-1.3.0/oatpp.lib) +target_link_libraries(${PROJECT_NAME} ws2_32) +else() +target_link_libraries(${PROJECT_NAME} ${EXTERNAL_INSTALL_LOCATION}/lib/oatpp-1.3.0/liboatpp.a) +endif(WIN32){{/addExternalLibs}} diff --git a/modules/openapi-generator/src/main/resources/cpp-oatpp-client/licenseInfo.mustache b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/licenseInfo.mustache new file mode 100644 index 000000000000..8d5259173a1b --- /dev/null +++ b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/licenseInfo.mustache @@ -0,0 +1,11 @@ +/** +* {{{appName}}} +* {{{appDescription}}} +* +* {{#version}}The version of the OpenAPI document: {{{.}}}{{/version}} +* {{#infoEmail}}Contact: {{{.}}}{{/infoEmail}} +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/cpp-oatpp-client/main-api-client.mustache b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/main-api-client.mustache new file mode 100644 index 000000000000..a6504fed825c --- /dev/null +++ b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/main-api-client.mustache @@ -0,0 +1,38 @@ +{{>licenseInfo}} + +#include "oatpp/web/client/HttpRequestExecutor.hpp" +#include "oatpp/parser/json/mapping/ObjectMapper.hpp" +#include "oatpp/network/tcp/client/ConnectionProvider.hpp" + +{{#apiInfo}}{{#apis}}{{#operations}} +#include "{{classname}}.hpp"{{/operations}}{{/apis}}{{/apiInfo}} + +static int _main_app(void) { + /* create connection provider */ + auto connectionProvider = oatpp::network::tcp::client::ConnectionProvider::createShared({"localhost", {{serverPort}}{{^serverPort}}8080{{/serverPort}}, oatpp::network::Address::IP_4}); + + /* create HTTP request executor */ + auto requestExecutor = oatpp::web::client::HttpRequestExecutor::createShared(connectionProvider); + + /* create JSON object mapper */ + auto objectMapper = oatpp::parser::json::mapping::ObjectMapper::createShared(); + +{{#apiInfo}}{{#apis}}{{#operations}} + /* create API client */ + auto {{classname}}Client = {{apiNamespace}}::{{classname}}::createShared(requestExecutor, objectMapper); +{{/operations}}{{/apis}}{{/apiInfo}} + + return 0; +} + +int main(int argc, char **argv) { + /* Init oatpp Environment */ + oatpp::base::Environment::init(); + + int ret = _main_app(); + + /* Destroy oatpp Environment */ + oatpp::base::Environment::destroy(); + + return ret; +} diff --git a/modules/openapi-generator/src/main/resources/cpp-oatpp-client/model-header.mustache b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/model-header.mustache new file mode 100644 index 000000000000..322867688f3d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/cpp-oatpp-client/model-header.mustache @@ -0,0 +1,61 @@ +{{>licenseInfo}} +{{#models}}{{#model}}/* + * {{classname}}.h + * + * {{description}} + */ + +#ifndef {{classname}}_H_ +#define {{classname}}_H_ + +{{{defaultInclude}}} +{{#imports}}{{{this}}} +{{/imports}} +{{^isEnum}} +#include "oatpp/core/macro/codegen.hpp" +{{/isEnum}} +#include "oatpp/core/Types.hpp" + +namespace {{modelNamespace}} +{ + +{{^isEnum}} +/* Begin DTO code-generation */ +#include OATPP_CODEGEN_BEGIN(DTO) + +/** + * Message Data-Transfer-Object + */ +class {{classname}} : public oatpp::DTO { + + DTO_INIT({{classname}}, DTO /* Extends */) + + {{#vars}} + DTO_FIELD({{#isModel}}oatpp::Object<{{{dataType}}}>{{/isModel}}{{^isModel}}{{{dataType}}}{{/isModel}}, {{baseName}}); + {{^required}} + DTO_FIELD(oatpp::Boolean, {{baseName}}IsSet);{{/required}} + {{/vars}} + +}; + +/* End DTO code-generation */ +#include OATPP_CODEGEN_END(DTO) +{{/isEnum}} + +{{#isEnum}} +typedef {{dataType}} {{classname}}; +class {{classname}}Values { +public: +{{#allowableValues}} +{{#enumVars}} + static {{classname}} {{value}}(void) { return "{{value}}"; } +{{/enumVars}} +{{/allowableValues}} +}; +{{/isEnum}} + +} // namespace {{modelNamespace}} + +#endif /* {{classname}}_H_ */ +{{/model}} +{{/models}} diff --git a/modules/openapi-generator/src/test/resources/3_0/cpp-oatpp-client/petstore.yaml b/modules/openapi-generator/src/test/resources/3_0/cpp-oatpp-client/petstore.yaml new file mode 100644 index 000000000000..a8f9809a1249 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/cpp-oatpp-client/petstore.yaml @@ -0,0 +1,741 @@ +openapi: 3.0.0 +servers: + - url: 'http://petstore.swagger.io/v2' +info: + description: >- + This is a sample server Petstore server. For this sample, you can use the api key + `special-key` to test the authorization filters. + version: 1.0.0 + title: OpenAPI Petstore + license: + name: Apache-2.0 + url: 'https://www.apache.org/licenses/LICENSE-2.0.html' +tags: + - name: pet + description: Everything about your Pets + - name: store + description: Access to Petstore orders + - name: user + description: Operations about user +paths: + /pet: + post: + tags: + - pet + summary: Add a new pet to the store + description: '' + operationId: addPet + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + $ref: '#/components/requestBodies/Pet' + put: + tags: + - pet + summary: Update an existing pet + description: '' + operationId: updatePet + externalDocs: + url: "http://petstore.swagger.io/v2/doc/updatePet" + description: "API documentation for the updatePet operation" + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + '405': + description: Validation exception + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + $ref: '#/components/requestBodies/Pet' + /pet/findByStatus: + get: + tags: + - pet + summary: Finds Pets by status + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: true + style: form + explode: false + deprecated: true + schema: + type: array + items: + type: string + enum: + - available + - pending + - sold + default: available + responses: + '200': + description: successful operation + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid status value + security: + - petstore_auth: + - 'read:pets' + /pet/findByTags: + get: + tags: + - pet + summary: Finds Pets by tags + description: >- + Multiple tags can be provided with comma separated strings. Use tag1, + tag2, tag3 for testing. + operationId: findPetsByTags + parameters: + - name: tags + in: query + description: Tags to filter by + required: true + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: successful operation + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid tag value + security: + - petstore_auth: + - 'read:pets' + deprecated: true + '/pet/{petId}': + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + security: + - api_key: [] + post: + tags: + - pet + summary: Updates a pet in the store with form data + description: '' + operationId: updatePetWithForm + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: integer + format: int64 + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + delete: + tags: + - pet + summary: Deletes a pet + description: '' + operationId: deletePet + parameters: + - name: api_key + in: header + required: false + schema: + type: string + - name: petId + in: path + description: Pet id to delete + required: true + schema: + type: integer + format: int64 + responses: + '400': + description: Invalid pet value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + '/pet/{petId}/uploadImage': + post: + tags: + - pet + summary: uploads an image + description: '' + operationId: uploadFile + parameters: + - name: petId + in: path + description: ID of pet to update + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + additionalMetadata: + description: Additional data to pass to server + type: string + file: + description: file to upload + type: string + format: binary + /store/inventory: + get: + tags: + - store + summary: Returns pet inventories by status + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + additionalProperties: + type: integer + format: int32 + security: + - api_key: [] + /store/order: + post: + tags: + - store + summary: Place an order for a pet + description: '' + operationId: placeOrder + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid Order + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + description: order placed for purchasing the pet + required: true + '/store/order/{orderId}': + get: + tags: + - store + summary: Find purchase order by ID + description: >- + For valid response try integer IDs with value <= 5 or > 10. Other values + will generate exceptions + operationId: getOrderById + parameters: + - name: orderId + in: path + description: ID of pet that needs to be fetched + required: true + schema: + type: integer + format: int64 + minimum: 1 + maximum: 5 + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid ID supplied + '404': + description: Order not found + delete: + tags: + - store + summary: Delete purchase order by ID + description: >- + For valid response try integer IDs with value < 1000. Anything above + 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - name: orderId + in: path + description: ID of the order that needs to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid ID supplied + '404': + description: Order not found + /user: + post: + tags: + - user + summary: Create user + description: This can only be done by the logged in user. + operationId: createUser + responses: + default: + description: successful operation + security: + - api_key: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Created user object + required: true + /user/createWithArray: + post: + tags: + - user + summary: Creates list of users with given input array + description: '' + operationId: createUsersWithArrayInput + responses: + default: + description: successful operation + security: + - api_key: [] + requestBody: + $ref: '#/components/requestBodies/UserArray' + /user/createWithList: + post: + tags: + - user + summary: Creates list of users with given input array + description: '' + operationId: createUsersWithListInput + responses: + default: + description: successful operation + security: + - api_key: [] + requestBody: + $ref: '#/components/requestBodies/UserArray' + /user/login: + get: + tags: + - user + summary: Logs user into the system + description: '' + operationId: loginUser + parameters: + - name: username + in: query + description: The user name for login + required: true + schema: + type: string + pattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$' + - name: password + in: query + description: The password for login in clear text + required: true + schema: + type: string + responses: + '200': + description: successful operation + headers: + Set-Cookie: + description: >- + Cookie authentication key for use with the `api_key` + apiKey authentication. + schema: + type: string + example: AUTH_KEY=abcde12345; Path=/; HttpOnly + X-Rate-Limit: + description: calls per hour allowed by the user + schema: + type: integer + format: int32 + X-Expires-After: + description: date in UTC when token expires + schema: + type: string + format: date-time + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + '400': + description: Invalid username/password supplied + /user/logout: + get: + tags: + - user + summary: Logs out current logged in user session + description: '' + operationId: logoutUser + responses: + default: + description: successful operation + security: + - api_key: [] + '/user/{username}': + get: + tags: + - user + summary: Get user by user name + description: '' + operationId: getUserByName + parameters: + - name: username + in: path + description: The name that needs to be fetched. Use user1 for testing. + required: true + schema: + type: string + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/User' + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Invalid username supplied + '404': + description: User not found + put: + tags: + - user + summary: Updated user + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - name: username + in: path + description: name that need to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid user supplied + '404': + description: User not found + security: + - api_key: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Updated user object + required: true + delete: + tags: + - user + summary: Delete user + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - name: username + in: path + description: The name that needs to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid username supplied + '404': + description: User not found + security: + - api_key: [] +externalDocs: + description: Find out more about Swagger + url: 'http://swagger.io' +components: + requestBodies: + UserArray: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + description: List of user object + required: true + Pet: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + description: Pet object that needs to be added to the store + required: true + securitySchemes: + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog' + scopes: + 'write:pets': modify pets in your account + 'read:pets': read your pets + api_key: + type: apiKey + name: api_key + in: header + schemas: + Order: + title: Pet Order + description: An order for a pets from the pet store + type: object + properties: + id: + type: integer + format: int64 + petId: + type: integer + format: int64 + quantity: + type: integer + format: int32 + shipDate: + type: string + format: date-time + status: + type: string + description: Order Status + enum: + - placed + - approved + - delivered + complete: + type: boolean + default: false + xml: + name: Order + Category: + title: Pet category + description: A category for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + pattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$' + xml: + name: Category + User: + title: a User + description: A User who is purchasing from the pet store + type: object + properties: + id: + type: integer + format: int64 + username: + type: string + firstName: + type: string + lastName: + type: string + email: + type: string + password: + type: string + phone: + type: string + userStatus: + type: integer + format: int32 + description: User Status + xml: + name: User + Tag: + title: Pet Tag + description: A tag for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: Tag + Pet: + title: a Pet + description: A pet for sale in the pet store + type: object + required: + - name + - photoUrls + properties: + id: + type: integer + format: int64 + category: + $ref: '#/components/schemas/Category' + name: + type: string + example: doggie + photoUrls: + type: array + xml: + name: photoUrl + wrapped: true + items: + type: string + tags: + type: array + xml: + name: tag + wrapped: true + items: + $ref: '#/components/schemas/Tag' + status: + type: string + description: pet status in the store + deprecated: true + enum: + - available + - pending + - sold + xml: + name: Pet + ApiResponse: + title: An uploaded response + description: Describes the result of uploading an image resource + type: object + properties: + code: + type: integer + format: int32 + type: + type: string + message: + type: string diff --git a/samples/client/petstore/cpp-oatpp/.openapi-generator-ignore b/samples/client/petstore/cpp-oatpp/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/client/petstore/cpp-oatpp/.openapi-generator/FILES b/samples/client/petstore/cpp-oatpp/.openapi-generator/FILES new file mode 100644 index 000000000000..9053625c3ff8 --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/.openapi-generator/FILES @@ -0,0 +1,12 @@ +CMakeLists.txt +README.md +api/PetApi.hpp +api/StoreApi.hpp +api/UserApi.hpp +main-api-client.cpp +model/ApiResponse.hpp +model/Category.hpp +model/Order.hpp +model/Pet.hpp +model/Tag.hpp +model/User.hpp diff --git a/samples/client/petstore/cpp-oatpp/.openapi-generator/VERSION b/samples/client/petstore/cpp-oatpp/.openapi-generator/VERSION new file mode 100644 index 000000000000..fc74d6ceba8e --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.15.0-SNAPSHOT diff --git a/samples/client/petstore/cpp-oatpp/CMakeLists.txt b/samples/client/petstore/cpp-oatpp/CMakeLists.txt new file mode 100644 index 000000000000..b4f622b85d20 --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required (VERSION 3.2) + +project(api-client) + +include(ExternalProject) + +set(EXTERNAL_INSTALL_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/external) + +ExternalProject_Add(OATPP + GIT_REPOSITORY https://github.com/oatpp/oatpp.git + BUILD_IN_SOURCE true + GIT_TAG 1.3.1 + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION} +) + +include_directories(${EXTERNAL_INSTALL_LOCATION}/include/oatpp-1.3.0/oatpp) + +include_directories(model) +include_directories(api) +include_directories(impl) + +file(GLOB SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/impl/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp +) + +add_executable(${PROJECT_NAME} ${SRCS}) +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) + +add_dependencies(${PROJECT_NAME} OATPP) +if(WIN32) +target_link_libraries(${PROJECT_NAME} ${EXTERNAL_INSTALL_LOCATION}/lib/oatpp-1.3.0/oatpp.lib) +target_link_libraries(${PROJECT_NAME} ws2_32) +else() +target_link_libraries(${PROJECT_NAME} ${EXTERNAL_INSTALL_LOCATION}/lib/oatpp-1.3.0/liboatpp.a) +endif(WIN32) diff --git a/samples/client/petstore/cpp-oatpp/README.md b/samples/client/petstore/cpp-oatpp/README.md new file mode 100644 index 000000000000..f59a250fa9ad --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/README.md @@ -0,0 +1,39 @@ +# REST API Client for OpenAPI Petstore + +## Overview +This API Client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. +It uses the [Oat++](https://github.com/oatpp/oatpp) Framework. + +## Files organization +The Oat++ C++ REST client generator creates two folders: +- `api`: This folder contains the handlers for each method specified in the OpenAPI definition. Every handler extracts +the path and parameters (if any) from the request issue them against the server. +- `model`: This folder contains the corresponding class for every object schema found in the OpenAPI specification. + +The main folder contains also a file with a main that can be used to issue REST requests through the client. +Of course, is you should customize this file based on your needs + +## Installation +First of all, you need to download and install the libraries listed [here](#libraries-required). + +Once the libraries are installed, in order to compile and run the client please follow the steps below: +```bash +mkdir build +cd build +cmake .. +make +``` + +Once compiled run the client: + +```bash +cd build +./api-client +``` + +## Libraries required +- [Oat++](https://oatpp.io/) + +## Namespaces +org.openapitools.client.api +org.openapitools.client.model diff --git a/samples/client/petstore/cpp-oatpp/api/PetApi.hpp b/samples/client/petstore/cpp-oatpp/api/PetApi.hpp new file mode 100644 index 000000000000..159d3e12af2c --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/api/PetApi.hpp @@ -0,0 +1,116 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +/* + * PetApi.h + * + * + */ + +#ifndef PetApi_H_ +#define PetApi_H_ + + + +#include "oatpp/web/client/ApiClient.hpp" +#include "oatpp/web/protocol/http/outgoing/MultipartBody.hpp" +#include "oatpp/core/macro/codegen.hpp" + +#include "ApiResponse.hpp" +#include "Pet.hpp" + +#include OATPP_CODEGEN_BEGIN(ApiClient) ///< Begin code-gen section + +namespace org::openapitools::client::api +{ + +class PetApi : public oatpp::web::client::ApiClient { +public: + + API_CLIENT_INIT(PetApi) + + /// + /// Add a new pet to the store + /// + /// + /// + /// + /// Pet object that needs to be added to the store + API_CALL("POST", "/pet", add_pet, BODY_DTO(oatpp::Object, pet)) + /// + /// Deletes a pet + /// + /// + /// + /// + /// Pet id to delete + /// (optional, default to "") + API_CALL("DELETE", "/pet/{petId}", delete_pet, PATH(oatpp::Int64, petId), HEADER(oatpp::String, apiKey, "apiKey")) + /// + /// Finds Pets by status + /// + /// + /// Multiple status values can be provided with comma separated strings + /// + /// Status values that need to be considered for filter + API_CALL("GET", "/pet/findByStatus", find_pets_by_status, QUERY(oatpp::Vector, status)) + /// + /// Finds Pets by tags + /// + /// + /// Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + /// + /// Tags to filter by + API_CALL("GET", "/pet/findByTags", find_pets_by_tags, QUERY(oatpp::Vector, tags)) + /// + /// Find pet by ID + /// + /// + /// Returns a single pet + /// + /// ID of pet to return + API_CALL("GET", "/pet/{petId}", get_pet_by_id, PATH(oatpp::Int64, petId)) + /// + /// Update an existing pet + /// + /// + /// + /// + /// Pet object that needs to be added to the store + API_CALL("PUT", "/pet", update_pet, BODY_DTO(oatpp::Object, pet)) + /// + /// Updates a pet in the store with form data + /// + /// + /// + /// + /// ID of pet that needs to be updated + /// Updated name of the pet (optional, default to "") + /// Updated status of the pet (optional, default to "") + API_CALL("POST", "/pet/{petId}", update_pet_with_form, PATH(oatpp::Int64, petId), BODY(std::shared_ptr, formData)) + /// + /// uploads an image + /// + /// + /// + /// + /// ID of pet to update + /// Additional data to pass to server (optional, default to "") + /// file to upload (optional, default to "") + API_CALL("POST", "/pet/{petId}/uploadImage", upload_file, PATH(oatpp::Int64, petId), BODY(std::shared_ptr, formData)) +}; + +#include OATPP_CODEGEN_END(ApiClient) ///< End code-gen section + +} // namespace org::openapitools::client::api + +#endif /* PetApi_H_ */ + diff --git a/samples/client/petstore/cpp-oatpp/api/StoreApi.hpp b/samples/client/petstore/cpp-oatpp/api/StoreApi.hpp new file mode 100644 index 000000000000..f48ec25ab0ab --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/api/StoreApi.hpp @@ -0,0 +1,77 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +/* + * StoreApi.h + * + * + */ + +#ifndef StoreApi_H_ +#define StoreApi_H_ + + + +#include "oatpp/web/client/ApiClient.hpp" +#include "oatpp/web/protocol/http/outgoing/MultipartBody.hpp" +#include "oatpp/core/macro/codegen.hpp" + +#include "Order.hpp" + +#include OATPP_CODEGEN_BEGIN(ApiClient) ///< Begin code-gen section + +namespace org::openapitools::client::api +{ + +class StoreApi : public oatpp::web::client::ApiClient { +public: + + API_CLIENT_INIT(StoreApi) + + /// + /// Delete purchase order by ID + /// + /// + /// For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + /// + /// ID of the order that needs to be deleted + API_CALL("DELETE", "/store/order/{orderId}", delete_order, PATH(oatpp::String, orderId)) + /// + /// Returns pet inventories by status + /// + /// + /// Returns a map of status codes to quantities + /// + API_CALL("GET", "/store/inventory", get_inventory) + /// + /// Find purchase order by ID + /// + /// + /// For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions + /// + /// ID of pet that needs to be fetched + API_CALL("GET", "/store/order/{orderId}", get_order_by_id, PATH(oatpp::Int64, orderId)) + /// + /// Place an order for a pet + /// + /// + /// + /// + /// order placed for purchasing the pet + API_CALL("POST", "/store/order", place_order, BODY_DTO(oatpp::Object, order)) +}; + +#include OATPP_CODEGEN_END(ApiClient) ///< End code-gen section + +} // namespace org::openapitools::client::api + +#endif /* StoreApi_H_ */ + diff --git a/samples/client/petstore/cpp-oatpp/api/UserApi.hpp b/samples/client/petstore/cpp-oatpp/api/UserApi.hpp new file mode 100644 index 000000000000..0a469f46d075 --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/api/UserApi.hpp @@ -0,0 +1,111 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +/* + * UserApi.h + * + * + */ + +#ifndef UserApi_H_ +#define UserApi_H_ + + + +#include "oatpp/web/client/ApiClient.hpp" +#include "oatpp/web/protocol/http/outgoing/MultipartBody.hpp" +#include "oatpp/core/macro/codegen.hpp" + +#include "User.hpp" + +#include OATPP_CODEGEN_BEGIN(ApiClient) ///< Begin code-gen section + +namespace org::openapitools::client::api +{ + +class UserApi : public oatpp::web::client::ApiClient { +public: + + API_CLIENT_INIT(UserApi) + + /// + /// Create user + /// + /// + /// This can only be done by the logged in user. + /// + /// Created user object + API_CALL("POST", "/user", create_user, BODY_DTO(oatpp::Object, user)) + /// + /// Creates list of users with given input array + /// + /// + /// + /// + /// List of user object + API_CALL("POST", "/user/createWithArray", create_users_with_array_input, BODY_DTO(oatpp::Vector>, user)) + /// + /// Creates list of users with given input array + /// + /// + /// + /// + /// List of user object + API_CALL("POST", "/user/createWithList", create_users_with_list_input, BODY_DTO(oatpp::Vector>, user)) + /// + /// Delete user + /// + /// + /// This can only be done by the logged in user. + /// + /// The name that needs to be deleted + API_CALL("DELETE", "/user/{username}", delete_user, PATH(oatpp::String, username)) + /// + /// Get user by user name + /// + /// + /// + /// + /// The name that needs to be fetched. Use user1 for testing. + API_CALL("GET", "/user/{username}", get_user_by_name, PATH(oatpp::String, username)) + /// + /// Logs user into the system + /// + /// + /// + /// + /// The user name for login + /// The password for login in clear text + API_CALL("GET", "/user/login", login_user, QUERY(oatpp::String, username), QUERY(oatpp::String, password)) + /// + /// Logs out current logged in user session + /// + /// + /// + /// + API_CALL("GET", "/user/logout", logout_user) + /// + /// Updated user + /// + /// + /// This can only be done by the logged in user. + /// + /// name that need to be deleted + /// Updated user object + API_CALL("PUT", "/user/{username}", update_user, PATH(oatpp::String, username), BODY_DTO(oatpp::Object, user)) +}; + +#include OATPP_CODEGEN_END(ApiClient) ///< End code-gen section + +} // namespace org::openapitools::client::api + +#endif /* UserApi_H_ */ + diff --git a/samples/client/petstore/cpp-oatpp/main-api-client.cpp b/samples/client/petstore/cpp-oatpp/main-api-client.cpp new file mode 100644 index 000000000000..d49b5ada062a --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/main-api-client.cpp @@ -0,0 +1,56 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ + +#include "oatpp/web/client/HttpRequestExecutor.hpp" +#include "oatpp/parser/json/mapping/ObjectMapper.hpp" +#include "oatpp/network/tcp/client/ConnectionProvider.hpp" + + +#include "PetApi.hpp" +#include "StoreApi.hpp" +#include "UserApi.hpp" + +static int _main_app(void) { + /* create connection provider */ + auto connectionProvider = oatpp::network::tcp::client::ConnectionProvider::createShared({"localhost", 8080, oatpp::network::Address::IP_4}); + + /* create HTTP request executor */ + auto requestExecutor = oatpp::web::client::HttpRequestExecutor::createShared(connectionProvider); + + /* create JSON object mapper */ + auto objectMapper = oatpp::parser::json::mapping::ObjectMapper::createShared(); + + + /* create API client */ + auto PetApiClient = org::openapitools::client::api::PetApi::createShared(requestExecutor, objectMapper); + + /* create API client */ + auto StoreApiClient = org::openapitools::client::api::StoreApi::createShared(requestExecutor, objectMapper); + + /* create API client */ + auto UserApiClient = org::openapitools::client::api::UserApi::createShared(requestExecutor, objectMapper); + + + return 0; +} + +int main(int argc, char **argv) { + /* Init oatpp Environment */ + oatpp::base::Environment::init(); + + int ret = _main_app(); + + /* Destroy oatpp Environment */ + oatpp::base::Environment::destroy(); + + return ret; +} diff --git a/samples/client/petstore/cpp-oatpp/model/ApiResponse.hpp b/samples/client/petstore/cpp-oatpp/model/ApiResponse.hpp new file mode 100644 index 000000000000..284c8eae3ca7 --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/model/ApiResponse.hpp @@ -0,0 +1,53 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +/* + * ApiResponse.h + * + * Describes the result of uploading an image resource + */ + +#ifndef ApiResponse_H_ +#define ApiResponse_H_ + + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/Types.hpp" + +namespace org::openapitools::client::model +{ + +/* Begin DTO code-generation */ +#include OATPP_CODEGEN_BEGIN(DTO) + +/** + * Message Data-Transfer-Object + */ +class ApiResponse : public oatpp::DTO { + + DTO_INIT(ApiResponse, DTO /* Extends */) + + DTO_FIELD(oatpp::Int32, code); + DTO_FIELD(oatpp::Boolean, codeIsSet); + DTO_FIELD(oatpp::String, type); + DTO_FIELD(oatpp::Boolean, typeIsSet); + DTO_FIELD(oatpp::String, message); + DTO_FIELD(oatpp::Boolean, messageIsSet); + +}; + +/* End DTO code-generation */ +#include OATPP_CODEGEN_END(DTO) + + +} // namespace org::openapitools::client::model + +#endif /* ApiResponse_H_ */ diff --git a/samples/client/petstore/cpp-oatpp/model/Category.hpp b/samples/client/petstore/cpp-oatpp/model/Category.hpp new file mode 100644 index 000000000000..6ab21e5221c4 --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/model/Category.hpp @@ -0,0 +1,51 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +/* + * Category.h + * + * A category for a pet + */ + +#ifndef Category_H_ +#define Category_H_ + + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/Types.hpp" + +namespace org::openapitools::client::model +{ + +/* Begin DTO code-generation */ +#include OATPP_CODEGEN_BEGIN(DTO) + +/** + * Message Data-Transfer-Object + */ +class Category : public oatpp::DTO { + + DTO_INIT(Category, DTO /* Extends */) + + DTO_FIELD(oatpp::Int64, id); + DTO_FIELD(oatpp::Boolean, idIsSet); + DTO_FIELD(oatpp::String, name); + DTO_FIELD(oatpp::Boolean, nameIsSet); + +}; + +/* End DTO code-generation */ +#include OATPP_CODEGEN_END(DTO) + + +} // namespace org::openapitools::client::model + +#endif /* Category_H_ */ diff --git a/samples/client/petstore/cpp-oatpp/model/Order.hpp b/samples/client/petstore/cpp-oatpp/model/Order.hpp new file mode 100644 index 000000000000..27e133bc9453 --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/model/Order.hpp @@ -0,0 +1,59 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +/* + * Order.h + * + * An order for a pets from the pet store + */ + +#ifndef Order_H_ +#define Order_H_ + + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/Types.hpp" + +namespace org::openapitools::client::model +{ + +/* Begin DTO code-generation */ +#include OATPP_CODEGEN_BEGIN(DTO) + +/** + * Message Data-Transfer-Object + */ +class Order : public oatpp::DTO { + + DTO_INIT(Order, DTO /* Extends */) + + DTO_FIELD(oatpp::Int64, id); + DTO_FIELD(oatpp::Boolean, idIsSet); + DTO_FIELD(oatpp::Int64, petId); + DTO_FIELD(oatpp::Boolean, petIdIsSet); + DTO_FIELD(oatpp::Int32, quantity); + DTO_FIELD(oatpp::Boolean, quantityIsSet); + DTO_FIELD(oatpp::String, shipDate); + DTO_FIELD(oatpp::Boolean, shipDateIsSet); + DTO_FIELD(oatpp::String, status); + DTO_FIELD(oatpp::Boolean, statusIsSet); + DTO_FIELD(oatpp::Boolean, complete); + DTO_FIELD(oatpp::Boolean, completeIsSet); + +}; + +/* End DTO code-generation */ +#include OATPP_CODEGEN_END(DTO) + + +} // namespace org::openapitools::client::model + +#endif /* Order_H_ */ diff --git a/samples/client/petstore/cpp-oatpp/model/Pet.hpp b/samples/client/petstore/cpp-oatpp/model/Pet.hpp new file mode 100644 index 000000000000..9d483308a474 --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/model/Pet.hpp @@ -0,0 +1,61 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +/* + * Pet.h + * + * A pet for sale in the pet store + */ + +#ifndef Pet_H_ +#define Pet_H_ + + +#include "Category.hpp" +#include "Tag.hpp" +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/Types.hpp" + +namespace org::openapitools::client::model +{ + +/* Begin DTO code-generation */ +#include OATPP_CODEGEN_BEGIN(DTO) + +/** + * Message Data-Transfer-Object + */ +class Pet : public oatpp::DTO { + + DTO_INIT(Pet, DTO /* Extends */) + + DTO_FIELD(oatpp::Int64, id); + DTO_FIELD(oatpp::Boolean, idIsSet); + DTO_FIELD(oatpp::Object, category); + DTO_FIELD(oatpp::Boolean, categoryIsSet); + DTO_FIELD(oatpp::String, name); + + DTO_FIELD(oatpp::Vector, photoUrls); + + DTO_FIELD(oatpp::Vector>, tags); + DTO_FIELD(oatpp::Boolean, tagsIsSet); + DTO_FIELD(oatpp::String, status); + DTO_FIELD(oatpp::Boolean, statusIsSet); + +}; + +/* End DTO code-generation */ +#include OATPP_CODEGEN_END(DTO) + + +} // namespace org::openapitools::client::model + +#endif /* Pet_H_ */ diff --git a/samples/client/petstore/cpp-oatpp/model/Tag.hpp b/samples/client/petstore/cpp-oatpp/model/Tag.hpp new file mode 100644 index 000000000000..befd6854d51e --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/model/Tag.hpp @@ -0,0 +1,51 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +/* + * Tag.h + * + * A tag for a pet + */ + +#ifndef Tag_H_ +#define Tag_H_ + + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/Types.hpp" + +namespace org::openapitools::client::model +{ + +/* Begin DTO code-generation */ +#include OATPP_CODEGEN_BEGIN(DTO) + +/** + * Message Data-Transfer-Object + */ +class Tag : public oatpp::DTO { + + DTO_INIT(Tag, DTO /* Extends */) + + DTO_FIELD(oatpp::Int64, id); + DTO_FIELD(oatpp::Boolean, idIsSet); + DTO_FIELD(oatpp::String, name); + DTO_FIELD(oatpp::Boolean, nameIsSet); + +}; + +/* End DTO code-generation */ +#include OATPP_CODEGEN_END(DTO) + + +} // namespace org::openapitools::client::model + +#endif /* Tag_H_ */ diff --git a/samples/client/petstore/cpp-oatpp/model/User.hpp b/samples/client/petstore/cpp-oatpp/model/User.hpp new file mode 100644 index 000000000000..b60150cf0b48 --- /dev/null +++ b/samples/client/petstore/cpp-oatpp/model/User.hpp @@ -0,0 +1,63 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +/* + * User.h + * + * A User who is purchasing from the pet store + */ + +#ifndef User_H_ +#define User_H_ + + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/Types.hpp" + +namespace org::openapitools::client::model +{ + +/* Begin DTO code-generation */ +#include OATPP_CODEGEN_BEGIN(DTO) + +/** + * Message Data-Transfer-Object + */ +class User : public oatpp::DTO { + + DTO_INIT(User, DTO /* Extends */) + + DTO_FIELD(oatpp::Int64, id); + DTO_FIELD(oatpp::Boolean, idIsSet); + DTO_FIELD(oatpp::String, username); + DTO_FIELD(oatpp::Boolean, usernameIsSet); + DTO_FIELD(oatpp::String, firstName); + DTO_FIELD(oatpp::Boolean, firstNameIsSet); + DTO_FIELD(oatpp::String, lastName); + DTO_FIELD(oatpp::Boolean, lastNameIsSet); + DTO_FIELD(oatpp::String, email); + DTO_FIELD(oatpp::Boolean, emailIsSet); + DTO_FIELD(oatpp::String, password); + DTO_FIELD(oatpp::Boolean, passwordIsSet); + DTO_FIELD(oatpp::String, phone); + DTO_FIELD(oatpp::Boolean, phoneIsSet); + DTO_FIELD(oatpp::Int32, userStatus); + DTO_FIELD(oatpp::Boolean, userStatusIsSet); + +}; + +/* End DTO code-generation */ +#include OATPP_CODEGEN_END(DTO) + + +} // namespace org::openapitools::client::model + +#endif /* User_H_ */ diff --git a/website/i18n/en.json b/website/i18n/en.json index 9f06b9b90e6f..f032b40060bf 100644 --- a/website/i18n/en.json +++ b/website/i18n/en.json @@ -87,6 +87,10 @@ "title": "Config Options for clojure", "sidebar_label": "clojure" }, + "generators/cpp-oatpp-client": { + "title": "Config Options for cpp-oatpp-client", + "sidebar_label": "cpp-oatpp-client" + }, "generators/cpp-oatpp-server": { "title": "Config Options for cpp-oatpp-server", "sidebar_label": "cpp-oatpp-server" From 67391a68bc963179285cbf694e5db61acb77d6d9 Mon Sep 17 00:00:00 2001 From: Kraust Date: Wed, 6 Aug 2025 19:13:07 -0400 Subject: [PATCH 2/5] Updated pipelines. --- .../workflows/samples-cpp-oatpp-client.yaml | 30 +++++++++++++++++++ .../workflows/samples-cpp-oatpp-server.yaml | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/samples-cpp-oatpp-client.yaml diff --git a/.github/workflows/samples-cpp-oatpp-client.yaml b/.github/workflows/samples-cpp-oatpp-client.yaml new file mode 100644 index 000000000000..4d133eb891e7 --- /dev/null +++ b/.github/workflows/samples-cpp-oatpp-client.yaml @@ -0,0 +1,30 @@ +name: Samples cpp oat++ client + +on: + push: + branches: + - "samples/client/petstore/cpp-oatpp/**" + pull_request: + paths: + - "samples/client/petstore/cpp-oatpp/**" + +env: + GRADLE_VERSION: 6.9 + +jobs: + build: + name: Build cpp oat++ client + strategy: + matrix: + sample: + - samples/client/petstore/cpp-oatpp + os: + - ubuntu-latest + - macOS-latest + - windows-latest + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - name: Build + working-directory: ${{ matrix.sample }} + run: cmake -B build && cmake --build build --verbose diff --git a/.github/workflows/samples-cpp-oatpp-server.yaml b/.github/workflows/samples-cpp-oatpp-server.yaml index 12ad210e5879..37ff5c81d66d 100644 --- a/.github/workflows/samples-cpp-oatpp-server.yaml +++ b/.github/workflows/samples-cpp-oatpp-server.yaml @@ -13,7 +13,7 @@ env: jobs: build: - name: Build cpp qt client + name: Build cpp oat++ server strategy: matrix: sample: From 80718ed4a83880b1d57d48390fd2bde40e6926fb Mon Sep 17 00:00:00 2001 From: Kraust Date: Wed, 6 Aug 2025 19:16:10 -0400 Subject: [PATCH 3/5] Should match formatting now. --- .../languages/CppOatppClientCodegen.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppOatppClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppOatppClientCodegen.java index 34dbdbef8d32..eec28ac05de1 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppOatppClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppOatppClientCodegen.java @@ -102,16 +102,16 @@ public CppOatppClientCodegen() { languageSpecificPrimitives = new HashSet<>( Arrays.asList( - "oatpp::String", - "oatpp::Boolean", - "oatpp::Int32", - "oatpp::Int64", - "oatpp::Vector", - "oatpp::Fields", - "oatpp::UnorderedSet", - "oatpp::Object", - "oatpp::Float64", - "oatpp::Any" + "oatpp::String", + "oatpp::Boolean", + "oatpp::Int32", + "oatpp::Int64", + "oatpp::Vector", + "oatpp::Fields", + "oatpp::UnorderedSet", + "oatpp::Object", + "oatpp::Float64", + "oatpp::Any" )); typeMapping = new HashMap<>(); @@ -332,7 +332,7 @@ public String getTypeDeclaration(Schema p) { return toModelName(openAPIType); } - String namespace = (String)additionalProperties.get("modelNamespace"); + String namespace = (String) additionalProperties.get("modelNamespace"); return namespace + "::" + openAPIType; } From 8e68d5dd39f14e303d0728cfaafac2094881a9f7 Mon Sep 17 00:00:00 2001 From: Kraust Date: Wed, 6 Aug 2025 19:17:54 -0400 Subject: [PATCH 4/5] Moved includes around. --- .../META-INF/services/org.openapitools.codegen.CodegenConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 7764b2ed5a0e..fe481e526af1 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -12,9 +12,9 @@ org.openapitools.codegen.languages.CrystalClientCodegen org.openapitools.codegen.languages.CLibcurlClientCodegen org.openapitools.codegen.languages.ClojureClientCodegen org.openapitools.codegen.languages.ConfluenceWikiCodegen +org.openapitools.codegen.languages.CppOatppClientCodegen org.openapitools.codegen.languages.CppQtClientCodegen org.openapitools.codegen.languages.CppQtQHttpEngineServerCodegen -org.openapitools.codegen.languages.CppOatppClientCodegen org.openapitools.codegen.languages.CppOatppServerCodegen org.openapitools.codegen.languages.CppPistacheServerCodegen org.openapitools.codegen.languages.CppRestbedServerCodegen From cd5933868e460d88993d8071a7adc105dfd7ed93 Mon Sep 17 00:00:00 2001 From: Kraust Date: Wed, 6 Aug 2025 19:23:17 -0400 Subject: [PATCH 5/5] Ran doc generator. --- docs/generators/cpp-oatpp-client.md | 64 ++++++++++++----------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/docs/generators/cpp-oatpp-client.md b/docs/generators/cpp-oatpp-client.md index 370d816f12d8..343f01645ead 100644 --- a/docs/generators/cpp-oatpp-client.md +++ b/docs/generators/cpp-oatpp-client.md @@ -11,35 +11,21 @@ title: Documentation for the cpp-oatpp-client Generator | generator type | CLIENT | | | generator language | C++ | | | generator default templating engine | mustache | | -| helpTxt | Generates a C++ client library (based on oat++). | | +| helpTxt | Generates a C++ API client (based on Oat++) | | ## CONFIG OPTIONS These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details. | Option | Description | Values | Default | | ------ | ----------- | ------ | ------- | -|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false| -|contentCompression|Enable Compressed Content Encoding for requests and responses| |false| -|cppNamespace|C++ namespace (convention: name::space::for::api).| |OpenAPI| -|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|
**false**
The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.
**true**
Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.
|true| -|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true| -|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|
**false**
No changes to the enum's are made, this is the default option.
**true**
With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.
|false| -|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|
**true**
The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.
**false**
The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.
|true| -|modelNamePrefix|Prefix that will be prepended to all model names.| |OAI| -|optionalProjectFile|Generate client.pri.| |true| -|packageName|C++ package (library) name.| |QtOpenAPIClient| -|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| +|addExternalLibs|Add the Possibility to fetch and compile external Libraries needed by this Framework.| |true| |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| -|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| -|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING | Type/Alias | Imports | | ---------- | ------- | -|OAIHttpFileElement|#include "OAIHttpFileElement.h"| -|QJsonValue|#include <QJsonValue>| ## INSTANTIATION TYPES @@ -51,20 +37,22 @@ These options may be applied as additional-properties (cli) or configOptions (pl ## LANGUAGE PRIMITIVES
    -
  • QByteArray
  • -
  • QDate
  • -
  • QDateTime
  • -
  • QString
  • -
  • bool
  • -
  • double
  • -
  • float
  • -
  • qint32
  • -
  • qint64
  • +
  • oatpp::Any
  • +
  • oatpp::Boolean
  • +
  • oatpp::Fields
  • +
  • oatpp::Float64
  • +
  • oatpp::Int32
  • +
  • oatpp::Int64
  • +
  • oatpp::Object
  • +
  • oatpp::String
  • +
  • oatpp::UnorderedSet
  • +
  • oatpp::Vector
## RESERVED WORDS
    +
  • NULL
  • alignas
  • alignof
  • and
  • @@ -222,9 +210,9 @@ These options may be applied as additional-properties (cli) or configOptions (pl |ExternalDocumentation|✓|OAS2,OAS3 |Examples|✓|OAS2,OAS3 |XMLStructureDefinitions|✗|OAS2,OAS3 -|MultiServer|✓|OAS3 -|ParameterizedServer|✓|OAS3 -|ParameterStyling|✓|OAS3 +|MultiServer|✗|OAS3 +|ParameterizedServer|✗|OAS3 +|ParameterStyling|✗|OAS3 |Callbacks|✗|OAS3 |LinkObjects|✗|OAS3 @@ -237,14 +225,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl |Body|✓|OAS2 |FormUnencoded|✓|OAS2 |FormMultipart|✓|OAS2 -|Cookie|✓|OAS3 +|Cookie|✗|OAS3 ### Schema Support Feature | Name | Supported | Defined By | | ---- | --------- | ---------- | |Simple|✓|OAS2,OAS3 |Composite|✓|OAS2,OAS3 -|Polymorphism|✓|OAS2,OAS3 +|Polymorphism|✗|OAS2,OAS3 |Union|✗|OAS3 |allOf|✗|OAS2,OAS3 |anyOf|✗|OAS3 @@ -254,14 +242,16 @@ These options may be applied as additional-properties (cli) or configOptions (pl ### Security Feature | Name | Supported | Defined By | | ---- | --------- | ---------- | -|BasicAuth|✓|OAS2,OAS3 -|ApiKey|✓|OAS2,OAS3 +|BasicAuth|✗|OAS2,OAS3 +|ApiKey|✗|OAS2,OAS3 |OpenIDConnect|✗|OAS3 -|BearerToken|✓|OAS3 -|OAuth2_Implicit|✓|OAS2,OAS3 -|OAuth2_Password|✓|OAS2,OAS3 -|OAuth2_ClientCredentials|✓|OAS2,OAS3 -|OAuth2_AuthorizationCode|✓|OAS2,OAS3 +|BearerToken|✗|OAS3 +|OAuth2_Implicit|✗|OAS2,OAS3 +|OAuth2_Password|✗|OAS2,OAS3 +|OAuth2_ClientCredentials|✗|OAS2,OAS3 +|OAuth2_AuthorizationCode|✗|OAS2,OAS3 +|SignatureAuth|✗|OAS3 +|AWSV4Signature|✗|ToolingExtension ### Wire Format Feature | Name | Supported | Defined By |