Compare commits

..

2 Commits

Author SHA1 Message Date
William Cheng
13f04829c7 update tests 2023-12-15 10:36:36 +08:00
William Cheng
7184c2a689 remove reserved word check in lambda 2023-12-15 09:31:04 +08:00
627 changed files with 1796 additions and 39672 deletions

View File

@@ -37,7 +37,6 @@ jobs:
- samples/client/petstore/kotlin-okhttp3
- samples/client/petstore/kotlin-retrofit2
- samples/client/petstore/kotlin-retrofit2-kotlinx_serialization
- samples/client/petstore/kotlin-retrofit2-jackson
- samples/client/petstore/kotlin-retrofit2-rx3
- samples/client/petstore/kotlin-string
- samples/client/petstore/kotlin-threetenbp

View File

@@ -1,32 +0,0 @@
name: Samples Postman
on:
pull_request:
paths:
- samples/schema/postman-collection/python/**
- .github/workflows/samples-postman.yaml
jobs:
build:
name: Test Python client
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sample:
# schema
- samples/schema/postman-collection
python-version:
- "3.11"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install
working-directory: ${{ matrix.sample }}
run: |
pip install -r python/requirements.txt
pip install -r python/test-requirements.txt
- name: Test
working-directory: ${{ matrix.sample }}
run: python -m pytest

View File

@@ -22,7 +22,6 @@ jobs:
# clients
- 'samples/client/petstore/java/okhttp-gson'
- samples/client/petstore/scalaz
- samples/client/petstore/scala-pekko
#- samples/client/petstore/scala-sttp # won't pass while the same tests in circleci pass
# servers
- samples/server/petstore/scala-lagom-server

View File

@@ -3,11 +3,11 @@
<extension>
<groupId>com.gradle</groupId>
<artifactId>gradle-enterprise-maven-extension</artifactId>
<version>1.20</version>
<version>1.17</version>
</extension>
<extension>
<groupId>com.gradle</groupId>
<artifactId>common-custom-user-data-maven-extension</artifactId>
<version>1.12.5</version>
<version>1.11.1</version>
</extension>
</extensions>

View File

@@ -46,8 +46,7 @@
</credentials>
</server>
<enabled>true</enabled> <!-- must be true for this experiment -->
<!-- Check credentials presence to avoid build cache errors on PR builds when credentials are not present -->
<storeEnabled>#{isTrue(env['CI']) and isTrue(env['GRADLE_ENTERPRISE_CACHE_USERNAME']) and isTrue(env['GRADLE_ENTERPRISE_CACHE_PASSWORD'])}</storeEnabled>
<storeEnabled>#{env['CI'] != null}</storeEnabled> <!-- adjust to an env var that is always present only in your CI environment -->
</remote>
</buildCache>
</gradleEnterprise>

View File

@@ -78,7 +78,7 @@ OpenAPI Generator allows generation of API client libraries (SDK generation), se
| | Languages/Frameworks |
| -------------------------------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.1, .NET Core 3.1, .NET 5.0. Libraries: RestSharp, GenericHost, HttpClient), **C++** (Arduino, cpp-restsdk, Qt5, Tizen, Unreal Engine 4), **Clojure**, **Crystal**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Apache HttpClient 4.x, Apache HttpClient 5.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured, Spring 5 Web Client, MicroProfile Rest Client, Helidon), **Jetbrains HTTP Client**, **Julia**, **k6**, **Kotlin**, **Lua**, **N4JS**, **Nim**, **Node.js/JavaScript** (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types, Apollo GraphQL DataStore), **Objective-C**, **OCaml**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (hyper, reqwest, rust-server), **Scala** (akka, http4s, scalaz, sttp, swagger-async-httpclient, pekko), **Swift** (2.x, 3.x, 4.x, 5.x), **Typescript** (AngularJS, Angular (9.x - 16.x), Aurelia, Axios, Fetch, Inversify, jQuery, Nestjs, Node, redux-query, Rxjs), **XoJo**, **Zapier** |
| **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.1, .NET Core 3.1, .NET 5.0. Libraries: RestSharp, GenericHost, HttpClient), **C++** (Arduino, cpp-restsdk, Qt5, Tizen, Unreal Engine 4), **Clojure**, **Crystal**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Apache HttpClient 4.x, Apache HttpClient 5.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured, Spring 5 Web Client, MicroProfile Rest Client, Helidon), **Jetbrains HTTP Client**, **Julia**, **k6**, **Kotlin**, **Lua**, **N4JS**, **Nim**, **Node.js/JavaScript** (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types, Apollo GraphQL DataStore), **Objective-C**, **OCaml**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (hyper, reqwest, rust-server), **Scala** (akka, http4s, scalaz, sttp, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x, 5.x), **Typescript** (AngularJS, Angular (9.x - 16.x), Aurelia, Axios, Fetch, Inversify, jQuery, Nestjs, Node, redux-query, Rxjs), **XoJo**, **Zapier** |
| **Server stubs** | **Ada**, **C#** (ASP.NET Core, Azure Functions), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin, Echo), **Haskell** (Servant, Yesod), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, Jersey, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples), [Vert.x](https://vertx.io/), [Apache Camel](https://camel.apache.org/), [Helidon](https://helidon.io/)), **Julia**, **Kotlin** (Spring Boot, [Ktor](https://github.com/ktorio/ktor), [Vert.x](https://vertx.io/)), **PHP** (Laravel, Lumen, [Mezzio (fka Zend Expressive)](https://github.com/mezzio/mezzio), Slim, Silex, [Symfony](https://symfony.com/)), **Python** (FastAPI, Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** ([rust-server](https://openapi-generator.tech/docs/generators/rust-server/)), **Scala** (Akka, [Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra) |
| **API documentation generators** | **HTML**, **Confluence Wiki**, **Asciidoc**, **Markdown**, **PlantUML** |
| **Configuration files** | [**Apache2**](https://httpd.apache.org/) |
@@ -621,7 +621,6 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
- [codecentric AG](https://www.codecentric.de/)
- [CoinAPI](https://www.coinapi.io/)
- [Commencis](https://www.commencis.com/)
- [cronn GmbH](https://www.cronn.de/)
- [Crossover Health](https://crossoverhealth.com/)
- [Cupix](https://www.cupix.com/)
- [Datadog](https://www.datadoghq.com)
@@ -1019,7 +1018,6 @@ Here is a list of template creators:
* Scala (Akka): @cchafer
* Scala (sttp): @chameleon82
* Scala (sttp4): @flsh86
* Scala (Pekko): @mickaelmagniez
* Swift: @tkqubo
* Swift 3: @hexelon
* Swift 4: @ehyche

View File

@@ -1,8 +0,0 @@
generatorName: java
outputDir: samples/client/petstore/java/resteasy-echo
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-echo.yaml
templateDir: modules/openapi-generator/src/main/resources/Java
additionalProperties:
artifactId: petstore-resteasy-echo
hideGenerationTimestamp: "true"
library: resteasy

View File

@@ -1,10 +0,0 @@
generatorName: kotlin
outputDir: samples/client/petstore/kotlin-retrofit2-jackson
library: jvm-retrofit2
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-client
additionalProperties:
serializationLibrary: jackson
artifactId: kotlin-petstore-retrofit2-jackson
enumPropertyNaming: UPPERCASE
serializableModel: "true"

View File

@@ -1,6 +0,0 @@
generatorName: scala-pekko
outputDir: samples/client/petstore/scala-pekko
inputSpec: modules/openapi-generator/src/test/resources/3_0/scala-pekko/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/scala-pekko-client
additionalProperties:
artifactId: scala-pekko-petstore-client

View File

@@ -59,7 +59,6 @@ The following generators are available:
* [rust](generators/rust.md)
* [scala-akka](generators/scala-akka.md)
* [scala-gatling](generators/scala-gatling.md)
* [scala-pekko](generators/scala-pekko.md)
* [scala-sttp](generators/scala-sttp.md)
* [scala-sttp4 (beta)](generators/scala-sttp4.md)
* [scalaz](generators/scalaz.md)

View File

@@ -45,7 +45,6 @@ The following generators are available:
* [ruby](ruby.md)
* [rust](rust.md)
* [scala-akka](scala-akka.md)
* [scala-pekko](scala-pekko.md)
* [scala-gatling](scala-gatling.md)
* [scalaz](scalaz.md)
* [swift4](swift4.md)

View File

@@ -1,246 +0,0 @@
---
title: Documentation for the scala-pekko Generator
---
## METADATA
| Property | Value | Notes |
| -------- | ----- | ----- |
| generator name | scala-pekko | pass this to the generate command after -g |
| generator stability | STABLE | |
| generator type | CLIENT | |
| generator language | Scala | |
| generator default templating engine | mustache | |
| helpTxt | Generates a Scala client library (beta) base on pekko/Spray. | |
## 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|
|apiPackage|package for generated api classes| |null|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for JDK 1.8+)</dd></dl>|java8|
|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.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|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.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>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.</dd></dl>|false|
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>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.</dd></dl>|true|
|mainPackage|Top-level package name, which defines 'apiPackage', 'modelPackage', 'invokerPackage'| |org.openapitools.client|
|modelPackage|package for generated models| |null|
|modelPropertyNaming|Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name| |camelCase|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |null|
## IMPORT MAPPING
| Type/Alias | Imports |
| ---------- | ------- |
|Array|java.util.List|
|ArrayList|java.util.ArrayList|
|BigDecimal|java.math.BigDecimal|
|Date|java.util.Date|
|DateTime|org.joda.time.*|
|File|java.io.File|
|HashMap|java.util.HashMap|
|ListBuffer|scala.collection.mutable.ListBuffer|
|ListSet|scala.collection.immutable.ListSet|
|LocalDate|org.joda.time.*|
|LocalDateTime|org.joda.time.*|
|LocalTime|org.joda.time.*|
|Timestamp|java.sql.Timestamp|
|URI|java.net.URI|
|UUID|java.util.UUID|
## INSTANTIATION TYPES
| Type/Alias | Instantiated By |
| ---------- | --------------- |
|array|ListBuffer|
|map|Map|
|set|Set|
## LANGUAGE PRIMITIVES
<ul class="column-ul">
<li>Any</li>
<li>Array</li>
<li>Boolean</li>
<li>Byte</li>
<li>Double</li>
<li>Float</li>
<li>Int</li>
<li>List</li>
<li>Long</li>
<li>Map</li>
<li>Object</li>
<li>Seq</li>
<li>String</li>
<li>boolean</li>
</ul>
## RESERVED WORDS
<ul class="column-ul">
<li>abstract</li>
<li>case</li>
<li>catch</li>
<li>class</li>
<li>def</li>
<li>do</li>
<li>else</li>
<li>extends</li>
<li>false</li>
<li>final</li>
<li>finally</li>
<li>for</li>
<li>forsome</li>
<li>if</li>
<li>implicit</li>
<li>import</li>
<li>lazy</li>
<li>match</li>
<li>new</li>
<li>null</li>
<li>object</li>
<li>override</li>
<li>package</li>
<li>private</li>
<li>protected</li>
<li>return</li>
<li>sealed</li>
<li>super</li>
<li>this</li>
<li>throw</li>
<li>trait</li>
<li>true</li>
<li>try</li>
<li>type</li>
<li>val</li>
<li>var</li>
<li>while</li>
<li>with</li>
<li>yield</li>
</ul>
## 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
|SignatureAuth|✗|OAS3
|AWSV4Signature|✗|ToolingExtension
### Wire Format Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|JSON|✓|OAS2,OAS3
|XML|✓|OAS2,OAS3
|PROTOBUF|✗|ToolingExtension
|Custom|✓|OAS2,OAS3

View File

@@ -4,7 +4,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-project</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>
@@ -129,7 +129,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.13</version>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>org.codehaus.janino</groupId>

View File

@@ -6,7 +6,7 @@
<artifactId>openapi-generator-project</artifactId>
<groupId>org.openapitools</groupId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>

View File

@@ -1,5 +1,5 @@
# RELEASE_VERSION
openApiGeneratorVersion=7.2.0
openApiGeneratorVersion=7.2.0-SNAPSHOT
# /RELEASE_VERSION
# BEGIN placeholders

View File

@@ -4,7 +4,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-project</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>

View File

@@ -1,3 +1,3 @@
# RELEASE_VERSION
openApiGeneratorVersion=7.2.0
openApiGeneratorVersion=7.2.0-SNAPSHOT
# /RELEASE_VERSION

View File

@@ -13,7 +13,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>

View File

@@ -15,7 +15,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>

View File

@@ -19,7 +19,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<dependencies>
<dependency>

View File

@@ -13,7 +13,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>

View File

@@ -13,7 +13,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>

View File

@@ -20,7 +20,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>

View File

@@ -5,7 +5,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-project</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>

View File

@@ -4,7 +4,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-project</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>

View File

@@ -4,7 +4,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-project</artifactId>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>
@@ -271,7 +271,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.13</version>
<version>1.2.11</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@@ -109,6 +109,7 @@ public class OpenAPINormalizer {
this.inputRules = inputRules;
if (Boolean.parseBoolean(inputRules.get(DISABLE_ALL))) {
LOGGER.info("Disabled all rules in OpenAPI Normalizer (DISABLE_ALL=true)");
this.disableAll = true;
return; // skip the rest
}
@@ -305,11 +306,6 @@ public class OpenAPINormalizer {
}
for (Parameter parameter : parameters) {
// dereference parameter
if (StringUtils.isNotEmpty(parameter.get$ref())) {
parameter = ModelUtils.getReferencedParameter(openAPI, parameter);
}
if (parameter.getSchema() == null) {
continue;
} else {
@@ -573,10 +569,6 @@ public class OpenAPINormalizer {
return;
}
if (schema.getAllOf().size() == 1) {
return;
}
for (Object item : schema.getAllOf()) {
if (!(item instanceof Schema)) {
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
@@ -944,17 +936,6 @@ public class OpenAPINormalizer {
String type = String.valueOf(schema.getTypes().iterator().next());
if ("array".equals(type)) {
ArraySchema as = new ArraySchema();
as.setDescription(schema.getDescription());
as.setDefault(schema.getDefault());
if (schema.getExample() != null) {
as.setExample(schema.getExample());
}
if (schema.getExamples() != null) {
as.setExamples(schema.getExamples());
}
as.setMinItems(schema.getMinItems());
as.setMaxItems(schema.getMaxItems());
as.setExtensions(schema.getExtensions());
as.setXml(schema.getXml());
// `items` is also a json schema
if (StringUtils.isNotEmpty(schema.getItems().get$ref())) {

View File

@@ -22,7 +22,10 @@ import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.model.*;
import org.openapitools.codegen.model.ModelMap;
import org.openapitools.codegen.model.ModelsMap;
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;
@@ -583,105 +586,6 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
return objs;
}
@Override
public WebhooksMap postProcessWebhooksWithModels(WebhooksMap objs, List<ModelMap> allModels) {
OperationMap objectMap = objs.getWebhooks();
List<CodegenOperation> operations = objectMap.getOperation();
for (CodegenOperation operation : operations) {
// http method verb conversion (e.g. PUT => Put)
operation.httpMethod = camelize(operation.httpMethod.toLowerCase(Locale.ROOT));
}
// remove model imports to avoid error
List<Map<String, String>> imports = objs.getImports();
if (imports == null)
return objs;
Iterator<Map<String, String>> iterator = imports.iterator();
while (iterator.hasNext()) {
String _import = iterator.next().get("import");
if (_import.startsWith(apiPackage()))
iterator.remove();
}
// this will only import "fmt" and "strings" if there are items in pathParams
for (CodegenOperation operation : operations) {
if (operation.pathParams != null && operation.pathParams.size() > 0) {
imports.add(createMapping("import", "strings"));
break; //just need to import once
}
}
boolean addedTimeImport = false;
boolean addedOSImport = false;
boolean addedReflectImport = false;
for (CodegenOperation operation : operations) {
// import "os" if the operation uses files
if (!addedOSImport && "*os.File".equals(operation.returnType)) {
imports.add(createMapping("import", "os"));
addedOSImport = true;
}
for (CodegenParameter param : operation.allParams) {
// import "os" if the operation uses files
if (!addedOSImport && "*os.File".equals(param.dataType)) {
imports.add(createMapping("import", "os"));
addedOSImport = true;
}
// import "time" if the operation has a time parameter.
if (!addedTimeImport && "time.Time".equals(param.dataType)) {
imports.add(createMapping("import", "time"));
addedTimeImport = true;
}
// import "reflect" package if the parameter is collectionFormat=multi
if (!addedReflectImport && param.isCollectionFormatMulti) {
imports.add(createMapping("import", "reflect"));
addedReflectImport = true;
}
// set x-exportParamName
char nameFirstChar = param.paramName.charAt(0);
if (Character.isUpperCase(nameFirstChar)) {
// First char is already uppercase, just use paramName.
param.vendorExtensions.put("x-export-param-name", param.paramName);
} else {
// It's a lowercase first char, let's convert it to uppercase
StringBuilder sb = new StringBuilder(param.paramName);
sb.setCharAt(0, Character.toUpperCase(nameFirstChar));
param.vendorExtensions.put("x-export-param-name", sb.toString());
}
}
setExportParameterName(operation.queryParams);
setExportParameterName(operation.formParams);
setExportParameterName(operation.headerParams);
setExportParameterName(operation.bodyParams);
setExportParameterName(operation.cookieParams);
setExportParameterName(operation.optionalParams);
setExportParameterName(operation.requiredParams);
}
// recursively add import for mapping one type to multiple imports
List<Map<String, String>> recursiveImports = objs.getImports();
if (recursiveImports == null)
return objs;
ListIterator<Map<String, String>> listIterator = imports.listIterator();
while (listIterator.hasNext()) {
String _import = listIterator.next().get("import");
// if the import package happens to be found in the importMapping (key)
// add the corresponding import package to the list
if (importMapping.containsKey(_import)) {
listIterator.add(createMapping("import", importMapping.get(_import)));
}
}
return objs;
}
private void setExportParameterName(List<CodegenParameter> codegenParameters) {
for (CodegenParameter param : codegenParameters) {
char nameFirstChar = param.paramName.charAt(0);

View File

@@ -1088,7 +1088,7 @@ public abstract class AbstractPythonCodegen extends DefaultCodegen implements Co
|| "float".equals(mapNumberTo)) {
this.mapNumberTo = mapNumberTo;
} else {
throw new IllegalArgumentException("mapNumberTo value must be Union[StrictFloat, StrictInt], StrictFloat or float");
throw new IllegalArgumentException("mapNumberTo value must be Union[StrictFloat, StrictInt], StrictStr or float");
}
}
@@ -2200,7 +2200,7 @@ public abstract class AbstractPythonCodegen extends DefaultCodegen implements Co
// TODO process the first one only at the moment
if (cmt != null)
// TODO: don't loop back to the deprecated getPydanticType method
return getPydanticType(cmt.getSchema(), typingImports, pydanticImports, datetimeImports, modelImports, exampleImports, postponedModelImports, postponedExampleImports, classname);
result = getPydanticType(cmt.getSchema(), typingImports, pydanticImports, datetimeImports, modelImports, exampleImports, postponedModelImports, postponedExampleImports, classname);
}
throw new RuntimeException("Error! Failed to process getPydanticType when getting the content: " + cp);
} else {

View File

@@ -629,9 +629,6 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
} else if (ModelUtils.isMapSchema(p)) {
Schema<?> inner = getSchemaAdditionalProperties(p);
String nullSafeSuffix = getNullSafeAdditionalProps() ? " | undefined" : "";
if (Boolean.TRUE.equals(inner.getNullable())) {
nullSafeSuffix += " | null";
}
return "{ [key: string]: " + getTypeDeclaration(unaliasSchema(inner)) + nullSafeSuffix + "; }";
} else if (ModelUtils.isFileSchema(p)) {
return "File";

View File

@@ -499,14 +499,8 @@ public class GoClientCodegen extends AbstractGoCodegen {
addedFmtImport = true;
}
if (model.hasRequired) {
if (!model.isAdditionalPropertiesTrue) {
imports.add(createMapping("import", "bytes"));
}
if (!addedFmtImport) {
imports.add(createMapping("import", "fmt"));
}
if (!addedFmtImport && model.hasRequired) {
imports.add(createMapping("import", "fmt"));
}
// additionalProperties: true and parent

View File

@@ -31,8 +31,6 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
import static org.openapitools.codegen.utils.StringUtils.camelize;
public class GoServerCodegen extends AbstractGoCodegen {
/**
@@ -324,77 +322,34 @@ public class GoServerCodegen extends AbstractGoCodegen {
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
// TODO: refactor abstractGoCodegen, decouple go client only code and remove this
objs = super.postProcessOperationsWithModels(objs, allModels);
OperationMap objectMap = objs.getOperations();
List<CodegenOperation> operations = objectMap.getOperation();
for (CodegenOperation operation : operations) {
// http method verb conversion (e.g. PUT => Put)
operation.httpMethod = camelize(operation.httpMethod.toLowerCase(Locale.ROOT));
}
// remove model imports to avoid error
List<Map<String, String>> imports = objs.getImports();
if (imports == null)
return objs;
Iterator<Map<String, String>> iterator = imports.iterator();
while (iterator.hasNext()) {
String _import = iterator.next().get("import");
if (_import.startsWith(apiPackage))
iterator.remove();
}
// override imports to only include packages for interface parameters
imports.clear();
boolean addedTimeImport = false;
boolean addedOSImport = false;
boolean addedReflectImport = false;
for (CodegenOperation operation : operations) {
for (CodegenParameter param : operation.allParams) {
// import "os" if the operation uses files
if (!addedOSImport && ("*os.File".equals(param.dataType) || "[]*os.File".equals(param.dataType))) {
if (!addedOSImport && ("*os.File".equals(param.dataType) || ("[]*os.File".equals(param.dataType)))) {
imports.add(createMapping("import", "os"));
addedOSImport = true;
}
// import "time" if the operation has a time parameter.
if (!addedTimeImport && "time.Time".equals(param.dataType)) {
imports.add(createMapping("import", "time"));
addedTimeImport = true;
// import "time" if the operation has a required time parameter
if (param.required) {
if (!addedTimeImport && "time.Time".equals(param.dataType)) {
imports.add(createMapping("import", "time"));
addedTimeImport = true;
}
}
// import "reflect" package if the parameter is collectionFormat=multi
if (!addedReflectImport && param.isCollectionFormatMulti) {
imports.add(createMapping("import", "reflect"));
addedReflectImport = true;
}
// set x-exportParamName
char nameFirstChar = param.paramName.charAt(0);
if (Character.isUpperCase(nameFirstChar)) {
// First char is already uppercase, just use paramName.
param.vendorExtensions.put("x-export-param-name", param.paramName);
} else {
// It's a lowercase first char, let's convert it to uppercase
StringBuilder sb = new StringBuilder(param.paramName);
sb.setCharAt(0, Character.toUpperCase(nameFirstChar));
param.vendorExtensions.put("x-export-param-name", sb.toString());
}
}
}
// recursively add import for mapping one type to multiple imports
List<Map<String, String>> recursiveImports = objs.getImports();
if (recursiveImports == null)
return objs;
ListIterator<Map<String, String>> listIterator = imports.listIterator();
while (listIterator.hasNext()) {
String _import = listIterator.next().get("import");
// if the import package happens to be found in the importMapping (key)
// add the corresponding import package to the list
if (importMapping.containsKey(_import)) {
listIterator.add(createMapping("import", importMapping.get(_import)));
}
}

View File

@@ -301,6 +301,10 @@ public class RubyClientCodegen extends AbstractRubyCodegen {
.doNotOverwrite());
supportingFiles.add(new SupportingFile("spec_helper.mustache", specFolder, "spec_helper.rb")
.doNotOverwrite());
supportingFiles.add(new SupportingFile("configuration_spec.mustache", specFolder, "configuration_spec.rb")
.doNotOverwrite());
supportingFiles.add(new SupportingFile("api_client_spec.mustache", specFolder, "api_client_spec.rb")
.doNotOverwrite());
// add lambda to convert a symbol to a string if an underscore is included (e.g. :'user_uuid' => 'user_uuid')
additionalProperties.put("lambdaFixHeaderKey", new Mustache.Lambda() {
@@ -410,10 +414,6 @@ public class RubyClientCodegen extends AbstractRubyCodegen {
return schemaMapping.get(name);
}
if (modelNameMapping.containsKey(name)) {
return modelNameMapping.get(name);
}
// memoization
String origName = name;
if (schemaKeyToModelNameCache.containsKey(origName)) {

View File

@@ -1,359 +0,0 @@
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright 2018 SmartBear Software
*
* 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 com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.security.SecurityScheme;
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.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.*;
import static org.openapitools.codegen.utils.StringUtils.camelize;
public class ScalaPekkoClientCodegen extends AbstractScalaCodegen implements CodegenConfig {
protected String mainPackage = "org.openapitools.client";
protected String groupId = "org.openapitools";
protected String artifactId = "openapi-client";
protected String artifactVersion = "1.0.0";
protected String resourcesFolder = "src/main/resources";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
protected String configKey = "apiRequest";
protected int defaultTimeoutInMs = 5000;
protected String configKeyPath = mainPackage;
protected boolean registerNonStandardStatusCodes = true;
protected boolean renderJavadoc = true;
protected boolean removeOAuthSecurities = true;
@SuppressWarnings("hiding")
protected final Logger LOGGER = LoggerFactory.getLogger(ScalaPekkoClientCodegen.class);
public ScalaPekkoClientCodegen() {
super();
modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
.wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.XML, WireFormatFeature.Custom))
.securityFeatures(EnumSet.of(
SecurityFeature.BasicAuth,
SecurityFeature.ApiKey,
SecurityFeature.BearerToken
))
.excludeGlobalFeatures(
GlobalFeature.XMLStructureDefinitions,
GlobalFeature.Callbacks,
GlobalFeature.LinkObjects,
GlobalFeature.ParameterStyling
)
.excludeSchemaSupportFeatures(
SchemaSupportFeature.Polymorphism
)
.excludeParameterFeatures(
ParameterFeature.Cookie
)
.includeClientModificationFeatures(
ClientModificationFeature.BasePath,
ClientModificationFeature.UserAgent
)
);
outputFolder = "generated-code/scala-pekko";
modelTemplateFiles.put("model.mustache", ".scala");
apiTemplateFiles.put("api.mustache", ".scala");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
modelDocTemplateFiles.put("model_doc.mustache", ".md");
embeddedTemplateDir = templateDir = "scala-pekko-client";
apiPackage = mainPackage + ".api";
modelPackage = mainPackage + ".model";
invokerPackage = mainPackage + ".core";
setReservedWordsLowerCase(
Arrays.asList(
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit",
"import", "lazy", "match", "new", "null", "object", "override", "package",
"private", "protected", "return", "sealed", "super", "this", "throw",
"trait", "try", "true", "type", "val", "var", "while", "with", "yield")
);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("configKey", configKey);
additionalProperties.put("configKeyPath", configKeyPath);
additionalProperties.put("defaultTimeout", defaultTimeoutInMs);
if (renderJavadoc) {
additionalProperties.put("javadocRenderer", new JavadocLambda());
}
additionalProperties.put("fnCapitalize", new CapitalizeLambda());
additionalProperties.put("fnCamelize", new CamelizeLambda(false));
additionalProperties.put("fnEnumEntry", new EnumEntryLambda());
importMapping.remove("Seq");
importMapping.remove("List");
importMapping.remove("Set");
importMapping.remove("Map");
importMapping.put("BigDecimal", "java.math.BigDecimal");
typeMapping = new HashMap<>();
typeMapping.put("array", "Seq");
typeMapping.put("set", "Set");
typeMapping.put("boolean", "Boolean");
typeMapping.put("string", "String");
typeMapping.put("int", "Int");
typeMapping.put("integer", "Int");
typeMapping.put("long", "Long");
typeMapping.put("float", "Float");
typeMapping.put("byte", "Byte");
typeMapping.put("short", "Short");
typeMapping.put("char", "Char");
typeMapping.put("double", "Double");
typeMapping.put("object", "Any");
typeMapping.put("file", "File");
typeMapping.put("binary", "File");
typeMapping.put("number", "BigDecimal");
typeMapping.put("decimal", "BigDecimal");
instantiationTypes.put("array", "ListBuffer");
instantiationTypes.put("map", "Map");
cliOptions.add(new CliOption("mainPackage", "Top-level package name, which defines 'apiPackage', 'modelPackage', 'invokerPackage'").defaultValue("org.openapitools.client"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
}
if (additionalProperties.containsKey("mainPackage")) {
setMainPackage((String) additionalProperties.get("mainPackage"));
additionalProperties.replace("configKeyPath", this.configKeyPath);
if (!additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
apiPackage = mainPackage + ".api";
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
}
if (!additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
modelPackage = mainPackage + ".model";
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
}
if (!additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
invokerPackage = mainPackage + ".core";
}
}
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("reference.mustache", resourcesFolder, "reference.conf"));
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
supportingFiles.add(new SupportingFile("apiRequest.mustache", invokerFolder, "ApiRequest.scala"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache", invokerFolder, "ApiInvoker.scala"));
supportingFiles.add(new SupportingFile("requests.mustache", invokerFolder, "requests.scala"));
supportingFiles.add(new SupportingFile("apiSettings.mustache", invokerFolder, "ApiSettings.scala"));
final String apiFolder = (sourceFolder + File.separator + apiPackage).replace(".", File.separator);
supportingFiles.add(new SupportingFile("project/build.properties.mustache", "project", "build.properties"));
supportingFiles.add(new SupportingFile("enumsSerializers.mustache", apiFolder, "EnumsSerializers.scala"));
supportingFiles.add(new SupportingFile("serializers.mustache", invokerFolder, "Serializers.scala"));
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "scala-pekko";
}
@Override
public String getHelp() {
return "Generates a Scala client library (beta) base on pekko/Spray.";
}
@Override
public String escapeReservedWord(String name) {
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "`" + name + "`";
}
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
if (registerNonStandardStatusCodes) {
try {
OperationMap opsMap = objs.getOperations();
HashSet<Integer> unknownCodes = new HashSet<>();
for (CodegenOperation operation : opsMap.getOperation()) {
for (CodegenResponse response : operation.responses) {
if ("default".equals(response.code)) {
continue;
}
try {
int code = Integer.parseInt(response.code);
if (code >= 600) {
unknownCodes.add(code);
}
} catch (NumberFormatException e) {
LOGGER.error("Status code is not an integer : response.code", e);
}
}
}
if (!unknownCodes.isEmpty()) {
additionalProperties.put("unknownStatusCodes", unknownCodes);
}
} catch (Exception e) {
LOGGER.error("Unable to find operations List", e);
}
}
return super.postProcessOperationsWithModels(objs, allModels);
}
@Override
public List<CodegenSecurity> fromSecurity(Map<String, SecurityScheme> schemes) {
final List<CodegenSecurity> codegenSecurities = super.fromSecurity(schemes);
if (!removeOAuthSecurities) {
return codegenSecurities;
}
// Remove OAuth securities
codegenSecurities.removeIf(security -> security.isOAuth);
if (codegenSecurities.isEmpty()) {
return null;
}
return codegenSecurities;
}
@Override
public String toParamName(String name) {
// obtain the name from parameterNameMapping directly if provided
if (parameterNameMapping.containsKey(name)) {
return parameterNameMapping.get(name);
}
return formatIdentifier(name, false);
}
@Override
public String toEnumName(CodegenProperty property) {
return formatIdentifier(property.baseName, true);
}
@Override
public String toDefaultValue(Schema p) {
if (p.getRequired() != null && p.getRequired().contains(p.getName())) {
return "None";
}
if (ModelUtils.isBooleanSchema(p)) {
return null;
} else if (ModelUtils.isDateSchema(p)) {
return null;
} else if (ModelUtils.isDateTimeSchema(p)) {
return null;
} else if (ModelUtils.isNumberSchema(p)) {
return null;
} else if (ModelUtils.isIntegerSchema(p)) {
return null;
} else if (ModelUtils.isMapSchema(p)) {
String inner = getSchemaType(ModelUtils.getAdditionalProperties(p));
return "Map[String, " + inner + "].empty ";
} else if (ModelUtils.isArraySchema(p)) {
ArraySchema ap = (ArraySchema) p;
String inner = getSchemaType(ap.getItems());
if (ModelUtils.isSet(ap)) {
return "Set[" + inner + "].empty ";
}
return "Seq[" + inner + "].empty ";
} else if (ModelUtils.isStringSchema(p)) {
return null;
} else {
return null;
}
}
private static class JavadocLambda extends CustomLambda {
@Override
public String formatFragment(String fragment) {
final String[] lines = fragment.split("\\r?\\n");
final StringBuilder sb = new StringBuilder();
sb.append(" /**\n");
for (String line : lines) {
sb.append(" * ").append(line).append("\n");
}
sb.append(" */\n");
return sb.toString();
}
}
private static class CapitalizeLambda extends CustomLambda {
@Override
public String formatFragment(String fragment) {
return StringUtils.capitalize(fragment);
}
}
private class EnumEntryLambda extends CustomLambda {
@Override
public String formatFragment(String fragment) {
return formatIdentifier(fragment, true);
}
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
public void setMainPackage(String mainPackage) {
this.configKeyPath = this.mainPackage = mainPackage;
}
@Override
public String apiDocFileFolder() {
return (outputFolder + File.separator + apiDocPath).replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + File.separator + modelDocPath).replace('/', File.separatorChar);
}
}

