forked from loafle/openapi-generator-original
Merge remote-tracking branch 'origin/master' into 5.1.x
This commit is contained in:
commit
18bec1da28
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -7,5 +7,5 @@
|
||||
- [ ] Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
|
||||
- [ ] If contributing template-only or documentation-only changes which will change sample output, [build the project](https://github.com/OpenAPITools/openapi-generator#14---build-projects) beforehand.
|
||||
- [ ] Run the shell script `./bin/generate-samples.sh`to update all Petstore samples related to your fix. This is important, as CI jobs will verify _all_ generator outputs of your HEAD commit as it would merge with master. These must match the expectations made by your contribution. You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example `./bin/generate-samples.sh bin/configs/java*`. For Windows users, please run the script in [Git BASH](https://gitforwindows.org/).
|
||||
- [ ] File the PR against the [correct branch](https://github.com/OpenAPITools/openapi-generator/wiki/Git-Branches): `master`
|
||||
- [ ] File the PR against the [correct branch](https://github.com/OpenAPITools/openapi-generator/wiki/Git-Branches): `master`, `5.1.x`, `6.0.x`
|
||||
- [ ] Copy the [technical committee](https://github.com/openapitools/openapi-generator/#62---openapi-generator-technical-committee) to review the pull request if your PR is targeting a particular programming language.
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -258,3 +258,6 @@ samples/client/petstore/c/*.so
|
||||
# Ruby
|
||||
samples/openapi3/client/petstore/ruby/Gemfile.lock
|
||||
samples/openapi3/client/petstore/ruby-faraday/Gemfile.lock
|
||||
|
||||
# Crystal
|
||||
samples/client/petstore/crystal/lib
|
||||
|
117
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
117
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2007-present the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MavenWrapperDownloader {
|
||||
|
||||
private static final String WRAPPER_VERSION = "0.5.6";
|
||||
/**
|
||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
|
||||
*/
|
||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
|
||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
|
||||
|
||||
/**
|
||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
|
||||
* use instead of the default one.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
|
||||
".mvn/wrapper/maven-wrapper.properties";
|
||||
|
||||
/**
|
||||
* Path where the maven-wrapper.jar will be saved to.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_JAR_PATH =
|
||||
".mvn/wrapper/maven-wrapper.jar";
|
||||
|
||||
/**
|
||||
* Name of the property which should be used to override the default download url for the wrapper.
|
||||
*/
|
||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("- Downloader started");
|
||||
File baseDirectory = new File(args[0]);
|
||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
||||
|
||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
||||
// wrapperUrl parameter.
|
||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
||||
String url = DEFAULT_DOWNLOAD_URL;
|
||||
if(mavenWrapperPropertyFile.exists()) {
|
||||
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
||||
try {
|
||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
||||
Properties mavenWrapperProperties = new Properties();
|
||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
||||
} finally {
|
||||
try {
|
||||
if(mavenWrapperPropertyFileInputStream != null) {
|
||||
mavenWrapperPropertyFileInputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore ...
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading from: " + url);
|
||||
|
||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
||||
if(!outputFile.getParentFile().exists()) {
|
||||
if(!outputFile.getParentFile().mkdirs()) {
|
||||
System.out.println(
|
||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
||||
try {
|
||||
downloadFileFromURL(url, outputFile);
|
||||
System.out.println("Done");
|
||||
System.exit(0);
|
||||
} catch (Throwable e) {
|
||||
System.out.println("- Error downloading");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
||||
String username = System.getenv("MVNW_USERNAME");
|
||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
URL website = new URL(urlString);
|
||||
ReadableByteChannel rbc;
|
||||
rbc = Channels.newChannel(website.openStream());
|
||||
FileOutputStream fos = new FileOutputStream(destination);
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
fos.close();
|
||||
rbc.close();
|
||||
}
|
||||
|
||||
}
|
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Binary file not shown.
3
.mvn/wrapper/maven-wrapper.properties
vendored
3
.mvn/wrapper/maven-wrapper.properties
vendored
@ -1 +1,2 @@
|
||||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
|
17
.travis.yml
17
.travis.yml
@ -62,6 +62,17 @@ addons:
|
||||
- petstore.swagger.io
|
||||
|
||||
before_install:
|
||||
# to run petstore server locally via docker
|
||||
- echo "$DOCKER_HUB_PASSWORD" | docker login --username=$DOCKER_HUB_USERNAME --password-stdin || true
|
||||
- docker pull swaggerapi/petstore
|
||||
- docker run -d -e SWAGGER_HOST=http://petstore.swagger.io -e SWAGGER_BASE_PATH=/v2 -p 80:8080 swaggerapi/petstore
|
||||
- docker ps -a
|
||||
# install crystal
|
||||
- curl -sSL https://dist.crystal-lang.org/apt/setup.sh | sudo bash
|
||||
- curl -sL "https://keybase.io/crystal/pgp_keys.asc" | sudo apt-key add -
|
||||
- echo "deb https://dist.crystal-lang.org/apt crystal main" | sudo tee /etc/apt/sources.list.d/crystal.list
|
||||
- sudo apt-get update
|
||||
- sudo apt install crystal
|
||||
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.22.0
|
||||
- export PATH="$HOME/.yarn/bin:$PATH"
|
||||
# install rust
|
||||
@ -75,10 +86,6 @@ before_install:
|
||||
- npm config set registry http://registry.npmjs.org/
|
||||
# set python 3.6.3 as default
|
||||
- source ~/virtualenv/python3.6/bin/activate
|
||||
# to run petstore server locally via docker
|
||||
- docker pull swaggerapi/petstore
|
||||
- docker run -d -e SWAGGER_HOST=http://petstore.swagger.io -e SWAGGER_BASE_PATH=/v2 -p 80:8080 swaggerapi/petstore
|
||||
- docker ps -a
|
||||
# -- skip bash test to shorten build time
|
||||
# Add bats test framework and cURL for Bash script integration tests
|
||||
#- sudo add-apt-repository ppa:duggan/bats --yes
|
||||
@ -124,7 +131,7 @@ before_install:
|
||||
fi;
|
||||
- pushd .; cd website; yarn install; popd
|
||||
# install Deno
|
||||
- sh -s v1.1.2 < ./CI/deno_install.sh
|
||||
- sh -s v1.6.2 < ./CI/deno_install.sh
|
||||
- export PATH="$HOME/.deno/bin:$PATH"
|
||||
|
||||
install:
|
||||
|
@ -41,13 +41,14 @@ elif [ "$NODE_INDEX" = "2" ]; then
|
||||
curl -sSL https://get.haskellstack.org/ | sh
|
||||
stack upgrade
|
||||
stack --version
|
||||
# install r
|
||||
# prepare r
|
||||
sudo sh -c 'echo "deb http://cran.rstudio.com/bin/linux/ubuntu trusty/" >> /etc/apt/sources.list'
|
||||
gpg --keyserver keyserver.ubuntu.com --recv-key E084DAB9
|
||||
gpg -a --export E084DAB9 | sudo apt-key add -
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install r-base
|
||||
R --version
|
||||
|
||||
# install curl
|
||||
sudo apt-get -y build-dep libcurl4-gnutls-dev
|
||||
sudo apt-get -y install libcurl4-gnutls-dev
|
||||
|
@ -49,6 +49,7 @@ Code change should conform to the programming style guide of the respective lang
|
||||
- C++: https://google.github.io/styleguide/cppguide.html
|
||||
- C++ (Tizen): https://wiki.tizen.org/Native_Platform_Coding_Idiom_and_Style_Guide#C.2B.2B_Coding_Style
|
||||
- Clojure: https://github.com/bbatsov/clojure-style-guide
|
||||
- Crystal: https://crystal-lang.org/reference/conventions/coding_style.html
|
||||
- Dart: https://www.dartlang.org/guides/language/effective-dart/style
|
||||
- Elixir: https://github.com/christopheradams/elixir_style_guide
|
||||
- Eiffel: https://www.eiffel.org/doc/eiffel/Coding%20Standards
|
||||
|
32
README.md
32
README.md
@ -9,7 +9,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[Master](https://github.com/OpenAPITools/openapi-generator/tree/master) (`5.0.0`):
|
||||
[Master](https://github.com/OpenAPITools/openapi-generator/tree/master) (`5.0.1`):
|
||||
[](https://travis-ci.org/OpenAPITools/openapi-generator)
|
||||
[](https://circleci.com/gh/OpenAPITools/openapi-generator)
|
||||
[](https://app.shippable.com/github/OpenAPITools/openapi-generator)
|
||||
@ -18,6 +18,22 @@
|
||||
[](https://app.bitrise.io/app/4a2b10a819d12b67)
|
||||
[](https://github.com/OpenAPITools/openapi-generator/actions?query=workflow%3A%22Check+Supported+Java+Versions%22)
|
||||
|
||||
[5.1.x](https://github.com/OpenAPITools/openapi-generator/tree/5.1.x) (`5.1.x`):
|
||||
[](https://travis-ci.org/OpenAPITools/openapi-generator)
|
||||
[](https://circleci.com/gh/OpenAPITools/openapi-generator)
|
||||
[](https://app.shippable.com/github/OpenAPITools/openapi-generator)
|
||||
[](https://ci.appveyor.com/project/WilliamCheng/openapi-generator-wh2wu)
|
||||
[](https://cloud.drone.io/OpenAPITools/openapi-generator)
|
||||
[](https://app.bitrise.io/app/4a2b10a819d12b67)
|
||||
|
||||
[6.0.x](https://github.com/OpenAPITools/openapi-generator/tree/6.0.x) (`6.0.x`):
|
||||
[](https://travis-ci.org/OpenAPITools/openapi-generator)
|
||||
[](https://circleci.com/gh/OpenAPITools/openapi-generator)
|
||||
[](https://app.shippable.com/github/OpenAPITools/openapi-generator)
|
||||
[](https://ci.appveyor.com/project/WilliamCheng/openapi-generator-wh2wu)
|
||||
[](https://cloud.drone.io/OpenAPITools/openapi-generator)
|
||||
[](https://app.bitrise.io/app/4a2b10a819d12b67)
|
||||
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
@ -60,11 +76,11 @@ 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.0, .NET Core 2.0), **C++** (cpp-restsdk, Qt5, Tizen), **Clojure**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Jersey1.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), **k6**, **Kotlin**, **Lua**, **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** (rust, rust-server), **Scala** (akka, http4s, scalaz, sttp, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x, 5.x), **Typescript** (AngularJS, Angular (2.x - 8.x), Aurelia, Axios, Fetch, Inversify, jQuery, Node, Rxjs) |
|
||||
| **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.0, .NET Core 2.0), **C++** (cpp-restsdk, Qt5, Tizen), **Clojure**, **Crystal**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Jersey1.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), **k6**, **Kotlin**, **Lua**, **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** (rust, rust-server), **Scala** (akka, http4s, scalaz, sttp, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x, 5.x), **Typescript** (AngularJS, Angular (2.x - 8.x), Aurelia, Axios, Fetch, Inversify, jQuery, Node, Rxjs) |
|
||||
| **Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin), **Haskell** (Servant), **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/)), **Kotlin** (Spring Boot, Ktor, Vertx), **PHP** (Laravel, Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (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** |
|
||||
| **Configuration files** | [**Apache2**](https://httpd.apache.org/) |
|
||||
| **Others** | **GraphQL**, **JMeter**, **MySQL Schema**, **Protocol Buffer** |
|
||||
| **Others** | **GraphQL**, **JMeter**, **Ktorm**, **MySQL Schema**, **Protocol Buffer** |
|
||||
|
||||
## Table of contents
|
||||
|
||||
@ -102,7 +118,9 @@ The OpenAPI Specification has undergone 3 revisions since initial creation in 20
|
||||
|
||||
| OpenAPI Generator Version | Release Date | Notes |
|
||||
| --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------------------------------- |
|
||||
| 5.0.1 (upcoming patch release) [SNAPSHOT](https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/5.0.1-SNAPSHOT/) | TBD | Patch release with enhancements, bug fixes, etc |
|
||||
| 6.0.0 (upcoming major release) [SNAPSHOT](https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/6.0.0-SNAPSHOT/) | Nov/Dec 2021 | Minor release with breaking changes (no fallback) |
|
||||
| 5.1.0 (upcoming minor release) [SNAPSHOT](https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/5.1.0-SNAPSHOT/) | Mar/Apr 2021 | Minor release with breaking changes (with fallback) |
|
||||
| 5.0.1 (upcoming patch release) [SNAPSHOT](https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/5.0.1-SNAPSHOT/) | Jan/Feb 2021 | Patch release with enhancements, bug fixes, etc |
|
||||
| [5.0.0](https://github.com/OpenAPITools/openapi-generator/releases/tag/v5.0.0) (latest stable release) | 21.12.2020 | Major release with breaking changes (no fallback) |
|
||||
| [4.3.1](https://github.com/OpenAPITools/openapi-generator/releases/tag/v4.3.1) | 06.05.2020 | Patch release (enhancements, bug fixes, etc) |
|
||||
|
||||
@ -824,6 +842,7 @@ Here is a list of template creators:
|
||||
* C# (.NET Standard 1.3 ): @Gronsak
|
||||
* C# (.NET 4.5 refactored): @jimschubert [:heart:](https://www.patreon.com/jimschubert)
|
||||
* Clojure: @xhh
|
||||
* Crystal: @wing328
|
||||
* Dart: @yissachar
|
||||
* Dart (refactor): @joernahrens
|
||||
* Dart 2: @swipesight
|
||||
@ -939,6 +958,7 @@ Here is a list of template creators:
|
||||
* Schema
|
||||
* Avro: @sgadouar
|
||||
* GraphQL: @wing328 [:heart:](https://www.patreon.com/wing328)
|
||||
* Ktorm: @Luiz-Monad
|
||||
* MySQL: @ybelenko
|
||||
* Protocol Buffer: @wing328
|
||||
|
||||
@ -990,11 +1010,11 @@ If you want to join the committee, please kindly apply by sending an email to te
|
||||
| Elm | @eriktim (2018/09) |
|
||||
| Erlang | @tsloughter (2017/11) @jfacorro (2018/10) @robertoaloi (2018/10) |
|
||||
| F# | @nmfisher (2019/05) |
|
||||
| Go | @antihax (2017/11) @grokify (2018/07) @kemokemo (2018/09) @bkabrda (2019/07) |
|
||||
| Go | @antihax (2017/11) @grokify (2018/07) @kemokemo (2018/09) @jirikuncar (2021/01) |
|
||||
| GraphQL | @renepardon (2018/12) |
|
||||
| Groovy | |
|
||||
| Haskell | |
|
||||
| Java | @bbdouglas (2017/07) @sreeshas (2017/08) @jfiala (2017/08) @lukoyanov (2017/09) @cbornet (2017/09) @jeff9finger (2018/01) @karismann (2019/03) @Zomzog (2019/04) @lwlee2608 (2019/10) @bkabrda (2020/01) |
|
||||
| Java | @bbdouglas (2017/07) @sreeshas (2017/08) @jfiala (2017/08) @lukoyanov (2017/09) @cbornet (2017/09) @jeff9finger (2018/01) @karismann (2019/03) @Zomzog (2019/04) @lwlee2608 (2019/10) @nmuesch (2021/01) |
|
||||
| Kotlin | @jimschubert (2017/09) [:heart:](https://www.patreon.com/jimschubert), @dr4ke616 (2018/08) @karismann (2019/03) @Zomzog (2019/04) @andrewemery (2019/10) @4brunu (2019/11) @yutaka0m (2020/03) |
|
||||
| Lua | @daurnimator (2017/08) |
|
||||
| Nim | |
|
||||
|
9
bin/configs/crystal.yaml
Normal file
9
bin/configs/crystal.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
generatorName: crystal
|
||||
outputDir: samples/client/petstore/crystal
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/crystal
|
||||
additionalProperties:
|
||||
shardVersion: 1.0.0
|
||||
moduleName: Petstore
|
||||
shardName: petstore
|
||||
strictSpecBehavior: false
|
7
bin/configs/ktorm-schema.yaml
Normal file
7
bin/configs/ktorm-schema.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
generatorName: ktorm-schema
|
||||
outputDir: samples/schema/petstore/ktorm
|
||||
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/ktorm-schema
|
||||
additionalProperties:
|
||||
hideGenerationTimestamp: true
|
||||
importModelPackageName: org.openapitools.client.models
|
8
bin/configs/ruby-extensions-x-auth-id-alias.yaml
Normal file
8
bin/configs/ruby-extensions-x-auth-id-alias.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
generatorName: ruby
|
||||
outputDir: samples/openapi3/client/extensions/x-auth-id-alias/ruby-client
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/extensions/x-auth-id-alias.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/ruby-client
|
||||
additionalProperties:
|
||||
gemName: x_auth_id_alias
|
||||
gemVersion: 1.0.0
|
||||
moduleName: XAuthIDAlias
|
6
bin/configs/typescript-angular-v9-provided-in-any.yaml
Normal file
6
bin/configs/typescript-angular-v9-provided-in-any.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
generatorName: typescript-angular
|
||||
outputDir: samples/client/petstore/typescript-angular-v9-provided-in-any/builds/default
|
||||
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
|
||||
additionalProperties:
|
||||
ngVersion: 9.0.0
|
||||
providedIn: any
|
@ -53,6 +53,7 @@ Code change should conform to the programming style guide of the respective lang
|
||||
- C++: https://google.github.io/styleguide/cppguide.html
|
||||
- C++ (Tizen): https://wiki.tizen.org/Native_Platform_Coding_Idiom_and_Style_Guide#C.2B.2B_Coding_Style
|
||||
- Clojure: https://github.com/bbatsov/clojure-style-guide
|
||||
- Crystal: https://crystal-lang.org/reference/conventions/coding_style.html
|
||||
- Dart: https://www.dartlang.org/guides/language/effective-dart/style
|
||||
- Elixir: https://github.com/christopheradams/elixir_style_guide
|
||||
- Eiffel: https://www.eiffel.org/doc/eiffel/Coding%20Standards
|
||||
|
@ -16,6 +16,7 @@ The following generators are available:
|
||||
* [cpp-restsdk](generators/cpp-restsdk.md)
|
||||
* [cpp-tizen](generators/cpp-tizen.md)
|
||||
* [cpp-ue4 (beta)](generators/cpp-ue4.md)
|
||||
* [crystal (beta)](generators/crystal.md)
|
||||
* [csharp](generators/csharp.md)
|
||||
* [csharp-dotnet2 (deprecated)](generators/csharp-dotnet2.md)
|
||||
* [csharp-netcore](generators/csharp-netcore.md)
|
||||
@ -141,6 +142,7 @@ The following generators are available:
|
||||
## SCHEMA generators
|
||||
* [avro-schema (beta)](generators/avro-schema.md)
|
||||
* [graphql-schema](generators/graphql-schema.md)
|
||||
* [ktorm-schema (beta)](generators/ktorm-schema.md)
|
||||
* [mysql-schema](generators/mysql-schema.md)
|
||||
* [protobuf-schema (beta)](generators/protobuf-schema.md)
|
||||
|
||||
|
@ -56,41 +56,109 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
||||
<li>_noreturn</li>
|
||||
<li>_static_assert</li>
|
||||
<li>_thread_local</li>
|
||||
<li>alignas</li>
|
||||
<li>alignof</li>
|
||||
<li>and</li>
|
||||
<li>and_eq</li>
|
||||
<li>asm</li>
|
||||
<li>atomic_cancel</li>
|
||||
<li>atomic_commit</li>
|
||||
<li>atomic_noexcept</li>
|
||||
<li>auto</li>
|
||||
<li>bitand</li>
|
||||
<li>bitor</li>
|
||||
<li>bool</li>
|
||||
<li>break</li>
|
||||
<li>case</li>
|
||||
<li>catch</li>
|
||||
<li>char</li>
|
||||
<li>char16_t</li>
|
||||
<li>char32_t</li>
|
||||
<li>char8_t</li>
|
||||
<li>class</li>
|
||||
<li>co_await</li>
|
||||
<li>co_return</li>
|
||||
<li>co_yield</li>
|
||||
<li>compl</li>
|
||||
<li>concept</li>
|
||||
<li>const</li>
|
||||
<li>const_cast</li>
|
||||
<li>consteval</li>
|
||||
<li>constexpr</li>
|
||||
<li>constinit</li>
|
||||
<li>continue</li>
|
||||
<li>decltype</li>
|
||||
<li>default</li>
|
||||
<li>delete</li>
|
||||
<li>do</li>
|
||||
<li>double</li>
|
||||
<li>dynamic_cast</li>
|
||||
<li>else</li>
|
||||
<li>enum</li>
|
||||
<li>explicit</li>
|
||||
<li>export</li>
|
||||
<li>extern</li>
|
||||
<li>false</li>
|
||||
<li>final</li>
|
||||
<li>float</li>
|
||||
<li>for</li>
|
||||
<li>friend</li>
|
||||
<li>goto</li>
|
||||
<li>if</li>
|
||||
<li>inline</li>
|
||||
<li>int</li>
|
||||
<li>long</li>
|
||||
<li>mutable</li>
|
||||
<li>namespace</li>
|
||||
<li>new</li>
|
||||
<li>noexcept</li>
|
||||
<li>not</li>
|
||||
<li>not_eq</li>
|
||||
<li>nullptr</li>
|
||||
<li>operator</li>
|
||||
<li>or</li>
|
||||
<li>or_eq</li>
|
||||
<li>override</li>
|
||||
<li>private</li>
|
||||
<li>protected</li>
|
||||
<li>public</li>
|
||||
<li>reflexpr</li>
|
||||
<li>register</li>
|
||||
<li>reinterpret_cast</li>
|
||||
<li>remove</li>
|
||||
<li>requires</li>
|
||||
<li>restrict</li>
|
||||
<li>return</li>
|
||||
<li>short</li>
|
||||
<li>signed</li>
|
||||
<li>sizeof</li>
|
||||
<li>static</li>
|
||||
<li>static_assert</li>
|
||||
<li>static_cast</li>
|
||||
<li>struct</li>
|
||||
<li>switch</li>
|
||||
<li>synchronized</li>
|
||||
<li>template</li>
|
||||
<li>this</li>
|
||||
<li>thread_local</li>
|
||||
<li>throw</li>
|
||||
<li>transaction_safe</li>
|
||||
<li>transaction_safe_dynamic</li>
|
||||
<li>true</li>
|
||||
<li>try</li>
|
||||
<li>typedef</li>
|
||||
<li>typeid</li>
|
||||
<li>typename</li>
|
||||
<li>union</li>
|
||||
<li>unsigned</li>
|
||||
<li>using</li>
|
||||
<li>virtual</li>
|
||||
<li>void</li>
|
||||
<li>volatile</li>
|
||||
<li>wchar_t</li>
|
||||
<li>while</li>
|
||||
<li>xor</li>
|
||||
<li>xor_eq</li>
|
||||
</ul>
|
||||
|
||||
## FEATURE SET
|
||||
|
226
docs/generators/crystal.md
Normal file
226
docs/generators/crystal.md
Normal file
@ -0,0 +1,226 @@
|
||||
---
|
||||
title: Config Options for crystal
|
||||
sidebar_label: crystal
|
||||
---
|
||||
|
||||
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|
|
||||
|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|
|
||||
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
|
||||
|legacyDiscriminatorBehavior|Set to true 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|
|
||||
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|
||||
|shardAuthor|shard author (only one is supported).| |null|
|
||||
|shardAuthorEmail|shard author email (only one is supported).| |null|
|
||||
|shardDescription|shard description.| |This shard maps to a REST API|
|
||||
|shardHomepage|shard homepage.| |http://org.openapitools|
|
||||
|shardLicense|shard license.| |unlicense|
|
||||
|shardName|shard name (e.g. twitter_client| |openapi_client|
|
||||
|shardVersion|shard version.| |1.0.0|
|
||||
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|
||||
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|
||||
|
||||
## IMPORT MAPPING
|
||||
|
||||
| Type/Alias | Imports |
|
||||
| ---------- | ------- |
|
||||
|
||||
|
||||
## INSTANTIATION TYPES
|
||||
|
||||
| Type/Alias | Instantiated By |
|
||||
| ---------- | --------------- |
|
||||
|array|Array|
|
||||
|map|Hash|
|
||||
|set|Set|
|
||||
|
||||
|
||||
## LANGUAGE PRIMITIVES
|
||||
|
||||
<ul class="column-ul">
|
||||
<li>Array</li>
|
||||
<li>Boolean</li>
|
||||
<li>Date</li>
|
||||
<li>File</li>
|
||||
<li>Float</li>
|
||||
<li>Hash</li>
|
||||
<li>Integer</li>
|
||||
<li>Object</li>
|
||||
<li>String</li>
|
||||
<li>Time</li>
|
||||
</ul>
|
||||
|
||||
## RESERVED WORDS
|
||||
|
||||
<ul class="column-ul">
|
||||
<li>abstract</li>
|
||||
<li>alias</li>
|
||||
<li>as</li>
|
||||
<li>as?</li>
|
||||
<li>asm</li>
|
||||
<li>begin</li>
|
||||
<li>break</li>
|
||||
<li>case</li>
|
||||
<li>class</li>
|
||||
<li>def</li>
|
||||
<li>do</li>
|
||||
<li>else</li>
|
||||
<li>elsif</li>
|
||||
<li>end</li>
|
||||
<li>ensure</li>
|
||||
<li>enum</li>
|
||||
<li>extend</li>
|
||||
<li>false</li>
|
||||
<li>for</li>
|
||||
<li>fun</li>
|
||||
<li>if</li>
|
||||
<li>in</li>
|
||||
<li>include</li>
|
||||
<li>instance</li>
|
||||
<li>is_a?</li>
|
||||
<li>lib</li>
|
||||
<li>macro</li>
|
||||
<li>module</li>
|
||||
<li>next</li>
|
||||
<li>nil</li>
|
||||
<li>nil?</li>
|
||||
<li>of</li>
|
||||
<li>out</li>
|
||||
<li>pointerof</li>
|
||||
<li>private</li>
|
||||
<li>protected</li>
|
||||
<li>require</li>
|
||||
<li>rescue</li>
|
||||
<li>responds_to?</li>
|
||||
<li>return</li>
|
||||
<li>select</li>
|
||||
<li>self</li>
|
||||
<li>sizeof</li>
|
||||
<li>struct</li>
|
||||
<li>super</li>
|
||||
<li>then</li>
|
||||
<li>true</li>
|
||||
<li>type</li>
|
||||
<li>typeof</li>
|
||||
<li>uninitialized</li>
|
||||
<li>union</li>
|
||||
<li>unless</li>
|
||||
<li>until</li>
|
||||
<li>verbatim</li>
|
||||
<li>when</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
|
||||
|Array|✓|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
|
||||
|
||||
### Security Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|BasicAuth|✓|OAS2,OAS3
|
||||
|ApiKey|✓|OAS2,OAS3
|
||||
|OpenIDConnect|✗|OAS3
|
||||
|BearerToken|✓|OAS3
|
||||
|OAuth2_Implicit|✓|OAS2,OAS3
|
||||
|OAuth2_Password|✗|OAS2,OAS3
|
||||
|OAuth2_ClientCredentials|✗|OAS2,OAS3
|
||||
|OAuth2_AuthorizationCode|✗|OAS2,OAS3
|
||||
|
||||
### Wire Format Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|JSON|✓|OAS2,OAS3
|
||||
|XML|✓|OAS2,OAS3
|
||||
|PROTOBUF|✗|ToolingExtension
|
||||
|Custom|✓|OAS2,OAS3
|
355
docs/generators/ktorm-schema.md
Normal file
355
docs/generators/ktorm-schema.md
Normal file
@ -0,0 +1,355 @@
|
||||
---
|
||||
title: Config Options for ktorm-schema
|
||||
sidebar_label: ktorm-schema
|
||||
---
|
||||
|
||||
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 |
|
||||
| ------ | ----------- | ------ | ------- |
|
||||
|addSurrogateKey|Adds the surrogate key for all models that don't already have a primary key (named by the above convention)| |false|
|
||||
|artifactId|Generated artifact id (name of jar).| |ktorm|
|
||||
|artifactVersion|Generated artifact's package version.| |1.0.0|
|
||||
|defaultDatabaseName|Default database name for all queries| |sqlite.db|
|
||||
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
|
||||
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|
||||
|identifierNamingConvention|Naming convention of Ktorm identifiers(table names and column names). This is not related to database name which is defined by defaultDatabaseName option|<dl><dt>**original**</dt><dd>Do not transform original names</dd><dt>**snake_case**</dt><dd>Use snake_case names</dd></dl>|original|
|
||||
|importModelPackageName|Package name of the imported models| |org.openapitools.database.models|
|
||||
|modelMutable|Create mutable models| |false|
|
||||
|packageName|Generated artifact package name.| |org.openapitools.database|
|
||||
|primaryKeyConvention|Primary key naming convention| |id|
|
||||
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |null|
|
||||
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |null|
|
||||
|sourceFolder|source folder for generated code| |src/main/kotlin|
|
||||
|
||||
## IMPORT MAPPING
|
||||
|
||||
| Type/Alias | Imports |
|
||||
| ---------- | ------- |
|
||||
|BigDecimal|java.math.BigDecimal|
|
||||
|Date|java.util.Date|
|
||||
|DateTime|java.time.LocalDateTime|
|
||||
|File|java.io.File|
|
||||
|LocalDate|java.time.LocalDate|
|
||||
|LocalDateTime|java.time.LocalDateTime|
|
||||
|LocalTime|java.time.LocalTime|
|
||||
|Timestamp|java.sql.Timestamp|
|
||||
|URI|java.net.URI|
|
||||
|UUID|java.util.UUID|
|
||||
|
||||
|
||||
## INSTANTIATION TYPES
|
||||
|
||||
| Type/Alias | Instantiated By |
|
||||
| ---------- | --------------- |
|
||||
|array|kotlin.collections.ArrayList|
|
||||
|list|kotlin.collections.ArrayList|
|
||||
|map|kotlin.collections.HashMap|
|
||||
|
||||
|
||||
## LANGUAGE PRIMITIVES
|
||||
|
||||
<ul class="column-ul">
|
||||
<li>kotlin.Array</li>
|
||||
<li>kotlin.Boolean</li>
|
||||
<li>kotlin.Byte</li>
|
||||
<li>kotlin.ByteArray</li>
|
||||
<li>kotlin.Char</li>
|
||||
<li>kotlin.Double</li>
|
||||
<li>kotlin.Float</li>
|
||||
<li>kotlin.Int</li>
|
||||
<li>kotlin.Long</li>
|
||||
<li>kotlin.Short</li>
|
||||
<li>kotlin.String</li>
|
||||
<li>kotlin.collections.List</li>
|
||||
<li>kotlin.collections.Map</li>
|
||||
<li>kotlin.collections.Set</li>
|
||||
</ul>
|
||||
|
||||
## RESERVED WORDS
|
||||
|
||||
<ul class="column-ul">
|
||||
<li>abort</li>
|
||||
<li>action</li>
|
||||
<li>add</li>
|
||||
<li>after</li>
|
||||
<li>all</li>
|
||||
<li>alter</li>
|
||||
<li>always</li>
|
||||
<li>analyze</li>
|
||||
<li>and</li>
|
||||
<li>any</li>
|
||||
<li>as</li>
|
||||
<li>asc</li>
|
||||
<li>attach</li>
|
||||
<li>autoincr</li>
|
||||
<li>autoincrement</li>
|
||||
<li>before</li>
|
||||
<li>begin</li>
|
||||
<li>between</li>
|
||||
<li>bitand</li>
|
||||
<li>bitnot</li>
|
||||
<li>bitor</li>
|
||||
<li>blob</li>
|
||||
<li>by</li>
|
||||
<li>cascade</li>
|
||||
<li>case</li>
|
||||
<li>cast</li>
|
||||
<li>check</li>
|
||||
<li>collate</li>
|
||||
<li>column</li>
|
||||
<li>comma</li>
|
||||
<li>commit</li>
|
||||
<li>concat</li>
|
||||
<li>conflict</li>
|
||||
<li>constraint</li>
|
||||
<li>create</li>
|
||||
<li>cross</li>
|
||||
<li>current</li>
|
||||
<li>current_date</li>
|
||||
<li>current_time</li>
|
||||
<li>current_timestamp</li>
|
||||
<li>database</li>
|
||||
<li>default</li>
|
||||
<li>deferrable</li>
|
||||
<li>deferred</li>
|
||||
<li>delete</li>
|
||||
<li>desc</li>
|
||||
<li>detach</li>
|
||||
<li>distinct</li>
|
||||
<li>do</li>
|
||||
<li>dot</li>
|
||||
<li>drop</li>
|
||||
<li>each</li>
|
||||
<li>else</li>
|
||||
<li>end</li>
|
||||
<li>eq</li>
|
||||
<li>escape</li>
|
||||
<li>except</li>
|
||||
<li>exclude</li>
|
||||
<li>exclusive</li>
|
||||
<li>exists</li>
|
||||
<li>explain</li>
|
||||
<li>fail</li>
|
||||
<li>filter</li>
|
||||
<li>first</li>
|
||||
<li>float</li>
|
||||
<li>following</li>
|
||||
<li>for</li>
|
||||
<li>foreign</li>
|
||||
<li>from</li>
|
||||
<li>full</li>
|
||||
<li>ge</li>
|
||||
<li>generated</li>
|
||||
<li>glob</li>
|
||||
<li>group</li>
|
||||
<li>groups</li>
|
||||
<li>gt</li>
|
||||
<li>having</li>
|
||||
<li>id</li>
|
||||
<li>if</li>
|
||||
<li>ignore</li>
|
||||
<li>immediate</li>
|
||||
<li>in</li>
|
||||
<li>index</li>
|
||||
<li>indexed</li>
|
||||
<li>initially</li>
|
||||
<li>inner</li>
|
||||
<li>insert</li>
|
||||
<li>instead</li>
|
||||
<li>integer</li>
|
||||
<li>intersect</li>
|
||||
<li>into</li>
|
||||
<li>is</li>
|
||||
<li>isnull</li>
|
||||
<li>join</li>
|
||||
<li>key</li>
|
||||
<li>last</li>
|
||||
<li>le</li>
|
||||
<li>left</li>
|
||||
<li>like</li>
|
||||
<li>limit</li>
|
||||
<li>lp</li>
|
||||
<li>lshift</li>
|
||||
<li>lt</li>
|
||||
<li>match</li>
|
||||
<li>minus</li>
|
||||
<li>natural</li>
|
||||
<li>ne</li>
|
||||
<li>no</li>
|
||||
<li>not</li>
|
||||
<li>nothing</li>
|
||||
<li>notnull</li>
|
||||
<li>null</li>
|
||||
<li>nulls</li>
|
||||
<li>of</li>
|
||||
<li>offset</li>
|
||||
<li>on</li>
|
||||
<li>or</li>
|
||||
<li>order</li>
|
||||
<li>others</li>
|
||||
<li>outer</li>
|
||||
<li>over</li>
|
||||
<li>partition</li>
|
||||
<li>plan</li>
|
||||
<li>plus</li>
|
||||
<li>pragma</li>
|
||||
<li>preceding</li>
|
||||
<li>primary</li>
|
||||
<li>query</li>
|
||||
<li>raise</li>
|
||||
<li>range</li>
|
||||
<li>recursive</li>
|
||||
<li>references</li>
|
||||
<li>regexp</li>
|
||||
<li>reindex</li>
|
||||
<li>release</li>
|
||||
<li>rem</li>
|
||||
<li>rename</li>
|
||||
<li>replace</li>
|
||||
<li>restrict</li>
|
||||
<li>right</li>
|
||||
<li>rollback</li>
|
||||
<li>row</li>
|
||||
<li>rows</li>
|
||||
<li>rp</li>
|
||||
<li>rshift</li>
|
||||
<li>savepoint</li>
|
||||
<li>select</li>
|
||||
<li>set</li>
|
||||
<li>slash</li>
|
||||
<li>star</li>
|
||||
<li>string</li>
|
||||
<li>table</li>
|
||||
<li>temp</li>
|
||||
<li>temporary</li>
|
||||
<li>then</li>
|
||||
<li>ties</li>
|
||||
<li>to</li>
|
||||
<li>transaction</li>
|
||||
<li>trigger</li>
|
||||
<li>unbounded</li>
|
||||
<li>union</li>
|
||||
<li>unique</li>
|
||||
<li>update</li>
|
||||
<li>using</li>
|
||||
<li>vacuum</li>
|
||||
<li>values</li>
|
||||
<li>variable</li>
|
||||
<li>view</li>
|
||||
<li>virtual</li>
|
||||
<li>when</li>
|
||||
<li>where</li>
|
||||
<li>window</li>
|
||||
<li>with</li>
|
||||
<li>without</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
|
||||
|Array|✓|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
|
||||
|
||||
### Security Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|BasicAuth|✗|OAS2,OAS3
|
||||
|ApiKey|✗|OAS2,OAS3
|
||||
|OpenIDConnect|✗|OAS3
|
||||
|BearerToken|✗|OAS3
|
||||
|OAuth2_Implicit|✗|OAS2,OAS3
|
||||
|OAuth2_Password|✗|OAS2,OAS3
|
||||
|OAuth2_ClientCredentials|✗|OAS2,OAS3
|
||||
|OAuth2_AuthorizationCode|✗|OAS2,OAS3
|
||||
|
||||
### Wire Format Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|JSON|✗|OAS2,OAS3
|
||||
|XML|✗|OAS2,OAS3
|
||||
|PROTOBUF|✗|ToolingExtension
|
||||
|Custom|✗|OAS2,OAS3
|
@ -19,6 +19,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
||||
|powershellGalleryUrl|URL to the module in PowerShell Gallery (e.g. https://www.powershellgallery.com/packages/PSTwitter/).| |null|
|
||||
|projectUri|A URL to the main website for this project| |null|
|
||||
|releaseNotes|Release notes of the generated PowerShell module| |null|
|
||||
|skipVerbParsing|Set skipVerbParsing to not try get powershell verbs of operation names| |null|
|
||||
|tags|Tags applied to the generated PowerShell module. These help with module discovery in online galleries| |null|
|
||||
|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and onlye one match in oneOf's schemas) will be skipped.| |null|
|
||||
|
||||
|
@ -25,7 +25,8 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
||||
|npmVersion|The version of your npm package. If not provided, using the version from the OpenAPI specification file.| |1.0.0|
|
||||
|nullSafeAdditionalProps|Set to make additional properties types declare that their indexer may return undefined| |false|
|
||||
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|
||||
|providedInRoot|Use this property to provide Injectables in root (it is only valid in angular version greater or equal to 6.0.0).| |false|
|
||||
|providedIn|Use this property to provide Injectables in wanted level (it is only valid in angular version greater or equal to 9.0.0).|<dl><dt>**root**</dt><dd>The application-level injector in most apps.</dd><dt>**none**</dt><dd>No providedIn (same as providedInRoot=false)</dd><dt>**any**</dt><dd>Provides a unique instance in each lazy loaded module while all eagerly loaded modules share one instance.</dd><dt>**platform**</dt><dd>A special singleton platform injector shared by all applications on the page.</dd></dl>|root|
|
||||
|providedInRoot|Use this property to provide Injectables in root (it is only valid in angular version greater or equal to 6.0.0). IMPORTANT: Deprecated for angular version greater or equal to 9.0.0, use **providedIn** instead.| |false|
|
||||
|queryParamObjectFormat|The format for query param objects: 'dot', 'json', 'key'.| |dot|
|
||||
|serviceFileSuffix|The suffix of the file of the generated service (service<suffix>.ts).| |.service|
|
||||
|serviceSuffix|The suffix of the generated service.| |Service|
|
||||
|
@ -1,5 +1,6 @@
|
||||
# RELEASE_VERSION
|
||||
openApiGeneratorVersion=5.1.0-SNAPSHOT
|
||||
>>>>>>> origin/master
|
||||
# /RELEASE_VERSION
|
||||
|
||||
# BEGIN placeholders
|
||||
|
@ -143,7 +143,111 @@ public class CLibcurlClientCodegen extends DefaultCodegen implements CodegenConf
|
||||
"_Imaginary",
|
||||
"_Noreturn",
|
||||
"_Static_assert",
|
||||
"_Thread_local")
|
||||
"_Thread_local",
|
||||
|
||||
// cpp reserved keywords
|
||||
// ref: https://en.cppreference.com/w/cpp/keyword
|
||||
"alignas",
|
||||
"alignof",
|
||||
"and",
|
||||
"and_eq",
|
||||
"asm",
|
||||
"atomic_cancel",
|
||||
"atomic_commit",
|
||||
"atomic_noexcept",
|
||||
//"auto",
|
||||
"bitand",
|
||||
"bitor",
|
||||
"bool",
|
||||
//"break",
|
||||
//"case",
|
||||
"catch",
|
||||
//"char",
|
||||
"char8_t",
|
||||
"char16_t",
|
||||
"char32_t",
|
||||
"class",
|
||||
"compl",
|
||||
"concept",
|
||||
//"const",
|
||||
"consteval",
|
||||
"constexpr",
|
||||
"constinit",
|
||||
"const_cast",
|
||||
//"continue",
|
||||
"co_await",
|
||||
"co_return",
|
||||
"co_yield",
|
||||
"decltype",
|
||||
//"default",
|
||||
"delete",
|
||||
//"do",
|
||||
//"double",
|
||||
"dynamic_cast",
|
||||
//"else",
|
||||
//"enum",
|
||||
"explicit",
|
||||
"export",
|
||||
//"extern",
|
||||
"false",
|
||||
//"float",
|
||||
//"for",
|
||||
"friend",
|
||||
//"goto",
|
||||
//"if",
|
||||
//"inline",
|
||||
//"int",
|
||||
//"long",
|
||||
"mutable",
|
||||
"namespace",
|
||||
"new",
|
||||
"noexcept",
|
||||
"not",
|
||||
"not_eq",
|
||||
"nullptr",
|
||||
"operator",
|
||||
"or",
|
||||
"or_eq",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"reflexpr",
|
||||
//"register",
|
||||
"reinterpret_cast",
|
||||
"requires",
|
||||
//"return",
|
||||
//"short",
|
||||
//"signed",
|
||||
//"sizeof",
|
||||
//"static",
|
||||
"static_assert",
|
||||
"static_cast",
|
||||
//"struct",
|
||||
//"switch",
|
||||
"synchronized",
|
||||
"template",
|
||||
"this",
|
||||
"thread_local",
|
||||
"throw",
|
||||
"true",
|
||||
"try",
|
||||
//"typedef",
|
||||
"typeid",
|
||||
"typename",
|
||||
//"union",
|
||||
//"unsigned",
|
||||
"using",
|
||||
"virtual",
|
||||
//"void",
|
||||
//"volatile",
|
||||
"wchar_t",
|
||||
//"while",
|
||||
"xor",
|
||||
"xor_eq",
|
||||
"final",
|
||||
"override",
|
||||
"transaction_safe",
|
||||
"transaction_safe_dynamic")
|
||||
);
|
||||
|
||||
instantiationTypes.clear();
|
||||
|
@ -787,8 +787,7 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
|
||||
}
|
||||
|
||||
// string
|
||||
String var = value.replaceAll("_", " ");
|
||||
//var = WordUtils.capitalizeFully(var);
|
||||
String var = value.replaceAll(" ", "_");
|
||||
var = camelize(var);
|
||||
var = var.replaceAll("\\W+", "");
|
||||
|
||||
|
@ -22,6 +22,7 @@ import io.swagger.v3.oas.models.media.Schema;
|
||||
import org.openapitools.codegen.*;
|
||||
import org.openapitools.codegen.meta.features.*;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -123,6 +124,11 @@ public class ConfluenceWikiCodegen extends DefaultCodegen implements CodegenConf
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
return postProcessModelsEnum(objs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// just return the original string
|
||||
@ -134,4 +140,14 @@ public class ConfluenceWikiCodegen extends DefaultCodegen implements CodegenConf
|
||||
// just return the original string
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeText(String input) {
|
||||
if (input == null) {
|
||||
return input;
|
||||
}
|
||||
|
||||
// chomp tailing newline because it breaks the tables and keep all other sign to show documentation properly
|
||||
return StringUtils.chomp(input);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,891 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
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.meta.GeneratorMetadata;
|
||||
import org.openapitools.codegen.meta.Stability;
|
||||
import org.openapitools.codegen.meta.features.*;
|
||||
import org.openapitools.codegen.templating.mustache.PrefixWithHashLambda;
|
||||
import org.openapitools.codegen.templating.mustache.TrimWhitespaceLambda;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.*;
|
||||
|
||||
import static org.openapitools.codegen.utils.StringUtils.camelize;
|
||||
import static org.openapitools.codegen.utils.StringUtils.underscore;
|
||||
|
||||
public class CrystalClientCodegen extends DefaultCodegen {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CrystalClientCodegen.class);
|
||||
private static final String NUMERIC_ENUM_PREFIX = "N";
|
||||
protected static int emptyMethodNameCounter = 0;
|
||||
|
||||
protected String shardName;
|
||||
protected String moduleName;
|
||||
protected String shardVersion = "1.0.0";
|
||||
protected String specFolder = "spec";
|
||||
protected String srcFolder = "src";
|
||||
protected String shardLicense = "unlicense";
|
||||
protected String shardHomepage = "https://openapitools.org";
|
||||
protected String shardSummary = "A Crystal SDK for the REST API";
|
||||
protected String shardDescription = "This shard maps to a REST API";
|
||||
protected String shardAuthor = "";
|
||||
protected String shardAuthorEmail = "";
|
||||
protected String apiDocPath = "docs/";
|
||||
protected String modelDocPath = "docs/";
|
||||
|
||||
public static final String SHARD_NAME = "shardName";
|
||||
public static final String SHARD_VERSION = "shardVersion";
|
||||
public static final String SHARD_LICENSE = "shardLicense";
|
||||
public static final String SHARD_HOMEPAGE = "shardHomepage";
|
||||
public static final String SHARD_SUMMARY = "shardSummary";
|
||||
public static final String SHARD_DESCRIPTION = "shardDescription";
|
||||
public static final String SHARD_AUTHOR = "shardAuthor";
|
||||
public static final String SHARD_AUTHOR_EMAIL = "shardAuthorEmail";
|
||||
|
||||
public CrystalClientCodegen() {
|
||||
super();
|
||||
|
||||
modifyFeatureSet(features -> features
|
||||
.includeDocumentationFeatures(DocumentationFeature.Readme)
|
||||
.wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.XML, WireFormatFeature.Custom))
|
||||
.securityFeatures(EnumSet.of(
|
||||
SecurityFeature.BasicAuth,
|
||||
SecurityFeature.BearerToken,
|
||||
SecurityFeature.ApiKey,
|
||||
SecurityFeature.OAuth2_Implicit
|
||||
))
|
||||
.excludeGlobalFeatures(
|
||||
GlobalFeature.XMLStructureDefinitions,
|
||||
GlobalFeature.Callbacks,
|
||||
GlobalFeature.LinkObjects,
|
||||
GlobalFeature.ParameterStyling,
|
||||
GlobalFeature.ParameterizedServer,
|
||||
GlobalFeature.MultiServer
|
||||
)
|
||||
.includeSchemaSupportFeatures(
|
||||
SchemaSupportFeature.Polymorphism
|
||||
)
|
||||
.excludeParameterFeatures(
|
||||
ParameterFeature.Cookie
|
||||
)
|
||||
.includeClientModificationFeatures(
|
||||
ClientModificationFeature.BasePath,
|
||||
ClientModificationFeature.UserAgent
|
||||
)
|
||||
);
|
||||
|
||||
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
|
||||
.stability(Stability.BETA)
|
||||
.build();
|
||||
|
||||
supportsInheritance = true;
|
||||
|
||||
// clear import mapping (from default generator) as crystal does not use it
|
||||
// at the moment
|
||||
importMapping.clear();
|
||||
|
||||
embeddedTemplateDir = templateDir = "crystal";
|
||||
outputFolder = "generated-code" + File.separator + "crystal";
|
||||
|
||||
modelPackage = "models";
|
||||
apiPackage = "api";
|
||||
modelTemplateFiles.put("model.mustache", ".cr");
|
||||
apiTemplateFiles.put("api.mustache", ".cr");
|
||||
|
||||
modelTestTemplateFiles.put("model_test.mustache", ".cr");
|
||||
apiTestTemplateFiles.put("api_test.mustache", ".cr");
|
||||
|
||||
// TODO support auto-generated doc
|
||||
//modelDocTemplateFiles.put("model_doc.mustache", ".md");
|
||||
//apiDocTemplateFiles.put("api_doc.mustache", ".md");
|
||||
|
||||
// default HIDE_GENERATION_TIMESTAMP to true
|
||||
hideGenerationTimestamp = Boolean.TRUE;
|
||||
|
||||
// reserved word. Ref: https://github.com/crystal-lang/crystal/wiki/Crystal-for-Rubyists#available-keywords
|
||||
reservedWords = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"abstract", "do", "if", "nil?", "select", "union",
|
||||
"alias", "else", "in", "of", "self", "unless",
|
||||
"as", "elsif", "include", "out", "sizeof", "until",
|
||||
"as?", "end", "instance", "sizeof", "pointerof", "struct", "verbatim",
|
||||
"asm", "ensure", "is_a?", "private", "super", "when",
|
||||
"begin", "enum", "lib", "protected", "then", "while",
|
||||
"break", "extend", "macro", "require", "true", "with",
|
||||
"case", "false", "module", "rescue", "type", "yield",
|
||||
"class", "for", "next", "responds_to?", "typeof",
|
||||
"def", "fun", "nil", "return", "uninitialized")
|
||||
);
|
||||
|
||||
languageSpecificPrimitives.clear();
|
||||
languageSpecificPrimitives.add("String");
|
||||
languageSpecificPrimitives.add("Boolean");
|
||||
languageSpecificPrimitives.add("Integer");
|
||||
languageSpecificPrimitives.add("Float");
|
||||
languageSpecificPrimitives.add("Date");
|
||||
languageSpecificPrimitives.add("Time");
|
||||
languageSpecificPrimitives.add("Array");
|
||||
languageSpecificPrimitives.add("Hash");
|
||||
languageSpecificPrimitives.add("File");
|
||||
languageSpecificPrimitives.add("Object");
|
||||
|
||||
typeMapping.clear();
|
||||
typeMapping.put("string", "String");
|
||||
typeMapping.put("boolean", "Bool");
|
||||
typeMapping.put("char", "Char");
|
||||
typeMapping.put("int", "Int32");
|
||||
typeMapping.put("integer", "Int32");
|
||||
typeMapping.put("long", "Int64");
|
||||
typeMapping.put("short", "Int32");
|
||||
typeMapping.put("float", "Float32");
|
||||
typeMapping.put("double", "Float64");
|
||||
typeMapping.put("number", "Float64");
|
||||
typeMapping.put("date", "Time");
|
||||
typeMapping.put("DateTime", "Time");
|
||||
typeMapping.put("array", "Array");
|
||||
typeMapping.put("List", "Array");
|
||||
typeMapping.put("set", "Set");
|
||||
typeMapping.put("map", "Hash");
|
||||
typeMapping.put("object", "Object");
|
||||
typeMapping.put("file", "File");
|
||||
typeMapping.put("binary", "String");
|
||||
typeMapping.put("ByteArray", "String");
|
||||
typeMapping.put("UUID", "String");
|
||||
typeMapping.put("URI", "String");
|
||||
|
||||
instantiationTypes.put("map", "Hash");
|
||||
instantiationTypes.put("array", "Array");
|
||||
instantiationTypes.put("set", "Set");
|
||||
|
||||
// remove modelPackage and apiPackage added by default
|
||||
cliOptions.removeIf(opt -> CodegenConstants.MODEL_PACKAGE.equals(opt.getOpt()) ||
|
||||
CodegenConstants.API_PACKAGE.equals(opt.getOpt()));
|
||||
|
||||
cliOptions.add(new CliOption(SHARD_NAME, "shard name (e.g. twitter_client").
|
||||
defaultValue("openapi_client"));
|
||||
|
||||
cliOptions.add(new CliOption(SHARD_VERSION, "shard version.").defaultValue("1.0.0"));
|
||||
|
||||
cliOptions.add(new CliOption(SHARD_LICENSE, "shard license.").
|
||||
defaultValue("unlicense"));
|
||||
|
||||
cliOptions.add(new CliOption(SHARD_HOMEPAGE, "shard homepage.").
|
||||
defaultValue("http://org.openapitools"));
|
||||
|
||||
cliOptions.add(new CliOption(SHARD_DESCRIPTION, "shard description.").
|
||||
defaultValue("This shard maps to a REST API"));
|
||||
|
||||
cliOptions.add(new CliOption(SHARD_AUTHOR, "shard author (only one is supported)."));
|
||||
|
||||
cliOptions.add(new CliOption(SHARD_AUTHOR_EMAIL, "shard author email (only one is supported)."));
|
||||
|
||||
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC).
|
||||
defaultValue(Boolean.TRUE.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("CRYSTAL_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Hint: Environment variable 'CRYSTAL_POST_PROCESS_FILE' (optional) not defined. E.g. to format the source code, please try 'export CRYSTAL_POST_PROCESS_FILE=\"/usr/local/bin/crystal tool format\"' (Linux/Mac)");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SHARD_NAME)) {
|
||||
setShardName((String) additionalProperties.get(SHARD_NAME));
|
||||
}
|
||||
additionalProperties.put(SHARD_NAME, shardName);
|
||||
|
||||
if (additionalProperties.containsKey(SHARD_VERSION)) {
|
||||
setShardVersion((String) additionalProperties.get(SHARD_VERSION));
|
||||
} else {
|
||||
// not set, pass the default value to template
|
||||
additionalProperties.put(SHARD_VERSION, shardVersion);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SHARD_LICENSE)) {
|
||||
setShardLicense((String) additionalProperties.get(SHARD_LICENSE));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SHARD_HOMEPAGE)) {
|
||||
setShardHomepage((String) additionalProperties.get(SHARD_HOMEPAGE));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SHARD_SUMMARY)) {
|
||||
setShardSummary((String) additionalProperties.get(SHARD_SUMMARY));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SHARD_DESCRIPTION)) {
|
||||
setShardDescription((String) additionalProperties.get(SHARD_DESCRIPTION));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SHARD_AUTHOR)) {
|
||||
setShardAuthor((String) additionalProperties.get(SHARD_AUTHOR));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SHARD_AUTHOR_EMAIL)) {
|
||||
setShardAuthorEmail((String) additionalProperties.get(SHARD_AUTHOR_EMAIL));
|
||||
}
|
||||
|
||||
// make api and model doc path available in mustache template
|
||||
additionalProperties.put("apiDocPath", apiDocPath);
|
||||
additionalProperties.put("modelDocPath", modelDocPath);
|
||||
|
||||
// use constant model/api package (folder path)
|
||||
setModelPackage("models");
|
||||
setApiPackage("api");
|
||||
|
||||
supportingFiles.add(new SupportingFile("shard_name.mustache", srcFolder, shardName + ".cr"));
|
||||
String shardFolder = srcFolder + File.separator + shardName;
|
||||
supportingFiles.add(new SupportingFile("api_error.mustache", shardFolder, "api_error.cr"));
|
||||
supportingFiles.add(new SupportingFile("configuration.mustache", shardFolder, "configuration.cr"));
|
||||
supportingFiles.add(new SupportingFile("api_client.mustache", shardFolder, "api_client.cr"));
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml"));
|
||||
supportingFiles.add(new SupportingFile("shard.mustache", "", "shard.yml"));
|
||||
|
||||
// crystal spec files
|
||||
supportingFiles.add(new SupportingFile("spec_helper.mustache", specFolder, "spec_helper.cr")
|
||||
.doNotOverwrite());
|
||||
|
||||
// add lambda for mustache templates
|
||||
additionalProperties.put("lambdaPrefixWithHash", new PrefixWithHashLambda());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Crystal client library (beta).";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "crystal";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator + srcFolder + File.separator + shardName + File.separator + apiPackage.replace("/", File.separator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + File.separator + srcFolder + File.separator + shardName + File.separator + modelPackage.replace("/", File.separator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiTestFileFolder() {
|
||||
return outputFolder + File.separator + specFolder + File.separator + apiPackage.replace("/", File.separator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelTestFileFolder() {
|
||||
return outputFolder + File.separator + specFolder + File.separator + modelPackage.replace("/", File.separator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiDocFileFolder() {
|
||||
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelDocFileFolder() {
|
||||
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema schema) {
|
||||
String openAPIType = super.getSchemaType(schema);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
} else {
|
||||
type = openAPIType;
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(final String name) {
|
||||
String modelName;
|
||||
modelName = sanitizeName(name);
|
||||
|
||||
if (!StringUtils.isEmpty(modelNamePrefix)) {
|
||||
modelName = modelNamePrefix + "_" + modelName;
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(modelNameSuffix)) {
|
||||
modelName = modelName + "_" + modelNameSuffix;
|
||||
}
|
||||
|
||||
// model name cannot use reserved keyword, e.g. return
|
||||
if (isReservedWord(modelName)) {
|
||||
modelName = camelize("Model" + modelName);
|
||||
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
|
||||
return modelName;
|
||||
}
|
||||
|
||||
// model name starts with number
|
||||
if (modelName.matches("^\\d.*")) {
|
||||
LOGGER.warn(modelName + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + modelName));
|
||||
modelName = "model_" + modelName; // e.g. 200Response => Model200Response (after camelize)
|
||||
}
|
||||
|
||||
// camelize the model name
|
||||
// phone_number => PhoneNumber
|
||||
return camelize(modelName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
return underscore(toModelName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelDocFilename(String name) {
|
||||
return toModelName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(final String name) {
|
||||
// replace - with _ e.g. created-at => created_at
|
||||
String filename = name;
|
||||
if (apiNameSuffix != null && apiNameSuffix.length() > 0) {
|
||||
filename = filename + "_" + apiNameSuffix;
|
||||
}
|
||||
|
||||
filename = filename.replaceAll("-", "_");
|
||||
|
||||
// e.g. PhoneNumberApi.cr => phone_number_api.cr
|
||||
return underscore(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiDocFilename(String name) {
|
||||
return toApiName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiTestFilename(String name) {
|
||||
return toApiFilename(name) + "_spec";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelTestFilename(String name) {
|
||||
return toModelFilename(name) + "_spec";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
return super.toApiName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumValue(String value, String datatype) {
|
||||
if ("Integer".equals(datatype) || "Float".equals(datatype)) {
|
||||
return value;
|
||||
} else {
|
||||
return "\"" + escapeText(value) + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumVarName(String name, String datatype) {
|
||||
if (name.length() == 0) {
|
||||
return "EMPTY";
|
||||
}
|
||||
|
||||
// number
|
||||
if ("Integer".equals(datatype) || "Float".equals(datatype)) {
|
||||
String varName = name;
|
||||
varName = varName.replaceAll("-", "MINUS_");
|
||||
varName = varName.replaceAll("\\+", "PLUS_");
|
||||
varName = varName.replaceAll("\\.", "_DOT_");
|
||||
return NUMERIC_ENUM_PREFIX + varName;
|
||||
}
|
||||
|
||||
// string
|
||||
String enumName = sanitizeName(underscore(name).toUpperCase(Locale.ROOT));
|
||||
enumName = enumName.replaceFirst("^_", "");
|
||||
enumName = enumName.replaceFirst("_$", "");
|
||||
|
||||
if (enumName.matches("\\d.*")) { // starts with number
|
||||
return NUMERIC_ENUM_PREFIX + enumName;
|
||||
} else {
|
||||
return enumName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumName(CodegenProperty property) {
|
||||
String enumName = underscore(toModelName(property.name)).toUpperCase(Locale.ROOT);
|
||||
enumName = enumName.replaceFirst("^_", "");
|
||||
enumName = enumName.replaceFirst("_$", "");
|
||||
|
||||
if (enumName.matches("\\d.*")) { // starts with number
|
||||
return NUMERIC_ENUM_PREFIX + enumName;
|
||||
} else {
|
||||
return enumName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
// process enum in models
|
||||
return postProcessModelsEnum(objs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOperationId(String operationId) {
|
||||
// rename to empty_method_name_1 (e.g.) if method name is empty
|
||||
if (StringUtils.isEmpty(operationId)) {
|
||||
operationId = underscore("empty_method_name_" + emptyMethodNameCounter++);
|
||||
LOGGER.warn("Empty method name (operationId) found. Renamed to " + operationId);
|
||||
return operationId;
|
||||
}
|
||||
|
||||
// method name cannot use reserved keyword, e.g. return
|
||||
if (isReservedWord(operationId)) {
|
||||
String newOperationId = underscore("call_" + operationId);
|
||||
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
|
||||
return newOperationId;
|
||||
}
|
||||
|
||||
// operationId starts with a number
|
||||
if (operationId.matches("^\\d.*")) {
|
||||
LOGGER.warn(operationId + " (starting with a number) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)));
|
||||
operationId = "call_" + operationId;
|
||||
}
|
||||
|
||||
return underscore(sanitizeName(operationId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiImport(String name) {
|
||||
return shardName + "/" + apiPackage() + "/" + toApiFilename(name);
|
||||
}
|
||||
|
||||
public void setShardName(String shardName) {
|
||||
this.shardName = shardName;
|
||||
}
|
||||
|
||||
public void setModuleName(String moduleName) {
|
||||
this.moduleName = moduleName;
|
||||
}
|
||||
|
||||
public void setShardVersion(String shardVersion) {
|
||||
this.shardVersion = shardVersion;
|
||||
}
|
||||
|
||||
public void setShardDescription(String shardDescription) {
|
||||
this.shardDescription = shardDescription;
|
||||
}
|
||||
|
||||
public void setShardSummary(String shardSummary) {
|
||||
this.shardSummary = shardSummary;
|
||||
}
|
||||
|
||||
public void setShardLicense(String shardLicense) {
|
||||
this.shardLicense = shardLicense;
|
||||
}
|
||||
|
||||
public void setShardHomepage(String shardHomepage) {
|
||||
this.shardHomepage = shardHomepage;
|
||||
}
|
||||
|
||||
public void setShardAuthor(String shardAuthor) {
|
||||
this.shardAuthor = shardAuthor;
|
||||
}
|
||||
|
||||
public void setShardAuthorEmail(String shardAuthorEmail) {
|
||||
this.shardAuthorEmail = shardAuthorEmail;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
|
||||
final Schema additionalProperties = getAdditionalProperties(schema);
|
||||
|
||||
if (additionalProperties != null) {
|
||||
codegenModel.additionalPropertiesType = getSchemaType(additionalProperties);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
|
||||
objs = super.postProcessOperationsWithModels(objs, allModels);
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
HashMap<String, CodegenModel> modelMaps = new HashMap<String, CodegenModel>();
|
||||
HashMap<String, Integer> processedModelMaps = new HashMap<String, Integer>();
|
||||
|
||||
for (Object o : allModels) {
|
||||
HashMap<String, Object> h = (HashMap<String, Object>) o;
|
||||
CodegenModel m = (CodegenModel) h.get("model");
|
||||
modelMaps.put(m.classname, m);
|
||||
}
|
||||
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
|
||||
for (CodegenOperation op : operationList) {
|
||||
for (CodegenParameter p : op.allParams) {
|
||||
p.vendorExtensions.put("x-crystal-example", constructExampleCode(p, modelMaps, processedModelMaps));
|
||||
}
|
||||
processedModelMaps.clear();
|
||||
for (CodegenParameter p : op.requiredParams) {
|
||||
p.vendorExtensions.put("x-crystal-example", constructExampleCode(p, modelMaps, processedModelMaps));
|
||||
}
|
||||
processedModelMaps.clear();
|
||||
for (CodegenParameter p : op.optionalParams) {
|
||||
p.vendorExtensions.put("x-crystal-example", constructExampleCode(p, modelMaps, processedModelMaps));
|
||||
}
|
||||
processedModelMaps.clear();
|
||||
for (CodegenParameter p : op.bodyParams) {
|
||||
p.vendorExtensions.put("x-crystal-example", constructExampleCode(p, modelMaps, processedModelMaps));
|
||||
}
|
||||
processedModelMaps.clear();
|
||||
for (CodegenParameter p : op.pathParams) {
|
||||
p.vendorExtensions.put("x-crystal-example", constructExampleCode(p, modelMaps, processedModelMaps));
|
||||
}
|
||||
processedModelMaps.clear();
|
||||
}
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
private String constructExampleCode(CodegenParameter codegenParameter, HashMap<String, CodegenModel> modelMaps, HashMap<String, Integer> processedModelMap) {
|
||||
if (codegenParameter.isArray) { // array
|
||||
return "[" + constructExampleCode(codegenParameter.items, modelMaps, processedModelMap) + "]";
|
||||
} else if (codegenParameter.isMap) {
|
||||
return "{ key: " + constructExampleCode(codegenParameter.items, modelMaps, processedModelMap) + "}";
|
||||
} else if (codegenParameter.isPrimitiveType) { // primitive type
|
||||
if (codegenParameter.isEnum) {
|
||||
// When inline enum, set example to first allowable value
|
||||
List<Object> values = (List<Object>) codegenParameter.allowableValues.get("values");
|
||||
codegenParameter.example = String.valueOf(values.get(0));
|
||||
}
|
||||
if (codegenParameter.isString || "String".equalsIgnoreCase(codegenParameter.baseType)) {
|
||||
if (!StringUtils.isEmpty(codegenParameter.example) && !"null".equals(codegenParameter.example)) {
|
||||
return "'" + codegenParameter.example + "'";
|
||||
}
|
||||
return "'" + codegenParameter.paramName + "_example'";
|
||||
} else if (codegenParameter.isBoolean) { // boolean
|
||||
if (Boolean.parseBoolean(codegenParameter.example)) {
|
||||
return "true";
|
||||
}
|
||||
return "false";
|
||||
} else if (codegenParameter.isUri) {
|
||||
if (!StringUtils.isEmpty(codegenParameter.example) && !"null".equals(codegenParameter.example)) {
|
||||
return "'" + codegenParameter.example + "'";
|
||||
}
|
||||
return "'https://example.com'";
|
||||
} else if (codegenParameter.isDateTime) {
|
||||
if (!StringUtils.isEmpty(codegenParameter.example) && !"null".equals(codegenParameter.example)) {
|
||||
return "Time.parse('" + codegenParameter.example + "')";
|
||||
}
|
||||
return "Time.now";
|
||||
} else if (codegenParameter.isDate) {
|
||||
if (!StringUtils.isEmpty(codegenParameter.example) && !"null".equals(codegenParameter.example)) {
|
||||
return "Date.parse('" + codegenParameter.example + "')";
|
||||
}
|
||||
return "Date.today";
|
||||
} else if (codegenParameter.isFile) {
|
||||
return "File.new('/path/to/some/file')";
|
||||
} else if (codegenParameter.isInteger) {
|
||||
if (!StringUtils.isEmpty(codegenParameter.example) && !"null".equals(codegenParameter.example)) {
|
||||
return codegenParameter.example;
|
||||
}
|
||||
return "37";
|
||||
} else { // number
|
||||
if (!StringUtils.isEmpty(codegenParameter.example) && !"null".equals(codegenParameter.example)) {
|
||||
return codegenParameter.example;
|
||||
}
|
||||
return "3.56";
|
||||
}
|
||||
} else { // model
|
||||
// look up the model
|
||||
if (modelMaps.containsKey(codegenParameter.dataType)) {
|
||||
return constructExampleCode(modelMaps.get(codegenParameter.dataType), modelMaps, processedModelMap);
|
||||
} else {
|
||||
//LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenParameter.dataType);
|
||||
return "TODO";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String constructExampleCode(CodegenProperty codegenProperty, HashMap<String, CodegenModel> modelMaps, HashMap<String, Integer> processedModelMap) {
|
||||
if (codegenProperty.isArray) { // array
|
||||
return "[" + constructExampleCode(codegenProperty.items, modelMaps, processedModelMap) + "]";
|
||||
} else if (codegenProperty.isMap) {
|
||||
return "{ key: " + constructExampleCode(codegenProperty.items, modelMaps, processedModelMap) + "}";
|
||||
} else if (codegenProperty.isPrimitiveType) { // primitive type
|
||||
if (codegenProperty.isEnum) {
|
||||
// When inline enum, set example to first allowable value
|
||||
List<Object> values = (List<Object>) codegenProperty.allowableValues.get("values");
|
||||
codegenProperty.example = String.valueOf(values.get(0));
|
||||
}
|
||||
if (codegenProperty.isString || "String".equalsIgnoreCase(codegenProperty.baseType)) {
|
||||
if (!StringUtils.isEmpty(codegenProperty.example) && !"null".equals(codegenProperty.example)) {
|
||||
return "'" + codegenProperty.example + "'";
|
||||
} else {
|
||||
return "'" + codegenProperty.name + "_example'";
|
||||
}
|
||||
} else if (codegenProperty.isBoolean) { // boolean
|
||||
if (Boolean.parseBoolean(codegenProperty.example)) {
|
||||
return "true";
|
||||
} else {
|
||||
return "false";
|
||||
}
|
||||
} else if (codegenProperty.isUri) {
|
||||
if (!StringUtils.isEmpty(codegenProperty.example) && !"null".equals(codegenProperty.example)) {
|
||||
return "'" + codegenProperty.example + "'";
|
||||
}
|
||||
return "'https://example.com'";
|
||||
} else if (codegenProperty.isDateTime) {
|
||||
if (!StringUtils.isEmpty(codegenProperty.example) && !"null".equals(codegenProperty.example)) {
|
||||
return "Time.parse('" + codegenProperty.example + "')";
|
||||
}
|
||||
return "Time.now";
|
||||
} else if (codegenProperty.isDate) {
|
||||
if (!StringUtils.isEmpty(codegenProperty.example) && !"null".equals(codegenProperty.example)) {
|
||||
return "Date.parse('" + codegenProperty.example + "')";
|
||||
}
|
||||
return "Date.today";
|
||||
} else if (codegenProperty.isFile) {
|
||||
return "File.new('/path/to/some/file')";
|
||||
} else if (codegenProperty.isInteger) {
|
||||
if (!StringUtils.isEmpty(codegenProperty.example) && !"null".equals(codegenProperty.example)) {
|
||||
return codegenProperty.example;
|
||||
}
|
||||
return "37";
|
||||
} else { // number
|
||||
if (!StringUtils.isEmpty(codegenProperty.example) && !"null".equals(codegenProperty.example)) {
|
||||
return codegenProperty.example;
|
||||
}
|
||||
return "3.56";
|
||||
}
|
||||
} else { // model
|
||||
// look up the model
|
||||
if (modelMaps.containsKey(codegenProperty.dataType)) {
|
||||
return constructExampleCode(modelMaps.get(codegenProperty.dataType), modelMaps, processedModelMap);
|
||||
} else {
|
||||
//LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenParameter.dataType);
|
||||
return "TODO";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String constructExampleCode(CodegenModel codegenModel, HashMap<String, CodegenModel> modelMaps, HashMap<String, Integer> processedModelMap) {
|
||||
// break infinite recursion. Return, in case a model is already processed in the current context.
|
||||
String model = codegenModel.name;
|
||||
if (processedModelMap.containsKey(model)) {
|
||||
int count = processedModelMap.get(model);
|
||||
if (count == 1) {
|
||||
processedModelMap.put(model, 2);
|
||||
} else if (count == 2) {
|
||||
return "";
|
||||
} else {
|
||||
throw new RuntimeException("Invalid count when constructing example: " + count);
|
||||
}
|
||||
} else if (codegenModel.isEnum) {
|
||||
List<Map<String, String>> enumVars = (List<Map<String, String>>) codegenModel.allowableValues.get("enumVars");
|
||||
return moduleName + "::" + codegenModel.classname + "::" + enumVars.get(0).get("name");
|
||||
} else if (codegenModel.oneOf != null && !codegenModel.oneOf.isEmpty()) {
|
||||
String subModel = (String) codegenModel.oneOf.toArray()[0];
|
||||
String oneOf = constructExampleCode(modelMaps.get(subModel), modelMaps, processedModelMap);
|
||||
return oneOf;
|
||||
} else {
|
||||
processedModelMap.put(model, 1);
|
||||
}
|
||||
|
||||
List<String> propertyExamples = new ArrayList<>();
|
||||
for (CodegenProperty codegenProperty : codegenModel.requiredVars) {
|
||||
propertyExamples.add(codegenProperty.name + ": " + constructExampleCode(codegenProperty, modelMaps, processedModelMap));
|
||||
}
|
||||
String example = moduleName + "::" + toModelName(model) + ".new";
|
||||
if (!propertyExamples.isEmpty()) {
|
||||
example += "({" + StringUtils.join(propertyExamples, ", ") + "})";
|
||||
}
|
||||
return example;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema schema) {
|
||||
if (ModelUtils.isArraySchema(schema)) {
|
||||
Schema inner = ((ArraySchema) schema).getItems();
|
||||
return getSchemaType(schema) + "(" + getTypeDeclaration(inner) + ")";
|
||||
} else if (ModelUtils.isMapSchema(schema)) {
|
||||
Schema inner = getAdditionalProperties(schema);
|
||||
return getSchemaType(schema) + "(String, " + getTypeDeclaration(inner) + ")";
|
||||
}
|
||||
|
||||
return super.getTypeDeclaration(schema);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toInstantiationType(Schema schema) {
|
||||
if (ModelUtils.isMapSchema(schema)) {
|
||||
return instantiationTypes.get("map");
|
||||
} else if (ModelUtils.isArraySchema(schema)) {
|
||||
String parentType;
|
||||
if (ModelUtils.isSet(schema)) {
|
||||
parentType = "set";
|
||||
} else {
|
||||
parentType = "array";
|
||||
}
|
||||
return instantiationTypes.get(parentType);
|
||||
}
|
||||
return super.toInstantiationType(schema);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
p = ModelUtils.getReferencedSchema(this.openAPI, p);
|
||||
if (ModelUtils.isIntegerSchema(p) || ModelUtils.isNumberSchema(p) || ModelUtils.isBooleanSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
}
|
||||
} else if (ModelUtils.isStringSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
if (p.getDefault() instanceof Date) {
|
||||
Date date = (Date) p.getDefault();
|
||||
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
return "Date.parse(\"" + String.format(Locale.ROOT, localDate.toString(), "") + "\")";
|
||||
} else if (p.getDefault() instanceof java.time.OffsetDateTime) {
|
||||
return "Time.parse(\"" + String.format(Locale.ROOT, ((java.time.OffsetDateTime) p.getDefault()).atZoneSameInstant(ZoneId.systemDefault()).toString(), "") + "\")";
|
||||
} else {
|
||||
return "'" + escapeText((String) p.getDefault()) + "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumDefaultValue(String value, String datatype) {
|
||||
return datatype + "::" + value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(final String name) {
|
||||
String varName;
|
||||
// sanitize name
|
||||
varName = sanitizeName(name);
|
||||
// if it's all uppper case, convert to lower case
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
varName = varName.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
// camelize (lower first character) the variable name
|
||||
// petId => pet_id
|
||||
varName = underscore(varName);
|
||||
|
||||
// for reserved word or word starting with number, append _
|
||||
if (isReservedWord(varName) || varName.matches("^\\d.*")) {
|
||||
varName = escapeReservedWord(varName);
|
||||
}
|
||||
|
||||
return varName;
|
||||
}
|
||||
|
||||
public String toRegularExpression(String pattern) {
|
||||
return addRegularExpressionDelimiter(pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
// should be the same as variable name
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove ' to avoid code injection
|
||||
return input.replace("'", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("=end", "=_end").replace("=begin", "=_begin").replace("#{", "\\#{");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessFile(File file, String fileType) {
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
String crystalPostProcessFile = System.getenv("CRYSTAL_POST_PROCESS_FILE");
|
||||
if (StringUtils.isEmpty(crystalPostProcessFile)) {
|
||||
return; // skip if CRYSTAL_POST_PROCESS_FILE env variable is not defined
|
||||
}
|
||||
// only process files with cr extension
|
||||
if ("cr".equals(FilenameUtils.getExtension(file.toString()))) {
|
||||
String command = crystalPostProcessFile + " " + file.toString();
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(command);
|
||||
int exitValue = p.waitFor();
|
||||
if (exitValue != 0) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream(), StandardCharsets.UTF_8));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
LOGGER.error("Error running the command ({}). Exit value: {}, Error output: {}", command, exitValue, sb.toString());
|
||||
} else {
|
||||
LOGGER.info("Successfully executed: " + command);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error running the command ({}). Exception: {}", command, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -472,13 +472,16 @@ public class DartClientCodegen extends DefaultCodegen {
|
||||
}
|
||||
|
||||
if (schema.getDefault() != null) {
|
||||
if (ModelUtils.isDateSchema(schema) || ModelUtils.isDateTimeSchema(schema)) {
|
||||
// this is currently not supported and would create compile errors
|
||||
return null;
|
||||
}
|
||||
if (ModelUtils.isStringSchema(schema)) {
|
||||
return "'" + schema.getDefault().toString().replace("'", "\\'") + "'";
|
||||
}
|
||||
return schema.getDefault().toString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -555,6 +558,18 @@ public class DartClientCodegen extends DefaultCodegen {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (CodegenParameter p : op.allParams) {
|
||||
if (p.isContainer) {
|
||||
final String type = p.isArray ? "array" : "map";
|
||||
if (typeMapping().containsKey(type)) {
|
||||
final String value = typeMapping().get(type);
|
||||
// Also add container imports for parameters.
|
||||
if (needToImport(value)) {
|
||||
op.imports.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
|
@ -126,6 +126,16 @@ public class DartDioClientCodegen extends DartClientCodegen {
|
||||
@Override
|
||||
public String toDefaultValue(Schema schema) {
|
||||
if (schema.getDefault() != null) {
|
||||
if (ModelUtils.isArraySchema(schema)) {
|
||||
return "ListBuilder()";
|
||||
}
|
||||
if (ModelUtils.isMapSchema(schema)) {
|
||||
return "MapBuilder()";
|
||||
}
|
||||
if (ModelUtils.isDateSchema(schema) || ModelUtils.isDateTimeSchema(schema)) {
|
||||
// this is currently not supported and would create compile errors
|
||||
return null;
|
||||
}
|
||||
if (ModelUtils.isStringSchema(schema)) {
|
||||
return "'" + schema.getDefault().toString().replaceAll("'", "\\'") + "'";
|
||||
}
|
||||
@ -279,6 +289,7 @@ public class DartDioClientCodegen extends DartClientCodegen {
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
|
||||
|
||||
Set<Map<String, Object>> serializers = new HashSet<>();
|
||||
Set<String> modelImports = new HashSet<>();
|
||||
Set<String> fullImports = new HashSet<>();
|
||||
|
||||
@ -304,6 +315,13 @@ public class DartDioClientCodegen extends DartClientCodegen {
|
||||
param.baseType = "MultipartFile";
|
||||
param.dataType = "MultipartFile";
|
||||
}
|
||||
if (param.isContainer) {
|
||||
final Map<String, Object> serializer = new HashMap<>();
|
||||
serializer.put("isArray", param.isArray);
|
||||
serializer.put("isMap", param.isMap);
|
||||
serializer.put("baseType", param.baseType);
|
||||
serializers.add(serializer);
|
||||
}
|
||||
}
|
||||
|
||||
op.vendorExtensions.put("x-is-json", isJson);
|
||||
@ -317,7 +335,7 @@ public class DartDioClientCodegen extends DartClientCodegen {
|
||||
Set<String> imports = new HashSet<>();
|
||||
for (String item : op.imports) {
|
||||
if (needToImport(item)) {
|
||||
if (importMapping().containsKey(item) && needToImport(item)) {
|
||||
if (importMapping().containsKey(item)) {
|
||||
fullImports.add(importMapping().get(item));
|
||||
} else {
|
||||
imports.add(underscore(item));
|
||||
@ -326,10 +344,19 @@ public class DartDioClientCodegen extends DartClientCodegen {
|
||||
}
|
||||
modelImports.addAll(imports);
|
||||
op.imports = imports;
|
||||
|
||||
if (op.returnContainer != null) {
|
||||
final Map<String, Object> serializer = new HashMap<>();
|
||||
serializer.put("isArray", Objects.equals("array", op.returnContainer));
|
||||
serializer.put("isMap", Objects.equals("map", op.returnContainer));
|
||||
serializer.put("baseType", op.returnBaseType);
|
||||
serializers.add(serializer);
|
||||
}
|
||||
}
|
||||
|
||||
objs.put("modelImports", modelImports);
|
||||
objs.put("fullImports", fullImports);
|
||||
objs.put("serializers", serializers);
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ public class HaskellHttpClientCodegen extends DefaultCodegen implements CodegenC
|
||||
protected Set<String> typeNames = new HashSet<String>();
|
||||
protected Set<String> modelTypeNames = new HashSet<String>();
|
||||
|
||||
final private static Pattern JSON_MIME_PATTERN = Pattern.compile("(?i)application/.*json(;.*)?");
|
||||
final private static Pattern CONTAINS_JSON_MIME_PATTERN = Pattern.compile("(?i)application/.*json(;.*)?");
|
||||
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
@ -1054,7 +1054,7 @@ public class HaskellHttpClientCodegen extends DefaultCodegen implements CodegenC
|
||||
String mimeType = getMimeDataType(mediaType);
|
||||
typeNames.add(mimeType);
|
||||
m.put(X_MEDIA_DATA_TYPE, mimeType);
|
||||
if (isJsonMimeType(mediaType)) {
|
||||
if (isJsonMimeType(mediaType) || ContainsJsonMimeType(mediaType)) {
|
||||
m.put(X_MEDIA_IS_JSON, "true");
|
||||
}
|
||||
if (isWildcardMimeType(mediaType)) {
|
||||
@ -1461,4 +1461,7 @@ public class HaskellHttpClientCodegen extends DefaultCodegen implements CodegenC
|
||||
}
|
||||
}
|
||||
}
|
||||
static boolean ContainsJsonMimeType(String mime) {
|
||||
return mime != null && CONTAINS_JSON_MIME_PATTERN.matcher(mime).matches();
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -55,6 +55,7 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
|
||||
protected HashSet methodNames; // store a list of method names to detect duplicates
|
||||
protected boolean useOneOfDiscriminatorLookup = false; // use oneOf discriminator's mapping for model lookup
|
||||
protected boolean discardReadOnly = false; // Discard the readonly property in initialize cmdlet
|
||||
protected boolean skipVerbParsing = false; // Attempt to parse cmdlets from operation names
|
||||
protected String projectUri;
|
||||
protected String licenseUri;
|
||||
protected String releaseNotes;
|
||||
@ -511,6 +512,8 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
|
||||
cliOptions.add(new CliOption("licenseUri","A URL to the license for the generated PowerShell module"));
|
||||
cliOptions.add(new CliOption("iconUri","A URL to an icon representing the generated PowerShell module"));
|
||||
cliOptions.add(new CliOption("releaseNotes","Release notes of the generated PowerShell module"));
|
||||
cliOptions.add(new CliOption("skipVerbParsing", "Set skipVerbParsing to not try get powershell verbs of operation names"));
|
||||
|
||||
// option to change how we process + set the data in the 'additionalProperties' keyword.
|
||||
CliOption disallowAdditionalPropertiesIfNotPresentOpt = CliOption.newBoolean(
|
||||
CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT,
|
||||
@ -601,6 +604,7 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
|
||||
this.iconUri = iconUri;
|
||||
}
|
||||
|
||||
public void setSkipVerbParsing(boolean skipVerbParsing) { this.skipVerbParsing = skipVerbParsing; };
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
@ -628,7 +632,13 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
|
||||
setDiscardReadOnly(convertPropertyToBooleanAndWriteBack("discardReadOnly"));
|
||||
} else {
|
||||
additionalProperties.put("discardReadOnly", discardReadOnly);
|
||||
}
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey("skipVerbParsing")) {
|
||||
setSkipVerbParsing(convertPropertyToBoolean("skipVerbParsing"));
|
||||
} else {
|
||||
additionalProperties.put("skipVerbParsing", skipVerbParsing);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey("tags")) {
|
||||
String[] entries = ((String) additionalProperties.get("tags")).split(",");
|
||||
@ -1212,20 +1222,22 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
|
||||
private String toMethodName(String operationId) {
|
||||
String methodName = camelize(operationId);
|
||||
|
||||
// check if method name starts with powershell verbs
|
||||
for (String verb : (HashSet<String>) powershellVerbs) {
|
||||
if (methodName.startsWith(verb)) {
|
||||
methodName = verb + "-" + apiNamePrefix + methodName.substring(verb.length());
|
||||
LOGGER.info("Naming the method using the PowerShell verb: {} => {}", operationId, methodName);
|
||||
return methodName;
|
||||
if (!skipVerbParsing) {
|
||||
// check if method name starts with powershell verbs
|
||||
for (String verb : (HashSet<String>) powershellVerbs) {
|
||||
if (methodName.startsWith(verb)) {
|
||||
methodName = verb + "-" + apiNamePrefix + methodName.substring(verb.length());
|
||||
LOGGER.info("Naming the method using the PowerShell verb: {} => {}", operationId, methodName);
|
||||
return methodName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : commonVerbs.entrySet()) {
|
||||
if (methodName.startsWith(entry.getKey())) {
|
||||
methodName = entry.getValue() + "-" + apiNamePrefix + methodName.substring(entry.getKey().length());
|
||||
LOGGER.info("Naming the method by mapping the common verbs (e.g. Create, Change) to PS verbs: {} => {}", operationId, methodName);
|
||||
return methodName;
|
||||
for (Map.Entry<String, String> entry : commonVerbs.entrySet()) {
|
||||
if (methodName.startsWith(entry.getKey())) {
|
||||
methodName = entry.getValue() + "-" + apiNamePrefix + methodName.substring(entry.getKey().length());
|
||||
LOGGER.info("Naming the method by mapping the common verbs (e.g. Create, Change) to PS verbs: {} => {}", operationId, methodName);
|
||||
return methodName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import io.swagger.v3.core.util.Json;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
@ -879,7 +880,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
|
||||
|
||||
public String toExampleValue(Schema schema, Object objExample) {
|
||||
String modelName = getModelName(schema);
|
||||
return toExampleValueRecursive(modelName, schema, objExample, 1, "", 0);
|
||||
return toExampleValueRecursive(modelName, schema, objExample, 1, "", 0, Sets.newHashSet());
|
||||
}
|
||||
|
||||
private Boolean simpleStringSchema(Schema schema) {
|
||||
@ -925,9 +926,12 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
|
||||
* ModelName( line 0
|
||||
* some_property='some_property_example' line 1
|
||||
* ) line 2
|
||||
* @param seenSchemas This set contains all the schemas passed into the recursive function. It is used to check
|
||||
* if a schema was already passed into the function and breaks the infinite recursive loop. The
|
||||
* only schemas that are not added are ones that contain $ref != null
|
||||
* @return the string example
|
||||
*/
|
||||
private String toExampleValueRecursive(String modelName, Schema schema, Object objExample, int indentationLevel, String prefix, Integer exampleLine) {
|
||||
private String toExampleValueRecursive(String modelName, Schema schema, Object objExample, int indentationLevel, String prefix, Integer exampleLine, Set<Schema> seenSchemas) {
|
||||
final String indentionConst = " ";
|
||||
String currentIndentation = "";
|
||||
String closingIndentation = "";
|
||||
@ -951,6 +955,27 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
|
||||
if (objExample != null) {
|
||||
example = objExample.toString();
|
||||
}
|
||||
// checks if the current schema has already been passed in. If so, breaks the current recursive pass
|
||||
if (seenSchemas.contains(schema)){
|
||||
if (modelName != null) {
|
||||
return fullPrefix + modelName + closeChars;
|
||||
} else {
|
||||
// this is a recursive schema
|
||||
// need to add a reasonable example to avoid
|
||||
// infinite recursion
|
||||
if(ModelUtils.isNullable(schema)) {
|
||||
// if the schema is nullable, then 'None' is a valid value
|
||||
return fullPrefix + "None" + closeChars;
|
||||
} else if(ModelUtils.isArraySchema(schema)) {
|
||||
// the schema is an array, add an empty array
|
||||
return fullPrefix + "[]" + closeChars;
|
||||
} else {
|
||||
// the schema is an object, make an empty object
|
||||
return fullPrefix + "{}" + closeChars;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null != schema.get$ref()) {
|
||||
Map<String, Schema> allDefinitions = ModelUtils.getSchemas(this.openAPI);
|
||||
String ref = ModelUtils.getSimpleRef(schema.get$ref());
|
||||
@ -960,7 +985,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
|
||||
return fullPrefix + "None" + closeChars;
|
||||
}
|
||||
String refModelName = getModelName(schema);
|
||||
return toExampleValueRecursive(refModelName, refSchema, objExample, indentationLevel, prefix, exampleLine);
|
||||
return toExampleValueRecursive(refModelName, refSchema, objExample, indentationLevel, prefix, exampleLine, seenSchemas);
|
||||
} else if (ModelUtils.isNullType(schema) || isAnyTypeSchema(schema)) {
|
||||
// The 'null' type is allowed in OAS 3.1 and above. It is not supported by OAS 3.0.x,
|
||||
// though this tooling supports it.
|
||||
@ -1058,7 +1083,8 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
|
||||
ArraySchema arrayschema = (ArraySchema) schema;
|
||||
Schema itemSchema = arrayschema.getItems();
|
||||
String itemModelName = getModelName(itemSchema);
|
||||
example = fullPrefix + "[" + "\n" + toExampleValueRecursive(itemModelName, itemSchema, objExample, indentationLevel + 1, "", exampleLine + 1) + ",\n" + closingIndentation + "]" + closeChars;
|
||||
seenSchemas.add(schema);
|
||||
example = fullPrefix + "[" + "\n" + toExampleValueRecursive(itemModelName, itemSchema, objExample, indentationLevel + 1, "", exampleLine + 1, seenSchemas) + ",\n" + closingIndentation + "]" + closeChars;
|
||||
return example;
|
||||
} else if (ModelUtils.isMapSchema(schema)) {
|
||||
if (modelName == null) {
|
||||
@ -1080,7 +1106,8 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
|
||||
addPropPrefix = ensureQuotes(key) + ": ";
|
||||
}
|
||||
String addPropsModelName = getModelName(addPropsSchema);
|
||||
example = fullPrefix + "\n" + toExampleValueRecursive(addPropsModelName, addPropsSchema, addPropsExample, indentationLevel + 1, addPropPrefix, exampleLine + 1) + ",\n" + closingIndentation + closeChars;
|
||||
seenSchemas.add(schema);
|
||||
example = fullPrefix + "\n" + toExampleValueRecursive(addPropsModelName, addPropsSchema, addPropsExample, indentationLevel + 1, addPropPrefix, exampleLine + 1, seenSchemas) + ",\n" + closingIndentation + closeChars;
|
||||
} else {
|
||||
example = fullPrefix + closeChars;
|
||||
}
|
||||
@ -1103,7 +1130,12 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
|
||||
return fullPrefix + closeChars;
|
||||
}
|
||||
}
|
||||
return exampleForObjectModel(schema, fullPrefix, closeChars, null, indentationLevel, exampleLine, closingIndentation);
|
||||
// Adds schema to seenSchemas before running example model function. romoves schema after running
|
||||
// the function. It also doesnt keep track of any schemas within the ObjectModel.
|
||||
seenSchemas.add(schema);
|
||||
String exampleForObjectModel = exampleForObjectModel(schema, fullPrefix, closeChars, null, indentationLevel, exampleLine, closingIndentation, seenSchemas);
|
||||
seenSchemas.remove(schema);
|
||||
return exampleForObjectModel;
|
||||
} else if (ModelUtils.isComposedSchema(schema)) {
|
||||
// TODO add examples for composed schema models without discriminators
|
||||
|
||||
@ -1117,7 +1149,12 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
|
||||
CodegenProperty cp = new CodegenProperty();
|
||||
cp.setName(disc.getPropertyName());
|
||||
cp.setExample(discPropNameValue);
|
||||
return exampleForObjectModel(modelSchema, fullPrefix, closeChars, cp, indentationLevel, exampleLine, closingIndentation);
|
||||
// Adds schema to seenSchemas before running example model function. romoves schema after running
|
||||
// the function. It also doesnt keep track of any schemas within the ObjectModel.
|
||||
seenSchemas.add(modelSchema);
|
||||
String exampleForObjectModel = exampleForObjectModel(modelSchema, fullPrefix, closeChars, cp, indentationLevel, exampleLine, closingIndentation, seenSchemas);
|
||||
seenSchemas.remove(modelSchema);
|
||||
return exampleForObjectModel;
|
||||
} else {
|
||||
return fullPrefix + closeChars;
|
||||
}
|
||||
@ -1130,7 +1167,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
|
||||
return example;
|
||||
}
|
||||
|
||||
private String exampleForObjectModel(Schema schema, String fullPrefix, String closeChars, CodegenProperty discProp, int indentationLevel, int exampleLine, String closingIndentation) {
|
||||
private String exampleForObjectModel(Schema schema, String fullPrefix, String closeChars, CodegenProperty discProp, int indentationLevel, int exampleLine, String closingIndentation, Set<Schema> seenSchemas) {
|
||||
Map<String, Schema> requiredAndOptionalProps = schema.getProperties();
|
||||
if (requiredAndOptionalProps == null || requiredAndOptionalProps.isEmpty()) {
|
||||
return fullPrefix + closeChars;
|
||||
@ -1150,7 +1187,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
|
||||
propModelName = getModelName(propSchema);
|
||||
propExample = exampleFromStringOrArraySchema(propSchema, null, propName);
|
||||
}
|
||||
example += toExampleValueRecursive(propModelName, propSchema, propExample, indentationLevel + 1, propName + "=", exampleLine + 1) + ",\n";
|
||||
example += toExampleValueRecursive(propModelName, propSchema, propExample, indentationLevel + 1, propName + "=", exampleLine + 1, seenSchemas) + ",\n";
|
||||
}
|
||||
// TODO handle additionalProperties also
|
||||
example += closingIndentation + closeChars;
|
||||
|
@ -522,7 +522,7 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
return ModelUtils.isSet(p) ? "Set<" + getTypeDeclaration(inner) + ">" : "[" + getTypeDeclaration(inner) + "]";
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
Schema inner = getAdditionalProperties(p);
|
||||
return "[String:" + getTypeDeclaration(inner) + "]";
|
||||
return "[String: " + getTypeDeclaration(inner) + "]";
|
||||
}
|
||||
return super.getTypeDeclaration(p);
|
||||
}
|
||||
@ -807,7 +807,7 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
@Override
|
||||
public String toEnumValue(String value, String datatype) {
|
||||
// for string, array of string
|
||||
if ("String".equals(datatype) || "[String]".equals(datatype) || "[String:String]".equals(datatype)) {
|
||||
if ("String".equals(datatype) || "[String]".equals(datatype) || "[String: String]".equals(datatype)) {
|
||||
return "\"" + String.valueOf(value) + "\"";
|
||||
} else {
|
||||
return String.valueOf(value);
|
||||
|
@ -41,6 +41,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
|
||||
private static String FILE_NAME_SUFFIX_PATTERN = "^[a-zA-Z0-9.-]*$";
|
||||
|
||||
public static enum QUERY_PARAM_OBJECT_FORMAT_TYPE {dot, json, key};
|
||||
public static enum PROVIDED_IN_LEVEL {none, root, any, platform};
|
||||
|
||||
private static final String DEFAULT_IMPORT_PREFIX = "./";
|
||||
|
||||
@ -50,6 +51,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
|
||||
public static final String TAGGED_UNIONS = "taggedUnions";
|
||||
public static final String NG_VERSION = "ngVersion";
|
||||
public static final String PROVIDED_IN_ROOT = "providedInRoot";
|
||||
public static final String PROVIDED_IN = "providedIn";
|
||||
public static final String ENFORCE_GENERIC_MODULE_WITH_PROVIDERS = "enforceGenericModuleWithProviders";
|
||||
public static final String API_MODULE_PREFIX = "apiModulePrefix";
|
||||
public static final String CONFIGURATION_PREFIX = "configurationPrefix";
|
||||
@ -72,6 +74,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
|
||||
protected String fileNaming = "camelCase";
|
||||
protected Boolean stringEnums = false;
|
||||
protected QUERY_PARAM_OBJECT_FORMAT_TYPE queryParamObjectFormat = QUERY_PARAM_OBJECT_FORMAT_TYPE.dot;
|
||||
protected PROVIDED_IN_LEVEL providedIn = PROVIDED_IN_LEVEL.root;
|
||||
|
||||
private boolean taggedUnions = false;
|
||||
|
||||
@ -104,8 +107,17 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
|
||||
"Use discriminators to create tagged unions instead of extending interfaces.",
|
||||
this.taggedUnions));
|
||||
this.cliOptions.add(CliOption.newBoolean(PROVIDED_IN_ROOT,
|
||||
"Use this property to provide Injectables in root (it is only valid in angular version greater or equal to 6.0.0).",
|
||||
"Use this property to provide Injectables in root (it is only valid in angular version greater or equal to 6.0.0). IMPORTANT: Deprecated for angular version greater or equal to 9.0.0, use **providedIn** instead.",
|
||||
false));
|
||||
CliOption providedInCliOpt = new CliOption(PROVIDED_IN,
|
||||
"Use this property to provide Injectables in wanted level (it is only valid in angular version greater or equal to 9.0.0).").defaultValue("root");
|
||||
Map<String, String> providedInOptions = new HashMap<>();
|
||||
providedInOptions.put(PROVIDED_IN_LEVEL.none.toString(), "No providedIn (same as providedInRoot=false)");
|
||||
providedInOptions.put(PROVIDED_IN_LEVEL.root.toString(), "The application-level injector in most apps.");
|
||||
providedInOptions.put(PROVIDED_IN_LEVEL.platform.toString(), "A special singleton platform injector shared by all applications on the page.");
|
||||
providedInOptions.put(PROVIDED_IN_LEVEL.any.toString(), "Provides a unique instance in each lazy loaded module while all eagerly loaded modules share one instance.");
|
||||
providedInCliOpt.setEnum(providedInOptions);
|
||||
this.cliOptions.add(providedInCliOpt);
|
||||
this.cliOptions.add(new CliOption(NG_VERSION, "The version of Angular. (At least 6.0.0)").defaultValue(this.ngVersion));
|
||||
this.cliOptions.add(new CliOption(API_MODULE_PREFIX, "The prefix of the generated ApiModule."));
|
||||
this.cliOptions.add(new CliOption(CONFIGURATION_PREFIX, "The prefix of the generated Configuration."));
|
||||
@ -188,13 +200,28 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
|
||||
taggedUnions = Boolean.parseBoolean(additionalProperties.get(TAGGED_UNIONS).toString());
|
||||
}
|
||||
|
||||
if (!additionalProperties.containsKey(PROVIDED_IN_ROOT)) {
|
||||
additionalProperties.put(PROVIDED_IN_ROOT, true);
|
||||
if (ngVersion.atLeast("9.0.0") && additionalProperties.containsKey(PROVIDED_IN)) {
|
||||
setProvidedIn(additionalProperties.get(PROVIDED_IN).toString());
|
||||
} else {
|
||||
additionalProperties.put(PROVIDED_IN_ROOT, Boolean.parseBoolean(
|
||||
additionalProperties.get(PROVIDED_IN_ROOT).toString()
|
||||
));
|
||||
// Keep for backward compatibility
|
||||
if (!additionalProperties.containsKey(PROVIDED_IN_ROOT)) {
|
||||
additionalProperties.put(PROVIDED_IN_ROOT, true);
|
||||
} else {
|
||||
if (ngVersion.atLeast("9.0.0")) {
|
||||
LOGGER.warn("{} will be deprecated, use {} {} instead", PROVIDED_IN_ROOT, PROVIDED_IN, PROVIDED_IN_LEVEL.values());
|
||||
}
|
||||
additionalProperties.put(PROVIDED_IN_ROOT, Boolean.parseBoolean(
|
||||
additionalProperties.get(PROVIDED_IN_ROOT).toString()
|
||||
));
|
||||
}
|
||||
if ((Boolean) additionalProperties.get(PROVIDED_IN_ROOT)) {
|
||||
providedIn = PROVIDED_IN_LEVEL.root;
|
||||
} else {
|
||||
providedIn = PROVIDED_IN_LEVEL.none;
|
||||
}
|
||||
}
|
||||
additionalProperties.put("providedIn", providedIn);
|
||||
additionalProperties.put("isProvidedInNone", getIsProvidedInNone());
|
||||
|
||||
if (ngVersion.atLeast("9.0.0")) {
|
||||
additionalProperties.put(ENFORCE_GENERIC_MODULE_WITH_PROVIDERS, true);
|
||||
@ -714,5 +741,29 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Injectable level
|
||||
*
|
||||
* @param level the wanted level
|
||||
*/
|
||||
public void setProvidedIn (String level) {
|
||||
try {
|
||||
providedIn = PROVIDED_IN_LEVEL.valueOf(level);
|
||||
} catch (IllegalArgumentException e) {
|
||||
String values = Stream.of(PROVIDED_IN_LEVEL.values())
|
||||
.map(value -> "'" + value.name() + "'")
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
String msg = String.format(Locale.ROOT, "Invalid providedIn level '%s'. Must be one of %s.", level, values);
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private boolean getIsProvidedInNone() {
|
||||
return PROVIDED_IN_LEVEL.none.equals(providedIn);
|
||||
}
|
||||
}
|
||||
|
@ -219,6 +219,14 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
super.postProcessParameter(parameter);
|
||||
if (parameter.isFormParam && parameter.isArray && "binary".equals(parameter.dataFormat)) {
|
||||
parameter.isCollectionFormatMulti = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
|
||||
Map<String, Object> result = super.postProcessAllModels(objs);
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.templating.mustache;
|
||||
|
||||
import com.samskivert.mustache.Mustache;
|
||||
import com.samskivert.mustache.Template.Fragment;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* Replaces duplicate whitespace characters in a fragment with single space.
|
||||
*
|
||||
* Register:
|
||||
* <pre>
|
||||
* additionalProperties.put("lambdaPrefixWithHash", new PrefixWithHashLambda());
|
||||
* </pre>
|
||||
*
|
||||
* Use:
|
||||
* <pre>
|
||||
* {{#lambdaPrefixWithHash}}{{name}}{{/lambdaPrefixWithHash}}
|
||||
* </pre>
|
||||
*/
|
||||
public class PrefixWithHashLambda implements Mustache.Lambda {
|
||||
private static final String WITH_HASH = "\n#";
|
||||
|
||||
private static final String NEWLINE_REGEX = "\\R";
|
||||
|
||||
@Override
|
||||
public void execute(Fragment fragment, Writer writer) throws IOException {
|
||||
writer.write(fragment.execute().replaceAll(NEWLINE_REGEX, WITH_HASH));
|
||||
}
|
||||
|
||||
}
|
@ -61,7 +61,7 @@ public class StringUtils {
|
||||
.build();
|
||||
}
|
||||
|
||||
private static Pattern capitalLetterPattern = Pattern.compile("([A-Z]+)([A-Z][a-z])");
|
||||
private static Pattern capitalLetterPattern = Pattern.compile("([A-Z]+)([A-Z][a-z][a-z]+)");
|
||||
private static Pattern lowercasePattern = Pattern.compile("([a-z\\d])([A-Z])");
|
||||
private static Pattern pkgSeparatorPattern = Pattern.compile("\\.");
|
||||
private static Pattern dollarPattern = Pattern.compile("\\$");
|
||||
|
@ -116,13 +116,13 @@ end:
|
||||
{{#pathParams}}
|
||||
|
||||
// Path Params
|
||||
long sizeOfPathParams_{{{paramName}}} = {{#pathParams}}{{#isLong}}sizeof({{paramName}})+3{{/isLong}}{{#isString}}strlen({{paramName}})+3{{/isString}}{{^-last}} + {{/-last}}{{/pathParams}} + strlen("{ {{paramName}} }");
|
||||
long sizeOfPathParams_{{{paramName}}} = {{#pathParams}}{{#isLong}}sizeof({{paramName}})+3{{/isLong}}{{#isString}}strlen({{paramName}})+3{{/isString}}{{^-last}} + {{/-last}}{{/pathParams}} + strlen("{ {{baseName}} }");
|
||||
{{#isNumeric}}
|
||||
if({{paramName}} == 0){
|
||||
goto end;
|
||||
}
|
||||
char* localVarToReplace_{{paramName}} = malloc(sizeOfPathParams_{{paramName}});
|
||||
snprintf(localVarToReplace_{{paramName}}, sizeOfPathParams_{{paramName}}, "{%s}", "{{paramName}}");
|
||||
snprintf(localVarToReplace_{{paramName}}, sizeOfPathParams_{{paramName}}, "{%s}", "{{baseName}}");
|
||||
|
||||
char localVarBuff_{{paramName}}[256];
|
||||
intToStr(localVarBuff_{{paramName}}, {{paramName}});
|
||||
@ -135,7 +135,7 @@ end:
|
||||
goto end;
|
||||
}
|
||||
char* localVarToReplace_{{paramName}} = malloc(sizeOfPathParams_{{paramName}});
|
||||
snprintf(localVarToReplace_{{paramName}}, sizeOfPathParams_{{paramName}}, "{%s}", "{{paramName}}");
|
||||
snprintf(localVarToReplace_{{paramName}}, sizeOfPathParams_{{paramName}}, "{%s}", "{{baseName}}");
|
||||
|
||||
char localVarBuff_{{paramName}}[256];
|
||||
intToStr(localVarBuff_{{paramName}}, {{paramName}});
|
||||
@ -148,7 +148,7 @@ end:
|
||||
goto end;
|
||||
}
|
||||
char* localVarToReplace_{{paramName}} = malloc(sizeOfPathParams_{{paramName}});
|
||||
snprintf(localVarToReplace_{{paramName}}, sizeOfPathParams_{{paramName}}, "{%s}", "{{paramName}}");
|
||||
snprintf(localVarToReplace_{{paramName}}, sizeOfPathParams_{{paramName}}, "{%s}", "{{baseName}}");
|
||||
|
||||
char localVarBuff_{{paramName}}[256];
|
||||
intToStr(localVarBuff_{{paramName}}, {{paramName}});
|
||||
@ -161,7 +161,7 @@ end:
|
||||
goto end;
|
||||
}
|
||||
char* localVarToReplace_{{paramName}} = malloc(sizeOfPathParams_{{paramName}});
|
||||
snprintf(localVarToReplace_{{paramName}}, sizeOfPathParams_{{paramName}}, "{%s}", "{{paramName}}");
|
||||
snprintf(localVarToReplace_{{paramName}}, sizeOfPathParams_{{paramName}}, "{%s}", "{{baseName}}");
|
||||
|
||||
char localVarBuff_{{paramName}}[256];
|
||||
intToStr(localVarBuff_{{paramName}}, {{paramName}});
|
||||
@ -174,7 +174,7 @@ end:
|
||||
goto end;
|
||||
}
|
||||
char* localVarToReplace_{{paramName}} = malloc(sizeOfPathParams_{{paramName}});
|
||||
sprintf(localVarToReplace_{{paramName}}, "{%s}", "{{paramName}}");
|
||||
sprintf(localVarToReplace_{{paramName}}, "{%s}", "{{baseName}}");
|
||||
|
||||
localVarPath = strReplace(localVarPath, localVarToReplace_{{paramName}}, {{paramName}});
|
||||
{{/isString}}
|
||||
@ -183,7 +183,7 @@ end:
|
||||
goto end;
|
||||
}
|
||||
char* localVarToReplace_{{paramName}} = malloc(sizeOfPathParams_{{paramName}});
|
||||
sprintf(localVarToReplace_{{paramName}}, "{%s}", "{{paramName}}");
|
||||
sprintf(localVarToReplace_{{paramName}}, "{%s}", "{{baseName}}");
|
||||
|
||||
localVarPath = strReplace(localVarPath, localVarToReplace_{{paramName}}, {{paramName}});
|
||||
{{/isUuid}}
|
||||
|
@ -396,7 +396,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} {
|
||||
*
|
||||
* @param secrets Hash map from authentication name to its secret.
|
||||
*/
|
||||
public ApiClient configureApiKeys(HashMap<String, String> secrets) {
|
||||
public ApiClient configureApiKeys(Map<String, String> secrets) {
|
||||
for (Map.Entry<String, Authentication> authEntry : authentications.entrySet()) {
|
||||
Authentication auth = authEntry.getValue();
|
||||
if (auth instanceof ApiKeyAuth) {
|
||||
|
@ -522,6 +522,15 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} {
|
||||
return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given {@code String} is a Problem JSON MIME (RFC-7807).
|
||||
* @param mediaType the input MediaType
|
||||
* @return boolean true if the MediaType represents Problem JSON, false otherwise
|
||||
*/
|
||||
public boolean isProblemJsonMime(String mediaType) {
|
||||
return "application/problem+json".equalsIgnoreCase(mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the Accept header's value from the given accepts array:
|
||||
* if JSON exists in the given array, use it;
|
||||
@ -536,7 +545,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} {
|
||||
}
|
||||
for (String accept : accepts) {
|
||||
MediaType mediaType = MediaType.parseMediaType(accept);
|
||||
if (isJsonMime(mediaType)) {
|
||||
if (isJsonMime(mediaType) && !isProblemJsonMime(accept)) {
|
||||
return Collections.singletonList(mediaType);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ org.openapitools.codegen.languages.AsciidocDocumentationCodegen
|
||||
org.openapitools.codegen.languages.AspNetCoreServerCodegen
|
||||
org.openapitools.codegen.languages.AvroSchemaCodegen
|
||||
org.openapitools.codegen.languages.BashClientCodegen
|
||||
org.openapitools.codegen.languages.CrystalClientCodegen
|
||||
org.openapitools.codegen.languages.CLibcurlClientCodegen
|
||||
org.openapitools.codegen.languages.ClojureClientCodegen
|
||||
org.openapitools.codegen.languages.ConfluenceWikiCodegen
|
||||
@ -44,6 +45,7 @@ org.openapitools.codegen.languages.KotlinClientCodegen
|
||||
org.openapitools.codegen.languages.KotlinServerCodegen
|
||||
org.openapitools.codegen.languages.KotlinSpringServerCodegen
|
||||
org.openapitools.codegen.languages.KotlinVertxServerCodegen
|
||||
org.openapitools.codegen.languages.KtormSchemaCodegen
|
||||
org.openapitools.codegen.languages.HaskellHttpClientCodegen
|
||||
org.openapitools.codegen.languages.HaskellServantCodegen
|
||||
org.openapitools.codegen.languages.JavaClientCodegen
|
||||
|
@ -75,10 +75,14 @@ h2. Models
|
||||
{anchor:{{classname}}ModelAnchor}
|
||||
h3. {{classname}}
|
||||
|
||||
{{description}}
|
||||
|
||||
||Field Name||Required||Type||Description||Enum||
|
||||
{{{description}}}
|
||||
|
||||
{{#isEnum}} ||Name||Value||Description||
|
||||
{{#allowableValues}} {{#enumVars}} |{{{name}}} |{{{value}}} |{{{enumDescription}}} |
|
||||
{{/enumVars}}
|
||||
{{/allowableValues}} {{/isEnum}}
|
||||
{{^isEnum}}||Field Name||Required||Type||Description||Enum||
|
||||
{{#vars}} |{{baseName}} |{{#required}}(/){{/required}}{{^required}}(x){{/required}} |{noformat:nopanel=true}{{{dataType}}}{noformat} |{{description}} | {{#isEnum}} {{_enum}} {{/isEnum}} |
|
||||
{{/vars}}
|
||||
{{/vars}} {{/isEnum}}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
|
9
modules/openapi-generator/src/main/resources/crystal/Gemfile.mustache
vendored
Normal file
9
modules/openapi-generator/src/main/resources/crystal/Gemfile.mustache
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gemspec
|
||||
|
||||
group :development, :test do
|
||||
gem 'rake', '~> 13.0.1'
|
||||
gem 'pry-byebug'
|
||||
gem 'rubocop', '~> 0.66.0'
|
||||
end
|
46
modules/openapi-generator/src/main/resources/crystal/README.mustache
vendored
Normal file
46
modules/openapi-generator/src/main/resources/crystal/README.mustache
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
# {{shardName}}
|
||||
|
||||
The Crystsal module for the {{appName}}
|
||||
|
||||
{{#appDescriptionWithNewLines}}
|
||||
{{{appDescriptionWithNewLines}}}
|
||||
{{/appDescriptionWithNewLines}}
|
||||
|
||||
This SDK is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: {{appVersion}}
|
||||
- Package version: {{shardVersion}}
|
||||
{{^hideGenerationTimestamp}}
|
||||
- Build date: {{generatedDate}}
|
||||
{{/hideGenerationTimestamp}}
|
||||
- Build package: {{generatorClass}}
|
||||
{{#infoUrl}}
|
||||
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
|
||||
{{/infoUrl}}
|
||||
|
||||
## Installation
|
||||
|
||||
### Install from Git
|
||||
|
||||
Add the following to shard.yaml
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
{{{shardName}}}:
|
||||
github: {{#gitUserId}}{{.}}{{/gitUserId}}{{^gitUserId}}YOUR_GIT_USERNAME{{/gitUserId}}/{{#gitRepoId}}{{.}}{{/gitRepoId}}{{^gitRepoId}}YOUR_GIT_REPO{{/gitRepoId}}
|
||||
version: ~> {{shardVersion}}
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
Install dependencies
|
||||
|
||||
```shell
|
||||
shards
|
||||
```
|
||||
|
||||
Run the tests:
|
||||
|
||||
```shell
|
||||
crystal spec
|
||||
```
|
10
modules/openapi-generator/src/main/resources/crystal/Rakefile.mustache
vendored
Normal file
10
modules/openapi-generator/src/main/resources/crystal/Rakefile.mustache
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
require "bundler/gem_tasks"
|
||||
|
||||
begin
|
||||
require 'rspec/core/rake_task'
|
||||
|
||||
RSpec::Core::RakeTask.new(:spec)
|
||||
task default: :spec
|
||||
rescue LoadError
|
||||
# no rspec available
|
||||
end
|
185
modules/openapi-generator/src/main/resources/crystal/api.mustache
vendored
Normal file
185
modules/openapi-generator/src/main/resources/crystal/api.mustache
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
require "uri"
|
||||
|
||||
module {{moduleName}}
|
||||
{{#operations}}
|
||||
class {{classname}}
|
||||
property api_client : ApiClient
|
||||
|
||||
def initialize(api_client = ApiClient.default)
|
||||
@api_client = api_client
|
||||
end
|
||||
{{#operation}}
|
||||
{{#summary}}
|
||||
# {{{summary}}}
|
||||
{{/summary}}
|
||||
{{#notes}}
|
||||
# {{{notes}}}
|
||||
{{/notes}}
|
||||
{{#allParams}}
|
||||
{{#required}}
|
||||
# @param {{paramName}} [{{{dataType}}}{{^required}}?{{/required}}] {{description}}
|
||||
{{/required}}
|
||||
{{/allParams}}
|
||||
# @return [{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}nil{{/returnType}}]
|
||||
def {{operationId}}({{#allParams}}{{paramName}} : {{{dataType}}}{{^required}}?{{/required}}{{^-last}}, {{/-last}}{{/allParams}})
|
||||
{{#returnType}}data, _status_code, _headers = {{/returnType}}{{operationId}}_with_http_info({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}})
|
||||
{{#returnType}}data{{/returnType}}{{^returnType}}nil{{/returnType}}
|
||||
end
|
||||
|
||||
{{#summary}}
|
||||
# {{summary}}
|
||||
{{/summary}}
|
||||
{{#notes}}
|
||||
# {{notes}}
|
||||
{{/notes}}
|
||||
{{#allParams}}
|
||||
{{#required}}
|
||||
# @param {{paramName}} [{{{dataType}}}{{^required}}?{{/required}}] {{description}}
|
||||
{{/required}}
|
||||
{{/allParams}}
|
||||
# @return [Array<({{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}nil{{/returnType}}, Integer, Hash)>] {{#returnType}}{{{returnType}}} data{{/returnType}}{{^returnType}}nil{{/returnType}}, response status code and response headers
|
||||
def {{operationId}}_with_http_info({{#allParams}}{{paramName}} : {{{dataType}}}{{^required}}?{{/required}}{{^-last}}, {{/-last}}{{/allParams}})
|
||||
if @api_client.config.debugging
|
||||
Log.debug {"Calling API: {{classname}}.{{operationId}} ..."}
|
||||
end
|
||||
{{#allParams}}
|
||||
{{^isNullable}}
|
||||
{{#required}}
|
||||
# verify the required parameter "{{paramName}}" is set
|
||||
if @api_client.config.client_side_validation && {{{paramName}}}.nil?
|
||||
raise ArgumentError.new("Missing the required parameter '{{paramName}}' when calling {{classname}}.{{operationId}}")
|
||||
end
|
||||
{{#isEnum}}
|
||||
{{^isContainer}}
|
||||
# verify enum value
|
||||
allowable_values = [{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]
|
||||
if @api_client.config.client_side_validation && !allowable_values.include?({{{paramName}}})
|
||||
raise ArgumentError.new("invalid value for \"{{{paramName}}}\", must be one of #{allowable_values}")
|
||||
end
|
||||
{{/isContainer}}
|
||||
{{/isEnum}}
|
||||
{{/required}}
|
||||
{{/isNullable}}
|
||||
{{^required}}
|
||||
{{#isEnum}}
|
||||
{{#collectionFormat}}
|
||||
allowable_values = [{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]
|
||||
if @api_client.config.client_side_validation && {{{paramName}}} && {{{paramName}}}.all? { |item| allowable_values.include?(item) }
|
||||
raise ArgumentError.new("invalid value for \"{{{paramName}}}\", must include one of #{allowable_values}")
|
||||
end
|
||||
{{/collectionFormat}}
|
||||
{{^collectionFormat}}
|
||||
allowable_values = [{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]
|
||||
if @api_client.config.client_side_validation && {{{paramName}}} && !allowable_values.include?({{{paramName}}}])
|
||||
raise ArgumentError.new("invalid value for \"{{{paramName}}}\", must be one of #{allowable_values}")
|
||||
end
|
||||
{{/collectionFormat}}
|
||||
{{/isEnum}}
|
||||
{{/required}}
|
||||
{{#hasValidation}}
|
||||
{{#maxLength}}
|
||||
if @api_client.config.client_side_validation && {{^required}}!{{{paramName}}}.nil? && {{/required}}{{{paramName}}}.to_s.length > {{{maxLength}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{paramName}}}\" when calling {{classname}}.{{operationId}}, the character length must be smaller than or equal to {{{maxLength}}}.")
|
||||
end
|
||||
|
||||
{{/maxLength}}
|
||||
{{#minLength}}
|
||||
if @api_client.config.client_side_validation && {{^required}}!{{{paramName}}}.nil? && {{/required}}{{{paramName}}}.to_s.length < {{{minLength}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{paramName}}}\" when calling {{classname}}.{{operationId}}, the character length must be great than or equal to {{{minLength}}}.")
|
||||
end
|
||||
|
||||
{{/minLength}}
|
||||
{{#maximum}}
|
||||
if @api_client.config.client_side_validation && {{^required}}!{{{paramName}}}.nil? && {{/required}}{{{paramName}}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{{maximum}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{paramName}}}\" when calling {{classname}}.{{operationId}}, must be smaller than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}{{{maximum}}}.")
|
||||
end
|
||||
|
||||
{{/maximum}}
|
||||
{{#minimum}}
|
||||
if @api_client.config.client_side_validation && {{^required}}!{{{paramName}}}.nil? && {{/required}}{{{paramName}}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{{minimum}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{paramName}}}\" when calling {{classname}}.{{operationId}}, must be greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}{{{minimum}}}.")
|
||||
end
|
||||
|
||||
{{/minimum}}
|
||||
{{#pattern}}
|
||||
pattern = Regexp.new({{{pattern}}})
|
||||
if @api_client.config.client_side_validation && {{^required}}{{{paramName}}}.nil? && {{/required}}{{{paramName}}} !~ pattern
|
||||
raise ArgumentError.new("invalid value for \"{{{paramName}}}\" when calling {{classname}}.{{operationId}}, must conform to the pattern #{pattern}.")
|
||||
end
|
||||
|
||||
{{/pattern}}
|
||||
{{#maxItems}}
|
||||
if @api_client.config.client_side_validation && {{^required}}{{{paramName}}}.nil? && {{/required}}{{{paramName}}}.length > {{{maxItems}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{paramName}}}\" when calling {{classname}}.{{operationId}}, number of items must be less than or equal to {{{maxItems}}}.")
|
||||
end
|
||||
|
||||
{{/maxItems}}
|
||||
{{#minItems}}
|
||||
if @api_client.config.client_side_validation && {{^required}}{{{paramName}}}.nil? && {{/required}}{{{paramName}}}.length < {{{minItems}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{paramName}}}\" when calling {{classname}}.{{operationId}}, number of items must be greater than or equal to {{{minItems}}}.")
|
||||
end
|
||||
|
||||
{{/minItems}}
|
||||
{{/hasValidation}}
|
||||
{{/allParams}}
|
||||
# resource path
|
||||
local_var_path = "{{{path}}}"{{#pathParams}}.sub("{" + "{{baseName}}" + "}", URI.encode({{paramName}}.to_s){{^strictSpecBehavior}}.gsub("%2F", "/"){{/strictSpecBehavior}}){{/pathParams}}
|
||||
|
||||
# query parameters
|
||||
query_params = Hash(Symbol, String).new
|
||||
{{#queryParams}}
|
||||
query_params[:"{{{baseName}}}"] = {{#collectionFormat}}@api_client.build_collection_param({{{paramName}}}, :{{{collectionFormat}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}}
|
||||
{{/queryParams}}
|
||||
|
||||
# header parameters
|
||||
header_params = Hash(String, String).new
|
||||
{{#hasProduces}}
|
||||
# HTTP header "Accept" (if needed)
|
||||
header_params["Accept"] = @api_client.select_header_accept([{{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}])
|
||||
{{/hasProduces}}
|
||||
{{#hasConsumes}}
|
||||
# HTTP header "Content-Type"
|
||||
header_params["Content-Type"] = @api_client.select_header_content_type([{{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}}])
|
||||
{{/hasConsumes}}
|
||||
{{#headerParams}}
|
||||
header_params["{{{baseName}}}"] = {{#collectionFormat}}@api_client.build_collection_param({{{paramName}}}, :{{{collectionFormat}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}}
|
||||
{{/headerParams}}
|
||||
|
||||
# form parameters
|
||||
form_params = Hash(Symbol, String).new
|
||||
{{#formParams}}
|
||||
form_params[:"{{baseName}}"] = {{#collectionFormat}}@api_client.build_collection_param({{{paramName}}}, :{{{collectionFormat}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}}
|
||||
{{/formParams}}
|
||||
|
||||
# http body (model)
|
||||
post_body = {{#bodyParam}}{{{paramName}}}.to_json{{/bodyParam}}{{^bodyParam}}nil{{/bodyParam}}
|
||||
|
||||
# return_type
|
||||
return_type = {{#returnType}}"{{{.}}}"{{/returnType}}{{^returnType}}nil{{/returnType}}
|
||||
|
||||
# auth_names
|
||||
auth_names = {{#authMethods}}{{#-first}}[{{/-first}}"{{name}}"{{^-last}}, {{/-last}}{{#-last}}]{{/-last}}{{/authMethods}}{{^authMethods}}[] of String{{/authMethods}}
|
||||
|
||||
data, status_code, headers = @api_client.call_api(:{{httpMethod}},
|
||||
local_var_path,
|
||||
:"{{classname}}.{{operationId}}",
|
||||
return_type,
|
||||
post_body,
|
||||
auth_names,
|
||||
header_params,
|
||||
query_params,
|
||||
form_params)
|
||||
if @api_client.config.debugging
|
||||
Log.debug {"API called: {{classname}}#{{operationId}}\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
|
||||
end
|
||||
return {{#returnType}}{{{.}}}.from_json(data){{/returnType}}{{^returnType}}nil{{/returnType}}, status_code, headers
|
||||
end
|
||||
{{^-last}}
|
||||
|
||||
{{/-last}}
|
||||
{{/operation}}
|
||||
end
|
||||
{{/operations}}
|
||||
end
|
402
modules/openapi-generator/src/main/resources/crystal/api_client.mustache
vendored
Normal file
402
modules/openapi-generator/src/main/resources/crystal/api_client.mustache
vendored
Normal file
@ -0,0 +1,402 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
require "json"
|
||||
require "time"
|
||||
|
||||
module {{moduleName}}
|
||||
class ApiClient
|
||||
# The Configuration object holding settings to be used in the API client.
|
||||
property config : Configuration
|
||||
|
||||
# Defines the headers to be used in HTTP requests of all API calls by default.
|
||||
#
|
||||
# @return [Hash]
|
||||
property default_headers : Hash(String, String)
|
||||
|
||||
# Initializes the ApiClient
|
||||
# @option config [Configuration] Configuration for initializing the object, default to Configuration.default
|
||||
def initialize(@config = Configuration.default)
|
||||
@user_agent = "{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/#{VERSION}/crystal{{/httpUserAgent}}"
|
||||
@default_headers = {
|
||||
"User-Agent" => @user_agent
|
||||
}
|
||||
end
|
||||
|
||||
def self.default
|
||||
@@default ||= ApiClient.new
|
||||
end
|
||||
|
||||
# Check if the given MIME is a JSON MIME.
|
||||
# JSON MIME examples:
|
||||
# application/json
|
||||
# application/json; charset=UTF8
|
||||
# APPLICATION/JSON
|
||||
# */*
|
||||
# @param [String] mime MIME
|
||||
# @return [Boolean] True if the MIME is application/json
|
||||
def json_mime?(mime)
|
||||
(mime == "*/*") || !(mime =~ /Application\/.*json(?!p)(;.*)?/i).nil?
|
||||
end
|
||||
|
||||
# Deserialize the response to the given return type.
|
||||
#
|
||||
# @param [Response] response HTTP response
|
||||
# @param [String] return_type some examples: "User", "Array<User>", "Hash<String, Integer>"
|
||||
def deserialize(response, return_type)
|
||||
body = response.body
|
||||
|
||||
# handle file downloading - return the File instance processed in request callbacks
|
||||
# note that response body is empty when the file is written in chunks in request on_body callback
|
||||
if return_type == "File"
|
||||
content_disposition = response.headers["Content-Disposition"].to_s
|
||||
if content_disposition && content_disposition =~ /filename=/i
|
||||
filename = content_disposition.match(/filename=[""]?([^""\s]+)[""]?/i).try &.[0]
|
||||
prefix = sanitize_filename(filename)
|
||||
else
|
||||
prefix = "download-"
|
||||
end
|
||||
if !prefix.nil? && prefix.ends_with?("-")
|
||||
prefix = prefix + "-"
|
||||
end
|
||||
encoding = response.headers["Content-Encoding"].to_s
|
||||
|
||||
# TODO add file support
|
||||
raise ApiError.new(code: 0, message: "File response not yet supported in the client.") if return_type
|
||||
return nil
|
||||
|
||||
#@tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding)
|
||||
#@tempfile.write(@stream.join.force_encoding(encoding))
|
||||
#@tempfile.close
|
||||
#Log.info { "Temp file written to #{@tempfile.path}, please copy the file to a proper folder "\
|
||||
# "with e.g. `FileUtils.cp(tempfile.path, \"/new/file/path\")` otherwise the temp file "\
|
||||
# "will be deleted automatically with GC. It's also recommended to delete the temp file "\
|
||||
# "explicitly with `tempfile.delete`" }
|
||||
#return @tempfile
|
||||
end
|
||||
|
||||
return nil if body.nil? || body.empty?
|
||||
|
||||
# return response body directly for String return type
|
||||
return body if return_type == "String"
|
||||
|
||||
# ensuring a default content type
|
||||
content_type = response.headers["Content-Type"] || "application/json"
|
||||
|
||||
raise ApiError.new(code: 0, message: "Content-Type is not supported: #{content_type}") unless json_mime?(content_type)
|
||||
|
||||
begin
|
||||
data = JSON.parse("[#{body}]")[0]
|
||||
rescue e : Exception
|
||||
if %w(String Date Time).includes?(return_type)
|
||||
data = body
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
convert_to_type data, return_type
|
||||
end
|
||||
|
||||
# Convert data to the given return type.
|
||||
# @param [Object] data Data to be converted
|
||||
# @param [String] return_type Return type
|
||||
# @return [Mixed] Data in a particular type
|
||||
def convert_to_type(data, return_type)
|
||||
return nil if data.nil?
|
||||
case return_type
|
||||
when "String"
|
||||
data.to_s
|
||||
when "Integer"
|
||||
data.to_s.to_i
|
||||
when "Float"
|
||||
data.to_s.to_f
|
||||
when "Boolean"
|
||||
data == true
|
||||
when "Time"
|
||||
# parse date time (expecting ISO 8601 format)
|
||||
Time.parse! data.to_s, "%Y-%m-%dT%H:%M:%S%Z"
|
||||
when "Date"
|
||||
# parse date (expecting ISO 8601 format)
|
||||
Time.parse! data.to_s, "%Y-%m-%d"
|
||||
when "Object"
|
||||
# generic object (usually a Hash), return directly
|
||||
data
|
||||
when /\AArray<(.+)>\z/
|
||||
# e.g. Array<Pet>
|
||||
sub_type = $1
|
||||
data.map { |item| convert_to_type(item, sub_type) }
|
||||
when /\AHash\<String, (.+)\>\z/
|
||||
# e.g. Hash<String, Integer>
|
||||
sub_type = $1
|
||||
({} of Symbol => String).tap do |hash|
|
||||
data.each { |k, v| hash[k] = convert_to_type(v, sub_type) }
|
||||
end
|
||||
else
|
||||
# models (e.g. Pet) or oneOf
|
||||
klass = Petstore.const_get(return_type)
|
||||
klass.respond_to?(:openapi_one_of) ? klass.build(data) : klass.build_from_hash(data)
|
||||
end
|
||||
end
|
||||
|
||||
# Sanitize filename by removing path.
|
||||
# e.g. ../../sun.gif becomes sun.gif
|
||||
#
|
||||
# @param [String] filename the filename to be sanitized
|
||||
# @return [String] the sanitized filename
|
||||
def sanitize_filename(filename)
|
||||
if filename.nil?
|
||||
return nil
|
||||
else
|
||||
filename.gsub(/.*[\/\\]/, "")
|
||||
end
|
||||
end
|
||||
|
||||
def build_request_url(path : String, operation : Symbol)
|
||||
# Add leading and trailing slashes to path
|
||||
path = "/#{path}".gsub(/\/+/, "/")
|
||||
@config.base_url(operation) + path
|
||||
end
|
||||
|
||||
# Update hearder and query params based on authentication settings.
|
||||
#
|
||||
# @param [Hash] header_params Header parameters
|
||||
# @param [Hash] query_params Query parameters
|
||||
# @param [String] auth_names Authentication scheme name
|
||||
def update_params_for_auth!(header_params, query_params, auth_names)
|
||||
Array{auth_names}.each do |auth_name|
|
||||
auth_setting = @config.auth_settings[auth_name]
|
||||
next unless auth_setting
|
||||
case auth_setting[:in]
|
||||
when "header" then header_params[auth_setting[:key]] = auth_setting[:value]
|
||||
when "query" then query_params[auth_setting[:key]] = auth_setting[:value]
|
||||
else raise ArgumentError.new("Authentication token must be in `query` of `header`")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Sets user agent in HTTP header
|
||||
#
|
||||
# @param [String] user_agent User agent (e.g. openapi-generator/ruby/1.0.0)
|
||||
def user_agent=(user_agent)
|
||||
@user_agent = user_agent
|
||||
@default_headers["User-Agent"] = @user_agent
|
||||
end
|
||||
|
||||
# Return Accept header based on an array of accepts provided.
|
||||
# @param [Array] accepts array for Accept
|
||||
# @return [String] the Accept header (e.g. application/json)
|
||||
def select_header_accept(accepts) : String
|
||||
#return nil if accepts.nil? || accepts.empty?
|
||||
# use JSON when present, otherwise use all of the provided
|
||||
json_accept = accepts.find { |s| json_mime?(s) }
|
||||
if json_accept.nil?
|
||||
accepts.join(",")
|
||||
else
|
||||
json_accept
|
||||
end
|
||||
end
|
||||
|
||||
# Return Content-Type header based on an array of content types provided.
|
||||
# @param [Array] content_types array for Content-Type
|
||||
# @return [String] the Content-Type header (e.g. application/json)
|
||||
def select_header_content_type(content_types)
|
||||
# use application/json by default
|
||||
return "application/json" if content_types.nil? || content_types.empty?
|
||||
# use JSON when present, otherwise use the first one
|
||||
json_content_type = content_types.find { |s| json_mime?(s) }
|
||||
json_content_type || content_types.first
|
||||
end
|
||||
|
||||
# Convert object (array, hash, object, etc) to JSON string.
|
||||
# @param [Object] model object to be converted into JSON string
|
||||
# @return [String] JSON string representation of the object
|
||||
def object_to_http_body(model)
|
||||
return model if model.nil? || model.is_a?(String)
|
||||
local_body = nil
|
||||
if model.is_a?(Array)
|
||||
local_body = model.map { |m| object_to_hash(m) }
|
||||
else
|
||||
local_body = object_to_hash(model)
|
||||
end
|
||||
local_body.to_json
|
||||
end
|
||||
|
||||
# Convert object(non-array) to hash.
|
||||
# @param [Object] obj object to be converted into JSON string
|
||||
# @return [String] JSON string representation of the object
|
||||
def object_to_hash(obj)
|
||||
if obj.respond_to?(:to_hash)
|
||||
obj.to_hash
|
||||
else
|
||||
obj
|
||||
end
|
||||
end
|
||||
|
||||
# Build parameter value according to the given collection format.
|
||||
# @param [String] collection_format one of :csv, :ssv, :tsv, :pipes and :multi
|
||||
def build_collection_param(param, collection_format)
|
||||
case collection_format
|
||||
when :csv
|
||||
param.join(",")
|
||||
when :ssv
|
||||
param.join(" ")
|
||||
when :tsv
|
||||
param.join("\t")
|
||||
when :pipes
|
||||
param.join("|")
|
||||
when :multi
|
||||
# return the array directly as typhoeus will handle it as expected
|
||||
param
|
||||
else
|
||||
fail "unknown collection format: #{collection_format.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
# Call an API with given options.
|
||||
#
|
||||
# @return [Array<(Object, Integer, Hash)>] an array of 3 elements:
|
||||
# the data deserialized from response body (could be nil), response status code and response headers.
|
||||
def call_api(http_method : Symbol, path : String, operation : Symbol, return_type : String, post_body : String?, auth_names = [] of String, header_params = {} of String => String, query_params = {} of Symbol => String, form_params = {} of Symbol => String)
|
||||
#ssl_options = {
|
||||
# :ca_file => @config.ssl_ca_file,
|
||||
# :verify => @config.ssl_verify,
|
||||
# :verify_mode => @config.ssl_verify_mode,
|
||||
# :client_cert => @config.ssl_client_cert,
|
||||
# :client_key => @config.ssl_client_key
|
||||
#}
|
||||
|
||||
#connection = Faraday.new(:url => config.base_url, :ssl => ssl_options) do |conn|
|
||||
# conn.basic_auth(config.username, config.password)
|
||||
# if opts[:header_params]["Content-Type"] == "multipart/form-data"
|
||||
# conn.request :multipart
|
||||
# conn.request :url_encoded
|
||||
# end
|
||||
# conn.adapter(Faraday.default_adapter)
|
||||
#end
|
||||
|
||||
if !post_body.nil? && !post_body.empty?
|
||||
# use JSON string in the payload
|
||||
form_or_body = post_body
|
||||
else
|
||||
# use HTTP forms in the payload
|
||||
# TDOD use HTTP form encoding
|
||||
form_or_body = form_params
|
||||
end
|
||||
|
||||
request = Crest::Request.new(http_method,
|
||||
build_request_url(path, operation),
|
||||
params: query_params,
|
||||
headers: header_params,
|
||||
#cookies: cookie_params, # TODO add cookies support
|
||||
form: form_or_body,
|
||||
logging: @config.debugging,
|
||||
handle_errors: false
|
||||
)
|
||||
|
||||
response = request.execute
|
||||
|
||||
if @config.debugging
|
||||
Log.debug {"HTTP response body ~BEGIN~\n#{response.body}\n~END~\n"}
|
||||
end
|
||||
|
||||
if !response.success?
|
||||
if response.status == 0
|
||||
# Errors from libcurl will be made visible here
|
||||
raise ApiError.new(code: 0,
|
||||
message: response.body)
|
||||
else
|
||||
raise ApiError.new(code: response.status_code,
|
||||
response_headers: response.headers,
|
||||
message: response.body)
|
||||
end
|
||||
end
|
||||
|
||||
return response.body, response.status_code, response.headers
|
||||
end
|
||||
|
||||
# Builds the HTTP request
|
||||
#
|
||||
# @param [String] http_method HTTP method/verb (e.g. POST)
|
||||
# @param [String] path URL path (e.g. /account/new)
|
||||
# @option opts [Hash] :header_params Header parameters
|
||||
# @option opts [Hash] :query_params Query parameters
|
||||
# @option opts [Hash] :form_params Query parameters
|
||||
# @option opts [Object] :body HTTP body (JSON/XML)
|
||||
# @return [Typhoeus::Request] A Typhoeus Request
|
||||
def build_request(http_method, path, request, opts = {} of Symbol => String)
|
||||
url = build_request_url(path, opts)
|
||||
http_method = http_method.to_sym.downcase
|
||||
|
||||
header_params = @default_headers.merge(opts[:header_params] || {} of Symbole => String)
|
||||
query_params = opts[:query_params] || {} of Symbol => String
|
||||
form_params = opts[:form_params] || {} of Symbol => String
|
||||
|
||||
update_params_for_auth! header_params, query_params, opts[:auth_names]
|
||||
|
||||
req_opts = {
|
||||
:method => http_method,
|
||||
:headers => header_params,
|
||||
:params => query_params,
|
||||
:params_encoding => @config.params_encoding,
|
||||
:timeout => @config.timeout,
|
||||
:verbose => @config.debugging
|
||||
}
|
||||
|
||||
if [:post, :patch, :put, :delete].include?(http_method)
|
||||
req_body = build_request_body(header_params, form_params, opts[:body])
|
||||
req_opts.update body: req_body
|
||||
if @config.debugging
|
||||
Log.debug {"HTTP request body param ~BEGIN~\n#{req_body}\n~END~\n"}
|
||||
end
|
||||
end
|
||||
request.headers = header_params
|
||||
request.body = req_body
|
||||
request.url url
|
||||
request.params = query_params
|
||||
download_file(request) if opts[:return_type] == "File"
|
||||
request
|
||||
end
|
||||
|
||||
# Builds the HTTP request body
|
||||
#
|
||||
# @param [Hash] header_params Header parameters
|
||||
# @param [Hash] form_params Query parameters
|
||||
# @param [Object] body HTTP body (JSON/XML)
|
||||
# @return [String] HTTP body data in the form of string
|
||||
def build_request_body(header_params, form_params, body)
|
||||
# http form
|
||||
if header_params["Content-Type"] == "application/x-www-form-urlencoded"
|
||||
data = URI.encode_www_form(form_params)
|
||||
elsif header_params["Content-Type"] == "multipart/form-data"
|
||||
data = {} of Symbol => String
|
||||
form_params.each do |key, value|
|
||||
case value
|
||||
when ::File, ::Tempfile
|
||||
# TODO hardcode to application/octet-stream, need better way to detect content type
|
||||
data[key] = Faraday::UploadIO.new(value.path, "application/octet-stream", value.path)
|
||||
when ::Array, nil
|
||||
# let Faraday handle Array and nil parameters
|
||||
data[key] = value
|
||||
else
|
||||
data[key] = value.to_s
|
||||
end
|
||||
end
|
||||
elsif body
|
||||
data = body.is_a?(String) ? body : body.to_json
|
||||
else
|
||||
data = nil
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
# TODO fix streaming response
|
||||
#def download_file(request)
|
||||
# @stream = []
|
||||
|
||||
# # handle streaming Responses
|
||||
# request.options.on_data = Proc.new do |chunk, overall_received_bytes|
|
||||
# @stream << chunk
|
||||
# end
|
||||
#end
|
||||
end
|
||||
end
|
138
modules/openapi-generator/src/main/resources/crystal/api_client_faraday_partial.mustache
vendored
Normal file
138
modules/openapi-generator/src/main/resources/crystal/api_client_faraday_partial.mustache
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
# Call an API with given options.
|
||||
#
|
||||
# @return [Array<(Object, Integer, Hash)>] an array of 3 elements:
|
||||
# the data deserialized from response body (could be nil), response status code and response headers.
|
||||
def call_api(http_method, path, opts = {} of Symbol => String)
|
||||
ssl_options = {
|
||||
:ca_file => @config.ssl_ca_file,
|
||||
:verify => @config.ssl_verify,
|
||||
:verify_mode => @config.ssl_verify_mode,
|
||||
:client_cert => @config.ssl_client_cert,
|
||||
:client_key => @config.ssl_client_key
|
||||
}
|
||||
|
||||
connection = Faraday.new(:url => config.base_url, :ssl => ssl_options) do |conn|
|
||||
conn.basic_auth(config.username, config.password)
|
||||
if opts[:header_params]["Content-Type"] == "multipart/form-data"
|
||||
conn.request :multipart
|
||||
conn.request :url_encoded
|
||||
end
|
||||
conn.adapter(Faraday.default_adapter)
|
||||
end
|
||||
|
||||
begin
|
||||
response = connection.public_send(http_method.to_sym.downcase) do |req|
|
||||
build_request(http_method, path, req, opts)
|
||||
end
|
||||
|
||||
if @config.debugging
|
||||
Log.debug {"HTTP response body ~BEGIN~\n#{response.body}\n~END~\n"}
|
||||
end
|
||||
|
||||
unless response.success?
|
||||
if response.status == 0
|
||||
# Errors from libcurl will be made visible here
|
||||
fail ApiError.new(code: 0,
|
||||
message: response.return_message)
|
||||
else
|
||||
fail ApiError.new(code: response.status,
|
||||
response_headers: response.headers,
|
||||
response_body: response.body),
|
||||
response.reason_phrase
|
||||
end
|
||||
end
|
||||
rescue Faraday::TimeoutError
|
||||
fail ApiError.new("Connection timed out")
|
||||
end
|
||||
|
||||
if opts[:return_type]
|
||||
data = deserialize(response, opts[:return_type])
|
||||
else
|
||||
data = nil
|
||||
end
|
||||
return data, response.status, response.headers
|
||||
end
|
||||
|
||||
# Builds the HTTP request
|
||||
#
|
||||
# @param [String] http_method HTTP method/verb (e.g. POST)
|
||||
# @param [String] path URL path (e.g. /account/new)
|
||||
# @option opts [Hash] :header_params Header parameters
|
||||
# @option opts [Hash] :query_params Query parameters
|
||||
# @option opts [Hash] :form_params Query parameters
|
||||
# @option opts [Object] :body HTTP body (JSON/XML)
|
||||
# @return [Typhoeus::Request] A Typhoeus Request
|
||||
def build_request(http_method, path, request, opts = {} of Symbol => String)
|
||||
url = build_request_url(path, opts)
|
||||
http_method = http_method.to_sym.downcase
|
||||
|
||||
header_params = @default_headers.merge(opts[:header_params] || {} of Symbole => String)
|
||||
query_params = opts[:query_params] || {} of Symbol => String
|
||||
form_params = opts[:form_params] || {} of Symbol => String
|
||||
|
||||
update_params_for_auth! header_params, query_params, opts[:auth_names]
|
||||
|
||||
req_opts = {
|
||||
:method => http_method,
|
||||
:headers => header_params,
|
||||
:params => query_params,
|
||||
:params_encoding => @config.params_encoding,
|
||||
:timeout => @config.timeout,
|
||||
:verbose => @config.debugging
|
||||
}
|
||||
|
||||
if [:post, :patch, :put, :delete].include?(http_method)
|
||||
req_body = build_request_body(header_params, form_params, opts[:body])
|
||||
req_opts.update body: req_body
|
||||
if @config.debugging
|
||||
Log.debug {"HTTP request body param ~BEGIN~\n#{req_body}\n~END~\n"}
|
||||
end
|
||||
end
|
||||
request.headers = header_params
|
||||
request.body = req_body
|
||||
request.url url
|
||||
request.params = query_params
|
||||
download_file(request) if opts[:return_type] == "File"
|
||||
request
|
||||
end
|
||||
|
||||
# Builds the HTTP request body
|
||||
#
|
||||
# @param [Hash] header_params Header parameters
|
||||
# @param [Hash] form_params Query parameters
|
||||
# @param [Object] body HTTP body (JSON/XML)
|
||||
# @return [String] HTTP body data in the form of string
|
||||
def build_request_body(header_params, form_params, body)
|
||||
# http form
|
||||
if header_params["Content-Type"] == "application/x-www-form-urlencoded"
|
||||
data = URI.encode_www_form(form_params)
|
||||
elsif header_params["Content-Type"] == "multipart/form-data"
|
||||
data = {} of Symbol => String
|
||||
form_params.each do |key, value|
|
||||
case value
|
||||
when ::File, ::Tempfile
|
||||
# TODO hardcode to application/octet-stream, need better way to detect content type
|
||||
data[key] = Faraday::UploadIO.new(value.path, "application/octet-stream", value.path)
|
||||
when ::Array, nil
|
||||
# let Faraday handle Array and nil parameters
|
||||
data[key] = value
|
||||
else
|
||||
data[key] = value.to_s
|
||||
end
|
||||
end
|
||||
elsif body
|
||||
data = body.is_a?(String) ? body : body.to_json
|
||||
else
|
||||
data = nil
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
def download_file(request)
|
||||
@stream = []
|
||||
|
||||
# handle streaming Responses
|
||||
request.options.on_data = Proc.new do |chunk, overall_received_bytes|
|
||||
@stream << chunk
|
||||
end
|
||||
end
|
153
modules/openapi-generator/src/main/resources/crystal/api_client_typhoeus_partial.mustache
vendored
Normal file
153
modules/openapi-generator/src/main/resources/crystal/api_client_typhoeus_partial.mustache
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
# Call an API with given options.
|
||||
#
|
||||
# @return [Array<(Object, Integer, Hash)>] an array of 3 elements:
|
||||
# the data deserialized from response body (could be nil), response status code and response headers.
|
||||
def call_api(http_method, path, opts = {} of Symbol => String)
|
||||
request = build_request(http_method, path, opts)
|
||||
response = request.run
|
||||
|
||||
if @config.debugging
|
||||
@config.logger.debug "HTTP response body ~BEGIN~\n#{response.body}\n~END~\n"
|
||||
end
|
||||
|
||||
unless response.success?
|
||||
if response.timed_out?
|
||||
fail ApiError.new("Connection timed out")
|
||||
elsif response.code == 0
|
||||
# Errors from libcurl will be made visible here
|
||||
fail ApiError.new(code: 0,
|
||||
message: response.return_message)
|
||||
else
|
||||
fail ApiError.new(code: response.code,
|
||||
response_headers: response.headers,
|
||||
response_body: response.body),
|
||||
response.status_message
|
||||
end
|
||||
end
|
||||
|
||||
if opts[:return_type]
|
||||
data = deserialize(response, opts[:return_type])
|
||||
else
|
||||
data = nil
|
||||
end
|
||||
return data, response.code, response.headers
|
||||
end
|
||||
|
||||
# Builds the HTTP request
|
||||
#
|
||||
# @param [String] http_method HTTP method/verb (e.g. POST)
|
||||
# @param [String] path URL path (e.g. /account/new)
|
||||
# @option opts [Hash] :header_params Header parameters
|
||||
# @option opts [Hash] :query_params Query parameters
|
||||
# @option opts [Hash] :form_params Query parameters
|
||||
# @option opts [Object] :body HTTP body (JSON/XML)
|
||||
# @return [Typhoeus::Request] A Typhoeus Request
|
||||
def build_request(http_method, path, opts = {} of Symbol => String)
|
||||
url = build_request_url(path, opts)
|
||||
http_method = http_method.to_sym.downcase
|
||||
|
||||
header_params = @default_headers.merge(opts[:header_params] || {} of Symbol => String)
|
||||
query_params = opts[:query_params] || {} of Symbol => String
|
||||
form_params = opts[:form_params] || {} of Symbol => String
|
||||
|
||||
{{#hasAuthMethods}}
|
||||
update_params_for_auth! header_params, query_params, opts[:auth_names]
|
||||
{{/hasAuthMethods}}
|
||||
|
||||
# set ssl_verifyhosts option based on @config.verify_ssl_host (true/false)
|
||||
_verify_ssl_host = @config.verify_ssl_host ? 2 : 0
|
||||
|
||||
req_opts = {
|
||||
:method => http_method,
|
||||
:headers => header_params,
|
||||
:params => query_params,
|
||||
:params_encoding => @config.params_encoding,
|
||||
:timeout => @config.timeout,
|
||||
:ssl_verifypeer => @config.verify_ssl,
|
||||
:ssl_verifyhost => _verify_ssl_host,
|
||||
:sslcert => @config.cert_file,
|
||||
:sslkey => @config.key_file,
|
||||
:verbose => @config.debugging
|
||||
}
|
||||
|
||||
# set custom cert, if provided
|
||||
req_opts[:cainfo] = @config.ssl_ca_cert if @config.ssl_ca_cert
|
||||
|
||||
if [:post, :patch, :put, :delete].include?(http_method)
|
||||
req_body = build_request_body(header_params, form_params, opts[:body])
|
||||
req_opts.update body: req_body
|
||||
if @config.debugging
|
||||
@config.logger.debug "HTTP request body param ~BEGIN~\n#{req_body}\n~END~\n"
|
||||
end
|
||||
end
|
||||
|
||||
request = Typhoeus::Request.new(url, req_opts)
|
||||
download_file(request) if opts[:return_type] == "File"
|
||||
request
|
||||
end
|
||||
|
||||
# Builds the HTTP request body
|
||||
#
|
||||
# @param [Hash] header_params Header parameters
|
||||
# @param [Hash] form_params Query parameters
|
||||
# @param [Object] body HTTP body (JSON/XML)
|
||||
# @return [String] HTTP body data in the form of string
|
||||
def build_request_body(header_params, form_params, body)
|
||||
# http form
|
||||
if header_params["Content-Type"] == "application/x-www-form-urlencoded" ||
|
||||
header_params["Content-Type"] == "multipart/form-data"
|
||||
data = {} of Symbol => String
|
||||
form_params.each do |key, value|
|
||||
case value
|
||||
when ::File, ::Array, nil
|
||||
# let typhoeus handle File, Array and nil parameters
|
||||
data[key] = value
|
||||
else
|
||||
data[key] = value.to_s
|
||||
end
|
||||
end
|
||||
elsif body
|
||||
data = body.is_a?(String) ? body : body.to_json
|
||||
else
|
||||
data = nil
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
# Save response body into a file in (the defined) temporary folder, using the filename
|
||||
# from the "Content-Disposition" header if provided, otherwise a random filename.
|
||||
# The response body is written to the file in chunks in order to handle files which
|
||||
# size is larger than maximum Ruby String or even larger than the maximum memory a Ruby
|
||||
# process can use.
|
||||
#
|
||||
# @see Configuration#temp_folder_path
|
||||
def download_file(request)
|
||||
tempfile = nil
|
||||
encoding = nil
|
||||
request.on_headers do |response|
|
||||
content_disposition = response.headers["Content-Disposition"]
|
||||
if content_disposition && content_disposition =~ /filename=/i
|
||||
filename = content_disposition[/filename=[""]?([^""\s]+)[""]?/, 1]
|
||||
prefix = sanitize_filename(filename)
|
||||
else
|
||||
prefix = "download-"
|
||||
end
|
||||
prefix = prefix + "-" unless prefix.end_with?("-")
|
||||
encoding = response.body.encoding
|
||||
tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding)
|
||||
@tempfile = tempfile
|
||||
end
|
||||
request.on_body do |chunk|
|
||||
chunk.force_encoding(encoding)
|
||||
tempfile.write(chunk)
|
||||
end
|
||||
request.on_complete do |response|
|
||||
if tempfile
|
||||
tempfile.close
|
||||
@config.logger.info "Temp file written to #{tempfile.path}, please copy the file to a proper folder "\
|
||||
"with e.g. `FileUtils.cp(tempfile.path, \"/new/file/path\")` otherwise the temp file "\
|
||||
"will be deleted automatically with GC. It's also recommended to delete the temp file "\
|
||||
"explicitly with `tempfile.delete`"
|
||||
end
|
||||
end
|
||||
end
|
118
modules/openapi-generator/src/main/resources/crystal/api_doc.mustache
vendored
Normal file
118
modules/openapi-generator/src/main/resources/crystal/api_doc.mustache
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
# {{moduleName}}::{{classname}}{{#description}}
|
||||
|
||||
{{description}}{{/description}}
|
||||
|
||||
All URIs are relative to *{{basePath}}*
|
||||
|
||||
| Method | HTTP request | Description |
|
||||
| ------ | ------------ | ----------- |
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
| [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} |
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
|
||||
## {{operationId}}
|
||||
|
||||
> {{#returnType}}{{#returnTypeIsPrimitive}}{{returnType}}{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}<{{{returnType}}}>{{/returnTypeIsPrimitive}} {{/returnType}}{{operationId}}{{#hasParams}}({{#requiredParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#optionalParams}}{{#-last}}{{#hasRequiredParams}}, {{/hasRequiredParams}}opts{{/-last}}{{/optionalParams}}){{/hasParams}}
|
||||
|
||||
{{{summary}}}{{#notes}}
|
||||
|
||||
{{{notes}}}{{/notes}}
|
||||
|
||||
### Examples
|
||||
|
||||
```ruby
|
||||
require 'time'
|
||||
require '{{{gemName}}}'
|
||||
{{#hasAuthMethods}}
|
||||
# setup authorization
|
||||
{{{moduleName}}}.configure do |config|{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
|
||||
# Configure HTTP basic authorization: {{{name}}}
|
||||
config.username = 'YOUR USERNAME'
|
||||
config.password = 'YOUR PASSWORD'{{/isBasicBasic}}{{#isBasicBearer}}
|
||||
# Configure Bearer authorization{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}: {{{name}}}
|
||||
config.access_token = 'YOUR_BEARER_TOKEN'{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}}
|
||||
# Configure API key authorization: {{{name}}}
|
||||
config.api_key['{{{keyParamName}}}'] = 'YOUR API KEY'
|
||||
# Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
|
||||
# config.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}}
|
||||
# Configure OAuth2 access token for authorization: {{{name}}}
|
||||
config.access_token = 'YOUR ACCESS TOKEN'{{/isOAuth}}
|
||||
{{/authMethods}}end
|
||||
{{/hasAuthMethods}}
|
||||
|
||||
api_instance = {{{moduleName}}}::{{{classname}}}.new
|
||||
{{#requiredParams}}
|
||||
{{{paramName}}} = {{{vendorExtensions.x-ruby-example}}} # {{{dataType}}} | {{{description}}}
|
||||
{{/requiredParams}}
|
||||
{{#optionalParams}}
|
||||
{{#-first}}
|
||||
opts = {
|
||||
{{/-first}}
|
||||
{{{paramName}}}: {{{vendorExtensions.x-ruby-example}}}{{^-last}},{{/-last}} # {{{dataType}}} | {{{description}}}
|
||||
{{#-last}}
|
||||
}
|
||||
{{/-last}}
|
||||
{{/optionalParams}}
|
||||
|
||||
begin
|
||||
{{#summary}}# {{{.}}}{{/summary}}
|
||||
{{#returnType}}result = {{/returnType}}api_instance.{{{operationId}}}{{#hasParams}}({{#requiredParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#optionalParams}}{{#-last}}{{#hasRequiredParams}}, {{/hasRequiredParams}}opts{{/-last}}{{/optionalParams}}){{/hasParams}}
|
||||
{{#returnType}}
|
||||
p result
|
||||
{{/returnType}}
|
||||
rescue {{{moduleName}}}::ApiError => e
|
||||
puts "Error when calling {{classname}}->{{{operationId}}}: #{e}"
|
||||
end
|
||||
```
|
||||
|
||||
#### Using the {{operationId}}_with_http_info variant
|
||||
|
||||
This returns an Array which contains the response data{{^returnType}} (`nil` in this case){{/returnType}}, status code and headers.
|
||||
|
||||
> <Array({{#returnType}}{{#returnTypeIsPrimitive}}{{returnType}}{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}<{{{returnType}}}>{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}nil{{/returnType}}, Integer, Hash)> {{operationId}}_with_http_info{{#hasParams}}({{#requiredParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#optionalParams}}{{#-last}}{{#hasRequiredParams}}, {{/hasRequiredParams}}opts{{/-last}}{{/optionalParams}}){{/hasParams}}
|
||||
|
||||
```ruby
|
||||
begin
|
||||
{{#summary}}# {{{.}}}{{/summary}}
|
||||
data, status_code, headers = api_instance.{{{operationId}}}_with_http_info{{#hasParams}}({{#requiredParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#optionalParams}}{{#-last}}{{#hasRequiredParams}}, {{/hasRequiredParams}}opts{{/-last}}{{/optionalParams}}){{/hasParams}}
|
||||
p status_code # => 2xx
|
||||
p headers # => { ... }
|
||||
p data # => {{#returnType}}{{#returnTypeIsPrimitive}}{{returnType}}{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}<{{{returnType}}}>{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}nil{{/returnType}}
|
||||
rescue {{{moduleName}}}::ApiError => e
|
||||
puts "Error when calling {{classname}}->{{{operationId}}}_with_http_info: #{e}"
|
||||
end
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
{{^allParams}}
|
||||
This endpoint does not need any parameter.
|
||||
{{/allParams}}
|
||||
{{#allParams}}
|
||||
{{#-first}}
|
||||
| Name | Type | Description | Notes |
|
||||
| ---- | ---- | ----------- | ----- |
|
||||
{{/-first}}
|
||||
| **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}} | {{description}} | {{^required}}[optional]{{/required}}{{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}} |
|
||||
{{/allParams}}
|
||||
|
||||
### Return type
|
||||
|
||||
{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}nil (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}}
|
||||
|
||||
{{/operation}}
|
||||
{{/operations}}
|
33
modules/openapi-generator/src/main/resources/crystal/api_error.mustache
vendored
Normal file
33
modules/openapi-generator/src/main/resources/crystal/api_error.mustache
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
module {{moduleName}}
|
||||
class ApiError < Exception
|
||||
getter code : Int32?
|
||||
getter response_headers : Hash(String, Array(String) | String)?
|
||||
|
||||
# Usage examples:
|
||||
# ApiError.new
|
||||
# ApiError.new(message: "message")
|
||||
# ApiError.new(code: 500, response_headers: {}, message: "")
|
||||
# ApiError.new(code: 404, message: "Not Found")
|
||||
def initialize(@code , @message, @response_headers)
|
||||
end
|
||||
|
||||
def initialize(@code , @message)
|
||||
end
|
||||
|
||||
# Override to_s to display a friendly error message
|
||||
def to_s
|
||||
msg = ""
|
||||
msg = msg + "\nHTTP status code: #{code}" if @code
|
||||
msg = msg + "\nResponse headers: #{response_headers}" if @response_headers
|
||||
if @message.nil? || @message.empty?
|
||||
msg = msg + "\nError message: the server returns an error but the HTTP respone body is empty."
|
||||
else
|
||||
msg = msg + "\nResponse body: #{@message}"
|
||||
end
|
||||
|
||||
msg
|
||||
end
|
||||
end
|
||||
end
|
12
modules/openapi-generator/src/main/resources/crystal/api_info.mustache
vendored
Normal file
12
modules/openapi-generator/src/main/resources/crystal/api_info.mustache
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{{#appName}}
|
||||
#{{{appName}}}
|
||||
|
||||
{{/appName}}
|
||||
{{#appDescription}}
|
||||
#{{{appDescription}}}
|
||||
|
||||
{{/appDescription}}
|
||||
{{#version}}The version of the OpenAPI document: {{version}}{{/version}}
|
||||
{{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}}
|
||||
Generated by: https://openapi-generator.tech
|
||||
OpenAPI Generator version: {{{generatorVersion}}}
|
38
modules/openapi-generator/src/main/resources/crystal/api_test.mustache
vendored
Normal file
38
modules/openapi-generator/src/main/resources/crystal/api_test.mustache
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
require "../spec_helper"
|
||||
require "json"
|
||||
require "time"
|
||||
|
||||
# Unit tests for {{moduleName}}::{{classname}}
|
||||
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
||||
# Please update as you see appropriate
|
||||
{{#operations}}describe "{{classname}}" do
|
||||
describe "test an instance of {{classname}}" do
|
||||
it "should create an instance of {{classname}}" do
|
||||
api_instance = {{moduleName}}::{{classname}}.new
|
||||
# TODO expect(api_instance).to be_instance_of({{moduleName}}::{{classname}})
|
||||
end
|
||||
end
|
||||
|
||||
{{#operation}}
|
||||
# unit tests for {{operationId}}
|
||||
{{#summary}}
|
||||
# {{summary}}
|
||||
{{/summary}}
|
||||
{{#notes}}
|
||||
# {{notes}}
|
||||
{{/notes}}
|
||||
{{#allParams}}{{#required}} # @param {{paramName}} {{description}}
|
||||
{{/required}}{{/allParams}} # @param [Hash] opts the optional parameters
|
||||
{{#allParams}}{{^required}} # @option opts [{{{dataType}}}] :{{paramName}} {{description}}
|
||||
{{/required}}{{/allParams}} # @return [{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}nil{{/returnType}}]
|
||||
describe "{{operationId}} test" do
|
||||
it "should work" do
|
||||
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
|
||||
end
|
||||
end
|
||||
|
||||
{{/operation}}
|
||||
end
|
||||
{{/operations}}
|
120
modules/openapi-generator/src/main/resources/crystal/base_object.mustache
vendored
Normal file
120
modules/openapi-generator/src/main/resources/crystal/base_object.mustache
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
# Builds the object from hash
|
||||
# @param [Hash] attributes Model attributes in the form of hash
|
||||
# @return [Object] Returns the model itself
|
||||
def self.build_from_hash(attributes)
|
||||
new.build_from_hash(attributes)
|
||||
end
|
||||
|
||||
# Builds the object from hash
|
||||
# @param [Hash] attributes Model attributes in the form of hash
|
||||
# @return [Object] Returns the model itself
|
||||
def build_from_hash(attributes)
|
||||
return nil unless attributes.is_a?(Hash)
|
||||
{{#parent}}
|
||||
super(attributes)
|
||||
{{/parent}}
|
||||
self.class.openapi_types.each_pair do |key, type|
|
||||
if attributes[self.class.attribute_map[key]].nil? && self.class.openapi_nullable.include?(key)
|
||||
self.send("#{key}=", nil)
|
||||
elsif type =~ /\AArray<(.*)>/i
|
||||
# check to ensure the input is an array given that the attribute
|
||||
# is documented as an array but the input is not
|
||||
if attributes[self.class.attribute_map[key]].is_a?(Array)
|
||||
self.send("#{key}=", attributes[self.class.attribute_map[key]].map { |v| _deserialize($1, v) })
|
||||
end
|
||||
elsif !attributes[self.class.attribute_map[key]].nil?
|
||||
self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
|
||||
end
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
# Deserializes the data based on type
|
||||
# @param string type Data type
|
||||
# @param string value Value to be deserialized
|
||||
# @return [Object] Deserialized data
|
||||
def _deserialize(type, value)
|
||||
case type.to_sym
|
||||
when :Time
|
||||
Time.parse(value)
|
||||
when :Date
|
||||
Date.parse(value)
|
||||
when :String
|
||||
value.to_s
|
||||
when :Integer
|
||||
value.to_i
|
||||
when :Float
|
||||
value.to_f
|
||||
when :Boolean
|
||||
if value.to_s =~ /\A(true|t|yes|y|1)\z/i
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
when :Object
|
||||
# generic object (usually a Hash), return directly
|
||||
value
|
||||
when /\AArray<(?<inner_type>.+)>\z/
|
||||
inner_type = Regexp.last_match[:inner_type]
|
||||
value.map { |v| _deserialize(inner_type, v) }
|
||||
when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
|
||||
k_type = Regexp.last_match[:k_type]
|
||||
v_type = Regexp.last_match[:v_type]
|
||||
({} of Symbol => String).tap do |hash|
|
||||
value.each do |k, v|
|
||||
hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
|
||||
end
|
||||
end
|
||||
else # model
|
||||
# models (e.g. Pet) or oneOf
|
||||
klass = {{moduleName}}.const_get(type)
|
||||
klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the string representation of the object
|
||||
# @return [String] String presentation of the object
|
||||
def to_s
|
||||
to_hash.to_s
|
||||
end
|
||||
|
||||
# to_body is an alias to to_hash (backward compatibility)
|
||||
# @return [Hash] Returns the object in the form of hash
|
||||
def to_body
|
||||
to_hash
|
||||
end
|
||||
|
||||
# Returns the object in the form of hash
|
||||
# @return [Hash] Returns the object in the form of hash
|
||||
def to_hash
|
||||
hash = {{^parent}}{} of Symbol => String{{/parent}}{{#parent}}super{{/parent}}
|
||||
self.class.attribute_map.each_pair do |attr, param|
|
||||
value = self.send(attr)
|
||||
if value.nil?
|
||||
is_nullable = self.class.openapi_nullable.include?(attr)
|
||||
next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
|
||||
end
|
||||
|
||||
hash[param] = _to_hash(value)
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
# Outputs non-array value in the form of hash
|
||||
# For object, use to_hash. Otherwise, just return the value
|
||||
# @param [Object] value Any valid value
|
||||
# @return [Hash] Returns the value in the form of hash
|
||||
def _to_hash(value)
|
||||
if value.is_a?(Array)
|
||||
value.compact.map { |v| _to_hash(v) }
|
||||
elsif value.is_a?(Hash)
|
||||
({} of Symbol => String).tap do |hash|
|
||||
value.each { |k, v| hash[k] = _to_hash(v) }
|
||||
end
|
||||
elsif value.respond_to? :to_hash
|
||||
value.to_hash
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
356
modules/openapi-generator/src/main/resources/crystal/configuration.mustache
vendored
Normal file
356
modules/openapi-generator/src/main/resources/crystal/configuration.mustache
vendored
Normal file
@ -0,0 +1,356 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
require "log"
|
||||
|
||||
module {{moduleName}}
|
||||
class Configuration
|
||||
# Defines url scheme
|
||||
property scheme : String
|
||||
|
||||
# Defines url host
|
||||
property host : String
|
||||
|
||||
# Defines url base path
|
||||
property base_path : String
|
||||
|
||||
# Define server configuration index
|
||||
property server_index : Int32
|
||||
|
||||
# Define server operation configuration index
|
||||
property server_operation_index : Hash(Symbol, String)
|
||||
|
||||
# Default server variables
|
||||
property server_variables : Hash(Symbol, String)
|
||||
|
||||
# Default server operation variables
|
||||
property server_operation_variables : Hash(Symbol, String)
|
||||
|
||||
# Defines API keys used with API Key authentications.
|
||||
#
|
||||
# @return [Hash] key: parameter name, value: parameter value (API key)
|
||||
#
|
||||
# @example parameter name is "api_key", API key is "xxx" (e.g. "api_key=xxx" in query string)
|
||||
# config.api_key[:"api_key"] = "xxx"
|
||||
property api_key : Hash(Symbol, String)
|
||||
|
||||
# Defines API key prefixes used with API Key authentications.
|
||||
#
|
||||
# @return [Hash] key: parameter name, value: API key prefix
|
||||
#
|
||||
# @example parameter name is "Authorization", API key prefix is "Token" (e.g. "Authorization: Token xxx" in headers)
|
||||
# config.api_key_prefix[:"api_key"] = "Token"
|
||||
property api_key_prefix : Hash(Symbol, String)
|
||||
|
||||
# Defines the username used with HTTP basic authentication.
|
||||
#
|
||||
# @return [String]
|
||||
property username : String?
|
||||
|
||||
# Defines the password used with HTTP basic authentication.
|
||||
#
|
||||
# @return [String]
|
||||
property password : String?
|
||||
|
||||
# Defines the access token (Bearer) used with OAuth2.
|
||||
property access_token : String?
|
||||
|
||||
# Set this to enable/disable debugging. When enabled (set to true), HTTP request/response
|
||||
# details will be logged with `logger.debug` (see the `logger` attribute).
|
||||
# Default to false.
|
||||
#
|
||||
# @return [true, false]
|
||||
property debugging : Bool
|
||||
|
||||
# Defines the temporary folder to store downloaded files
|
||||
# (for API endpoints that have file response).
|
||||
# Default to use `Tempfile`.
|
||||
#
|
||||
# @return [String]
|
||||
property temp_folder_path : String?
|
||||
|
||||
# The time limit for HTTP request in seconds.
|
||||
# Default to 0 (never times out).
|
||||
property timeout : Int32
|
||||
|
||||
# Set this to false to skip client side validation in the operation.
|
||||
# Default to true.
|
||||
# @return [true, false]
|
||||
property client_side_validation : Bool
|
||||
|
||||
### TLS/SSL setting
|
||||
# Set this to false to skip verifying SSL certificate when calling API from https server.
|
||||
# Default to true.
|
||||
#
|
||||
# @note Do NOT set it to false in production code, otherwise you would face multiple types of cryptographic attacks.
|
||||
#
|
||||
# @return [true, false]
|
||||
#TODO attr_accessor :verify_ssl
|
||||
|
||||
### TLS/SSL setting
|
||||
# Set this to false to skip verifying SSL host name
|
||||
# Default to true.
|
||||
#
|
||||
# @note Do NOT set it to false in production code, otherwise you would face multiple types of cryptographic attacks.
|
||||
#
|
||||
# @return [true, false]
|
||||
# TODO attr_accessor :verify_ssl_host
|
||||
|
||||
### TLS/SSL setting
|
||||
# Set this to customize the certificate file to verify the peer.
|
||||
#
|
||||
# @return [String] the path to the certificate file
|
||||
#
|
||||
# @see The `cainfo` option of Typhoeus, `--cert` option of libcurl. Related source code:
|
||||
# https://github.com/typhoeus/typhoeus/blob/master/lib/typhoeus/easy_factory.rb#L145
|
||||
# TODO attr_accessor :ssl_ca_cert
|
||||
|
||||
### TLS/SSL setting
|
||||
# Client certificate file (for client certificate)
|
||||
# TODO attr_accessor :cert_file
|
||||
|
||||
### TLS/SSL setting
|
||||
# Client private key file (for client certificate)
|
||||
# TODO attr_accessor :key_file
|
||||
|
||||
# Set this to customize parameters encoding of array parameter with multi collectionFormat.
|
||||
# Default to Nil.
|
||||
#
|
||||
# @see The params_encoding option of Ethon. Related source code:
|
||||
# https://github.com/typhoeus/ethon/blob/master/lib/ethon/easy/queryable.rb#L96
|
||||
#property params_encoding : String?
|
||||
|
||||
def initialize
|
||||
@scheme = "{{scheme}}"
|
||||
@host = "{{host}}{{#port}}:{{{.}}}{{/port}}"
|
||||
@base_path = "{{contextPath}}"
|
||||
@server_index = 0
|
||||
@server_operation_index = {} of Symbol => String
|
||||
@server_variables = {} of Symbol => String
|
||||
@server_operation_variables = {} of Symbol => String
|
||||
@api_key = {} of Symbol => String
|
||||
@api_key_prefix = {} of Symbol => String
|
||||
@timeout = 0
|
||||
@client_side_validation = true
|
||||
@verify_ssl = true
|
||||
@verify_ssl_host = true
|
||||
#@params_encoding = nil
|
||||
#@cert_file = nil
|
||||
#@key_file = nil
|
||||
@debugging = false
|
||||
@username = nil
|
||||
@password = nil
|
||||
@access_token = nil
|
||||
@temp_folder_path = nil
|
||||
|
||||
# TODO revise below to support block
|
||||
#yield(self) if block_given?
|
||||
end
|
||||
|
||||
# The default Configuration object.
|
||||
def self.default
|
||||
@@default ||= Configuration.new
|
||||
end
|
||||
|
||||
def configure
|
||||
yield(self) if block_given?
|
||||
end
|
||||
|
||||
def scheme=(scheme)
|
||||
# remove :// from scheme
|
||||
@scheme = scheme.sub(/:\/\//, "")
|
||||
end
|
||||
|
||||
def host=(host)
|
||||
# remove http(s):// and anything after a slash
|
||||
@host = host.sub(/https?:\/\//, "").split("/").first
|
||||
end
|
||||
|
||||
def base_path=(base_path)
|
||||
# Add leading and trailing slashes to base_path
|
||||
@base_path = "/#{base_path}".gsub(/\/+/, "/")
|
||||
@base_path = "" if @base_path == "/"
|
||||
end
|
||||
|
||||
# Returns base URL for specified operation based on server settings
|
||||
def base_url(operation = Nil)
|
||||
# TODO revise below to support operation-level server setting
|
||||
#index = server_operation_index.fetch(operation, server_index)
|
||||
return "#{scheme}://#{[host, base_path].join("/").gsub(/\/+/, "/")}".sub(/\/+\z/, "") #if index == Nil
|
||||
|
||||
#server_url(index, server_operation_variables.fetch(operation, server_variables), operation_server_settings[operation])
|
||||
end
|
||||
|
||||
# Gets API key (with prefix if set).
|
||||
# @param [String] param_name the parameter name of API key auth
|
||||
def api_key_with_prefix(param_name)
|
||||
if @api_key_prefix[param_name]
|
||||
"#{@api_key_prefix[param_name]} #{@api_key[param_name]}"
|
||||
else
|
||||
@api_key[param_name]
|
||||
end
|
||||
end
|
||||
|
||||
# Gets Basic Auth token string
|
||||
def basic_auth_token
|
||||
"Basic " + ["#{username}:#{password}"].pack("m").delete("\r\n")
|
||||
end
|
||||
|
||||
# Returns Auth Settings hash for api client.
|
||||
def auth_settings
|
||||
Hash{ {{#authMethods}}{{#isApiKey}}"{{name}}" => {
|
||||
type: "api_key",
|
||||
in: {{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}},
|
||||
key: "{{keyParamName}}",
|
||||
value: api_key_with_prefix("{{keyParamName}}")
|
||||
},
|
||||
{{/isApiKey}}
|
||||
{{#isBasic}}
|
||||
{{#isBasicBasic}}
|
||||
"{{name}}" =>
|
||||
{
|
||||
type: "basic",
|
||||
in: "header",
|
||||
key: "Authorization",
|
||||
value: basic_auth_token
|
||||
},
|
||||
{{/isBasicBasic}}
|
||||
{{#isBasicBearer}}
|
||||
"{{name}}" =>
|
||||
{
|
||||
type: "bearer",
|
||||
in: "header",
|
||||
{{#bearerFormat}}
|
||||
format: "{{{.}}}",
|
||||
{{/bearerFormat}}
|
||||
key: "Authorization",
|
||||
value: "Bearer #{access_token}"
|
||||
},
|
||||
{{/isBasicBearer}}
|
||||
{{/isBasic}}
|
||||
{{#isOAuth}}
|
||||
"{{name}}" =>
|
||||
{
|
||||
type: "oauth2",
|
||||
in: "header",
|
||||
key: "Authorization",
|
||||
value: "Bearer #{access_token}"
|
||||
},
|
||||
{{/isOAuth}}
|
||||
{{/authMethods}}
|
||||
}
|
||||
end
|
||||
|
||||
# Returns an array of Server setting
|
||||
def server_settings
|
||||
[
|
||||
{{#servers}}
|
||||
{
|
||||
url: "{{{url}}}",
|
||||
description: "{{{description}}}{{^description}}No description provided{{/description}}",
|
||||
{{#variables}}
|
||||
{{#-first}}
|
||||
variables: {
|
||||
{{/-first}}
|
||||
{{{name}}}: {
|
||||
description: "{{{description}}}{{^description}}No description provided{{/description}}",
|
||||
default_value: "{{{defaultValue}}}",
|
||||
{{#enumValues}}
|
||||
{{#-first}}
|
||||
enum_values: [
|
||||
{{/-first}}
|
||||
"{{{.}}}"{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
]
|
||||
{{/-last}}
|
||||
{{/enumValues}}
|
||||
}{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
}
|
||||
{{/-last}}
|
||||
{{/variables}}
|
||||
}{{^-last}},{{/-last}}
|
||||
{{/servers}}
|
||||
]
|
||||
end
|
||||
|
||||
def operation_server_settings
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
{{#servers}}
|
||||
{{#-first}}
|
||||
{
|
||||
"{{{classname}}}.{{{nickname}}}": [
|
||||
{{/-first}}
|
||||
{
|
||||
url: "{{{url}}}",
|
||||
description: "{{{description}}}{{^description}}No description provided{{/description}}",
|
||||
{{#variables}}
|
||||
{{#-first}}
|
||||
variables: {
|
||||
{{/-first}}
|
||||
{{{name}}}: {
|
||||
description: "{{{description}}}{{^description}}No description provided{{/description}}",
|
||||
default_value: "{{{defaultValue}}}",
|
||||
{{#enumValues}}
|
||||
{{#-first}}
|
||||
enum_values: [
|
||||
{{/-first}}
|
||||
"{{{.}}}"{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
]
|
||||
{{/-last}}
|
||||
{{/enumValues}}
|
||||
}{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
}
|
||||
{{/-last}}
|
||||
{{/variables}}
|
||||
}{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
],
|
||||
}
|
||||
{{/-last}}
|
||||
{{/servers}}
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
end
|
||||
|
||||
# Returns URL based on server settings
|
||||
#
|
||||
# @param index array index of the server settings
|
||||
# @param variables hash of variable and the corresponding value
|
||||
def server_url(index, variables = {} of Symbol => String, servers = Nil)
|
||||
servers = server_settings if servers == Nil
|
||||
|
||||
# check array index out of bound
|
||||
if (index < 0 || index >= servers.size)
|
||||
raise ArgumentError.new("Invalid index #{index} when selecting the server. Must be less than #{servers.size}")
|
||||
end
|
||||
|
||||
server = servers[index]
|
||||
url = server[:url]
|
||||
|
||||
return url unless server.key? :variables
|
||||
|
||||
# go through variable and assign a value
|
||||
server[:variables].each do |name, variable|
|
||||
if variables.key?(name)
|
||||
if (!server[:variables][name].key?(:enum_values) || server[:variables][name][:enum_values].include?(variables[name]))
|
||||
url.gsub! "{" + name.to_s + "}", variables[name]
|
||||
else
|
||||
raise ArgumentError.new("The variable `#{name}` in the server URL has invalid value #{variables[name]}. Must be #{server[:variables][name][:enum_values]}.")
|
||||
end
|
||||
else
|
||||
# use default value
|
||||
url.gsub! "{" + name.to_s + "}", server[:variables][name][:default_value]
|
||||
end
|
||||
end
|
||||
|
||||
url
|
||||
end
|
||||
end
|
||||
end
|
34
modules/openapi-generator/src/main/resources/crystal/configuration_spec.mustache
vendored
Normal file
34
modules/openapi-generator/src/main/resources/crystal/configuration_spec.mustache
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
=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
|
||||
end
|
29
modules/openapi-generator/src/main/resources/crystal/configuration_tls_faraday_partial.mustache
vendored
Normal file
29
modules/openapi-generator/src/main/resources/crystal/configuration_tls_faraday_partial.mustache
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
### TLS/SSL setting
|
||||
# Set this to false to skip verifying SSL certificate when calling API from https server.
|
||||
# Default to true.
|
||||
#
|
||||
# @note Do NOT set it to false in production code, otherwise you would face multiple types of cryptographic attacks.
|
||||
#
|
||||
# @return [true, false]
|
||||
#TODO attr_accessor :ssl_verify
|
||||
|
||||
### TLS/SSL setting
|
||||
# Any `OpenSSL::SSL::` constant (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL.html)
|
||||
#
|
||||
# @note Do NOT set it to false in production code, otherwise you would face multiple types of cryptographic attacks.
|
||||
#
|
||||
#TODO attr_accessor :ssl_verify_mode
|
||||
|
||||
### TLS/SSL setting
|
||||
# Set this to customize the certificate file to verify the peer.
|
||||
#
|
||||
# @return [String] the path to the certificate file
|
||||
#TODO attr_accessor :ssl_ca_file
|
||||
|
||||
### TLS/SSL setting
|
||||
# Client certificate file (for client certificate)
|
||||
#TODO attr_accessor :ssl_client_cert
|
||||
|
||||
### TLS/SSL setting
|
||||
# Client private key file (for client certificate)
|
||||
#TODO attr_accessor :ssl_client_key
|
34
modules/openapi-generator/src/main/resources/crystal/configuration_tls_typhoeus_partial.mustache
vendored
Normal file
34
modules/openapi-generator/src/main/resources/crystal/configuration_tls_typhoeus_partial.mustache
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
### TLS/SSL setting
|
||||
# Set this to false to skip verifying SSL certificate when calling API from https server.
|
||||
# Default to true.
|
||||
#
|
||||
# @note Do NOT set it to false in production code, otherwise you would face multiple types of cryptographic attacks.
|
||||
#
|
||||
# @return [true, false]
|
||||
#TODO attr_accessor :verify_ssl
|
||||
|
||||
### TLS/SSL setting
|
||||
# Set this to false to skip verifying SSL host name
|
||||
# Default to true.
|
||||
#
|
||||
# @note Do NOT set it to false in production code, otherwise you would face multiple types of cryptographic attacks.
|
||||
#
|
||||
# @return [true, false]
|
||||
# TODO attr_accessor :verify_ssl_host
|
||||
|
||||
### TLS/SSL setting
|
||||
# Set this to customize the certificate file to verify the peer.
|
||||
#
|
||||
# @return [String] the path to the certificate file
|
||||
#
|
||||
# @see The `cainfo` option of Typhoeus, `--cert` option of libcurl. Related source code:
|
||||
# https://github.com/typhoeus/typhoeus/blob/master/lib/typhoeus/easy_factory.rb#L145
|
||||
# TODO attr_accessor :ssl_ca_cert
|
||||
|
||||
### TLS/SSL setting
|
||||
# Client certificate file (for client certificate)
|
||||
# TODO attr_accessor :cert_file
|
||||
|
||||
### TLS/SSL setting
|
||||
# Client private key file (for client certificate)
|
||||
# TODO attr_accessor :key_file
|
58
modules/openapi-generator/src/main/resources/crystal/git_push.sh.mustache
vendored
Executable file
58
modules/openapi-generator/src/main/resources/crystal/git_push.sh.mustache
vendored
Executable file
@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
|
||||
#
|
||||
# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" "gitlab.com"
|
||||
|
||||
git_user_id=$1
|
||||
git_repo_id=$2
|
||||
release_note=$3
|
||||
git_host=$4
|
||||
|
||||
if [ "$git_host" = "" ]; then
|
||||
git_host="{{{gitHost}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_host to $git_host"
|
||||
fi
|
||||
|
||||
if [ "$git_user_id" = "" ]; then
|
||||
git_user_id="{{{gitUserId}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
|
||||
fi
|
||||
|
||||
if [ "$git_repo_id" = "" ]; then
|
||||
git_repo_id="{{{gitRepoId}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
|
||||
fi
|
||||
|
||||
if [ "$release_note" = "" ]; then
|
||||
release_note="{{{releaseNote}}}"
|
||||
echo "[INFO] No command line input provided. Set \$release_note to $release_note"
|
||||
fi
|
||||
|
||||
# Initialize the local directory as a Git repository
|
||||
git init
|
||||
|
||||
# Adds the files in the local repository and stages them for commit.
|
||||
git add .
|
||||
|
||||
# Commits the tracked changes and prepares them to be pushed to a remote repository.
|
||||
git commit -m "$release_note"
|
||||
|
||||
# Sets the new remote
|
||||
git_remote=`git remote`
|
||||
if [ "$git_remote" = "" ]; then # git remote not defined
|
||||
|
||||
if [ "$GIT_TOKEN" = "" ]; then
|
||||
echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
|
||||
git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
|
||||
else
|
||||
git remote add origin https://${git_user_id}:${GIT_TOKEN}@${git_host}/${git_user_id}/${git_repo_id}.git
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
git pull origin master
|
||||
|
||||
# Pushes (Forces) the changes in the local repository up to the remote repository
|
||||
echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
|
||||
git push origin master 2>&1 | grep -v 'To https'
|
||||
|
39
modules/openapi-generator/src/main/resources/crystal/gitignore.mustache
vendored
Normal file
39
modules/openapi-generator/src/main/resources/crystal/gitignore.mustache
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# Generated by: https://openapi-generator.tech
|
||||
#
|
||||
|
||||
*.gem
|
||||
*.rbc
|
||||
/.config
|
||||
/coverage/
|
||||
/InstalledFiles
|
||||
/pkg/
|
||||
/spec/reports/
|
||||
/spec/examples.txt
|
||||
/test/tmp/
|
||||
/test/version_tmp/
|
||||
/tmp/
|
||||
|
||||
## Specific to RubyMotion:
|
||||
.dat*
|
||||
.repl_history
|
||||
build/
|
||||
|
||||
## Documentation cache and generated files:
|
||||
/.yardoc/
|
||||
/_yardoc/
|
||||
/doc/
|
||||
/rdoc/
|
||||
|
||||
## Environment normalization:
|
||||
/.bundle/
|
||||
/vendor/bundle
|
||||
/lib/bundler/man/
|
||||
|
||||
# for a library or gem, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# Gemfile.lock
|
||||
# .ruby-version
|
||||
# .ruby-gemset
|
||||
|
||||
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
||||
.rvmrc
|
23
modules/openapi-generator/src/main/resources/crystal/model.mustache
vendored
Normal file
23
modules/openapi-generator/src/main/resources/crystal/model.mustache
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
require "time"
|
||||
|
||||
module {{moduleName}}
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
{{#isEnum}}
|
||||
{{>partial_model_enum_class}}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#oneOf}}
|
||||
{{#-first}}
|
||||
{{>partial_oneof_module}}
|
||||
{{/-first}}
|
||||
{{/oneOf}}
|
||||
{{^oneOf}}
|
||||
{{>partial_model_generic}}
|
||||
{{/oneOf}}
|
||||
{{/isEnum}}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
end
|
12
modules/openapi-generator/src/main/resources/crystal/model_doc.mustache
vendored
Normal file
12
modules/openapi-generator/src/main/resources/crystal/model_doc.mustache
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
{{#oneOf}}
|
||||
{{#-first}}
|
||||
{{>partial_oneof_module_doc}}
|
||||
{{/-first}}
|
||||
{{/oneOf}}
|
||||
{{^oneOf}}
|
||||
{{>partial_model_generic_doc}}
|
||||
{{/oneOf}}
|
||||
{{/model}}
|
||||
{{/models}}
|
75
modules/openapi-generator/src/main/resources/crystal/model_test.mustache
vendored
Normal file
75
modules/openapi-generator/src/main/resources/crystal/model_test.mustache
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
require "../spec_helper"
|
||||
require "json"
|
||||
require "time"
|
||||
|
||||
# Unit tests for {{moduleName}}::{{classname}}
|
||||
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
||||
# Please update as you see appropriate
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
describe {{moduleName}}::{{classname}} do
|
||||
{{^oneOf}}
|
||||
|
||||
describe "test an instance of {{classname}}" do
|
||||
it "should create an instance of {{classname}}" do
|
||||
#instance = {{moduleName}}::{{classname}}.new
|
||||
#expect(instance).to be_instance_of({{moduleName}}::{{classname}})
|
||||
end
|
||||
end
|
||||
{{#vars}}
|
||||
describe "test attribute '{{{name}}}'" do
|
||||
it "should work" do
|
||||
{{#isEnum}}
|
||||
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
|
||||
# validator = Petstore::EnumTest::EnumAttributeValidator.new("{{{dataType}}}", [{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}])
|
||||
# validator.allowable_values.each do |value|
|
||||
# expect { instance.{{name}} = value }.not_to raise_error
|
||||
# end
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
|
||||
{{/isEnum}}
|
||||
end
|
||||
end
|
||||
|
||||
{{/vars}}
|
||||
{{/oneOf}}
|
||||
{{#oneOf}}
|
||||
{{#-first}}
|
||||
describe ".openapi_one_of" do
|
||||
it "lists the items referenced in the oneOf array" do
|
||||
expect(described_class.openapi_one_of).to_not be_empty
|
||||
end
|
||||
end
|
||||
|
||||
{{#discriminator}}
|
||||
{{#propertyName}}
|
||||
describe ".openapi_discriminator_name" do
|
||||
it "returns the value of the "discriminator" property" do
|
||||
expect(described_class.openapi_discriminator_name).to_not be_empty
|
||||
end
|
||||
end
|
||||
|
||||
{{/propertyName}}
|
||||
{{#mappedModels}}
|
||||
{{#-first}}
|
||||
describe ".openapi_discriminator_mapping" do
|
||||
it "returns the key/values of the "mapping" property" do
|
||||
expect(described_class.openapi_discriminator_mapping.values.sort).to eq(described_class.openapi_one_of.sort)
|
||||
end
|
||||
end
|
||||
|
||||
{{/-first}}
|
||||
{{/mappedModels}}
|
||||
{{/discriminator}}
|
||||
describe ".build" do
|
||||
it "returns the correct model" do
|
||||
end
|
||||
end
|
||||
{{/-first}}
|
||||
{{/oneOf}}
|
||||
end
|
||||
{{/model}}
|
||||
{{/models}}
|
20
modules/openapi-generator/src/main/resources/crystal/partial_model_enum_class.mustache
vendored
Normal file
20
modules/openapi-generator/src/main/resources/crystal/partial_model_enum_class.mustache
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
class {{classname}}{{#allowableValues}}{{#enumVars}}
|
||||
{{{name}}} = {{{value}}}.freeze{{/enumVars}}
|
||||
|
||||
{{/allowableValues}}
|
||||
# Builds the enum from string
|
||||
# @param [String] The enum value in the form of the string
|
||||
# @return [String] The enum value
|
||||
def self.build_from_hash(value)
|
||||
new.build_from_hash(value)
|
||||
end
|
||||
|
||||
# Builds the enum from string
|
||||
# @param [String] The enum value in the form of the string
|
||||
# @return [String] The enum value
|
||||
def build_from_hash(value)
|
||||
constantValues = {{classname}}.constants.select { |c| {{classname}}::const_get(c) == value }
|
||||
raise "Invalid ENUM value #{value} for class #{{{classname}}}" if constantValues.empty?
|
||||
value
|
||||
end
|
||||
end
|
296
modules/openapi-generator/src/main/resources/crystal/partial_model_generic.mustache
vendored
Normal file
296
modules/openapi-generator/src/main/resources/crystal/partial_model_generic.mustache
vendored
Normal file
@ -0,0 +1,296 @@
|
||||
{{#description}}
|
||||
# {{{description}}}
|
||||
{{/description}}
|
||||
class {{classname}}{{#parent}} < {{{.}}}{{/parent}} include JSON::Serializable
|
||||
include JSON::Serializable {{#vars}}
|
||||
{{#description}}
|
||||
# {{{description}}}
|
||||
{{/description}}
|
||||
@[JSON::Field(key: {{{baseName}}}, type: {{{dataType}}}{{#default}}, default: {{{.}}}{{/default}}{{#isNullable}}, nilable: true, emit_null: true{{/isNullable}})]
|
||||
property {{{name}}} : {{{dataType}}}
|
||||
|
||||
{{/vars}}
|
||||
{{#hasEnums}}
|
||||
class EnumAttributeValidator
|
||||
getter datatype : String
|
||||
getter allowable_values : Array(String)
|
||||
|
||||
def initialize(datatype, allowable_values)
|
||||
@datatype = datatype
|
||||
@allowable_values = allowable_values.map do |value|
|
||||
case datatype.to_s
|
||||
when /Integer/i
|
||||
value.to_i
|
||||
when /Float/i
|
||||
value.to_f
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def valid?(value)
|
||||
!value || allowable_values.include?(value)
|
||||
end
|
||||
end
|
||||
|
||||
{{/hasEnums}}
|
||||
{{#anyOf}}
|
||||
{{#-first}}
|
||||
# List of class defined in anyOf (OpenAPI v3)
|
||||
def self.openapi_any_of
|
||||
[
|
||||
{{/-first}}
|
||||
:"{{{.}}}"{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
]
|
||||
end
|
||||
|
||||
{{/-last}}
|
||||
{{/anyOf}}
|
||||
{{#allOf}}
|
||||
{{#-first}}
|
||||
# List of class defined in allOf (OpenAPI v3)
|
||||
def self.openapi_all_of
|
||||
[
|
||||
{{/-first}}
|
||||
:"{{{.}}}"{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
]
|
||||
end
|
||||
|
||||
{{/-last}}
|
||||
{{/allOf}}
|
||||
{{#discriminator}}
|
||||
{{#propertyName}}
|
||||
# discriminator's property name in OpenAPI v3
|
||||
def self.openapi_discriminator_name
|
||||
:"{{{.}}}"
|
||||
end
|
||||
|
||||
{{/propertyName}}
|
||||
{{/discriminator}}
|
||||
# Initializes the object
|
||||
# @param [Hash] attributes Model attributes in the form of hash
|
||||
def initialize({{#vars}}@{{{name}}} : {{{dataType}}}{{^required}} | Nil{{/required}}{{^-last}}, {{/-last}}{{/vars}})
|
||||
end
|
||||
|
||||
# Show invalid properties with the reasons. Usually used together with valid?
|
||||
# @return Array for valid properties with the reasons
|
||||
def list_invalid_properties
|
||||
invalid_properties = {{^parent}}Array.new{{/parent}}{{#parent}}super{{/parent}}
|
||||
{{#vars}}
|
||||
{{^isNullable}}
|
||||
{{#required}}
|
||||
if @{{{name}}}.nil?
|
||||
invalid_properties.push("invalid value for \"{{{name}}}\", {{{name}}} cannot be nil.")
|
||||
end
|
||||
|
||||
{{/required}}
|
||||
{{/isNullable}}
|
||||
{{#hasValidation}}
|
||||
{{#maxLength}}
|
||||
if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}}.to_s.length > {{{maxLength}}}
|
||||
invalid_properties.push("invalid value for \"{{{name}}}\", the character length must be smaller than or equal to {{{maxLength}}}.")
|
||||
end
|
||||
|
||||
{{/maxLength}}
|
||||
{{#minLength}}
|
||||
if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}}.to_s.length < {{{minLength}}}
|
||||
invalid_properties.push("invalid value for \"{{{name}}}\", the character length must be great than or equal to {{{minLength}}}.")
|
||||
end
|
||||
|
||||
{{/minLength}}
|
||||
{{#maximum}}
|
||||
if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{{maximum}}}
|
||||
invalid_properties.push("invalid value for \"{{{name}}}\", must be smaller than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}{{{maximum}}}.")
|
||||
end
|
||||
|
||||
{{/maximum}}
|
||||
{{#minimum}}
|
||||
if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{{minimum}}}
|
||||
invalid_properties.push("invalid value for \"{{{name}}}\", must be greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}{{{minimum}}}.")
|
||||
end
|
||||
|
||||
{{/minimum}}
|
||||
{{#pattern}}
|
||||
pattern = Regexp.new({{{pattern}}})
|
||||
if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}} !~ pattern
|
||||
invalid_properties.push("invalid value for \"{{{name}}}\", must conform to the pattern #{pattern}.")
|
||||
end
|
||||
|
||||
{{/pattern}}
|
||||
{{#maxItems}}
|
||||
if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}}.length > {{{maxItems}}}
|
||||
invalid_properties.push("invalid value for \"{{{name}}}\", number of items must be less than or equal to {{{maxItems}}}."
|
||||
end
|
||||
|
||||
{{/maxItems}}
|
||||
{{#minItems}}
|
||||
if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}}.length < {{{minItems}}}
|
||||
invalid_properties.push("invalid value for \"{{{name}}}\", number of items must be greater than or equal to {{{minItems}}}."
|
||||
end
|
||||
|
||||
{{/minItems}}
|
||||
{{/hasValidation}}
|
||||
{{/vars}}
|
||||
invalid_properties
|
||||
end
|
||||
|
||||
# Check to see if the all the properties in the model are valid
|
||||
# @return true if the model is valid
|
||||
def valid?
|
||||
{{#vars}}
|
||||
{{^isNullable}}
|
||||
{{#required}}
|
||||
return false if @{{{name}}}.nil?
|
||||
{{/required}}
|
||||
{{/isNullable}}
|
||||
{{#isEnum}}
|
||||
{{^isContainer}}
|
||||
{{{name}}}_validator = EnumAttributeValidator.new("{{{dataType}}}", [{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}])
|
||||
return false unless {{{name}}}_validator.valid?(@{{{name}}})
|
||||
{{/isContainer}}
|
||||
{{/isEnum}}
|
||||
{{#hasValidation}}
|
||||
{{#maxLength}}
|
||||
return false if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}}.to_s.length > {{{maxLength}}}
|
||||
{{/maxLength}}
|
||||
{{#minLength}}
|
||||
return false if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}}.to_s.length < {{{minLength}}}
|
||||
{{/minLength}}
|
||||
{{#maximum}}
|
||||
return false if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{{maximum}}}
|
||||
{{/maximum}}
|
||||
{{#minimum}}
|
||||
return false if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{{minimum}}}
|
||||
{{/minimum}}
|
||||
{{#pattern}}
|
||||
return false if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}} !~ Regexp.new({{{pattern}}})
|
||||
{{/pattern}}
|
||||
{{#maxItems}}
|
||||
return false if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}}.length > {{{maxItems}}}
|
||||
{{/maxItems}}
|
||||
{{#minItems}}
|
||||
return false if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}}.length < {{{minItems}}}
|
||||
{{/minItems}}
|
||||
{{/hasValidation}}
|
||||
{{/vars}}
|
||||
{{#anyOf}}
|
||||
{{#-first}}
|
||||
_any_of_found = false
|
||||
self.class.openapi_any_of.each do |_class|
|
||||
_any_of = {{moduleName}}.const_get(_class).build_from_hash(self.to_hash)
|
||||
if _any_of.valid?
|
||||
_any_of_found = true
|
||||
end
|
||||
end
|
||||
|
||||
if !_any_of_found
|
||||
return false
|
||||
end
|
||||
|
||||
{{/-first}}
|
||||
{{/anyOf}}
|
||||
true{{#parent}} && super{{/parent}}
|
||||
end
|
||||
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
{{^isContainer}}
|
||||
# Custom attribute writer method checking allowed values (enum).
|
||||
# @param [Object] {{{name}}} Object to be assigned
|
||||
def {{{name}}}=({{{name}}})
|
||||
validator = EnumAttributeValidator.new("{{{dataType}}}", [{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}])
|
||||
unless validator.valid?({{{name}}})
|
||||
raise ArgumentError.new("invalid value for \"{{{name}}}\", must be one of #{validator.allowable_values}.")
|
||||
end
|
||||
@{{{name}}} = {{{name}}}
|
||||
end
|
||||
|
||||
{{/isContainer}}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#hasValidation}}
|
||||
# Custom attribute writer method with validation
|
||||
# @param [Object] {{{name}}} Value to be assigned
|
||||
def {{{name}}}=({{{name}}})
|
||||
{{^isNullable}}
|
||||
{{#required}}
|
||||
if {{{name}}}.nil?
|
||||
raise ArgumentError.new("{{{name}}} cannot be nil")
|
||||
end
|
||||
|
||||
{{/required}}
|
||||
{{/isNullable}}
|
||||
{{#maxLength}}
|
||||
if {{^required}}!{{{name}}}.nil? && {{/required}}{{{name}}}.to_s.length > {{{maxLength}}}
|
||||
raise ArgumentError.new("invalid value for "{{{name}}}", the character length must be smaller than or equal to {{{maxLength}}}.")
|
||||
end
|
||||
|
||||
{{/maxLength}}
|
||||
{{#minLength}}
|
||||
if {{^required}}!{{{name}}}.nil? && {{/required}}{{{name}}}.to_s.length < {{{minLength}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{name}}}\", the character length must be great than or equal to {{{minLength}}}.")
|
||||
end
|
||||
|
||||
{{/minLength}}
|
||||
{{#maximum}}
|
||||
if {{^required}}!{{{name}}}.nil? && {{/required}}{{{name}}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{{maximum}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{name}}}\", must be smaller than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}{{{maximum}}}.")
|
||||
end
|
||||
|
||||
{{/maximum}}
|
||||
{{#minimum}}
|
||||
if {{^required}}!{{{name}}}.nil? && {{/required}}{{{name}}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{{minimum}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{name}}}\", must be greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}{{{minimum}}}.")
|
||||
end
|
||||
|
||||
{{/minimum}}
|
||||
{{#pattern}}
|
||||
pattern = Regexp.new({{{pattern}}})
|
||||
if {{^required}}!{{{name}}}.nil? && {{/required}}{{{name}}} !~ pattern
|
||||
raise ArgumentError.new("invalid value for \"{{{name}}}\", must conform to the pattern #{pattern}.")
|
||||
end
|
||||
|
||||
{{/pattern}}
|
||||
{{#maxItems}}
|
||||
if {{^required}}!{{{name}}}.nil? && {{/required}}{{{name}}}.length > {{{maxItems}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{name}}}\", number of items must be less than or equal to {{{maxItems}}}.")
|
||||
end
|
||||
|
||||
{{/maxItems}}
|
||||
{{#minItems}}
|
||||
if {{^required}}!{{{name}}}.nil? && {{/required}}{{{name}}}.length < {{{minItems}}}
|
||||
raise ArgumentError.new("invalid value for \"{{{name}}}\", number of items must be greater than or equal to {{{minItems}}}.")
|
||||
end
|
||||
|
||||
{{/minItems}}
|
||||
@{{{name}}} = {{{name}}}
|
||||
end
|
||||
|
||||
{{/hasValidation}}
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
# Checks equality by comparing each attribute.
|
||||
# @param [Object] Object to be compared
|
||||
def ==(o)
|
||||
return true if self.equal?(o)
|
||||
self.class == o.class{{#vars}} &&
|
||||
{{name}} == o.{{name}}{{/vars}}{{#parent}} && super(o){{/parent}}
|
||||
end
|
||||
|
||||
# @see the `==` method
|
||||
# @param [Object] Object to be compared
|
||||
def eql?(o)
|
||||
self == o
|
||||
end
|
||||
|
||||
# Calculates hash code according to all attributes.
|
||||
# @return [Integer] Hash code
|
||||
def hash
|
||||
[{{#vars}}{{name}}{{^-last}}, {{/-last}}{{/vars}}].hash
|
||||
end
|
||||
|
||||
{{> base_object}}
|
||||
end
|
28
modules/openapi-generator/src/main/resources/crystal/partial_model_generic_doc.mustache
vendored
Normal file
28
modules/openapi-generator/src/main/resources/crystal/partial_model_generic_doc.mustache
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# {{moduleName}}::{{classname}}
|
||||
|
||||
## Properties
|
||||
|
||||
| Name | Type | Description | Notes |
|
||||
| ---- | ---- | ----------- | ----- |
|
||||
{{#vars}}
|
||||
| **{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional]{{/required}}{{#isReadOnly}}[readonly]{{/isReadOnly}}{{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}} |
|
||||
{{/vars}}
|
||||
|
||||
## Example
|
||||
|
||||
```ruby
|
||||
require '{{{gemName}}}'
|
||||
|
||||
{{^vars}}
|
||||
instance = {{moduleName}}::{{classname}}.new()
|
||||
{{/vars}}
|
||||
{{#vars}}
|
||||
{{#-first}}
|
||||
instance = {{moduleName}}::{{classname}}.new(
|
||||
{{/-first}}
|
||||
{{name}}: {{example}}{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
)
|
||||
{{/-last}}
|
||||
{{/vars}}
|
||||
```
|
137
modules/openapi-generator/src/main/resources/crystal/partial_oneof_module.mustache
vendored
Normal file
137
modules/openapi-generator/src/main/resources/crystal/partial_oneof_module.mustache
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
{{#description}}
|
||||
# {{{description}}}
|
||||
{{/description}}
|
||||
module {{classname}}
|
||||
class << self
|
||||
{{#oneOf}}
|
||||
{{#-first}}
|
||||
# List of class defined in oneOf (OpenAPI v3)
|
||||
def openapi_one_of
|
||||
[
|
||||
{{/-first}}
|
||||
:'{{{.}}}'{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
]
|
||||
end
|
||||
|
||||
{{/-last}}
|
||||
{{/oneOf}}
|
||||
{{#discriminator}}
|
||||
{{#propertyName}}
|
||||
# Discriminator's property name (OpenAPI v3)
|
||||
def openapi_discriminator_name
|
||||
:'{{{.}}}'
|
||||
end
|
||||
|
||||
{{/propertyName}}
|
||||
{{#mappedModels}}
|
||||
{{#-first}}
|
||||
# Discriminator's mapping (OpenAPI v3)
|
||||
def openapi_discriminator_mapping
|
||||
{
|
||||
{{/-first}}
|
||||
:'{{{mappingName}}}' => :'{{{modelName}}}'{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
}
|
||||
end
|
||||
|
||||
{{/-last}}
|
||||
{{/mappedModels}}
|
||||
{{/discriminator}}
|
||||
# Builds the object
|
||||
# @param [Mixed] Data to be matched against the list of oneOf items
|
||||
# @return [Object] Returns the model or the data itself
|
||||
def build(data)
|
||||
{{#discriminator}}
|
||||
discriminator_value = data[openapi_discriminator_name]
|
||||
return nil unless discriminator_value
|
||||
{{#mappedModels}}
|
||||
{{#-first}}
|
||||
|
||||
klass = openapi_discriminator_mapping[discriminator_value.to_sym]
|
||||
return nil unless klass
|
||||
|
||||
{{moduleName}}.const_get(klass).build_from_hash(data)
|
||||
{{/-first}}
|
||||
{{/mappedModels}}
|
||||
{{^mappedModels}}
|
||||
{{moduleName}}.const_get(discriminator_value).build_from_hash(data)
|
||||
{{/mappedModels}}
|
||||
{{/discriminator}}
|
||||
{{^discriminator}}
|
||||
# Go through the list of oneOf items and attempt to identify the appropriate one.
|
||||
# Note:
|
||||
# - We do not attempt to check whether exactly one item matches.
|
||||
# - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
|
||||
# due to the way the deserialization is made in the base_object template (it just casts without verifying).
|
||||
# - TODO: scalar values are defacto behaving as if they were nullable.
|
||||
# - TODO: logging when debugging is set.
|
||||
openapi_one_of.each do |klass|
|
||||
begin
|
||||
next if klass == :AnyType # "nullable: true"
|
||||
typed_data = find_and_cast_into_type(klass, data)
|
||||
return typed_data if typed_data
|
||||
rescue # rescue all errors so we keep iterating even if the current item lookup raises
|
||||
end
|
||||
end
|
||||
|
||||
openapi_one_of.include?(:AnyType) ? data : nil
|
||||
{{/discriminator}}
|
||||
end
|
||||
{{^discriminator}}
|
||||
|
||||
private
|
||||
|
||||
SchemaMismatchError = Class.new(StandardError)
|
||||
|
||||
# Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse.
|
||||
def find_and_cast_into_type(klass, data)
|
||||
return if data.nil?
|
||||
|
||||
case klass.to_s
|
||||
when 'Boolean'
|
||||
return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass)
|
||||
when 'Float'
|
||||
return data if data.instance_of?(Float)
|
||||
when 'Integer'
|
||||
return data if data.instance_of?(Integer)
|
||||
when 'Time'
|
||||
return Time.parse(data)
|
||||
when 'Date'
|
||||
return Date.parse(data)
|
||||
when 'String'
|
||||
return data if data.instance_of?(String)
|
||||
when 'Object' # "type: object"
|
||||
return data if data.instance_of?(Hash)
|
||||
when /\AArray<(?<sub_type>.+)>\z/ # "type: array"
|
||||
if data.instance_of?(Array)
|
||||
sub_type = Regexp.last_match[:sub_type]
|
||||
return data.map { |item| find_and_cast_into_type(sub_type, item) }
|
||||
end
|
||||
when /\AHash<String, (?<sub_type>.+)>\z/ # "type: object" with "additionalProperties: { ... }"
|
||||
if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) }
|
||||
sub_type = Regexp.last_match[:sub_type]
|
||||
return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) }
|
||||
end
|
||||
else # model
|
||||
const = {{moduleName}}.const_get(klass)
|
||||
if const
|
||||
if const.respond_to?(:openapi_one_of) # nested oneOf model
|
||||
model = const.build(data)
|
||||
return model if model
|
||||
else
|
||||
# raise if data contains keys that are not known to the model
|
||||
raise unless (data.keys - const.acceptable_attributes).empty?
|
||||
model = const.build_from_hash(data)
|
||||
return model if model && model.valid?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
raise # if no match by now, raise
|
||||
rescue
|
||||
raise SchemaMismatchError, "#{data} doesn't match the #{klass} type"
|
||||
end
|
||||
{{/discriminator}}
|
||||
end
|
||||
end
|
92
modules/openapi-generator/src/main/resources/crystal/partial_oneof_module_doc.mustache
vendored
Normal file
92
modules/openapi-generator/src/main/resources/crystal/partial_oneof_module_doc.mustache
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
# {{moduleName}}::{{classname}}
|
||||
|
||||
## Class instance methods
|
||||
|
||||
### `openapi_one_of`
|
||||
|
||||
Returns the list of classes defined in oneOf.
|
||||
|
||||
#### Example
|
||||
|
||||
```ruby
|
||||
require '{{{gemName}}}'
|
||||
|
||||
{{moduleName}}::{{classname}}.openapi_one_of
|
||||
# =>
|
||||
{{#oneOf}}
|
||||
{{#-first}}
|
||||
# [
|
||||
{{/-first}}
|
||||
# :'{{{.}}}'{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
# ]
|
||||
{{/-last}}
|
||||
{{/oneOf}}
|
||||
```
|
||||
{{#discriminator}}
|
||||
{{#propertyName}}
|
||||
|
||||
### `openapi_discriminator_name`
|
||||
|
||||
Returns the discriminator's property name.
|
||||
|
||||
#### Example
|
||||
|
||||
```ruby
|
||||
require '{{{gemName}}}'
|
||||
|
||||
{{moduleName}}::{{classname}}.openapi_discriminator_name
|
||||
# => :'{{{.}}}'
|
||||
```
|
||||
{{/propertyName}}
|
||||
{{#mappedModels}}
|
||||
{{#-first}}
|
||||
|
||||
### `openapi_discriminator_name`
|
||||
|
||||
Returns the discriminator's mapping.
|
||||
|
||||
#### Example
|
||||
|
||||
```ruby
|
||||
require '{{{gemName}}}'
|
||||
|
||||
{{moduleName}}::{{classname}}.openapi_discriminator_mapping
|
||||
# =>
|
||||
# {
|
||||
{{/-first}}
|
||||
# :'{{{mappingName}}}' => :'{{{modelName}}}'{{^-last}},{{/-last}}
|
||||
{{#-last}}
|
||||
# }
|
||||
{{/-last}}
|
||||
{{/mappedModels}}
|
||||
{{/discriminator}}
|
||||
|
||||
### build
|
||||
|
||||
Find the appropriate object from the `openapi_one_of` list and casts the data into it.
|
||||
|
||||
#### Example
|
||||
|
||||
```ruby
|
||||
require '{{{gemName}}}'
|
||||
|
||||
{{moduleName}}::{{classname}}.build(data)
|
||||
# => {{#oneOf}}{{#-first}}#<{{{.}}}:0x00007fdd4aab02a0>{{/-first}}{{/oneOf}}
|
||||
|
||||
{{moduleName}}::{{classname}}.build(data_that_doesnt_match)
|
||||
# => nil
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| **data** | **Mixed** | data to be matched against the list of oneOf items |
|
||||
|
||||
#### Return type
|
||||
|
||||
{{#oneOf}}
|
||||
- `{{{.}}}`
|
||||
{{/oneOf}}
|
||||
- `nil` (if no type matches)
|
2
modules/openapi-generator/src/main/resources/crystal/rspec.mustache
vendored
Normal file
2
modules/openapi-generator/src/main/resources/crystal/rspec.mustache
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
--color
|
||||
--require spec_helper
|
148
modules/openapi-generator/src/main/resources/crystal/rubocop.mustache
vendored
Normal file
148
modules/openapi-generator/src/main/resources/crystal/rubocop.mustache
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
# This file is based on https://github.com/rails/rails/blob/master/.rubocop.yml (MIT license)
|
||||
# Automatically generated by OpenAPI Generator (https://openapi-generator.tech)
|
||||
AllCops:
|
||||
TargetRubyVersion: 2.4
|
||||
# RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
|
||||
# to ignore them, so only the ones explicitly set in this file are enabled.
|
||||
DisabledByDefault: true
|
||||
Exclude:
|
||||
- '**/templates/**/*'
|
||||
- '**/vendor/**/*'
|
||||
- 'actionpack/lib/action_dispatch/journey/parser.rb'
|
||||
|
||||
# Prefer &&/|| over and/or.
|
||||
Style/AndOr:
|
||||
Enabled: true
|
||||
|
||||
# Align `when` with `case`.
|
||||
Layout/CaseIndentation:
|
||||
Enabled: true
|
||||
|
||||
# Align comments with method definitions.
|
||||
Layout/CommentIndentation:
|
||||
Enabled: true
|
||||
|
||||
Layout/ElseAlignment:
|
||||
Enabled: true
|
||||
|
||||
Layout/EmptyLineAfterMagicComment:
|
||||
Enabled: true
|
||||
|
||||
# In a regular class definition, no empty lines around the body.
|
||||
Layout/EmptyLinesAroundClassBody:
|
||||
Enabled: true
|
||||
|
||||
# In a regular method definition, no empty lines around the body.
|
||||
Layout/EmptyLinesAroundMethodBody:
|
||||
Enabled: true
|
||||
|
||||
# In a regular module definition, no empty lines around the body.
|
||||
Layout/EmptyLinesAroundModuleBody:
|
||||
Enabled: true
|
||||
|
||||
Layout/FirstArgumentIndentation:
|
||||
Enabled: true
|
||||
|
||||
# Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
|
||||
Style/HashSyntax:
|
||||
Enabled: false
|
||||
|
||||
# Method definitions after `private` or `protected` isolated calls need one
|
||||
# extra level of indentation.
|
||||
Layout/IndentationConsistency:
|
||||
Enabled: true
|
||||
EnforcedStyle: indented_internal_methods
|
||||
|
||||
# Two spaces, no tabs (for indentation).
|
||||
Layout/IndentationWidth:
|
||||
Enabled: true
|
||||
|
||||
Layout/LeadingCommentSpace:
|
||||
Enabled: true
|
||||
|
||||
Layout/SpaceAfterColon:
|
||||
Enabled: true
|
||||
|
||||
Layout/SpaceAfterComma:
|
||||
Enabled: true
|
||||
|
||||
Layout/SpaceAroundEqualsInParameterDefault:
|
||||
Enabled: true
|
||||
|
||||
Layout/SpaceAroundKeyword:
|
||||
Enabled: true
|
||||
|
||||
Layout/SpaceAroundOperators:
|
||||
Enabled: true
|
||||
|
||||
Layout/SpaceBeforeComma:
|
||||
Enabled: true
|
||||
|
||||
Layout/SpaceBeforeFirstArg:
|
||||
Enabled: true
|
||||
|
||||
Style/DefWithParentheses:
|
||||
Enabled: true
|
||||
|
||||
# Defining a method with parameters needs parentheses.
|
||||
Style/MethodDefParentheses:
|
||||
Enabled: true
|
||||
|
||||
Style/FrozenStringLiteralComment:
|
||||
Enabled: false
|
||||
EnforcedStyle: always
|
||||
|
||||
# Use `foo {}` not `foo{}`.
|
||||
Layout/SpaceBeforeBlockBraces:
|
||||
Enabled: true
|
||||
|
||||
# Use `foo { bar }` not `foo {bar}`.
|
||||
Layout/SpaceInsideBlockBraces:
|
||||
Enabled: true
|
||||
|
||||
# Use `{ a: 1 }` not `{a:1}`.
|
||||
Layout/SpaceInsideHashLiteralBraces:
|
||||
Enabled: true
|
||||
|
||||
Layout/SpaceInsideParens:
|
||||
Enabled: true
|
||||
|
||||
# Check quotes usage according to lint rule below.
|
||||
#Style/StringLiterals:
|
||||
# Enabled: true
|
||||
# EnforcedStyle: single_quotes
|
||||
|
||||
# Detect hard tabs, no hard tabs.
|
||||
Layout/IndentationStyle:
|
||||
Enabled: true
|
||||
|
||||
# Blank lines should not have any spaces.
|
||||
Layout/TrailingEmptyLines:
|
||||
Enabled: true
|
||||
|
||||
# No trailing whitespace.
|
||||
Layout/TrailingWhitespace:
|
||||
Enabled: false
|
||||
|
||||
# Use quotes for string literals when they are enough.
|
||||
Style/RedundantPercentQ:
|
||||
Enabled: true
|
||||
|
||||
# Align `end` with the matching keyword or starting expression except for
|
||||
# assignments, where it should be aligned with the LHS.
|
||||
Layout/EndAlignment:
|
||||
Enabled: true
|
||||
EnforcedStyleAlignWith: variable
|
||||
AutoCorrect: true
|
||||
|
||||
# Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
|
||||
Lint/RequireParentheses:
|
||||
Enabled: true
|
||||
|
||||
Style/RedundantReturn:
|
||||
Enabled: true
|
||||
AllowMultipleReturnValues: true
|
||||
|
||||
Style/Semicolon:
|
||||
Enabled: true
|
||||
AllowAsExpressionSeparator: true
|
20
modules/openapi-generator/src/main/resources/crystal/shard.mustache
vendored
Normal file
20
modules/openapi-generator/src/main/resources/crystal/shard.mustache
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
name: {{{moduleName}}}
|
||||
version: {{{shardVersion}}}
|
||||
authors:
|
||||
- {{{shardAuthors}}}
|
||||
description: |
|
||||
- {{{ shardDescription}}}
|
||||
crystal: ">= 0.35.1"
|
||||
dependencies:
|
||||
crest:
|
||||
github: mamantoha/crest
|
||||
version: ~> 0.26.0
|
||||
|
||||
development_dependencies:
|
||||
kemal:
|
||||
github: kemalcr/kemal
|
||||
version: ~>0.27.0
|
||||
ameba:
|
||||
github: crystal-ameba/ameba
|
||||
|
||||
license: {{{shardLicense}}}
|
27
modules/openapi-generator/src/main/resources/crystal/shard_name.mustache
vendored
Normal file
27
modules/openapi-generator/src/main/resources/crystal/shard_name.mustache
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
# Dependencies
|
||||
require "crest"
|
||||
require "log"
|
||||
|
||||
module {{moduleName}}
|
||||
Log = ::Log.for("{{moduleName}}") # => Log for {{moduleName}} source
|
||||
|
||||
VERSION = {{ `shards version #{__DIR__}`.chomp.stringify }}
|
||||
|
||||
# Customize default settings for the SDK using block.
|
||||
# {{moduleName}}.configure do |config|
|
||||
# config.username = "xxx"
|
||||
# config.password = "xxx"
|
||||
# end
|
||||
# If no block given, return the default Configuration object.
|
||||
def configure
|
||||
if block_given?
|
||||
yield(Configuration.default)
|
||||
else
|
||||
Configuration.default
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "./{{shardName}}/**"
|
6
modules/openapi-generator/src/main/resources/crystal/spec_helper.mustache
vendored
Normal file
6
modules/openapi-generator/src/main/resources/crystal/spec_helper.mustache
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
# load modules
|
||||
require "spec"
|
||||
require "json"
|
||||
require "../src/{{{shardName}}}"
|
8
modules/openapi-generator/src/main/resources/crystal/travis.mustache
vendored
Normal file
8
modules/openapi-generator/src/main/resources/crystal/travis.mustache
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
language: crystal
|
||||
|
||||
script:
|
||||
- crystal spec
|
||||
# uncomment below to check the code format
|
||||
# - crystal tool format --check
|
5
modules/openapi-generator/src/main/resources/crystal/version.mustache
vendored
Normal file
5
modules/openapi-generator/src/main/resources/crystal/version.mustache
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
|
||||
|
||||
module {{moduleName}}
|
||||
VERSION = '{{shardVersion}}'
|
||||
end
|
@ -65,10 +65,10 @@ namespace {{packageName}}.Client
|
||||
/// <returns>A JSON string.</returns>
|
||||
public string Serialize(object obj)
|
||||
{
|
||||
if (obj != null && obj is {{{packageName}}}.Model.AbstractOpenAPISchema)
|
||||
if (obj != null && obj is {{{packageName}}}.{{modelPackage}}.AbstractOpenAPISchema)
|
||||
{
|
||||
// the object to be serialized is an oneOf/anyOf schema
|
||||
return (({{{packageName}}}.Model.AbstractOpenAPISchema)obj).ToJson();
|
||||
return (({{{packageName}}}.{{modelPackage}}.AbstractOpenAPISchema)obj).ToJson();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -576,7 +576,7 @@ namespace {{packageName}}.Client
|
||||
}
|
||||
|
||||
// if the response type is oneOf/anyOf, call FromJSON to deserialize the data
|
||||
if (typeof({{{packageName}}}.Model.AbstractOpenAPISchema).IsAssignableFrom(typeof(T)))
|
||||
if (typeof({{{packageName}}}.{{modelPackage}}.AbstractOpenAPISchema).IsAssignableFrom(typeof(T)))
|
||||
{
|
||||
T instance = (T)Activator.CreateInstance(typeof(T));
|
||||
MethodInfo method = typeof(T).GetMethod("FromJson");
|
||||
|
@ -1 +1,9 @@
|
||||
analyzer:
|
||||
analyzer:
|
||||
language:
|
||||
strict-inference: true
|
||||
strict-raw-types: true
|
||||
strong-mode:
|
||||
implicit-dynamic: false
|
||||
implicit-casts: false
|
||||
exclude:
|
||||
- test/*.dart
|
||||
|
@ -1,3 +1,4 @@
|
||||
{{>header}}
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:dio/dio.dart';
|
||||
@ -31,8 +32,8 @@ class {{classname}} {
|
||||
}) async {
|
||||
final String _path = '{{{path}}}'{{#pathParams}}.replaceAll('{' r'{{baseName}}' '}', {{{paramName}}}.toString()){{/pathParams}};
|
||||
|
||||
final Map<String, dynamic> queryParams = {};
|
||||
final Map<String, dynamic> headerParams = {
|
||||
final queryParams = <String, dynamic>{};
|
||||
final headerParams = <String, dynamic>{
|
||||
if (headers != null) ...headers,
|
||||
};
|
||||
dynamic bodyData;
|
||||
@ -43,15 +44,15 @@ class {{classname}} {
|
||||
{{#queryParams}}
|
||||
queryParams[r'{{baseName}}'] = {{paramName}};
|
||||
{{/queryParams}}
|
||||
queryParams.removeWhere((key, value) => value == null);
|
||||
headerParams.removeWhere((key, value) => value == null);
|
||||
queryParams.removeWhere((key, dynamic value) => value == null);
|
||||
headerParams.removeWhere((key, dynamic value) => value == null);
|
||||
|
||||
final List<String> contentTypes = [{{^hasConsumes}}];{{/hasConsumes}}{{#hasConsumes}}{{#consumes}}
|
||||
final contentTypes = <String>[{{^hasConsumes}}];{{/hasConsumes}}{{#hasConsumes}}{{#consumes}}
|
||||
'{{{mediaType}}}',{{/consumes}}
|
||||
];{{/hasConsumes}}
|
||||
{{#hasFormParams}}
|
||||
|
||||
final Map<String, dynamic> formData = {};
|
||||
final formData = <String, dynamic>{};
|
||||
{{#isMultipart}}
|
||||
{{#formParams}}
|
||||
{{^isFile}}
|
||||
@ -76,18 +77,30 @@ class {{classname}} {
|
||||
{{/hasFormParams}}
|
||||
{{#bodyParam}}
|
||||
|
||||
{{#isArray}}
|
||||
{{#isContainer}}
|
||||
{{#isArray}}
|
||||
const type = FullType(BuiltList, [FullType({{baseType}})]);
|
||||
final serializedBody = _serializers.serialize({{paramName}}, specifiedType: type);
|
||||
{{/isArray}}
|
||||
{{^isArray}}
|
||||
final serializedBody = _serializers.serialize({{paramName}});
|
||||
{{/isArray}}
|
||||
{{/isArray}}
|
||||
{{#isMap}}
|
||||
const type = FullType(BuiltMap, [FullType(String), FullType({{baseType}})]);
|
||||
final serializedBody = _serializers.serialize({{paramName}}, specifiedType: type);
|
||||
{{/isMap}}
|
||||
{{/isContainer}}
|
||||
{{^isContainer}}
|
||||
{{#isPrimitiveType}}
|
||||
var serializedBody = {{paramName}};
|
||||
{{/isPrimitiveType}}
|
||||
{{^isPrimitiveType}}
|
||||
final bodySerializer = _serializers.serializerForType({{{baseType}}}) as Serializer<{{{baseType}}}>;
|
||||
final serializedBody = _serializers.serializeWith(bodySerializer, {{paramName}});
|
||||
{{/isPrimitiveType}}
|
||||
{{/isContainer}}
|
||||
final json{{paramName}} = json.encode(serializedBody);
|
||||
bodyData = json{{paramName}};
|
||||
{{/bodyParam}}
|
||||
|
||||
return _dio.request(
|
||||
return _dio.request<dynamic>(
|
||||
_path,
|
||||
queryParameters: queryParams,
|
||||
data: bodyData,
|
||||
@ -97,8 +110,8 @@ class {{classname}} {
|
||||
responseType: ResponseType.bytes,
|
||||
{{/isResponseFile}}
|
||||
headers: headerParams,
|
||||
extra: {
|
||||
'secure': [{{^hasAuthMethods}}],{{/hasAuthMethods}}{{#hasAuthMethods}}
|
||||
extra: <String, dynamic>{
|
||||
'secure': <Map<String, String>>[{{^hasAuthMethods}}],{{/hasAuthMethods}}{{#hasAuthMethods}}
|
||||
{{#authMethods}}{
|
||||
'type': '{{type}}',
|
||||
'name': '{{name}}',{{#isApiKey}}
|
||||
@ -124,14 +137,22 @@ class {{classname}} {
|
||||
final data = response.data as {{{returnType}}};
|
||||
{{/returnTypeIsPrimitive}}
|
||||
{{^returnTypeIsPrimitive}}
|
||||
final serializer = _serializers.serializerForType({{{returnType}}});
|
||||
final data = _serializers.deserializeWith<{{{returnType}}}>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
|
||||
final serializer = _serializers.serializerForType({{{returnType}}}) as Serializer<{{{returnType}}}>;
|
||||
final data = _serializers.deserializeWith<{{{returnType}}}>(
|
||||
serializer,
|
||||
response.data is String ? jsonDecode(response.data as String) : response.data,
|
||||
);
|
||||
{{/returnTypeIsPrimitive}}
|
||||
{{/returnSimpleType}}
|
||||
{{^returnSimpleType}}
|
||||
const collectionType = {{#isMap}}BuiltMap{{/isMap}}{{^isMap}}BuiltList{{/isMap}};
|
||||
const type = FullType(collectionType, [{{#isMap}}FullType(String), {{/isMap}}FullType({{{returnBaseType}}})]);
|
||||
final {{{returnType}}} data = _serializers.deserialize(response.data is String ? jsonDecode(response.data) : response.data, specifiedType: type);
|
||||
final data = _serializers.deserialize(
|
||||
response.data is String
|
||||
? jsonDecode(response.data as String)
|
||||
: response.data,
|
||||
specifiedType: type,
|
||||
) as {{{returnType}}};
|
||||
{{/returnSimpleType}}
|
||||
{{/isResponseFile}}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
{{>header}}
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
@ -1,3 +1,4 @@
|
||||
{{>header}}
|
||||
library {{pubName}}.api;
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
|
@ -1,3 +1,4 @@
|
||||
{{>header}}
|
||||
import 'dart:async';
|
||||
import 'package:{{pubName}}/auth/auth.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
@ -6,12 +7,12 @@ class ApiKeyAuthInterceptor extends AuthInterceptor {
|
||||
Map<String, String> apiKeys = {};
|
||||
|
||||
@override
|
||||
Future onRequest(RequestOptions options) {
|
||||
final authInfo = getAuthInfo(options, "apiKey");
|
||||
for (var info in authInfo) {
|
||||
final authName = info["name"];
|
||||
final authKeyName = info["keyName"];
|
||||
final authWhere = info["where"];
|
||||
Future<dynamic> onRequest(RequestOptions options) {
|
||||
final authInfo = getAuthInfo(options, 'apiKey');
|
||||
for (final info in authInfo) {
|
||||
final authName = info['name'] as String;
|
||||
final authKeyName = info['keyName'] as String;
|
||||
final authWhere = info['where'] as String;
|
||||
final apiKey = apiKeys[authName];
|
||||
if (apiKey != null) {
|
||||
if (authWhere == 'query') {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
|
||||
{{>header}}
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
abstract class AuthInterceptor extends Interceptor {
|
||||
@ -8,11 +7,11 @@ abstract class AuthInterceptor extends Interceptor {
|
||||
* Can return null if type is not present on auth data or if route doesn't need authentication
|
||||
*/
|
||||
List<Map<String, dynamic>> getAuthInfo(RequestOptions route, String type) {
|
||||
if (route.extra.containsKey("secure")) {
|
||||
final auth = route.extra["secure"];
|
||||
List<Map<String, dynamic>> results = [];
|
||||
for (var info in auth) {
|
||||
if(info["type"] == type) {
|
||||
if (route.extra.containsKey('secure')) {
|
||||
final auth = route.extra['secure'] as List<Map<String, String>>;
|
||||
final results = <Map<String, dynamic>>[];
|
||||
for (final info in auth) {
|
||||
if (info['type'] == type) {
|
||||
results.add(info);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
{{>header}}
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:{{pubName}}/auth/auth.dart';
|
||||
@ -14,13 +15,13 @@ class BasicAuthInterceptor extends AuthInterceptor {
|
||||
Map<String, BasicAuthInfo> authInfo = {};
|
||||
|
||||
@override
|
||||
Future onRequest(RequestOptions options) {
|
||||
Future<dynamic> onRequest(RequestOptions options) {
|
||||
final metadataAuthInfo = getAuthInfo(options, 'basic');
|
||||
for (var info in metadataAuthInfo) {
|
||||
final authName = info['name'];
|
||||
for (final info in metadataAuthInfo) {
|
||||
final authName = info['name'] as String;
|
||||
final basicAuthInfo = authInfo[authName];
|
||||
if(basicAuthInfo != null) {
|
||||
String basicAuth = 'Basic ' + base64Encode(utf8.encode('${basicAuthInfo.username}:${basicAuthInfo.password}'));
|
||||
if (basicAuthInfo != null) {
|
||||
final basicAuth = 'Basic ' + base64Encode(utf8.encode('${basicAuthInfo.username}:${basicAuthInfo.password}'));
|
||||
options.headers['Authorization'] = basicAuth;
|
||||
break;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
{{>header}}
|
||||
import 'dart:async';
|
||||
import 'package:{{pubName}}/auth/auth.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
@ -6,12 +7,12 @@ class OAuthInterceptor extends AuthInterceptor {
|
||||
Map<String, String> tokens = {};
|
||||
|
||||
@override
|
||||
Future onRequest(RequestOptions options) {
|
||||
final authInfo = getAuthInfo(options, "oauth");
|
||||
for (var info in authInfo) {
|
||||
final token = tokens[info["name"]];
|
||||
if(token != null) {
|
||||
options.headers["Authorization"] = "Bearer ${token}";
|
||||
Future<dynamic> onRequest(RequestOptions options) {
|
||||
final authInfo = getAuthInfo(options, 'oauth');
|
||||
for (final info in authInfo) {
|
||||
final token = tokens[info['name']];
|
||||
if (token != null) {
|
||||
options.headers['Authorization'] = 'Bearer ${token}';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ abstract class {{classname}} implements Built<{{classname}}, {{classname}}Builde
|
||||
static void _initializeBuilder({{{classname}}}Builder b) => b{{#vars}}{{#defaultValue}}
|
||||
..{{{name}}} = {{#isEnum}}{{^isContainer}}const {{{classname}}}{{{enumName}}}._({{/isContainer}}{{/isEnum}}{{{defaultValue}}}{{#isEnum}}{{^isContainer}}){{/isContainer}}{{/isEnum}}{{/defaultValue}}{{/vars}};
|
||||
|
||||
factory {{classname}}([updates({{classname}}Builder b)]) = _${{classname}};
|
||||
factory {{classname}}([void updates({{classname}}Builder b)]) = _${{classname}};
|
||||
static Serializer<{{classname}}> get serializer => _${{#lambda.camelcase}}{{{classname}}}{{/lambda.camelcase}}Serializer;
|
||||
}
|
||||
{{!
|
||||
|
6
modules/openapi-generator/src/main/resources/dart-dio/header.mustache
vendored
Normal file
6
modules/openapi-generator/src/main/resources/dart-dio/header.mustache
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.6
|
||||
|
||||
// ignore_for_file: unused_import
|
@ -1,3 +1,4 @@
|
||||
{{>header}}
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
import 'package:time_machine/time_machine.dart';
|
||||
|
@ -1,3 +1,4 @@
|
||||
{{>header}}
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
{{#imports}}
|
||||
|
@ -2,7 +2,7 @@ name: {{pubName}}
|
||||
version: {{pubVersion}}
|
||||
description: {{pubDescription}}
|
||||
environment:
|
||||
sdk: ">=2.3.0 <3.0.0"
|
||||
sdk: ">=2.6.0 <3.0.0"
|
||||
dependencies:
|
||||
dio: ^3.0.9
|
||||
built_value: ^7.1.0
|
||||
|
@ -1,3 +1,4 @@
|
||||
{{>header}}
|
||||
library serializers;
|
||||
|
||||
import 'package:built_value/iso_8601_date_time_serializer.dart';
|
||||
@ -9,25 +10,26 @@ import 'package:built_value/standard_json_plugin.dart';
|
||||
import 'package:{{pubName}}/local_date_serializer.dart';{{/timeMachine}}
|
||||
{{#models}}{{#model}}import 'package:{{pubName}}/model/{{classFilename}}.dart';
|
||||
{{/model}}{{/models}}
|
||||
|
||||
part 'serializers.g.dart';
|
||||
|
||||
@SerializersFor(const [
|
||||
{{#models}}{{#model}}{{classname}},
|
||||
{{/model}}{{/models}}
|
||||
@SerializersFor(const [{{#models}}{{#model}}
|
||||
{{classname}},{{/model}}{{/models}}
|
||||
])
|
||||
|
||||
//allow all models to be serialized within a list
|
||||
Serializers serializers = (_$serializers.toBuilder()
|
||||
{{#models}}{{#model}}..addBuilderFactory(
|
||||
const FullType(BuiltList, const [const FullType({{classname}})]),
|
||||
() => new ListBuilder<{{classname}}>())
|
||||
{{/model}}{{/models}}
|
||||
..add(Iso8601DateTimeSerializer())
|
||||
).build();
|
||||
Serializers serializers = (_$serializers.toBuilder(){{#apiInfo}}{{#apis}}{{#serializers}}
|
||||
..addBuilderFactory(
|
||||
{{#isArray}}
|
||||
const FullType(BuiltList, [FullType({{baseType}})]),
|
||||
() => ListBuilder<{{baseType}}>(),
|
||||
{{/isArray}}
|
||||
{{#isMap}}
|
||||
const FullType(BuiltMap, [FullType(String), FullType({{baseType}})]),
|
||||
() => MapBuilder<String, {{baseType}}>(),
|
||||
{{/isMap}}
|
||||
){{/serializers}}{{/apis}}{{/apiInfo}}{{#timeMachine}}
|
||||
..add(OffsetDateSerializer())
|
||||
..add(OffsetDateTimeSerializer()){{/timeMachine}}
|
||||
..add(Iso8601DateTimeSerializer()))
|
||||
.build();
|
||||
|
||||
Serializers standardSerializers =
|
||||
(serializers.toBuilder()
|
||||
{{#timeMachine}}..add(OffsetDateSerializer())
|
||||
..add(OffsetDateTimeSerializer())
|
||||
{{/timeMachine}}..addPlugin(StandardJsonPlugin())).build();
|
||||
(serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
|
||||
|
@ -33,7 +33,7 @@ import Uuid exposing (Uuid){{/includeUuid}}
|
||||
{-| {{{notes}}}
|
||||
-}
|
||||
{{/notes}}
|
||||
{{operationId}} : {{#allParams}}{{^required}}Maybe {{/required}}{{#isArray}}List {{/isArray}}{{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{#isModel}}Api.Data.{{/isModel}}{{dataType}}{{/datatypeWithEnum}} -> {{/allParams}}{{#authMethods}}{{#isBasicBearer}}String -> {{/isBasicBearer}}{{/authMethods}}Api.Request {{^responses}}(){{/responses}}{{#responses}}{{#is2xx}}{{^dataType}}(){{/dataType}}{{#isMap}}(Dict.Dict String {{/isMap}}{{#isArray}}(List {{/isArray}}{{^primitiveType}}{{^isUuid}}Api.Data.{{/isUuid}}{{/primitiveType}}{{#items}}{{#isModel}}Api.Data.{{/isModel}}{{/items}}{{dataType}}{{#isArray}}){{/isArray}}{{#isMap}}){{/isMap}}{{/is2xx}}{{/responses}}
|
||||
{{operationId}} : {{#allParams}}{{^required}}Maybe {{/required}}{{#isArray}}List {{/isArray}}{{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{#isModel}}Api.Data.{{/isModel}}{{dataType}}{{/datatypeWithEnum}} -> {{/allParams}}{{#authMethods}}{{#isBasicBearer}}String -> {{/isBasicBearer}}{{/authMethods}}Api.Request {{^responses}}(){{/responses}}{{#responses}}{{#is2xx}}{{^dataType}}(){{/dataType}}{{#isMap}}(Dict.Dict String {{/isMap}}{{#isArray}}(List {{#items}}{{#isModel}}Api.Data.{{/isModel}}{{/items}}{{/isArray}}{{^isArray}}{{^primitiveType}}{{^isUuid}}Api.Data.{{/isUuid}}{{/primitiveType}}{{/isArray}}{{dataType}}{{#isArray}}){{/isArray}}{{#isMap}}){{/isMap}}{{/is2xx}}{{/responses}}
|
||||
{{operationId}}{{#allParams}} {{>paramName}}{{/allParams}}{{#authMethods}}{{#isBasicBearer}} auth_token{{/isBasicBearer}}{{/authMethods}} =
|
||||
Api.request
|
||||
"{{httpMethod}}"
|
||||
|
@ -1 +1 @@
|
||||
{{#isArray}}(Json.Decode.list {{/isArray}}{{#isMap}}(Json.Decode.dict {{/isMap}}{{#items}}{{>recordFieldValueDecoder}}{{/items}}{{^isContainer}}{{#isCircularReference}}(Json.Decode.lazy (\_ -> {{/isCircularReference}}{{>fieldDecoder}}{{#isCircularReference}})){{/isCircularReference}}{{/isContainer}}{{#isArray}}){{/isArray}}{{#isMap}}){{/isMap}}
|
||||
{{#isArray}}(Json.Decode.list {{/isArray}}{{#isMap}}(Json.Decode.dict {{/isMap}}{{#items}}{{>recordFieldValueDecoder}}{{/items}}{{^isArray}}{{#isCircularReference}}(Json.Decode.lazy (\_ -> {{/isCircularReference}}{{>fieldDecoder}}{{#isCircularReference}})){{/isCircularReference}}{{/isArray}}{{#isArray}}){{/isArray}}{{#isMap}}){{/isMap}}
|
@ -32,7 +32,7 @@ interface {{classname}}Delegate {
|
||||
/**
|
||||
* @see {{classname}}#{{operationId}}
|
||||
*/
|
||||
fun {{operationId}}({{#allParams}}{{paramName}}: {{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{{dataType}}}{{/isBodyParam}}{{/isFile}}{{#isFile}}Resource?{{/isFile}}{{^-last}},
|
||||
fun {{operationId}}({{#allParams}}{{paramName}}: {{^isFile}}{{>optionalDataType}}{{/isFile}}{{#isFile}}Resource?{{/isFile}}{{^-last}},
|
||||
{{/-last}}{{/allParams}}): {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {
|
||||
{{>methodBody}}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
{{#useBeanValidation}}{{#required}}{{^isReadOnly}}
|
||||
@get:NotNull{{/isReadOnly}}{{/required}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swaggerAnnotations}}
|
||||
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swaggerAnnotations}}{{#deprecated}}
|
||||
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swaggerAnnotations}}
|
||||
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swaggerAnnotations}}{{#deprecated}}
|
||||
@Deprecated(message = ""){{/deprecated}}
|
||||
@field:JsonProperty("{{{baseName}}}"){{#isInherited}} override{{/isInherited}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isArray}}{{baseType}}<{{/isArray}}{{classname}}.{{nameInCamelCase}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}
|
@ -1,4 +1,3 @@
|
||||
{{#useBeanValidation}}{{#required}}{{^isReadOnly}}
|
||||
@get:NotNull {{/isReadOnly}}{{/required}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swaggerAnnotations}}
|
||||
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swaggerAnnotations}}
|
||||
@field:JsonProperty("{{{baseName}}}"){{#isInherited}} override{{/isInherited}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isArray}}{{baseType}}<{{/isArray}}{{classname}}.{{nameInCamelCase}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isReadOnly}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}{{/isReadOnly}}
|
||||
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swaggerAnnotations}}
|
||||
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swaggerAnnotations}}
|
||||
@field:JsonProperty("{{{baseName}}}", required = true){{#isInherited}} override{{/isInherited}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isArray}}{{baseType}}<{{/isArray}}{{classname}}.{{nameInCamelCase}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isReadOnly}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}{{/isReadOnly}}
|
48
modules/openapi-generator/src/main/resources/ktorm-schema/README.mustache
vendored
Normal file
48
modules/openapi-generator/src/main/resources/ktorm-schema/README.mustache
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
# {{packageName}} - Kotlin database library for {{appName}}
|
||||
|
||||
## Requires
|
||||
|
||||
{{#jvm}}
|
||||
* Kotlin 1.3.61
|
||||
* Gradle 4.9
|
||||
{{/jvm}}
|
||||
{{#multiplatform}}
|
||||
* Kotlin 1.3.50
|
||||
{{/multiplatform}}
|
||||
|
||||
## Build
|
||||
|
||||
{{#jvm}}
|
||||
First, create the gradle wrapper script:
|
||||
|
||||
```
|
||||
gradle wrapper
|
||||
```
|
||||
|
||||
Then, run:
|
||||
|
||||
{{/jvm}}
|
||||
```
|
||||
./gradlew check assemble
|
||||
```
|
||||
|
||||
This runs all tests and packages the library.
|
||||
|
||||
## Features/Implementation Notes
|
||||
|
||||
* Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions.
|
||||
* Supports Mapper using API model classes.
|
||||
* Supports SQLite types.
|
||||
|
||||
{{#generateModelDocs}}
|
||||
<a name="documentation-for-models"></a>
|
||||
## Documentation for Models
|
||||
|
||||
{{#modelPackage}}
|
||||
{{#models}}{{#model}} - [{{{modelPackage}}}.{{{classname}}}]({{modelDocPath}}{{{classname}}}.md)
|
||||
{{/model}}{{/models}}
|
||||
{{/modelPackage}}
|
||||
{{^modelPackage}}
|
||||
No model defined in this package
|
||||
{{/modelPackage}}
|
||||
{{/generateModelDocs}}
|
35
modules/openapi-generator/src/main/resources/ktorm-schema/build.gradle.mustache
vendored
Normal file
35
modules/openapi-generator/src/main/resources/ktorm-schema/build.gradle.mustache
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
group '{{groupId}}'
|
||||
version '{{artifactVersion}}'
|
||||
|
||||
wrapper {
|
||||
gradleVersion = '4.9'
|
||||
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
|
||||
}
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.72'
|
||||
ext.ktorm_version = '3.2.0'
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo1.maven.org/maven2" }
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo1.maven.org/maven2" }
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation "org.ktorm:ktorm-core:$ktorm_version"
|
||||
testImplementation "io.kotlintest:kotlintest-runner-junit5:3.1.0"
|
||||
}
|
102
modules/openapi-generator/src/main/resources/ktorm-schema/data_class.mustache
vendored
Normal file
102
modules/openapi-generator/src/main/resources/ktorm-schema/data_class.mustache
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
{{#vendorExtensions}}{{#x-ktorm-schema}}{{^discriminator}}
|
||||
/**
|
||||
* {{{description}}}
|
||||
{{#allVars}}
|
||||
* @param {{{name}}} {{{description}}}
|
||||
{{/allVars}}
|
||||
*/
|
||||
{{#isDeprecated}}
|
||||
@Deprecated(message = "This schema is deprecated.")
|
||||
{{/isDeprecated}}
|
||||
{{#nonPublicApi}}internal {{/nonPublicApi}}object {{{classname}}}s : BaseTable<{{{classname}}}>("{{#tableDefinition}}{{{tblName}}}{{/tableDefinition}}") {
|
||||
{{#allVars}}
|
||||
{{^isArray}}
|
||||
{{#isEnum}}
|
||||
{{#required}}{{>data_class_enum_req}}{{/required}}{{^required}}{{>data_class_enum_opt}}{{/required}}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#required}}{{>data_class_field_req}}{{/required}}{{^required}}{{>data_class_field_opt}}{{/required}}
|
||||
{{/isEnum}}
|
||||
{{/isArray}}
|
||||
{{/allVars}}
|
||||
|
||||
/**
|
||||
* Create an entity of type {{{classname}}} from the model
|
||||
*/
|
||||
override fun doCreateEntity(row: QueryRowSet, withReferences: Boolean) = {{{classname}}}(
|
||||
{{#allVars}}
|
||||
{{#vendorExtensions}}
|
||||
{{#x-ktorm-schema}}
|
||||
{{^isArray}}
|
||||
{{#relation}}
|
||||
{{#required}}{{>data_class_bind_ref_req}}{{/required}}{{^required}}{{>data_class_bind_ref_opt}}{{/required}}{{^-last}},{{/-last}}
|
||||
{{/relation}}
|
||||
{{^relation}}
|
||||
{{#required}}{{>data_class_bind_field_req}}{{/required}}{{^required}}{{>data_class_bind_field_opt}}{{/required}}{{^-last}},{{/-last}}
|
||||
{{/relation}}
|
||||
{{/isArray}}
|
||||
{{#isArray}}
|
||||
{{#required}}{{>data_class_bind_list_req}}{{/required}}{{^required}}{{>data_class_bind_list_opt}}{{/required}}{{^-last}},{{/-last}}
|
||||
{{/isArray}}
|
||||
{{/x-ktorm-schema}}
|
||||
{{/vendorExtensions}}
|
||||
{{/allVars}}
|
||||
)
|
||||
|
||||
/**
|
||||
* Assign all the columns from the entity of type {{{classname}}} to the DML expression.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* ```kotlin
|
||||
* let entity = {{{classname}}}()
|
||||
* database.update({{{classname}}}s, {
|
||||
* assignFrom(entity)
|
||||
* })
|
||||
* ```
|
||||
* @return the builder with the columns for the update or insert.
|
||||
*/
|
||||
fun AssignmentsBuilder.assignFrom(entity: {{{classname}}}) {
|
||||
this.apply {
|
||||
{{#allVars}}
|
||||
{{^isArray}}
|
||||
{{>data_class_set}}
|
||||
{{/isArray}}
|
||||
{{/allVars}}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{{#allVars}}
|
||||
{{#isArray}}
|
||||
{{#vendorExtensions}}
|
||||
{{#x-ktorm-schema}}
|
||||
{{#isDeprecated}}
|
||||
@Deprecated(message = "This schema is deprecated.")
|
||||
{{/isDeprecated}}
|
||||
{{#relationDefinition}}
|
||||
|
||||
{{#nonPublicApi}}internal {{/nonPublicApi}}object {{{relName}}} : BaseTable<Pair<{{{pkColKotlinType}}}, {{{fkColKotlinType}}}>>("{{{relTblName}}}") {
|
||||
val {{{pkName}}} = {{{pkColType}}}("{{{pkColName}}}")
|
||||
val {{{fkName}}} = {{{fkColType}}}("{{{fkColName}}}")
|
||||
|
||||
override fun doCreateEntity(row: QueryRowSet, withReferences: Boolean): Pair<{{{pkColKotlinType}}}, {{{fkColKotlinType}}}> =
|
||||
Pair(row[{{{pkName}}}] ?: {{#pkIsString}}""{{/pkIsString}}{{#pkIsNumeric}}0{{/pkIsNumeric}}, row[{{{fkName}}}] ?: {{#fkIsString}}""{{/fkIsString}}{{#fkIsNumeric}}0{{/fkIsNumeric}})
|
||||
|
||||
fun AssignmentsBuilder.assignFrom(entity: Pair<{{{pkColKotlinType}}}, {{{fkColKotlinType}}}>) {
|
||||
this.apply {
|
||||
set({{{relName}}}.{{{pkName}}}, entity.first)
|
||||
set({{{relName}}}.{{{fkName}}}, entity.second)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
{{/relationDefinition}}
|
||||
{{/x-ktorm-schema}}
|
||||
{{/vendorExtensions}}
|
||||
{{/isArray}}
|
||||
{{/allVars}}
|
||||
{{/discriminator}}
|
||||
{{/x-ktorm-schema}}
|
||||
{{/vendorExtensions}}
|
1
modules/openapi-generator/src/main/resources/ktorm-schema/data_class_bind_field_opt.mustache
vendored
Normal file
1
modules/openapi-generator/src/main/resources/ktorm-schema/data_class_bind_field_opt.mustache
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{#vendorExtensions}}{{#x-ktorm-schema}}{{#columnDefinition}} {{{name}}} = row[{{{name}}}] {{#defaultvalue}}?: {{{defaultvalue}}}{{/defaultvalue}} /* {{{colKotlinType}}}? */{{/columnDefinition}}{{/x-ktorm-schema}}{{/vendorExtensions}}{{#description}} /* {{{description}}} */{{/description}}
|
1
modules/openapi-generator/src/main/resources/ktorm-schema/data_class_bind_field_req.mustache
vendored
Normal file
1
modules/openapi-generator/src/main/resources/ktorm-schema/data_class_bind_field_req.mustache
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{#vendorExtensions}}{{#x-ktorm-schema}}{{#columnDefinition}} {{{name}}} = row[{{{name}}}]{{#isEnum}} ?: {{{classname}}}.{{{nameInCamelCase}}}.valueOf({{#isString}}""{{/isString}}{{#isNumeric}}0{{/isNumeric}}){{/isEnum}}{{^isEnum}}{{#isString}} ?: ""{{/isString}}{{#isNumeric}} ?: 0{{/isNumeric}}{{#isBoolean}} ?: false{{/isBoolean}}{{/isEnum}} /* {{{colKotlinType}}} */{{/columnDefinition}}{{/x-ktorm-schema}}{{/vendorExtensions}}{{#description}} /* {{{description}}} */{{/description}}
|
1
modules/openapi-generator/src/main/resources/ktorm-schema/data_class_bind_list_opt.mustache
vendored
Normal file
1
modules/openapi-generator/src/main/resources/ktorm-schema/data_class_bind_list_opt.mustache
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{#vendorExtensions}}{{#x-ktorm-schema}}{{#columnDefinition}} {{{name}}} = emptyList() /* {{{colKotlinType}}}? */{{/columnDefinition}}{{/x-ktorm-schema}}{{/vendorExtensions}}{{#description}} /* {{{description}}} */{{/description}}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user