View File

@@ -72,16 +72,6 @@ public class CamelCaseLambda implements Mustache.Lambda {
String text = camelize(fragment.execute().replace(" ", "_"), option);
if (generator != null) {
text = generator.sanitizeName(text);
if (generator.reservedWords().contains(text)) {
// Escaping must be done *after* camelize, because generators may escape using characters removed by camelize function.
text = generator.escapeReservedWord(text);
}
if (escapeParam) {
// NOTE: many generators call escapeReservedWord in toParamName, but we can't assume that's always the case.
// Here, we'll have to accept that we may be duplicating some work.
text = generator.toParamName(text);
}
}
writer.write(text);
}

View File

@@ -40,10 +40,6 @@ public class CaseFormatLambda implements Mustache.Lambda {
@Override
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
String text = initialFormat.converterTo(targetFormat).convert(fragment.execute());
if (generator != null && generator.reservedWords().contains(text)) {
text = generator.escapeReservedWord(text);
}
if (text != null) {
writer.write(text);
}

View File

@@ -53,9 +53,6 @@ public class LowercaseLambda implements Mustache.Lambda {
@Override
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
String text = fragment.execute().toLowerCase(Locale.ROOT);
if (generator != null && generator.reservedWords().contains(text)) {
text = generator.escapeReservedWord(text);
}
writer.write(text);
}

View File

@@ -498,7 +498,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
if (param.getValue() instanceof File) {
File file = (File) param.getValue();
try {
multipart.addFormData(param.getKey(),new FileInputStream(file),MediaType.APPLICATION_OCTET_STREAM_TYPE, file.getName());
multipart.addFormData(param.getKey(),new FileInputStream(file),MediaType.APPLICATION_OCTET_STREAM_TYPE);
} catch (FileNotFoundException e) {
throw new ApiException("Could not serialize multipart/form-data "+e.getMessage());
}

View File

@@ -904,7 +904,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
}
private void logResponse(ClientHttpResponse response) throws IOException {
log.info("HTTP Status Code: " + response.getStatusCode().value());
log.info("HTTP Status Code: " + response.getRawStatusCode());
log.info("Status Text: " + response.getStatusText());
log.info("HTTP Headers: " + headersToString(response.getHeaders()));
log.info("Response Body: " + bodyToString(response.getBody()));

View File

@@ -92,10 +92,11 @@ public class {{classname}} {
final MultiValueMap<String, Object> formParams = new LinkedMultiValueMap<String, Object>();
{{#hasQueryParams}}
{{#queryParams}}{{#isExplode}}{{#hasVars}}{{#vars}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}.{{getter}}()));
{{/vars}}{{/hasVars}}{{^hasVars}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));
{{/hasVars}}{{/isExplode}}{{^isExplode}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));
{{/isExplode}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}}
{{#queryParams}}
queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));
{{/queryParams}}
{{/hasQueryParams}}
{{#hasHeaderParams}}
{{#headerParams}}
if ({{paramName}} != null)

View File

@@ -114,7 +114,6 @@ org.openapitools.codegen.languages.RustClientCodegen
org.openapitools.codegen.languages.RustServerCodegen
org.openapitools.codegen.languages.ScalatraServerCodegen
org.openapitools.codegen.languages.ScalaAkkaClientCodegen
org.openapitools.codegen.languages.ScalaPekkoClientCodegen
org.openapitools.codegen.languages.ScalaAkkaHttpServerCodegen
org.openapitools.codegen.languages.ScalaFinchServerCodegen
org.openapitools.codegen.languages.ScalaGatlingCodegen

View File

@@ -7,18 +7,12 @@ import (
)
type {{classname}} struct {
}
{{#operation}}
// {{httpMethod}} {{{basePathWithoutHost}}}{{{path}}}{{#summary}}
// {{{.}}} {{/summary}}
// {{httpMethod}} {{{basePathWithoutHost}}}{{{path}}}
// {{{summary}}}
{{#isDeprecated}}
// Deprecated
// Deprecated
{{/isDeprecated}}
func (api *{{classname}}) {{nickname}}(c *gin.Context) {
// Your handler implementation
c.JSON(200, gin.H{"status": "OK"})
}
{{nickname}} gin.HandlerFunc
{{/operation}}
{{/operations}}
}{{/operations}}

View File

@@ -51,8 +51,7 @@ func DefaultHandleFunc(c *gin.Context) {
type ApiHandleFunctions struct {
{{#apiInfo}}{{#apis}}{{#operations}}
// Routes for the {{classname}} part of the API
{{classname}} {{classname}}{{/operations}}{{/apis}}{{/apiInfo}}{{#webhooks}}{{#operations}}
{{classname}} {{classname}}{{/operations}}{{/webhooks}}
{{classname}} {{classname}}{{/operations}}{{/apis}}{{/apiInfo}}
}
func getRoutes(handleFunctions ApiHandleFunctions) []Route {

View File

@@ -28,5 +28,5 @@ type {{classname}}Servicer interface { {{#operations}}{{#operation}}
{{#isDeprecated}}
// Deprecated
{{/isDeprecated}}
{{operationId}}(context.Context{{#allParams}}, {{#isNullable}}*{{/isNullable}}{{dataType}}{{/allParams}}) (ImplResponse, error){{/operation}}{{/operations}}
{{operationId}}(context.Context{{#allParams}}, {{dataType}}{{/allParams}}) (ImplResponse, error){{/operation}}{{/operations}}
}{{/apis}}{{/apiInfo}}

View File

@@ -1,7 +1,6 @@
{{>partial_header}}
package {{packageName}}
{{#operations}}
import (
"encoding/json"
{{#isBodyParam}}
@@ -12,8 +11,6 @@ import (
{{/isBodyParam}}
"net/http"
"strings"
{{#imports}} "{{import}}"
{{/imports}}
{{#routers}}
{{#mux}}
@@ -24,7 +21,6 @@ import (
{{/chi}}
{{/routers}}
)
{{/operations}}
// {{classname}}Controller binds http requests to an api service and writes the service results to the http response
type {{classname}}Controller struct {
@@ -208,188 +204,105 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
{{/isPathParam}}
{{#isQueryParam}}
{{#isDateTime}}
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}time.Time
if query.Has("{{baseName}}"){
param, err := parseTime(query.Get("{{baseName}}"))
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
{{#required}}
if !query.Has("{{baseName}}"){
c.errorHandler(w, r, &RequiredError{"{{baseName}}"}, nil)
return
{{/required}}
}
{{/isDateTime}}
{{#isNumber}}
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}float32
if query.Has("{{baseName}}") {
param, err := parseNumericParameter[float32](
query.Get("{{baseName}}"),
WithParse[float32](parseFloat32),{{#minimum}}
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float32]({{maximum}}),{{/maximum}}
)
if err != nil {
{{paramName}}Param, err := parseTime(query.Get("{{baseName}}"))
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{/required}}
{{^required}}
{{paramName}}Param, err := parseTime(query.Get("{{baseName}}"))
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
}
{{/required}}
{{/isDateTime}}
{{#isNumber}}
{{paramName}}Param, err := parseNumericParameter[float32](
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[float32]({{defaultValue}}, parseFloat32),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[float32](parseFloat32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[float32](parseFloat32),{{/required}}{{/defaultValue}}{{#minimum}}
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param float32 = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isNumber}}
{{#isFloat}}
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}float32
if query.Has("{{baseName}}") {
param, err := parseNumericParameter[float32](
query.Get("{{baseName}}"),
WithParse[float32](parseFloat32),{{#minimum}}
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
{{paramName}}Param, err := parseNumericParameter[float32](
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[float32]({{defaultValue}}, parseFloat32),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[float32](parseFloat32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[float32](parseFloat32),{{/required}}{{/defaultValue}}{{#minimum}}
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param float32 = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isFloat}}
{{#isDouble}}
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}float64
if query.Has("{{baseName}}") {
param, err := parseNumericParameter[float64](
query.Get("{{baseName}}"),
WithParse[float64](parseFloat64),{{#minimum}}
WithMinimum[float64]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float64]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
{{paramName}}Param, err := parseNumericParameter[float64](
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[float64]({{defaultValue}}, parseFloat64),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[float64](parseFloat64),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[float64](parseFloat64),{{/required}}{{/defaultValue}}{{#minimum}}
WithMinimum[float64]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float64]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param float64 = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isDouble}}
{{#isLong}}
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}int64
if query.Has("{{baseName}}") {
param, err := parseNumericParameter[int64](
query.Get("{{baseName}}"),
WithParse[int64](parseInt64),{{#minimum}}
WithMinimum[int64]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[int64]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
{{paramName}}Param, err := parseNumericParameter[int64](
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[int64]({{defaultValue}}, parseInt64),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[int64](parseInt64),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[int64](parseInt64),{{/required}}{{/defaultValue}}{{#minimum}}
WithMinimum[int64]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[int64]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param int64 = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isLong}}
{{#isInteger}}
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}int32
if query.Has("{{baseName}}") {
param, err := parseNumericParameter[int32](
query.Get("{{baseName}}"),
WithParse[int32](parseInt32),{{#minimum}}
WithMinimum[int32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[int32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
{{paramName}}Param, err := parseNumericParameter[int32](
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[int32]({{defaultValue}}, parseInt32),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[int32](parseInt32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[int32](parseInt32),{{/required}}{{/defaultValue}}{{#minimum}}
WithMinimum[int32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[int32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param int32 = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isInteger}}
{{#isBoolean}}
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}bool
if query.Has("{{baseName}}") {
param, err := parseBoolParameter(
query.Get("{{baseName}}"),
WithParse[bool](parseBool),{{#minimum}}
WithMinimum[bool]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[bool]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
{{paramName}}Param, err := parseBoolParameter(
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[bool]({{defaultValue}}, parseBool),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[bool](parseBool),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[bool](parseBool),{{/required}}{{/defaultValue}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param bool = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isBoolean}}
{{#isArray}}
@@ -500,23 +413,46 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
{{^isBoolean}}
{{^isArray}}
{{^isDateTime}}
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}{{dataType}}
{{#defaultValue}}
{{paramName}}Param := "{{defaultValue}}"
if query.Has("{{baseName}}") {
param := {{^isString}}{{dataType}}({{/isString}}query.Get("{{baseName}}"){{^isString}}){{/isString}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
param := {{^isString}}{{dataType}}({{/isString}}{{defaultValue}}{{^isString}}){{/isString}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
{{paramName}}Param = {{^isString}}{{dataType}}( {{/isString}}query.Get("{{baseName}}"){{^isString}} ){{/isString}}
}
{{/defaultValue}}
{{^defaultValue}}
{{^required}}
var {{paramName}}Param {{dataType}}
if query.Has("{{baseName}}") {
{{^isEnumRef}}
{{paramName}}Param = query.Get("{{baseName}}")
{{/isEnumRef}}
{{#isEnumRef}}
var err error
{{paramName}}Param, err = New{{dataType}}FromValue(query.Get("{{baseName}}"))
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{/isEnumRef}}
}
{{/required}}
{{#required}}
{{^isEnumRef}}
{{paramName}}Param := query.Get("{{baseName}}")
{{/isEnumRef}}
{{#isEnumRef}}
if !query.Has("{{baseName}}"){
c.errorHandler(w, r, &RequiredError{"{{baseName}}"}, nil)
return
}
{{paramName}}Param, err := New{{dataType}}FromValue(query.Get("{{baseName}}"))
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{/isEnumRef}}
{{/required}}
{{/defaultValue}}
{{/isDateTime}}
{{/isArray}}
{{/isBoolean}}
@@ -528,20 +464,15 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
{{/isQueryParam}}
{{#isFormParam}}
{{#isFile}}
var {{paramName}}Param {{#isArray}}[]*os.File{{/isArray}}{{^isArray}}*os.File{{/isArray}}
{
{{#isArray}}
param, err := ReadFormFilesToTempFiles(r, "{{baseName}}")
{{/isArray}}
{{^isArray}}
param, err := ReadFormFileToTempFile(r, "{{baseName}}")
{{/isArray}}
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{paramName}}Param = param
{{paramName}}Param, err := ReadFormFilesToTempFiles(r, "{{baseName}}")
{{/isArray}}
{{^isArray}}
{{paramName}}Param, err := ReadFormFileToTempFile(r, "{{baseName}}")
{{/isArray}}
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{/isFile}}
{{#isLong}}{{#isArray}}

View File

@@ -23,7 +23,7 @@ func New{{classname}}Service() {{classname}}Servicer {
{{#isDeprecated}}
// Deprecated
{{/isDeprecated}}
func (s *{{classname}}Service) {{nickname}}(ctx context.Context{{#allParams}}, {{paramName}} {{#isNullable}}*{{/isNullable}}{{dataType}}{{/allParams}}) (ImplResponse, error) {
func (s *{{classname}}Service) {{nickname}}(ctx context.Context{{#allParams}}, {{paramName}} {{dataType}}{{/allParams}}) (ImplResponse, error) {
// TODO - update {{nickname}} with the required logic for this service method.
// Add {{classFilename}}_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

View File

@@ -340,11 +340,11 @@ func (o {{classname}}) ToMap() (map[string]interface{}, error) {
}
{{#isAdditionalPropertiesTrue}}
func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
func (o *{{{classname}}}) UnmarshalJSON(bytes []byte) (err error) {
{{/isAdditionalPropertiesTrue}}
{{^isAdditionalPropertiesTrue}}
{{#hasRequired}}
func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
func (o *{{{classname}}}) UnmarshalJSON(bytes []byte) (err error) {
{{/hasRequired}}
{{/isAdditionalPropertiesTrue}}
{{#hasRequired}}
@@ -359,7 +359,7 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
allProperties := make(map[string]interface{})
err = json.Unmarshal(data, &allProperties)
err = json.Unmarshal(bytes, &allProperties)
if err != nil {
return err;
@@ -391,7 +391,7 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
var{{{classname}}}WithoutEmbeddedStruct := {{{classname}}}WithoutEmbeddedStruct{}
err = json.Unmarshal(data, &var{{{classname}}}WithoutEmbeddedStruct)
err = json.Unmarshal(bytes, &var{{{classname}}}WithoutEmbeddedStruct)
if err == nil {
var{{{classname}}} := _{{{classname}}}{}
{{#vars}}
@@ -404,7 +404,7 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
var{{{classname}}} := _{{{classname}}}{}
err = json.Unmarshal(data, &var{{{classname}}})
err = json.Unmarshal(bytes, &var{{{classname}}})
if err == nil {
o.{{{parent}}} = var{{{classname}}}.{{{parent}}}
} else {
@@ -413,7 +413,7 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
additionalProperties := make(map[string]interface{})
if err = json.Unmarshal(data, &additionalProperties); err == nil {
if err = json.Unmarshal(bytes, &additionalProperties); err == nil {
{{#vars}}
delete(additionalProperties, "{{{baseName}}}")
{{/vars}}
@@ -444,7 +444,7 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
{{#isMap}}
var{{{classname}}} := _{{{classname}}}{}
err = json.Unmarshal(data, &var{{{classname}}})
err = json.Unmarshal(bytes, &var{{{classname}}})
if err != nil {
return err
@@ -454,7 +454,7 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
additionalProperties := make(map[string]interface{})
if err = json.Unmarshal(data, &additionalProperties); err == nil {
if err = json.Unmarshal(bytes, &additionalProperties); err == nil {
{{#vars}}
delete(additionalProperties, "{{{baseName}}}")
{{/vars}}
@@ -467,7 +467,7 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
{{^parent}}
var{{{classname}}} := _{{{classname}}}{}
err = json.Unmarshal(data, &var{{{classname}}})
err = json.Unmarshal(bytes, &var{{{classname}}})
if err != nil {
return err
@@ -477,7 +477,7 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
additionalProperties := make(map[string]interface{})
if err = json.Unmarshal(data, &additionalProperties); err == nil {
if err = json.Unmarshal(bytes, &additionalProperties); err == nil {
{{#vars}}
delete(additionalProperties, "{{{baseName}}}")
{{/vars}}
@@ -495,9 +495,7 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
{{#hasRequired}}
var{{{classname}}} := _{{{classname}}}{}
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
err = decoder.Decode(&var{{{classname}}})
err = json.Unmarshal(bytes, &var{{{classname}}})
if err != nil {
return err
@@ -511,8 +509,8 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
{{/hasRequired}}
{{/isAdditionalPropertiesTrue}}
{{#isArray}}
func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
return json.Unmarshal(data, &o.Items)
func (o *{{{classname}}}) UnmarshalJSON(bytes []byte) (err error) {
return json.Unmarshal(bytes, &o.Items)
}
{{/isArray}}

View File

@@ -210,9 +210,6 @@ dependencies {
{{#kotlinx_serialization}}
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
{{/kotlinx_serialization}}
{{#jackson}}
implementation "com.squareup.retrofit2:converter-jackson:$retrofitVersion"
{{/jackson}}
implementation "com.squareup.retrofit2:converter-scalars:$retrofitVersion"
{{/jvm-retrofit2}}
testImplementation "io.kotlintest:kotlintest-runner-junit5:3.4.2"

View File

@@ -51,7 +51,6 @@ import retrofit2.converter.moshi.MoshiConverterFactory
{{/moshi}}
{{#jackson}}
import com.fasterxml.jackson.databind.ObjectMapper
import retrofit2.converter.jackson.JacksonConverterFactory
{{/jackson}}
{{#kotlinx_serialization}}
@@ -89,9 +88,6 @@ import okhttp3.MediaType.Companion.toMediaType
{{#kotlinx_serialization}}
kotlinxSerializationJson.asConverterFactory("application/json".toMediaType()),
{{/kotlinx_serialization}}
{{#jackson}}
JacksonConverterFactory.create(),
{{/jackson}}
)
) {
private val apiAuthorizations = mutableMapOf<String, Interceptor>()

View File

@@ -97,11 +97,8 @@ class {{classname}}:
{{/servers.0}}
_collection_formats: Dict[str, str] = {
{{#allParams}}
{{#isArray}}
'{{baseName}}': '{{collectionFormat}}',
{{/isArray}}
{{/allParams}}
{{#allParams}}{{#isArray}}
'{{baseName}}': '{{collectionFormat}}',{{/isArray}}{{/allParams}}
}
_path_params: Dict[str, str] = {}

View File

@@ -0,0 +1,257 @@
=begin
{{> api_info}}
=end
require 'spec_helper'
describe {{moduleName}}::ApiClient do
context 'initialization' do
context 'URL stuff' do
context 'host' do
it 'removes http from host' do
{{moduleName}}.configure { |c| c.host = 'http://example.com' }
expect({{moduleName}}::Configuration.default.host).to eq('example.com')
end
it 'removes https from host' do
{{moduleName}}.configure { |c| c.host = 'https://wookiee.com' }
expect({{moduleName}}::ApiClient.default.config.host).to eq('wookiee.com')
end
it 'removes trailing path from host' do
{{moduleName}}.configure { |c| c.host = 'hobo.com/v4' }
expect({{moduleName}}::Configuration.default.host).to eq('hobo.com')
end
end
context 'base_path' do
it "prepends a slash to base_path" do
{{moduleName}}.configure { |c| c.base_path = 'v4/dog' }
expect({{moduleName}}::Configuration.default.base_path).to eq('/v4/dog')
end
it "doesn't prepend a slash if one is already there" do
{{moduleName}}.configure { |c| c.base_path = '/v4/dog' }
expect({{moduleName}}::Configuration.default.base_path).to eq('/v4/dog')
end
it "ends up as a blank string if nil" do
{{moduleName}}.configure { |c| c.base_path = nil }
expect({{moduleName}}::Configuration.default.base_path).to eq('')
end
end
end
end
{{#isTyphoeus}}
describe 'params_encoding in #build_request' do
let(:config) { {{moduleName}}::Configuration.new }
let(:api_client) { {{moduleName}}::ApiClient.new(config) }
it 'defaults to nil' do
expect({{moduleName}}::Configuration.default.params_encoding).to eq(nil)
expect(config.params_encoding).to eq(nil)
request = api_client.build_request(:get, '/test')
expect(request.options[:params_encoding]).to eq(nil)
end
it 'can be customized' do
config.params_encoding = :multi
request = api_client.build_request(:get, '/test')
expect(request.options[:params_encoding]).to eq(:multi)
end
end
describe 'timeout in #build_request' do
let(:config) { {{moduleName}}::Configuration.new }
let(:api_client) { {{moduleName}}::ApiClient.new(config) }
it 'defaults to 0' do
expect({{moduleName}}::Configuration.default.timeout).to eq(0)
expect(config.timeout).to eq(0)
request = api_client.build_request(:get, '/test')
expect(request.options[:timeout]).to eq(0)
end
it 'can be customized' do
config.timeout = 100
request = api_client.build_request(:get, '/test')
expect(request.options[:timeout]).to eq(100)
end
end
{{/isTyphoeus}}
{{#isFaraday}}
describe 'proxy in #build_connection' do
let(:config) { {{moduleName}}::Configuration.new }
let(:api_client) { {{moduleName}}::ApiClient.new(config) }
let(:proxy_uri) { URI('http://example.org:8080') }
it 'defaults to nil' do
expect({{moduleName}}::Configuration.default.proxy).to be_nil
expect(config.proxy).to be_nil
connection = api_client.build_connection
expect(connection.proxy_for_request('/test')).to be_nil
end
it 'can be customized with a string' do
config.proxy = proxy_uri.to_s
connection = api_client.build_connection
configured_proxy = connection.proxy_for_request('/test')
expect(configured_proxy).not_to be_nil
expect(configured_proxy.uri.to_s).to eq proxy_uri.to_s
end
it 'can be customized with a hash' do
config.proxy = { uri: proxy_uri }
connection = api_client.build_connection
configured_proxy = connection.proxy_for_request('/test')
expect(configured_proxy).not_to be_nil
expect(configured_proxy.uri).to eq proxy_uri
end
end
{{/isFaraday}}
describe '#deserialize' do
it "handles Array<Integer>" do
api_client = {{moduleName}}::ApiClient.new
headers = { 'Content-Type' => 'application/json' }
response = double('response', headers: headers, body: '[12, 34]')
data = api_client.deserialize(response, 'Array<Integer>')
expect(data).to be_instance_of(Array)
expect(data).to eq([12, 34])
end
it 'handles Array<Array<Integer>>' do
api_client = {{moduleName}}::ApiClient.new
headers = { 'Content-Type' => 'application/json' }
response = double('response', headers: headers, body: '[[12, 34], [56]]')
data = api_client.deserialize(response, 'Array<Array<Integer>>')
expect(data).to be_instance_of(Array)
expect(data).to eq([[12, 34], [56]])
end
it 'handles Hash<String, String>' do
api_client = {{moduleName}}::ApiClient.new
headers = { 'Content-Type' => 'application/json' }
response = double('response', headers: headers, body: '{"message": "Hello"}')
data = api_client.deserialize(response, 'Hash<String, String>')
expect(data).to be_instance_of(Hash)
expect(data).to eq(:message => 'Hello')
end
end
describe "#object_to_hash" do
it 'ignores nils and includes empty arrays' do
# uncomment below to test object_to_hash for model
# api_client = {{moduleName}}::ApiClient.new
# _model = {{moduleName}}::ModelName.new
# update the model attribute below
# _model.id = 1
# update the expected value (hash) below
# expected = {id: 1, name: '', tags: []}
# expect(api_client.object_to_hash(_model)).to eq(expected)
end
end
describe '#build_collection_param' do
let(:param) { ['aa', 'bb', 'cc'] }
let(:api_client) { {{moduleName}}::ApiClient.new }
it 'works for csv' do
expect(api_client.build_collection_param(param, :csv)).to eq('aa,bb,cc')
end
it 'works for ssv' do
expect(api_client.build_collection_param(param, :ssv)).to eq('aa bb cc')
end
it 'works for tsv' do
expect(api_client.build_collection_param(param, :tsv)).to eq("aa\tbb\tcc")
end
it 'works for pipes' do
expect(api_client.build_collection_param(param, :pipes)).to eq('aa|bb|cc')
end
it 'works for multi' do
expect(api_client.build_collection_param(param, :multi)).to eq(['aa', 'bb', 'cc'])
end
it 'fails for invalid collection format' do
expect { api_client.build_collection_param(param, :INVALID) }.to raise_error(RuntimeError, 'unknown collection format: :INVALID')
end
end
describe '#json_mime?' do
let(:api_client) { {{moduleName}}::ApiClient.new }
it 'works' do
expect(api_client.json_mime?(nil)).to eq false
expect(api_client.json_mime?('')).to eq false
expect(api_client.json_mime?('application/json')).to eq true
expect(api_client.json_mime?('application/json; charset=UTF8')).to eq true
expect(api_client.json_mime?('APPLICATION/JSON')).to eq true
expect(api_client.json_mime?('application/xml')).to eq false
expect(api_client.json_mime?('text/plain')).to eq false
expect(api_client.json_mime?('application/jsonp')).to eq false
end
end
describe '#select_header_accept' do
let(:api_client) { {{moduleName}}::ApiClient.new }
it 'works' do
expect(api_client.select_header_accept(nil)).to be_nil
expect(api_client.select_header_accept([])).to be_nil
expect(api_client.select_header_accept(['application/json'])).to eq('application/json')
expect(api_client.select_header_accept(['application/xml', 'application/json; charset=UTF8'])).to eq('application/json; charset=UTF8')
expect(api_client.select_header_accept(['APPLICATION/JSON', 'text/html'])).to eq('APPLICATION/JSON')
expect(api_client.select_header_accept(['application/xml'])).to eq('application/xml')
expect(api_client.select_header_accept(['text/html', 'application/xml'])).to eq('text/html,application/xml')
end
end
describe '#select_header_content_type' do
let(:api_client) { {{moduleName}}::ApiClient.new }
it 'works' do
expect(api_client.select_header_content_type(nil)).to be_nil
expect(api_client.select_header_content_type([])).to be_nil
expect(api_client.select_header_content_type(['application/json'])).to eq('application/json')
expect(api_client.select_header_content_type(['application/xml', 'application/json; charset=UTF8'])).to eq('application/json; charset=UTF8')
expect(api_client.select_header_content_type(['APPLICATION/JSON', 'text/html'])).to eq('APPLICATION/JSON')
expect(api_client.select_header_content_type(['application/xml'])).to eq('application/xml')
expect(api_client.select_header_content_type(['text/plain', 'application/xml'])).to eq('text/plain')
end
end
describe '#sanitize_filename' do
let(:api_client) { {{moduleName}}::ApiClient.new }
it 'works' do
expect(api_client.sanitize_filename('sun')).to eq('sun')
expect(api_client.sanitize_filename('sun.gif')).to eq('sun.gif')
expect(api_client.sanitize_filename('../sun.gif')).to eq('sun.gif')
expect(api_client.sanitize_filename('/var/tmp/sun.gif')).to eq('sun.gif')
expect(api_client.sanitize_filename('./sun.gif')).to eq('sun.gif')
expect(api_client.sanitize_filename('..\sun.gif')).to eq('sun.gif')
expect(api_client.sanitize_filename('\var\tmp\sun.gif')).to eq('sun.gif')
expect(api_client.sanitize_filename('c:\var\tmp\sun.gif')).to eq('sun.gif')
expect(api_client.sanitize_filename('.\sun.gif')).to eq('sun.gif')
end
end
end

View File

@@ -0,0 +1,111 @@
=begin
{{> api_info}}
=end
require 'spec_helper'
describe {{moduleName}}::Configuration do
let(:config) { {{moduleName}}::Configuration.default }
before(:each) do
# uncomment below to setup host and base_path
# require 'URI'
# uri = URI.parse("{{{basePath}}}")
# {{moduleName}}.configure do |c|
# c.host = uri.host
# c.base_path = uri.path
# end
end
describe '#base_url' do
it 'should have the default value' do
# uncomment below to test default value of the base path
# expect(config.base_url).to eq("{{{basePath}}}")
end
it 'should remove trailing slashes' do
[nil, '', '/', '//'].each do |base_path|
config.base_path = base_path
# uncomment below to test trailing slashes
# expect(config.base_url).to eq("{{{basePath}}}")
end
end
end
{{#isFaraday}}
describe '#configure_faraday_connection' do
let(:faraday_connection) { Faraday::Connection.new }
before do
stub_const('CustomAdapter', Class.new(Faraday::Adapter))
stub_const('AnotherCustomAdapter', Class.new(Faraday::Adapter))
config.configure_faraday_connection do |conn|
conn.adapter CustomAdapter
conn.response :logger, nil, headers: true, bodies: true, log_level: :debug do |logger|
logger.filter(/(Authorization: )(.*)/, '\1[REDACTED]')
end
end
end
it 'adds a block that will be used to configure the connection' do
expect(faraday_connection.adapter).to eq(Faraday::Adapter::NetHttp)
expect(faraday_connection.builder.handlers).to_not include(Faraday::Response::Logger)
config.configure_connection(faraday_connection)
expect(faraday_connection.adapter).to eq(CustomAdapter)
expect(faraday_connection.builder.handlers).to include(Faraday::Response::Logger)
end
it 'supports multiple configuration blocks' do
config.configure_faraday_connection do |conn|
conn.adapter AnotherCustomAdapter
end
expect(faraday_connection.adapter).to eq(Faraday::Adapter::NetHttp)
expect(faraday_connection.builder.handlers).to_not include(Faraday::Response::Logger)
config.configure_connection(faraday_connection)
expect(faraday_connection.adapter).to eq(AnotherCustomAdapter)
expect(faraday_connection.builder.handlers).to include(Faraday::Response::Logger)
end
end
{{/isFaraday}}
{{#isHttpx}}
describe '#configure' do
let(:session) { HTTPX::Session.new }
before do
module CustomPlugin
module InstanceMethods; end
end
module AnotherCustomPlugin
module InstanceMethods; end
end
config.configure_session do |session|
session.plugin(CustomPlugin)
end
end
it 'adds a block that will be used to configure the connection' do
sess = config.configure(session)
expect(sess.class.ancestors).to include(CustomPlugin::InstanceMethods)
end
it 'supports multiple configuration blocks' do
config.configure_session do |session|
session.plugin(AnotherCustomPlugin)
end
sess = config.configure(session)
expect(sess.class.ancestors).to include(CustomPlugin::InstanceMethods)
expect(sess.class.ancestors).to include(AnotherCustomPlugin::InstanceMethods)
end
end
{{/isHttpx}}
end

View File

@@ -1,171 +0,0 @@
# {{artifactId}}
{{appName}}
- API version: {{appVersion}}
{{^hideGenerationTimestamp}}
- Build date: {{generatedDate}}
{{/hideGenerationTimestamp}}
{{{appDescriptionWithNewLines}}}
{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}
*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)*
## Requirements
Building the API client library requires:
1. Java 1.7+
2. Maven/Gradle/SBT
## Installation
To install the API client library to your local Maven repository, simply execute:
```shell
mvn clean install
```
To deploy it to a remote Maven repository instead, configure the settings of the repository and execute:
```shell
mvn clean deploy
```
Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information.
### Maven users
Add this dependency to your project's POM:
```xml
<dependency>
<groupId>{{{groupId}}}</groupId>
<artifactId>{{{artifactId}}}</artifactId>
<version>{{{artifactVersion}}}</version>
<scope>compile</scope>
</dependency>
```
### Gradle users
Add this dependency to your project's build file:
```groovy
compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}"
```
### SBT users
```scala
libraryDependencies += "{{{groupId}}}" % "{{{artifactId}}}" % "{{{artifactVersion}}}"
```
## Getting Started
Please follow the [installation](#installation) instruction and execute the following Java code:
```scala
{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}
import {{invokerPackage}}._
import {{modelPackage}}._
import {{{package}}}.{{{classname}}}
import org.apache.pekko.actor.ActorSystem
import scala.concurrent.Future
import scala.util.{Failure, Success}
object {{{classname}}}Example extends App {
implicit val system: ActorSystem = ActorSystem()
import system.dispatcher{{#hasAuthMethods}}
{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
// Configure HTTP basic authorization: {{{name}}}
implicit val {{{name}}}: BasicCredentials = BasicCredentials("YOUR USERNAME", "YOUR PASSWORD"){{/isBasicBasic}}{{#isBasicBearer}}
// Configure HTTP bearer authorization: {{{name}}}
implicit val {{{name}}}: BearerToken = BearerToken("BEARER TOKEN"){{/isBasicBearer}}{{/isBasic}}{{#isApiKey}}
// Configure API key authorization: {{{name}}}
implicit val {{{name}}}: ApiKeyValue = ApiKeyValue("YOUR API KEY"){{/isApiKey}}
{{/authMethods}}
{{/hasAuthMethods}}
// Create invoker to execute requests
val apiInvoker = ApiInvoker()
val apiInstance = {{{classname}}}("{{{basePath}}}"){{#allParams}}
val {{{paramName}}}: {{{dataType}}} = {{{example}}} // {{{dataType}}} | {{{description}}}
{{/allParams}}
val request = apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}})
val response = apiInvoker.execute(request)
response.onComplete {
case Success(org.openapitools.client.core.ApiResponse(code, content, headers)) =>
System.out.println(s"Status code: $code}")
System.out.println(s"Response headers: ${headers.mkString(", ")}"){{#returnType}}
System.out.println(s"Response body: $content"){{/returnType}}
case Failure(error @ ApiError(code, message, responseContent, cause, headers)) =>
System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}")
System.err.println(s"Status code: $code}")
System.err.println(s"Reason: $responseContent")
System.err.println(s"Response headers: ${headers.mkString(", ")}")
error.printStackTrace();
case Failure(exception) =>
System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}")
exception.printStackTrace();
}
}
{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}}
```
## Documentation for API Endpoints
All URIs are relative to *{{basePath}}*
Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
## Documentation for Models
{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md)
{{/model}}{{/models}}
<a id="documentation-for-authorization"></a>
## Documentation for Authorization
{{^authMethods}}Endpoints do not require authorization.{{/authMethods}}
{{#hasAuthMethods}}Authentication schemes defined for the API:{{/hasAuthMethods}}
{{#authMethods}}
<a id="{{name}}"></a>
### {{name}}
{{#isApiKey}}- **Type**: API key
- **API key parameter name**: {{keyParamName}}
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
{{/isApiKey}}
{{#isBasicBasic}}- **Type**: HTTP basic authentication
{{/isBasicBasic}}
{{#isBasicBearer}}- **Type**: HTTP Bearer Token authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}
{{/isBasicBearer}}
{{#isHttpSignature}}- **Type**: HTTP signature authentication
{{/isHttpSignature}}
{{#isOAuth}}- **Type**: OAuth
- **Flow**: {{flow}}
- **Authorization URL**: {{authorizationUrl}}
- **Scopes**: {{^scopes}}N/A{{/scopes}}
{{#scopes}} - {{scope}}: {{description}}
{{/scopes}}
{{/isOAuth}}
{{/authMethods}}
## Author
{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}}
{{/-last}}{{/apis}}{{/apiInfo}}

View File

@@ -1,52 +0,0 @@
{{>licenseInfo}}
package {{package}}
{{#imports}}
import {{import}}
{{/imports}}
import {{invokerPackage}}._
import {{invokerPackage}}.CollectionFormats._
import {{invokerPackage}}.ApiKeyLocations._
{{#operations}}
object {{classname}} {
def apply(baseUrl: String = "{{{basePath}}}") = new {{classname}}(baseUrl)
}
class {{classname}}(baseUrl: String) {
{{#operation}}
{{#javadocRenderer}}
{{>javadoc}}
{{/javadocRenderer}}
def {{operationId}}({{>methodParameters}}): ApiRequest[{{>operationReturnType}}] =
ApiRequest[{{>operationReturnType}}](ApiMethods.{{httpMethod.toUpperCase}}, baseUrl, "{{{path}}}", {{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}}{{^consumes}}"application/json"{{/consumes}})
{{#authMethods}}{{#isApiKey}}.withApiKey(apiKey, "{{keyParamName}}", {{#isKeyInQuery}}QUERY{{/isKeyInQuery}}{{#isKeyInHeader}}HEADER{{/isKeyInHeader}}{{#isKeyInCookie}}COOKIE{{/isKeyInCookie}})
{{/isApiKey}}{{#isBasic}}{{#isBasicBasic}}.withCredentials(basicAuth){{/isBasicBasic}}{{#isBasicBearer}}.withCredentials(bearerToken){{/isBasicBearer}}{{/isBasic}}{{/authMethods}}{{#bodyParam}}.withBody({{paramName}})
{{/bodyParam}}{{#formParams}}.withFormParam({{>paramCreation}})
{{/formParams}}{{#queryParams}}.withQueryParam({{>paramCreation}})
{{/queryParams}}{{#pathParams}}.withPathParam({{>paramCreation}})
{{/pathParams}}{{#headerParams}}.withHeaderParam({{>paramCreation}})
{{/headerParams}}{{#responses}}{{^isWildcard}}{{#dataType}}.with{{>responseState}}Response[{{dataType}}]({{code}})
{{/dataType}}{{^dataType}}.with{{>responseState}}Response[Unit]({{code}})
{{/dataType}}{{/isWildcard}}{{/responses}}{{#responses}}{{#isWildcard}}{{#dataType}}.withDefault{{>responseState}}Response[{{dataType}}]
{{/dataType}}{{^dataType}}.withDefault{{>responseState}}Response[Unit]
{{/dataType}}{{/isWildcard}}{{/responses}}
{{^responseHeaders.isEmpty}}
object {{#fnCapitalize}}{{operationId}}{{/fnCapitalize}}Headers {
{{#responseHeaders}}
def {{{name}}}(r: ApiReturnWithHeaders) = r.get{{^isContainer}}{{baseType}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}Header("{{baseName}}")
{{/responseHeaders}}
}
{{/responseHeaders.isEmpty}}
{{/operation}}
{{#unknownStatusCodes}}
ApiInvoker.addCustomStatusCode({{{value}}}, isSuccess = false)
{{/unknownStatusCodes}}
}
{{/operations}}

View File

@@ -1,285 +0,0 @@
{{>licenseInfo}}
package {{invokerPackage}}
import java.io.File
import org.apache.pekko.actor.ActorSystem
import org.apache.pekko.http.scaladsl.Http
import org.apache.pekko.http.scaladsl.coding._
import org.apache.pekko.http.scaladsl.model.Multipart.FormData.BodyPart
import org.apache.pekko.http.scaladsl.model.Uri.Query
import org.apache.pekko.http.scaladsl.model._
import org.apache.pekko.http.scaladsl.model.headers._
import org.apache.pekko.http.scaladsl.unmarshalling.{ Unmarshal, Unmarshaller }
import org.apache.pekko.stream.Materializer
import org.apache.pekko.stream.scaladsl.Source
import org.apache.pekko.util.{ ByteString, Timeout }
import com.github.pjfanning.pekkohttpjson4s.Json4sSupport
import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization
import scala.collection.immutable
import scala.concurrent.{ ExecutionContext, ExecutionContextExecutor, Future }
import scala.reflect.ClassTag
object ApiInvoker {
def apply()(implicit system: ActorSystem): ApiInvoker =
apply(DefaultFormats ++ Serializers.all)
def apply(serializers: Iterable[Serializer[_]])(implicit system: ActorSystem): ApiInvoker =
apply(DefaultFormats ++ Serializers.all ++ serializers)
def apply(formats: Formats)(implicit system: ActorSystem): ApiInvoker = new ApiInvoker(formats)
/**
* Allows request execution without calling apiInvoker.execute(request)
* request.response can be used to get a future of the ApiResponse generated.
* request.result can be used to get a future of the expected ApiResponse content. If content doesn't match, a
* Future will fail with a ClassCastException
*
* @param request the apiRequest to be executed
*/
implicit class ApiRequestImprovements[T: Manifest](request: ApiRequest[T]) {
def response(invoker: ApiInvoker)(implicit ec: ExecutionContext, system: ActorSystem): Future[ApiResponse[T]] =
response(ec, system, invoker)
def response(implicit ec: ExecutionContext, system: ActorSystem, invoker: ApiInvoker): Future[ApiResponse[T]] =
invoker.execute(request)
def result[U <: T](implicit c: ClassTag[U], ec: ExecutionContext, system: ActorSystem, invoker: ApiInvoker): Future[U] =
invoker.execute(request).map(_.content).mapTo[U]
}
/**
* Allows transformation from ApiMethod to spray HttpMethods
*
* @param method the ApiMethod to be converted
*/
implicit class ApiMethodExtensions(val method: ApiMethod) {
def toAkkaHttpMethod: HttpMethod = HttpMethods.getForKey(method.value).getOrElse(HttpMethods.GET)
}
}
trait UnitJSONSupport {
}
class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomContentTypes with Json4sSupport {
import {{{invokerPackage}}}.ApiInvoker._
import {{{invokerPackage}}}.ParametersMap._
implicit val ec: ExecutionContextExecutor = system.dispatcher
implicit val jsonFormats: Formats = formats
protected val settings: ApiSettings = ApiSettings(system)
private implicit val materializer: Materializer = Materializer(system)
private implicit val serialization: Serialization = jackson.Serialization
private val http = Http()
val CompressionFilter: HttpMessage => Boolean = (msg: HttpMessage) =>
Seq(
{ _: HttpMessage => settings.compressionEnabled },
Encoder.DefaultFilter,
(message: HttpMessage) => {
val long = message.entity().getContentLengthOption()
if (long.isPresent) long.getAsLong > settings.compressionSizeThreshold else true
}
)
.map(f => f(msg))
.forall(identity)
private def addAuthentication(credentialsSeq: Seq[Credentials]) = {
request: HttpRequest =>
credentialsSeq.foldLeft(request) {
case (req, BasicCredentials(login, password)) =>
req.addHeader(Authorization(BasicHttpCredentials(login, password)))
case (req, ApiKeyCredentials(keyValue, keyName, ApiKeyLocations.HEADER)) =>
req.addHeader(RawHeader(keyName, keyValue.value))
case (req, BearerToken(token)) =>
req.addHeader(RawHeader("Authorization", s"Bearer $token"))
case (req, _) => req
}
}
private def headers(headers: Map[String, Any]): immutable.Seq[HttpHeader] =
headers.asFormattedParams
.map { case (name, value) => RawHeader(name, value.toString) }
.to(immutable.Seq)
private def bodyPart(name: String, value: Any): BodyPart = {
value match {
case f: File =>
BodyPart.fromFile(
name,
ContentType(MediaTypes.`application/octet-stream`),
f,
f.length().toInt
)
case v: String =>
BodyPart.Strict(name, v.toString)
case NumericValue(v) =>
BodyPart.Strict(name, v.toString)
case m: ApiModel =>
BodyPart.Strict(name, Serialization.write(m))
}
}
private def formDataContent(request: ApiRequest[_]) = {
val params = request.formParams.asFormattedParams
if (params.isEmpty)
None
else
Some(
normalizedContentType(request.contentType).mediaType match {
case MediaTypes.`multipart/form-data` =>
Multipart.FormData(Source(params.toList.map { case (name, value) => bodyPart(name, value) }))
case MediaTypes.`application/x-www-form-urlencoded` =>
FormData(params.view.mapValues(_.toString).toMap)
case _: MediaType => // Default : application/x-www-form-urlencoded.
FormData(params.view.mapValues(_.toString).toMap)
}
)
}
private def bodyContent(request: ApiRequest[_]): Option[Any] = request
.bodyParam
.map(Extraction.decompose)
.map(compact)
private def createRequest(uri: Uri, request: ApiRequest[_]): HttpRequest = {
val httpRequest = request.method.toAkkaHttpMethod match {
case m@(HttpMethods.GET | HttpMethods.DELETE) => HttpRequest(m, uri)
case m@(HttpMethods.POST | HttpMethods.PUT | HttpMethods.PATCH) =>
formDataContent(request) orElse bodyContent(request) match {
case Some(c: FormData) =>
HttpRequest(m, uri, entity = c.toEntity)
case Some(c: Multipart.FormData) =>
HttpRequest(m, uri, entity = c.toEntity)
case Some(c: String) =>
HttpRequest(m, uri, entity = HttpEntity(normalizedContentType(request.contentType), ByteString(c)))
case _ =>
HttpRequest(m, uri, entity = HttpEntity(normalizedContentType(request.contentType), ByteString("")))
}
case m: HttpMethod => HttpRequest(m, uri)
}
addAuthentication(request.credentials)(
httpRequest.withHeaders(headers(request.headerParams))
)
}
def makeQuery(r: ApiRequest[_]): Query = {
r.credentials.foldLeft(r.queryParams) {
case (params, ApiKeyCredentials(key, keyName, ApiKeyLocations.QUERY)) =>
params + (keyName -> key.value)
case (params, _) => params
}.asFormattedParams
.view
.mapValues(_.toString)
.toMap
.foldRight[Query](Uri.Query.Empty) {
case ((name, value), acc) => acc.+:(name, value)
}
}
def makeUri(r: ApiRequest[_]): Uri = {
val opPath = r.operationPath.replaceAll("\\{format\\}", "json")
val opPathWithParams = r.pathParams.asFormattedParams
.view
.mapValues(_.toString)
.toMap
.foldLeft(opPath) {
case (path, (name, value)) => path.replaceAll(s"\\{$name\\}", value)
}
val query = makeQuery(r)
Uri(r.basePath + opPathWithParams).withQuery(query)
}
def execute[T: Manifest](r: ApiRequest[T]): Future[ApiResponse[T]] = {
implicit val timeout: Timeout = settings.connectionTimeout
val request = createRequest(makeUri(r), r)
http
.singleRequest(request)
.map { response =>
val decoder: Decoder with Decoder = response.encoding match {
case HttpEncodings.gzip =>
Coders.Gzip
case HttpEncodings.deflate =>
Coders.Deflate
case HttpEncodings.identity =>
Coders.NoCoding
case HttpEncoding(encoding) =>
throw new IllegalArgumentException(s"Unsupported encoding: $encoding")
}
decoder.decodeMessage(response)
}
.flatMap(unmarshallApiResponse(r))
}
def unmarshallApiResponse[T: Manifest](request: ApiRequest[T])(response: HttpResponse): Future[ApiResponse[T]] = {
def responseForState[V](state: ResponseState, value: V): ApiResponse[V] = {
state match {
case ResponseState.Success =>
ApiResponse(response.status.intValue, value, response.headers.map(header => (header.name, header.value)).toMap)
case ResponseState.Error =>
throw ApiError(
response.status.intValue,
"Error response received",
Some(value),
headers = response.headers.map(header => (header.name, header.value)).toMap
)
}
}
val mf = implicitly(manifest[T])
request
.responseForCode(response.status.intValue) match {
case Some((Manifest.Unit, state: ResponseState)) =>
Future(responseForState(state, ()).asInstanceOf[ApiResponse[T]])
case Some((manifest, state: ResponseState)) if manifest == mf =>
implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](mf, serialization, formats)
Unmarshal(response.entity)
.to[T]
.recoverWith {
case e => throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e)
}
.map(value => responseForState(state, value))
case None | Some(_) =>
Future.failed(ApiError(response.status.intValue, "Unexpected response code", Some(response.entity.toString)))
}
}
}
sealed trait CustomContentTypes {
protected def normalizedContentType(original: String): ContentType =
ContentType(parseContentType(original).mediaType, () => HttpCharsets.`UTF-8`)
protected def parseContentType(contentType: String): ContentType = {
ContentType.parse(contentType) match {
case Right(ct: ContentType) =>
ct
case Left(error: List[ErrorInfo]) =>
throw new IllegalArgumentException(
s"Error converting '$contentType' to a ContentType header: '${error.map(_.summary).mkString(", ")}'"
)
}
}
}

View File

@@ -1,57 +0,0 @@
{{>licenseInfo}}
package {{invokerPackage}}
sealed trait ResponseState
object ResponseState {
case object Success extends ResponseState
case object Error extends ResponseState
}
case class ApiRequest[U](
// required fields
method: ApiMethod,
basePath: String,
operationPath: String,
contentType: String,
// optional fields
responses: Map[Int, (Manifest[_], ResponseState)] = Map.empty,
bodyParam: Option[Any] = None,
formParams: Map[String, Any] = Map.empty,
pathParams: Map[String, Any] = Map.empty,
queryParams: Map[String, Any] = Map.empty,
headerParams: Map[String, Any] = Map.empty,
credentials: Seq[Credentials] = List.empty) {
def withCredentials(cred: Credentials): ApiRequest[U] = copy[U](credentials = credentials :+ cred)
def withApiKey(key: ApiKeyValue, keyName: String, location: ApiKeyLocation): ApiRequest[U] = withCredentials(ApiKeyCredentials(key, keyName, location))
def withSuccessResponse[T](code: Int)(implicit m: Manifest[T]): ApiRequest[U] = copy[U](responses = responses + (code -> (m, ResponseState.Success)))
def withErrorResponse[T](code: Int)(implicit m: Manifest[T]): ApiRequest[U] = copy[U](responses = responses + (code -> (m, ResponseState.Error)))
def withDefaultSuccessResponse[T](implicit m: Manifest[T]): ApiRequest[U] = withSuccessResponse[T](0)
def withDefaultErrorResponse[T](implicit m: Manifest[T]): ApiRequest[U] = withErrorResponse[T](0)
def responseForCode(statusCode: Int): Option[(Manifest[_], ResponseState)] = responses.get(statusCode) orElse responses.get(0)
def withoutBody(): ApiRequest[U] = copy[U](bodyParam = None)
def withBody(body: Any): ApiRequest[U] = copy[U](bodyParam = Some(body))
def withFormParam(name: String, value: Any): ApiRequest[U] = copy[U](formParams = formParams + (name -> value))
def withPathParam(name: String, value: Any): ApiRequest[U] = copy[U](pathParams = pathParams + (name -> value))
def withQueryParam(values: Map[String, Any]): ApiRequest[U] = copy[U](queryParams = queryParams ++ values)
def withQueryParam(name: String, value: Any): ApiRequest[U] = copy[U](queryParams = queryParams + (name -> value))
def withHeaderParam(name: String, value: Any): ApiRequest[U] = copy[U](headerParams = headerParams + (name -> value))
}

View File

@@ -1,44 +0,0 @@
{{>licenseInfo}}
package {{invokerPackage}}
import java.util.concurrent.TimeUnit
import org.apache.pekko.actor.{ActorSystem, ExtendedActorSystem, Extension, ExtensionId, ExtensionIdProvider}
import org.apache.pekko.http.scaladsl.model.{StatusCode, StatusCodes}
import org.apache.pekko.http.scaladsl.model.headers.RawHeader
import com.typesafe.config.Config
import scala.jdk.CollectionConverters._
import scala.concurrent.duration.FiniteDuration
class ApiSettings(config: Config) extends Extension {
def this(system: ExtendedActorSystem) = this(system.settings.config)
private def cfg = config.getConfig("{{configKeyPath}}.{{configKey}}")
val alwaysTrustCertificates: Boolean = cfg.getBoolean("trust-certificates")
val defaultHeaders: List[RawHeader] = cfg.getConfig("default-headers").entrySet.asScala.toList.map(c => RawHeader(c.getKey, c.getValue.render))
val connectionTimeout = FiniteDuration(cfg.getDuration("connection-timeout", TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS)
val compressionEnabled: Boolean = cfg.getBoolean("compression.enabled")
val compressionSizeThreshold: Int = cfg.getBytes("compression.size-threshold").toInt
val customCodes: List[StatusCode]= cfg.getConfigList("custom-codes").asScala.toList.map { c =>
StatusCodes.custom(
c.getInt("code"),
c.getString("reason"),
if (c.hasPath("defaultMessage")) c.getString("defaultMessage") else c.getString("reason"),
c.getBoolean("success"),
if (c.hasPath("allowsEntity")) c.getBoolean("allowsEntity") else true
)
}
}
object ApiSettings extends ExtensionId[ApiSettings] with ExtensionIdProvider {
override def lookup = ApiSettings
override def createExtension(system: ExtendedActorSystem): ApiSettings =
new ApiSettings(system)
// needed to get the type right when used from Java
override def get(system: ActorSystem): ApiSettings = super.get(system)
}

View File

@@ -1,114 +0,0 @@
# {{classname}}{{#description}}
{{.}}{{/description}}
All URIs are relative to *{{basePath}}*
Method | HTTP request | Description
------------- | ------------- | -------------
{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}}
[**{{operationId}}WithHttpInfo**]({{classname}}.md#{{operationId}}WithHttpInfo) | **{{httpMethod}}** {{path}} | {{summary}}
{{/operation}}{{/operations}}
{{#operations}}
{{#operation}}
## {{operationId}}
> {{operationId}}({{#hasParams}}{{operationId}}Request{{/hasParams}}): ApiRequest[{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Unit{{/returnType}}]
{{summary}}{{#notes}}
{{.}}{{/notes}}
### Example
```scala
// Import classes:
{{#imports}}
import {{import}}
{{/imports}}
import {{invokerPackage}}._
import {{invokerPackage}}.CollectionFormats._
import {{invokerPackage}}.ApiKeyLocations._
import org.apache.pekko.actor.ActorSystem
import scala.concurrent.Future
import scala.util.{Failure, Success}
object Example extends App {
implicit val system: ActorSystem = ActorSystem()
import system.dispatcher
{{#hasAuthMethods}}
{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
// Configure HTTP basic authorization: {{{name}}}
implicit val {{{name}}}: BasicCredentials = BasicCredentials("YOUR USERNAME", "YOUR PASSWORD"){{/isBasicBasic}}{{#isBasicBearer}}
// Configure HTTP bearer authorization: {{{name}}}
implicit val {{{name}}}: BearerToken = BearerToken("BEARER TOKEN"){{/isBasicBearer}}{{/isBasic}}{{#isApiKey}}
// Configure API key authorization: {{{name}}}
implicit val {{{name}}}: ApiKeyValue = ApiKeyValue("YOUR API KEY"){{/isApiKey}}
{{/authMethods}}
{{/hasAuthMethods}}
val apiInvoker = ApiInvoker()
val apiInstance = {{{classname}}}("{{{basePath}}}"){{#allParams}}
val {{{paramName}}}: {{{dataType}}} = {{{example}}} // {{{dataType}}} | {{{description}}}
{{/allParams}}
val request = apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}})
val response = apiInvoker.execute(request)
response.onComplete {
case Success(ApiResponse(code, content, headers)) =>
System.out.println(s"Status code: $code}")
System.out.println(s"Response headers: ${headers.mkString(", ")}"){{#returnType}}
System.out.println(s"Response body: $content"){{/returnType}}
case Failure(error @ ApiError(code, message, responseContent, cause, headers)) =>
System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}")
System.err.println(s"Status code: $code}")
System.err.println(s"Reason: $responseContent")
System.err.println(s"Response headers: ${headers.mkString(", ")}")
error.printStackTrace();
case Failure(exception) =>
System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}")
exception.printStackTrace();
}
}
```
### Parameters
{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}}
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}}
{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{.}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}}
{{/allParams}}
### Return type
{{#returnType}}ApiRequest[{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}]{{/returnType}}
{{^returnType}}ApiRequest[Unit] (empty response body){{/returnType}}
### Authorization
{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}}
### HTTP request headers
- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}}
- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}}
{{#responses.0}}
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
{{#responses}}
| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}} <br> {{/headers}}{{^headers.0}} - {{/headers.0}} |
{{/responses}}
{{/responses.0}}
{{/operation}}
{{/operations}}

View File

@@ -1,29 +0,0 @@
version := "{{artifactVersion}}"
name := "{{artifactId}}"
organization := "{{groupId}}"
scalaVersion := "2.13.12"
val PekkoVersion = "1.0.2"
libraryDependencies ++= Seq(
"com.typesafe" % "config" % "1.4.3",
"org.apache.pekko" %% "pekko-actor" % PekkoVersion,
"org.apache.pekko" %% "pekko-stream" % PekkoVersion,
"org.apache.pekko" %% "pekko-stream" % PekkoVersion,
"com.github.pjfanning" %% "pekko-http-json4s" % "2.3.2",
"org.json4s" %% "json4s-jackson" % "4.0.7",
"org.json4s" %% "json4s-ext" % "4.0.7",
// test dependencies
"org.scalatest" %% "scalatest" % "3.2.17" % "test",
"org.scalatestplus" %% "junit-4-13" % "3.2.17.0" % "test"
)
resolvers ++= Seq(Resolver.mavenLocal)
scalacOptions := Seq(
"-unchecked",
"-deprecation",
"-feature"
)
publishArtifact in (Compile, packageDoc) := false

View File

@@ -1,32 +0,0 @@
# {{#vendorExtensions.x-is-one-of-interface}}Trait {{/vendorExtensions.x-is-one-of-interface}}{{classname}}
{{#description}}{{&description}}
{{/description}}
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isContainer}}{{#isArray}}{{#items}}{{#isModel}}[{{/isModel}}{{/items}}**{{baseType}}{{#items}}&lt;{{dataType}}&gt;**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isModel}}{{/items}}{{/isArray}}{{#isMap}}{{#items}}{{#isModel}}[{{/isModel}}**Map&lt;String, {{dataType}}&gt;**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isModel}}{{/items}}{{/isMap}}{{/isContainer}}{{^isContainer}}{{#isModel}}[{{/isModel}}**{{dataType}}**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isModel}}{{/isContainer}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#isReadOnly}} [readonly]{{/isReadOnly}}
{{/vars}}
{{#vars}}{{#isEnum}}
## Enum: {{datatypeWithEnum}}
Allowed values: {{#allowableValues}}[{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}}
{{/isEnum}}{{/vars}}
{{#vendorExtensions.x-implements.0}}
## Implemented Interfaces
{{#vendorExtensions.x-implements}}
* {{{.}}}
{{/vendorExtensions.x-implements}}
{{/vendorExtensions.x-implements.0}}
{{#vendorExtensions.x-is-one-of-interface}}
## Implementing Classes
{{#oneOf}}
* {{{.}}}
{{/oneOf}}
{{/vendorExtensions.x-is-one-of-interface}}

View File

@@ -1,7 +0,0 @@
# {{classname}}
## Enum
{{#allowableValues}}{{#enumVars}}
* `{{name}}` (value: `{{{value}}}`)
{{/enumVars}}{{/allowableValues}}

View File

@@ -1,42 +0,0 @@
{{>licenseInfo}}
package {{apiPackage}}
{{#models.0}}
import {{modelPackage}}._
{{/models.0}}
import org.json4s._
import scala.reflect.ClassTag
object EnumsSerializers {
def all: Seq[Serializer[_]] = Seq[Serializer[_]](){{#models}}{{#model}}{{#hasEnums}}{{#vars}}{{#isEnum}} :+
new EnumNameSerializer({{classname}}Enums.{{datatypeWithEnum}}){{/isEnum}}{{/vars}}{{/hasEnums}}{{/model}}{{/models}}
private class EnumNameSerializer[E <: Enumeration: ClassTag](enum: E)
extends Serializer[E#Value] {
import JsonDSL._
val EnumerationClass: Class[E#Value] = classOf[E#Value]
def deserialize(implicit format: Formats):
PartialFunction[(TypeInfo, JValue), E#Value] = {
case (t @ TypeInfo(EnumerationClass, _), json) if isValid(json) =>
json match {
case JString(value) =>
enum.withName(value)
case value =>
throw new MappingException(s"Can't convert $value to $EnumerationClass")
}
}
private[this] def isValid(json: JValue) = json match {
case JString(value) if enum.values.exists(_.toString == value) => true
case _ => false
}
def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
case i: E#Value => i.toString
}
}
}

View File

@@ -1,25 +0,0 @@
{{#notes}}
{{{.}}}
{{/notes}}
Expected answers:
{{#responses}}
code {{code}} : {{{dataType}}} {{#message}}({{{.}}}){{/message}}
{{#headers}}
{{#-first}}
Headers :
{{/-first}}
{{{baseName}}} - {{{description}}}
{{/headers}}
{{/responses}}
{{#authMethods.0}}
Available security schemes:
{{#authMethods}}
{{name}} ({{type}})
{{/authMethods}}
{{/authMethods.0}}
{{#allParams}}
@param {{{paramName}}} {{{description}}}
{{/allParams}}

View File

@@ -1,11 +0,0 @@
/**
* {{{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.
*/

View File

@@ -1 +0,0 @@
{{#allParams}}{{paramName}}: {{#required}}{{dataType}}{{/required}}{{^required}}{{#isContainer}}{{dataType}}{{/isContainer}}{{^isContainer}}Option[{{dataType}}]{{/isContainer}}{{/required}}{{^defaultValue}}{{^required}}{{^isContainer}} = None{{/isContainer}}{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allParams}}{{#authMethods.0}})(implicit {{#authMethods}}{{#isApiKey}}apiKey: ApiKeyValue{{/isApiKey}}{{#isBasic}}{{#isBasicBasic}}basicAuth: BasicCredentials{{/isBasicBasic}}{{#isBasicBearer}}bearerToken: BearerToken{{/isBasicBearer}}{{/isBasic}}{{^-last}}, {{/-last}}{{/authMethods}}{{/authMethods.0}}

View File

@@ -1,41 +0,0 @@
{{>licenseInfo}}
package {{package}}
{{#imports}}
import {{import}}
{{/imports}}
import {{invokerPackage}}.ApiModel
{{#models}}
{{#model}}
case class {{classname}} (
{{#vars}}
{{#description}}
/* {{{.}}} */
{{/description}}
{{{name}}}: {{^required}}Option[{{/required}}{{^isEnum}}{{dataType}}{{/isEnum}}{{#isEnum}}{{classname}}Enums.{{datatypeWithEnum}}{{/isEnum}}{{^required}}] = None{{/required}}{{^-last}},{{/-last}}
{{/vars}}
) extends ApiModel
{{#hasEnums}}
object {{classname}}Enums {
{{#vars}}
{{#isEnum}}
type {{datatypeWithEnum}} = {{datatypeWithEnum}}.Value
{{/isEnum}}
{{/vars}}
{{#vars}}
{{#isEnum}}
object {{datatypeWithEnum}} extends Enumeration {
{{#_enum}}
val {{#fnEnumEntry}}{{.}}{{/fnEnumEntry}} = Value("{{.}}")
{{/_enum}}
}
{{/isEnum}}
{{/vars}}
}
{{/hasEnums}}
{{/model}}
{{/models}}

View File

@@ -1,9 +0,0 @@
{{#models}}{{#model}}
{{#isEnum}}
{{>enum_doc}}
{{/isEnum}}
{{^isEnum}}
{{>class_doc}}
{{/isEnum}}
{{/model}}{{/models}}

View File

@@ -1 +0,0 @@
{{{returnType}}}{{^returnType}}Unit{{/returnType}}

View File

@@ -1 +0,0 @@
{{#isMap}}{{baseName}}{{/isMap}}{{^isMap}}"{{baseName}}", {{#isContainer}}ArrayValues({{{paramName}}}{{#collectionFormat}}, {{collectionFormat.toUpperCase}}{{/collectionFormat}}){{/isContainer}}{{^isContainer}}{{{paramName}}}{{/isContainer}}{{/isMap}}

View File

@@ -1,254 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<name>{{artifactId}}</name>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
<version>{{artifactVersion}}</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<scala.version>2.13.12</scala.version>
<json4s.jackson.version>4.0.7</json4s.jackson.version>
<json4s.ext.version>4.0.7</json4s.ext.version>
<pekko.version>1.0.2</pekko.version>
<pekko.http.version>1.0.0</pekko.http.version>
<typesafeconfig.version>1.4.3</typesafeconfig.version>
<pekko.http.json4s.version>2.3.2</pekko.http.json4s.version>
<scala.test.version>3.2.17</scala.test.version>
<scala.test.plus.version>3.2.17.0</scala.test.plus.version>
<scala.maven.plugin.version>3.3.1</scala.maven.plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.typesafe</groupId>
<artifactId>config</artifactId>
<version>${typesafeconfig.version}</version>
</dependency>
<dependency>
<groupId>org.apache.pekko</groupId>
<artifactId>pekko-actor_2.13</artifactId>
<version>${pekko.version}</version>
</dependency>
<dependency>
<groupId>org.apache.pekko</groupId>
<artifactId>pekko-stream_2.13</artifactId>
<version>${pekko.version}</version>
</dependency>
<dependency>
<groupId>org.apache.pekko</groupId>
<artifactId>pekko-http_2.13</artifactId>
<version>${pekko.http.version}</version>
</dependency>
<dependency>
<groupId>org.json4s</groupId>
<artifactId>json4s-jackson_2.13</artifactId>
<version>${json4s.jackson.version}</version>
</dependency>
<dependency>
<groupId>org.json4s</groupId>
<artifactId>json4s-ext_2.13</artifactId>
<version>${json4s.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.github.pjfanning</groupId>
<artifactId>pekko-http-json4s_2.13</artifactId>
<version>${pekko.http.json4s.version}</version>
</dependency>
<!--test dependencies-->
<dependency>
<groupId>org.scalatest</groupId>
<artifactId>scalatest_2.13</artifactId>
<version>${scala.test.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.scalatestplus</groupId>
<artifactId>junit-4-13_2.13</artifactId>
<version>${scala.test.plus.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M1</version>
<executions>
<execution>
<id>enforce-maven</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>2.2.0</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<configuration>
<systemProperties>
<property>
<name>loggerPath</name>
<value>conf/log4j.properties</value>
</property>
</systemProperties>
<argLine>-Xms512m -Xmx1500m</argLine>
<parallel>methods</parallel>
<threadCount>4</threadCount>
<forkMode>pertest</forkMode>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- attach test jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
<configuration>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>add_sources</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>
src/main/java
</source>
</sources>
</configuration>
</execution>
<execution>
<id>add_test_sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>
src/test/java
</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>${scala.maven.plugin.version}</version>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<args>
<arg>-feature</arg>
</args>
<jvmArgs>
<jvmArg>-Xms128m</jvmArg>
<jvmArg>-Xmx1500m</jvmArg>
</jvmArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,24 +0,0 @@
{{configKeyPath}} {
{{configKey}} {
compression {
enabled: false
size-threshold: 0
}
trust-certificates: true
connection-timeout: {{defaultTimeout}}ms
default-headers {
"userAgent": "{{artifactId}}_{{artifactVersion}}"
}
// let you define custom http status code, as in :
// { code: 601, reason: "some custom http status code", success: false }
custom-codes : []
}
}
spray.can.host-connector.max-redirects = 10

View File

@@ -1,192 +0,0 @@
{{>licenseInfo}}
package {{invokerPackage}}
import java.io.File
import java.net.URLEncoder
import java.util.UUID
import java.time.OffsetDateTime
import scala.util.Try
sealed trait ApiReturnWithHeaders {
def headers: Map[String, String]
def header(name: String): Option[String] = headers.get(name)
def getStringHeader(name: String): Option[String] = header(name)
// workaround: return date time header in string instead of datetime object
def getDateTimeHeader(name: String): Option[String] = header(name)
def getIntHeader(name: String): Option[Int] = castedHeader(name, java.lang.Integer.parseInt)
def getLongHeader(name: String): Option[Long] = castedHeader(name, java.lang.Long.parseLong)
def getFloatHeader(name: String): Option[Float] = castedHeader(name, java.lang.Float.parseFloat)
def getDoubleHeader(name: String): Option[Double] = castedHeader(name, java.lang.Double.parseDouble)
def getBooleanHeader(name: String): Option[Boolean] = castedHeader(name, java.lang.Boolean.parseBoolean)
def getOffsetDateTimeHeader(name: String): Option[OffsetDateTime] = castedHeader(name, java.time.OffsetDateTime.parse)
private def castedHeader[U](name: String, conversion: String => U): Option[U] = {
Try {
header(name).map(conversion)
}.get
}
}
sealed case class ApiResponse[T](code: Int, content: T, headers: Map[String, String] = Map.empty)
extends ApiReturnWithHeaders
sealed case class ApiError[T](code: Int, message: String, responseContent: Option[T], cause: Throwable = null, headers: Map[String, String] = Map.empty)
extends Throwable(s"($code) $message.${responseContent.map(s => s" Content : $s").getOrElse("")}", cause)
with ApiReturnWithHeaders
sealed case class ApiMethod(value: String)
object ApiMethods {
val CONNECT = ApiMethod("CONNECT")
val DELETE = ApiMethod("DELETE")
val GET = ApiMethod("GET")
val HEAD = ApiMethod("HEAD")
val OPTIONS = ApiMethod("OPTIONS")
val PATCH = ApiMethod("PATCH")
val POST = ApiMethod("POST")
val PUT = ApiMethod("PUT")
val TRACE = ApiMethod("TRACE")
}
/**
* This trait needs to be added to any model defined by the api.
*/
trait ApiModel
/**
* Single trait defining a credential that can be transformed to a paramName / paramValue tuple
*/
sealed trait Credentials {
def asQueryParam: Option[(String, String)] = None
}
sealed case class BasicCredentials(user: String, password: String) extends Credentials
sealed case class BearerToken(token: String) extends Credentials
sealed case class ApiKeyCredentials(key: ApiKeyValue, keyName: String, location: ApiKeyLocation) extends Credentials {
override def asQueryParam: Option[(String, String)] = location match {
case ApiKeyLocations.QUERY => Some((keyName, key.value))
case _ => None
}
}
sealed case class ApiKeyValue(value: String)
sealed trait ApiKeyLocation
object ApiKeyLocations {
case object QUERY extends ApiKeyLocation
case object HEADER extends ApiKeyLocation
case object COOKIE extends ApiKeyLocation
}
/**
* Case class used to unapply numeric values only in pattern matching
*
* @param value the string representation of the numeric value
*/
sealed case class NumericValue(value: String) {
override def toString: String = value
}
object NumericValue {
def unapply(n: Any): Option[NumericValue] = n match {
case (_: Int | _: Long | _: Float | _: Double | _: Boolean | _: Byte) => Some(NumericValue(String.valueOf(n)))
case _ => None
}
}
/**
* Used for params being arrays
*/
sealed case class ArrayValues(values: Seq[Any], format: CollectionFormat = CollectionFormats.CSV)
object ArrayValues {
def apply(values: Option[Seq[Any]], format: CollectionFormat): ArrayValues =
ArrayValues(values.getOrElse(Seq.empty), format)
def apply(values: Option[Seq[Any]]): ArrayValues = ArrayValues(values, CollectionFormats.CSV)
}
/**
* Defines how arrays should be rendered in query strings.
*/
sealed trait CollectionFormat
trait MergedArrayFormat extends CollectionFormat {
def separator: String
}
object CollectionFormats {
case object CSV extends MergedArrayFormat {
override val separator = ","
}
case object TSV extends MergedArrayFormat {
override val separator = "\t"
}
case object SSV extends MergedArrayFormat {
override val separator = " "
}
case object PIPES extends MergedArrayFormat {
override val separator = "|"
}
case object MULTI extends CollectionFormat
}
object ParametersMap {
/**
* Pimp parameters maps (Map[String, Any]) in order to transform them in a sequence of String -> Any tuples,
* with valid url-encoding, arrays handling, files preservation, ...
*/
implicit class ParametersMapImprovements(val m: Map[String, Any]) {
def asFormattedParamsList: List[(String, Any)] = m.toList.flatMap(formattedParams)
def asFormattedParams: Map[String, Any] = m.flatMap(formattedParams)
private def urlEncode(v: Any) = URLEncoder.encode(String.valueOf(v), "utf-8").replaceAll("\\+", "%20")
private def formattedParams(tuple: (String, Any)): Seq[(String, Any)] = formattedParams(tuple._1, tuple._2)
private def formattedParams(name: String, value: Any): Seq[(String, Any)] = value match {
case arr: ArrayValues =>
arr.format match {
case CollectionFormats.MULTI => arr.values.flatMap(formattedParams(name, _))
case format: MergedArrayFormat => Seq((name, arr.values.mkString(format.separator)))
}
case None => Seq.empty
case Some(opt) => formattedParams(name, opt)
case s: Seq[Any] => formattedParams(name, ArrayValues(s))
case v: String => Seq((name, urlEncode(v)))
case v: UUID => formattedParams(name, v.toString)
case NumericValue(v) => Seq((name, urlEncode(v)))
case f: File => Seq((name, f))
case m: ApiModel => Seq((name, m))
}
}
}

View File

@@ -1 +0,0 @@
{{#is2xx}}Success{{/is2xx}}{{#is3xx}}Success{{/is3xx}}{{#is4xx}}Error{{/is4xx}}{{#is5xx}}Error{{/is5xx}}{{#isDefault}}Error{{/isDefault}}

View File

@@ -1,53 +0,0 @@
package {{invokerPackage}}
{{#java8}}
import java.time.{LocalDate, LocalDateTime, OffsetDateTime, ZoneId}
import java.time.format.DateTimeFormatter
{{/java8}}
{{#joda}}
import org.joda.time.format.ISODateTimeFormat
import org.joda.time.{LocalDate, DateTime}
{{/joda}}
import org.json4s.{Serializer, CustomSerializer, JNull}
import org.json4s.ext.JavaTypesSerializers
import org.json4s.JsonAST.JString
import scala.util.Try
object Serializers {
{{#java8}}
case object DateTimeSerializer extends CustomSerializer[OffsetDateTime]( _ => ( {
case JString(s) =>
Try(OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME)) orElse
Try(LocalDateTime.parse(s).atZone(ZoneId.systemDefault()).toOffsetDateTime) getOrElse null
}, {
case d: OffsetDateTime =>
JString(d.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME))
}))
case object LocalDateSerializer extends CustomSerializer[LocalDate]( _ => ( {
case JString(s) => LocalDate.parse(s)
}, {
case d: LocalDate =>
JString(d.format(DateTimeFormatter.ISO_LOCAL_DATE))
}))
{{/java8}}
{{#joda}}
case object DateTimeSerializer extends CustomSerializer[DateTime](_ => ( {
case JString(s) =>
ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(s)
}, {
case d: DateTime => JString(ISODateTimeFormat.dateTime().print(d))
}))
case object LocalDateSerializer extends CustomSerializer[LocalDate]( _ => ( {
case JString(s) => ISODateTimeFormat.localDateParser().parseLocalDate(s)
}, {
case d: LocalDate => JString(ISODateTimeFormat.date().print(d))
}))
{{/joda}}
def all: Seq[Serializer[_]] = JavaTypesSerializers.all :+ DateTimeSerializer :+ LocalDateSerializer
}

View File

@@ -406,12 +406,7 @@ extension {{projectName}}API {
localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}}
let localVariableURLString = {{projectName}}API.basePath + localVariablePath
{{#bodyParam}}
{{#isBinary}}
let localVariableParameters = ["body": {{paramName}}]
{{/isBinary}}
{{^isBinary}}
let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}})
{{/isBinary}}
{{/bodyParam}}
{{^bodyParam}}
{{#hasFormParams}}
@@ -436,10 +431,9 @@ extension {{projectName}}API {
]){{/hasQueryParams}}{{^hasQueryParams}}
let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}}
let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}}{{^hasConsumes}}
:{{/hasConsumes}}{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}}
"Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{^hasFormParams}}{{#hasConsumes}}
"Content-Type": {{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasConsumes}}{{/hasFormParams}}{{#headerParams}}
let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}}
:{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}}
"Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}}
{{> _param}},{{/headerParams}}
]

View File

@@ -592,20 +592,14 @@ private class OctetStreamEncoding: ParameterEncoding {
var urlRequest = urlRequest
guard let body = parameters?["body"] else { return urlRequest }
var requestBodyComponents = URLComponents()
requestBodyComponents.queryItems = APIHelper.mapValuesToQueryItems(parameters ?? [:])
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type")
}
switch body {
case let fileURL as URL:
urlRequest.httpBody = try Data(contentsOf: fileURL)
case let data as Data:
urlRequest.httpBody = data
default:
fatalError("Unprocessable body \(body)")
}
urlRequest.httpBody = requestBodyComponents.query?.data(using: .utf8)
return urlRequest
}

View File

@@ -297,7 +297,7 @@ export const {{classname}}Factory = function (configuration?: Configuration, bas
* @throws {RequiredError}
*/
{{#useSingleRequestParameter}}
{{nickname}}({{#allParams.0}}requestParameters: {{classname}}{{operationIdCamelCase}}Request{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, {{/allParams.0}}options?: RawAxiosRequestConfig): AxiosPromise<{{{returnType}}}{{^returnType}}void{{/returnType}}> {
{{nickname}}({{#allParams.0}}requestParameters: {{classname}}{{operationIdCamelCase}}Request{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, {{/allParams.0}}options?: AxiosRequestConfig): AxiosPromise<{{{returnType}}}{{^returnType}}void{{/returnType}}> {
return localVarFp.{{nickname}}({{#allParams.0}}{{#allParams}}requestParameters.{{paramName}}, {{/allParams}}{{/allParams.0}}options).then((request) => request(axios, basePath));
},
{{/useSingleRequestParameter}}

View File

@@ -22,6 +22,16 @@ let primitives = [
"any"
];
const supportedMediaTypes: { [mediaType: string]: number } = {
"application/json": Infinity,
"application/json-patch+json": 1,
"application/merge-patch+json": 1,
"application/strategic-merge-patch+json": 1,
"application/octet-stream": 0,
"application/x-www-form-urlencoded": 0
}
let enumsMap: Set<string> = new Set<string>([
{{#models}}
{{#model}}
@@ -49,58 +59,6 @@ let typeMap: {[index: string]: any} = {
{{/models}}
}
type MimeTypeDescriptor = {
type: string;
subtype: string;
subtypeTokens: string[];
};
/**
* Every mime-type consists of a type, subtype, and optional parameters.
* The subtype can be composite, including information about the content format.
* For example: `application/json-patch+json`, `application/merge-patch+json`.
*
* This helper transforms a string mime-type into an internal representation.
* This simplifies the implementation of predicates that in turn define common rules for parsing or stringifying
* the payload.
*/
const parseMimeType = (mimeType: string): MimeTypeDescriptor => {
const [type, subtype] = mimeType.split('/');
return {
type,
subtype,
subtypeTokens: subtype.split('+'),
};
};
type MimeTypePredicate = (mimeType: string) => boolean;
// This factory creates a predicate function that checks a string mime-type against defined rules.
const mimeTypePredicateFactory = (predicate: (descriptor: MimeTypeDescriptor) => boolean): MimeTypePredicate => (mimeType) => predicate(parseMimeType(mimeType));
// Use this factory when you need to define a simple predicate based only on type and, if applicable, subtype.
const mimeTypeSimplePredicateFactory = (type: string, subtype?: string): MimeTypePredicate => mimeTypePredicateFactory((descriptor) => {
if (descriptor.type !== type) return false;
if (subtype != null && descriptor.subtype !== subtype) return false;
return true;
});
// Creating a set of named predicates that will help us determine how to handle different mime-types
const isTextLikeMimeType = mimeTypeSimplePredicateFactory('text');
const isJsonMimeType = mimeTypeSimplePredicateFactory('application', 'json');
const isJsonLikeMimeType = mimeTypePredicateFactory((descriptor) => descriptor.type === 'application' && descriptor.subtypeTokens.some((item) => item === 'json'));
const isOctetStreamMimeType = mimeTypeSimplePredicateFactory('application', 'octet-stream');
const isFormUrlencodedMimeType = mimeTypeSimplePredicateFactory('application', 'x-www-form-urlencoded');
// Defining a list of mime-types in the order of prioritization for handling.
const supportedMimeTypePredicatesWithPriority: MimeTypePredicate[] = [
isJsonMimeType,
isJsonLikeMimeType,
isTextLikeMimeType,
isOctetStreamMimeType,
isFormUrlencodedMimeType,
];
export class ObjectSerializer {
public static findCorrectType(data: any, expectedType: string) {
if (data == undefined) {
@@ -246,27 +204,31 @@ export class ObjectSerializer {
}
const normalMediaTypes = mediaTypes.map(this.normalizeMediaType);
for (const predicate of supportedMimeTypePredicatesWithPriority) {
for (const mediaType of normalMediaTypes) {
if (mediaType != null && predicate(mediaType)) {
return mediaType;
}
let selectedMediaType: string | undefined = undefined;
let selectedRank: number = -Infinity;
for (const mediaType of normalMediaTypes) {
if (supportedMediaTypes[mediaType!] > selectedRank) {
selectedMediaType = mediaType;
selectedRank = supportedMediaTypes[mediaType!];
}
}
throw new Error("None of the given media types are supported: " + mediaTypes.join(", "));
if (selectedMediaType === undefined) {
throw new Error("None of the given media types are supported: " + mediaTypes.join(", "));
}
return selectedMediaType!;
}
/**
* Convert data to a string according the given media type
*/
public static stringify(data: any, mediaType: string): string {
if (isTextLikeMimeType(mediaType)) {
if (mediaType === "text/plain") {
return String(data);
}
if (isJsonLikeMimeType(mediaType)) {
if (mediaType === "application/json" || mediaType === "application/json-patch+json" || mediaType === "application/merge-patch+json" || mediaType === "application/strategic-merge-patch+json") {
return JSON.stringify(data);
}
@@ -281,14 +243,18 @@ export class ObjectSerializer {
throw new Error("Cannot parse content. No Content-Type defined.");
}
if (isTextLikeMimeType(mediaType)) {
if (mediaType === "text/plain") {
return rawData;
}
if (isJsonLikeMimeType(mediaType)) {
if (mediaType === "application/json" || mediaType === "application/json-patch+json" || mediaType === "application/merge-patch+json" || mediaType === "application/strategic-merge-patch+json") {
return JSON.parse(rawData);
}
if (mediaType === "text/html") {
return rawData;
}
throw new Error("The mediaType " + mediaType + " is not supported by ObjectSerializer.parse.");
}
}

View File

@@ -13,8 +13,8 @@
},
"dependencies": {
"lodash": "^4.17.21",
"zapier-platform-core": "15.5.1",
"form-data": "^4.0.0"
"zapier-platform-core": "15.4.1",
"form-data": "2.1.4"
},
"devDependencies": {
"mocha": "^10.2.0",
@@ -22,6 +22,6 @@
},
"private": true,
"zapier": {
"convertedByCLIVersion": "15.5.1"
"convertedByCLIVersion": "15.4.1"
}
}

View File

@@ -74,12 +74,10 @@ public class GoGinServerCodegenTest {
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
//files.forEach(File::deleteOnExit);
files.forEach(File::deleteOnExit);
TestUtils.assertFileContains(Paths.get(output + "/go/routers.go"),
"NewPetPost");
TestUtils.assertFileContains(Paths.get(output + "/go/api_default.go"),
" c.JSON(200, gin.H{\"status\": \"OK\"})");
}
}

View File

@@ -64,9 +64,7 @@ import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import junit.framework.AssertionFailedError;
import lombok.SneakyThrows;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenConstants;
@@ -766,50 +764,6 @@ public class JavaClientCodegenTest {
files.forEach(File::deleteOnExit);
}
@Test
public void testMultiPartSpecifiesFileName_Issue17367() throws IOException {
File output = Files.createTempDirectory("test").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("java")
.setLibrary(JavaClientCodegen.RESTEASY)
.setValidateSpec(false)
.setInputSpec("src/test/resources/3_0/issue-17367.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "true");
generator.setGenerateMetadata(false);
List<File> files = generator.opts(clientOptInput).generate();
try {
validateJavaSourceFiles(files);
File apiClient = files.stream()
.filter(f -> f.getName().equals("ApiClient.java"))
.findFirst()
.orElseThrow(() -> new AssertionFailedError(
"ApiClient.java not found"));
Stream<String> contents = Arrays.stream(Files.readString(apiClient.toPath(),
StandardCharsets.UTF_8).split("\n"));
// https://docs.jboss.org/resteasy/docs/6.2.5.Final/javadocs/org/jboss/resteasy/plugins/providers/multipart/MultipartFormDataOutput.html#addFormData(java.lang.String,java.lang.Object,jakarta.ws.rs.core.MediaType,java.lang.String)
assertTrue(contents.anyMatch(l -> l.matches(
".*multipart\\.addFormData\\(param.getKey\\(\\),\\s*" +
"new\\s+FileInputStream\\(file\\),\\s*" +
"MediaType\\.APPLICATION_OCTET_STREAM_TYPE,\\s*" +
"file.getName\\(\\)\\);.*")));
} finally {
files.forEach(File::deleteOnExit);
}
}
@Test
public void testAuthorizationsMethodsSizeWhenFiltered() {
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue4584.yaml");
@@ -2068,7 +2022,7 @@ public class JavaClientCodegenTest {
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
List<File> files = generator.opts(clientOptInput).generate();
Assert.assertEquals(files.size(), 27);
Assert.assertEquals(files.size(), 24);
validateJavaSourceFiles(files);
TestUtils.assertFileContains(
@@ -2272,30 +2226,6 @@ public class JavaClientCodegenTest {
+ " objectParam.getSomeInteger()));");
}
@Test
public void shouldProperlyExplodeWebClientQueryParameters() {
final Map<String, File> files = generateFromContract(
"src/test/resources/3_0/java/explode-query-parameter.yaml",
JavaClientCodegen.WEBCLIENT
);
JavaFileAssert.assertThat(files.get("DefaultApi.java"))
.printFileContent()
.assertMethod("searchRequestCreation")
.bodyContainsLines(
"queryParams.putAll(apiClient.parameterToMultiValueMap(null, \"regular-param\","
+ " regularParam));")
.bodyContainsLines(
"queryParams.putAll(apiClient.parameterToMultiValueMap(null, \"someString\","
+ " objectParam.getSomeString()));")
.bodyContainsLines(
"queryParams.putAll(apiClient.parameterToMultiValueMap(null, \"someBoolean\","
+ " objectParam.getSomeBoolean()));")
.bodyContainsLines(
"queryParams.putAll(apiClient.parameterToMultiValueMap(null, \"someInteger\","
+ " objectParam.getSomeInteger()));");
}
private static Map<String, File> generateFromContract(final String pathToSpecification, final String library) {
return generateFromContract(pathToSpecification, library, new HashMap<>());
}

View File

@@ -1,69 +0,0 @@
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright 2018 SmartBear Software
*
* 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.options;
import com.google.common.collect.ImmutableMap;
import org.openapitools.codegen.CodegenConstants;
import java.util.Map;
public class ScalaPekkoClientOptionsProvider implements OptionsProvider {
public static final String SOURCE_FOLDER_VALUE = "sourceFolder";
public static final String MODEL_PACKAGE_VALUE = "package";
public static final String API_PACKAGE_VALUE = "apiPackage";
public static final String SORT_PARAMS_VALUE = "false";
public static final String SORT_MODEL_PROPERTIES_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
public static final String MAIN_PACKAGE_VALUE = "net.test";
public static final String MODEL_PROPERTY_NAMING = "camelCase";
public static final String DATE_LIBRARY = "joda";
public static final String ENUM_UNKNOWN_DEFAULT_CASE_VALUE = "false";
@Override
public String getLanguage() {
return "scala-pekko";
}
@Override
public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE)
.put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE)
.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.SOURCE_FOLDER, SOURCE_FOLDER_VALUE)
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
.put("mainPackage", MAIN_PACKAGE_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING)
.put("dateLibrary", DATE_LIBRARY)
.put(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "true")
.put(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT, "true")
.put(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE, ENUM_UNKNOWN_DEFAULT_CASE_VALUE)
.build();
}
@Override
public boolean isServer() {
return false;
}
}

View File

@@ -402,6 +402,29 @@ public class PostmanCollectionCodegenTest {
assertFileContains(path, "\\\"acceptHeader\\\" : \\\"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\\\"");
}
@Test
public void testDeprecatedEndpoint() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
// verify request name (from path)
assertFileContains(path, "(DEPRECATED)");
}
@Test
public void testGeneratedVariables() throws Exception {
@@ -456,6 +479,36 @@ public class PostmanCollectionCodegenTest {
}
@Test
public void testHeaderParameters() throws IOException {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("./src/test/resources/SampleProject.yaml")
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
TestUtils.assertFileExists(path);
TestUtils.assertFileContains(path, "{ \"key\": \"Content-Type\", \"value\": \"application/json\"");
TestUtils.assertFileContains(path, "{ \"key\": \"Accept\", \"value\": \"application/json\"");
// header without default value (disabled: true)
TestUtils.assertFileContains(path, "{ \"key\": \"Custom-Header\", \"value\": \"\", \"description\": \"Custom HTTP header\", \"disabled\": true");
// header with default value (disabled: false)
TestUtils.assertFileContains(path, "{ \"key\": \"Another-Custom-Header\", \"value\": \"abc\", \"description\": \"Custom HTTP header with default\", \"disabled\": false");
}
@Test
public void testFormatDescription() {
@@ -702,4 +755,53 @@ public class PostmanCollectionCodegenTest {
assertEquals(true, postmanV2Generator.codegenOperationsByTag.containsKey("default"));
}
@Test
public void testRequiredQueryParameter() throws IOException {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
TestUtils.assertFileExists(path);
// verify param pUserId is set as disabled=false
TestUtils.assertFileContains(path, "{ \"key\": \"pUserId\", \"value\": \"888\", \"description\": \"Query Id.\", \"disabled\": false");
}
@Test
public void testQueryParameterDescription() throws IOException {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-v2")
.setInputSpec("./src/test/resources/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
TestUtils.assertFileExists(path);
// verify param pUserId is set as disabled=false
TestUtils.assertFileContains(path, "{ \"key\": \"pUserId\", \"value\": \"888\", \"description\": \"Query Id.\"");
}
}

View File

@@ -52,7 +52,7 @@ public class CamelCaseLambdaTest extends LambdaTest {
when(generator.escapeReservedWord("reservedWord")).thenReturn("escapedReservedWord");
// When & Then
test("escapedReservedWord", "{{#camelcase}}reserved-word{{/camelcase}}", ctx);
test("reservedWord", "{{#camelcase}}reserved-word{{/camelcase}}", ctx);
}
@Test
@@ -66,7 +66,7 @@ public class CamelCaseLambdaTest extends LambdaTest {
when(generator.toParamName("inputText")).thenReturn("inputTextAsParam");
// When & Then
test("inputTextAsParam", "{{#camelcase}}Input_text{{/camelcase}}", ctx);
test("inputText", "{{#camelcase}}Input_text{{/camelcase}}", ctx);
}
}

View File

@@ -43,7 +43,7 @@ public class LowercaseLambdaTest extends LambdaTest {
when(generator.escapeReservedWord("reserved")).thenReturn("escaped-reserved");
// When & Then
test("escaped-reserved", "{{#lowercase}}rEservEd{{/lowercase}}", ctx);
test("reserved", "{{#lowercase}}rEservEd{{/lowercase}}", ctx);
}
}

View File

@@ -55,7 +55,7 @@ public class PascalCaseLambdaTest extends LambdaTest {
when(generator.escapeReservedWord("ReservedWord")).thenReturn("escapedReservedWord");
// When & Then
test("escapedReservedWord", "{{#pascalcase}}reserved-word{{/pascalcase}}", ctx);
test("ReservedWord", "{{#pascalcase}}reserved-word{{/pascalcase}}", ctx);
}
@Test
@@ -69,7 +69,7 @@ public class PascalCaseLambdaTest extends LambdaTest {
when(generator.toParamName("InputText")).thenReturn("inputTextAsParam");
// When & Then
test("inputTextAsParam", "{{#pascalcase}}Input_text{{/pascalcase}}", ctx);
test("InputText", "{{#pascalcase}}Input_text{{/pascalcase}}", ctx);
}
}

View File

@@ -96,9 +96,4 @@ components:
mum_or_dad:
type: string
required:
- isParent
allOfWithSingleItem:
description: allOf with a single item
nullable: true
allOf:
- $ref: '#/components/schemas/AnotherParent'
- isParent

View File

@@ -135,53 +135,6 @@ paths:
security:
- petstore_auth:
- 'read:pets'
/pet/searchPetWithManyFilters:
get:
tags:
- pet
summary: Search Pets by filters
description: >-
Search endpoint
operationId: searchPet
parameters:
- name: age
in: query
description: age of the pet
schema:
type: integer
format: int64
nullable: true
- name: price
in: query
description: Price of the pet
schema:
type: number
nullable: true
- name: bornAfter
in: query
description: Find pets born after this date
style: form
explode: false
schema:
type: string
format: date-time
nullable: true
- description: Is the pet classified as old
in: query
name: old
schema:
type: boolean
nullable: true
style: form
responses:
'200':
description: successful operation
content:
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
/pet/findByTags:
get:
tags:
@@ -220,10 +173,6 @@ paths:
schema:
type: string
format: date-time
- name: colour
in: query
schema:
$ref: '#/components/schemas/Colour'
responses:
'200':
description: successful operation
@@ -1079,12 +1028,6 @@ components:
enum:
- male
- female
Colour:
type: string
nullable: true
enum:
- Blue
- White
ApiResponse:
title: An uploaded response
description: Describes the result of uploading an image resource

View File

@@ -1,24 +0,0 @@
openapi: 3.0.0
info:
version: 1.0.0
title: Foo API
servers:
- url: http://127.0.0.1:8080/{basePath}
variables:
basePath:
default: v1
paths:
/foo:
post:
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
bar:
type: string
format: binary
responses:
'200':
description: OK

View File

@@ -1365,19 +1365,6 @@ paths:
type: array
items:
$ref: "#/components/schemas/ListOfObjects"
/fake/ref_enum_string:
get:
tags:
- fake
summary: test ref to enum string
operationId: fake_ref_enum_string
responses:
200:
description: OK
content:
plain/text:
schema:
$ref: "#/components/schemas/EnumClass"
servers:
- url: 'http://{server}.swagger.io:{port}/v2'
description: petstore server

View File

@@ -1,742 +0,0 @@
openapi: 3.0.0
servers:
- url: 'https://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
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
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:
'200':
description: successful operation
'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:
- auth_cookie: []
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:
- auth_cookie: []
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:
- auth_cookie: []
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 `auth_cookie`
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:
- auth_cookie: []
'/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:
- auth_cookie: []
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:
- auth_cookie: []
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
auth_cookie:
type: apiKey
name: AUTH_KEY
in: cookie
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
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

View File

@@ -599,30 +599,10 @@ paths:
responses:
'200':
$ref: '#/components/responses/ref'
/ref/ref_to_parameter:
get:
operationId: ref_to_ref_parameter
tags:
- fake
responses:
'200':
$ref: '#/components/responses/ref'
parameters:
- $ref: '#/components/parameters/ref_to_uuid'
externalDocs:
description: Find out more about Swagger
url: 'http://swagger.io'
components:
parameters:
ref_to_uuid:
description: to test ref to parameter (uuid)
name: ref_to_uuid
in: header
required: true
schema:
type: string
format: uuid
example: 61864654-6e6b-4152-a62f-795fdd606bc2
requestBodies:
UserArray:
content:
@@ -842,8 +822,3 @@ components:
any_type_test:
properties:
any_type_property: {}
array_prop:
type: array
description: test array in 3.1 spec
items:
type: string

View File

@@ -13,7 +13,7 @@
<packaging>pom</packaging>
<name>openapi-generator-project</name>
<!-- RELEASE_VERSION -->
<version>7.2.0</version>
<version>7.2.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<url>https://github.com/openapitools/openapi-generator</url>
<scm>
@@ -1239,7 +1239,7 @@
<slf4j.version>1.7.36</slf4j.version>
<spotbugs-plugin.version>3.1.12.2</spotbugs-plugin.version>
<swagger-parser-groupid.version>io.swagger.parser.v3</swagger-parser-groupid.version>
<swagger-parser.version>2.1.19</swagger-parser.version>
<swagger-parser.version>2.1.18</swagger-parser.version>
<testng.version>7.5</testng.version>
<violations-maven-plugin.version>1.34</violations-maven-plugin.version>
<wagon-ssh-external.version>3.4.3</wagon-ssh-external.version>

View File

@@ -13,7 +13,6 @@ package openapi
import (
"encoding/json"
"bytes"
"fmt"
)
@@ -255,7 +254,7 @@ func (o Pet) ToMap() (map[string]interface{}, error) {
return toSerialize, nil
}
func (o *Pet) UnmarshalJSON(data []byte) (err error) {
func (o *Pet) UnmarshalJSON(bytes []byte) (err error) {
// This validates that all required properties are included in the JSON object
// by unmarshalling the object into a generic map with string keys and checking
// that every required field exists as a key in the generic map.
@@ -266,7 +265,7 @@ func (o *Pet) UnmarshalJSON(data []byte) (err error) {
allProperties := make(map[string]interface{})
err = json.Unmarshal(data, &allProperties)
err = json.Unmarshal(bytes, &allProperties)
if err != nil {
return err;
@@ -280,9 +279,7 @@ func (o *Pet) UnmarshalJSON(data []byte) (err error) {
varPet := _Pet{}
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
err = decoder.Decode(&varPet)
err = json.Unmarshal(bytes, &varPet)
if err != nil {
return err

View File

@@ -810,7 +810,7 @@ public class ApiClient extends JavaTimeFormatter {
}
private void logResponse(ClientHttpResponse response) throws IOException {
log.info("HTTP Status Code: " + response.getStatusCode().value());
log.info("HTTP Status Code: " + response.getRawStatusCode());
log.info("Status Text: " + response.getStatusText());
log.info("HTTP Headers: " + headersToString(response.getHeaders()));
log.info("Response Body: " + bodyToString(response.getBody()));

View File

@@ -239,6 +239,7 @@ class AuthApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}
@@ -482,6 +483,7 @@ class AuthApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}

View File

@@ -247,6 +247,7 @@ class BodyApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}
@@ -502,6 +503,7 @@ class BodyApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}
@@ -777,6 +779,7 @@ class BodyApi:
_host = None
_collection_formats: Dict[str, str] = {
'files': 'csv',
}
@@ -1048,6 +1051,7 @@ class BodyApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}
@@ -1318,6 +1322,7 @@ class BodyApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}
@@ -1588,6 +1593,7 @@ class BodyApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}
@@ -1858,6 +1864,7 @@ class BodyApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}
@@ -2128,6 +2135,7 @@ class BodyApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}

View File

@@ -282,6 +282,7 @@ class FormApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}
@@ -621,6 +622,7 @@ class FormApi:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}

Some files were not shown because too many files have changed in this diff Show More