Add a new crystal client generator (beta) (#8304)

* add crytsal client generator

* update samples

* update doc

* regenerate spec

* regenerate spec

* various fixes

* test crystal in circleci

* test crystal client in drone ci

* Revert "test crystal client in drone ci"

This reverts commit 317f2cf2a09f902c08ced214e8e5802fa79c3de8.

* fix install

* fix installation

* test crystal in travis

* cache image

* add --cache-from

* update doc

* run petstore with mvn

* install crystal

* fix install crystal

* sudo mvn

* run server

* using mvnw

* fix form or body parameter

* remove crystal from circleci

* fix test

* remove cache-from

* update doc
This commit is contained in:
William Cheng 2021-01-07 17:10:22 +08:00 committed by GitHub
parent c67dc5d7d5
commit 1df719801e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
83 changed files with 8309 additions and 7 deletions

3
.gitignore vendored
View File

@ -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

View File

@ -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,11 +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
- 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
# -- 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

View File

@ -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

View File

@ -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

View File

@ -76,7 +76,7 @@ OpenAPI Generator allows generation of API client libraries (SDK generation), se
| | Languages/Frameworks |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.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/) |
@ -842,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

9
bin/configs/crystal.yaml Normal file
View 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

View File

@ -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

View File

@ -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)

226
docs/generators/crystal.md Normal file
View 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

View File

@ -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());
}
}
}
}

View File

@ -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));
}
}

View File

@ -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

View 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

View 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
```

View 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

View 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

View 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

View 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

View 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

View 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}}

View 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

View 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}}}

View 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}}

View 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

View 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

View 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

View 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

View 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

View 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'

View 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

View 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

View File

@ -0,0 +1,12 @@
{{#models}}
{{#model}}
{{#oneOf}}
{{#-first}}
{{>partial_oneof_module_doc}}
{{/-first}}
{{/oneOf}}
{{^oneOf}}
{{>partial_model_generic_doc}}
{{/oneOf}}
{{/model}}
{{/models}}

View 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}}

View 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

View 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

View 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}}
```

View 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

View 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)

View File

@ -0,0 +1,2 @@
--color
--require spec_helper

View 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

View 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}}}

View 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}}/**"

View File

@ -0,0 +1,6 @@
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
# load modules
require "spec"
require "json"
require "../src/{{{shardName}}}"

View 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

View File

@ -0,0 +1,5 @@
# {{#lambdaPrefixWithHash}}{{> api_info}}{{/lambdaPrefixWithHash}}
module {{moduleName}}
VERSION = '{{shardVersion}}'
end

View File

@ -1181,6 +1181,7 @@
</property>
</activation>
<modules>
<module>samples/client/petstore/crystal</module>
<!-- servers -->
<module>samples/server/petstore/python-aiohttp</module>
<module>samples/server/petstore/python-aiohttp-srclayout</module>

View 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

View File

@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -0,0 +1,19 @@
.gitignore
.travis.yml
README.md
git_push.sh
shard.yml
spec/spec_helper.cr
src/petstore.cr
src/petstore/api/pet_api.cr
src/petstore/api/store_api.cr
src/petstore/api/user_api.cr
src/petstore/api_client.cr
src/petstore/api_error.cr
src/petstore/configuration.cr
src/petstore/models/api_response.cr
src/petstore/models/category.cr
src/petstore/models/order.cr
src/petstore/models/pet.cr
src/petstore/models/tag.cr
src/petstore/models/user.cr

View File

@ -0,0 +1 @@
5.0.1-SNAPSHOT

View File

@ -0,0 +1,2 @@
--color
--require spec_helper

View 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

View File

@ -0,0 +1,16 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
language: crystal
script:
- crystal spec
# uncomment below to check the code format
# - crystal tool format --check

View File

@ -0,0 +1,38 @@
# petstore
The Crystsal module for the OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
This SDK is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 1.0.0
- Package version: 1.0.0
- Build package: org.openapitools.codegen.languages.CrystalClientCodegen
## Installation
### Install from Git
Add the following to shard.yaml
```yaml
dependencies:
petstore:
github: GIT_USER_ID/GIT_REPO_ID
version: ~> 1.0.0
```
## Development
Install dependencies
```shell
shards
```
Run the tests:
```shell
crystal spec
```

Binary file not shown.

View File

@ -0,0 +1,7 @@
# Require ameba cli which starts the inspection.
require "ameba/cli"
# Require ameba extensions here which are added as project dependencies.
# Example:
#
# require "ameba-performance"

View 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="github.com"
echo "[INFO] No command line input provided. Set \$git_host to $git_host"
fi
if [ "$git_user_id" = "" ]; then
git_user_id="GIT_USER_ID"
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
fi
if [ "$git_repo_id" = "" ]; then
git_repo_id="GIT_REPO_ID"
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
fi
if [ "$release_note" = "" ]; then
release_note="Minor update"
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'

View File

@ -0,0 +1,56 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.openapitools</groupId>
<artifactId>CrystalPetstoreClientTests</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>Crystal OpenAPI Petstore Client</name>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>shards-install</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>shards</executable>
</configuration>
</execution>
<execution>
<id>crystal-spec</id>
<phase>integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>crystal</executable>
<arguments>
<argument>spec</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,34 @@
version: 2.0
shards:
ameba:
git: https://github.com/crystal-ameba/ameba.git
version: 0.13.3
crest:
git: https://github.com/mamantoha/crest.git
version: 0.26.1
exception_page:
git: https://github.com/crystal-loot/exception_page.git
version: 0.1.4
http-client-digest_auth:
git: https://github.com/mamantoha/http-client-digest_auth.git
version: 0.4.0
http_proxy:
git: https://github.com/mamantoha/http_proxy.git
version: 0.7.2
kemal:
git: https://github.com/kemalcr/kemal.git
version: 0.27.0
kilt:
git: https://github.com/jeromegn/kilt.git
version: 0.4.0
radix:
git: https://github.com/luislavena/radix.git
version: 0.3.9

View File

@ -0,0 +1,20 @@
name: Petstore
version: 1.0.0
authors:
-
description: |
-
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:

View File

@ -0,0 +1,137 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "../spec_helper"
require "json"
require "time"
# Unit tests for Petstore::PetApi
# Automatically generated by openapi-generator (https://openapi-generator.tech)
# Please update as you see appropriate
describe "PetApi" do
describe "test an instance of PetApi" do
it "should create an instance of PetApi" do
api_instance = Petstore::PetApi.new
# TODO expect(api_instance).to be_instance_of(Petstore::PetApi)
end
end
# unit tests for add_pet
# Add a new pet to the store
# @param pet Pet object that needs to be added to the store
# @param [Hash] opts the optional parameters
# @return [Pet]
describe "add_pet test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for delete_pet
# Deletes a pet
# @param pet_id Pet id to delete
# @param [Hash] opts the optional parameters
# @option opts [String] :api_key
# @return [nil]
describe "delete_pet test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for find_pets_by_status
# Finds Pets by status
# Multiple status values can be provided with comma separated strings
# @param status Status values that need to be considered for filter
# @param [Hash] opts the optional parameters
# @return [Array(Pet)]
describe "find_pets_by_status test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for find_pets_by_tags
# Finds Pets by tags
# Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
# @param tags Tags to filter by
# @param [Hash] opts the optional parameters
# @return [Array(Pet)]
describe "find_pets_by_tags test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for get_pet_by_id
# Find pet by ID
# Returns a single pet
# @param pet_id ID of pet to return
# @param [Hash] opts the optional parameters
# @return [Pet]
describe "get_pet_by_id test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
api_instance = Petstore::PetApi.new
# create a pet to start with
pet_id = Int64.new(91829)
pet = Petstore::Pet.new(id: pet_id, category: Petstore::Category.new(id: pet_id + 10, name: "crystal category"), name: "crystal", photo_urls: ["https://crystal-lang.org"], tags: [Petstore::Tag.new(id: pet_id + 100, name: "crystal tag")], status: "available")
api_instance.add_pet(pet)
result = api_instance.get_pet_by_id(pet_id: pet_id)
result.id.should eq pet_id
result.category.id.should eq pet_id + 10
result.category.name.should eq "crystal category"
result.name.should eq "crystal"
result.photo_urls.should eq ["https://crystal-lang.org"]
result.status.should eq "available"
result.tags[0].id.should eq pet_id + 100
end
end
# unit tests for update_pet
# Update an existing pet
# @param pet Pet object that needs to be added to the store
# @param [Hash] opts the optional parameters
# @return [Pet]
describe "update_pet test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for update_pet_with_form
# Updates a pet in the store with form data
# @param pet_id ID of pet that needs to be updated
# @param [Hash] opts the optional parameters
# @option opts [String] :name Updated name of the pet
# @option opts [String] :status Updated status of the pet
# @return [nil]
describe "update_pet_with_form test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for upload_file
# uploads an image
# @param pet_id ID of pet to update
# @param [Hash] opts the optional parameters
# @option opts [String] :additional_metadata Additional data to pass to server
# @option opts [File] :file file to upload
# @return [ApiResponse]
describe "upload_file test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
end

View File

@ -0,0 +1,72 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "../spec_helper"
require "json"
require "time"
# Unit tests for Petstore::StoreApi
# Automatically generated by openapi-generator (https://openapi-generator.tech)
# Please update as you see appropriate
describe "StoreApi" do
describe "test an instance of StoreApi" do
it "should create an instance of StoreApi" do
api_instance = Petstore::StoreApi.new
# TODO expect(api_instance).to be_instance_of(Petstore::StoreApi)
end
end
# unit tests for delete_order
# Delete purchase order by ID
# For valid response try integer IDs with value &lt; 1000. Anything above 1000 or nonintegers will generate API errors
# @param order_id ID of the order that needs to be deleted
# @param [Hash] opts the optional parameters
# @return [nil]
describe "delete_order test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for get_inventory
# Returns pet inventories by status
# Returns a map of status codes to quantities
# @param [Hash] opts the optional parameters
# @return [Hash(String, Int32)]
describe "get_inventory test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for get_order_by_id
# Find purchase order by ID
# For valid response try integer IDs with value &lt;&#x3D; 5 or &gt; 10. Other values will generated exceptions
# @param order_id ID of pet that needs to be fetched
# @param [Hash] opts the optional parameters
# @return [Order]
describe "get_order_by_id test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for place_order
# Place an order for a pet
# @param order order placed for purchasing the pet
# @param [Hash] opts the optional parameters
# @return [Order]
describe "place_order test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
end

View File

@ -0,0 +1,118 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "../spec_helper"
require "json"
require "time"
# Unit tests for Petstore::UserApi
# Automatically generated by openapi-generator (https://openapi-generator.tech)
# Please update as you see appropriate
describe "UserApi" do
describe "test an instance of UserApi" do
it "should create an instance of UserApi" do
api_instance = Petstore::UserApi.new
# TODO expect(api_instance).to be_instance_of(Petstore::UserApi)
end
end
# unit tests for create_user
# Create user
# This can only be done by the logged in user.
# @param user Created user object
# @param [Hash] opts the optional parameters
# @return [nil]
describe "create_user test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for create_users_with_array_input
# Creates list of users with given input array
# @param user List of user object
# @param [Hash] opts the optional parameters
# @return [nil]
describe "create_users_with_array_input test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for create_users_with_list_input
# Creates list of users with given input array
# @param user List of user object
# @param [Hash] opts the optional parameters
# @return [nil]
describe "create_users_with_list_input test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for delete_user
# Delete user
# This can only be done by the logged in user.
# @param username The name that needs to be deleted
# @param [Hash] opts the optional parameters
# @return [nil]
describe "delete_user test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for get_user_by_name
# Get user by user name
# @param username The name that needs to be fetched. Use user1 for testing.
# @param [Hash] opts the optional parameters
# @return [User]
describe "get_user_by_name test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for login_user
# Logs user into the system
# @param username The user name for login
# @param password The password for login in clear text
# @param [Hash] opts the optional parameters
# @return [String]
describe "login_user test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for logout_user
# Logs out current logged in user session
# @param [Hash] opts the optional parameters
# @return [nil]
describe "logout_user test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
# unit tests for update_user
# Updated user
# This can only be done by the logged in user.
# @param username name that need to be deleted
# @param user Updated user object
# @param [Hash] opts the optional parameters
# @return [nil]
describe "update_user test" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
end

View File

@ -0,0 +1,44 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "../spec_helper"
require "json"
require "time"
# Unit tests for Petstore::ApiResponse
# Automatically generated by openapi-generator (https://openapi-generator.tech)
# Please update as you see appropriate
describe Petstore::ApiResponse do
describe "test an instance of ApiResponse" do
it "should create an instance of ApiResponse" do
#instance = Petstore::ApiResponse.new
#expect(instance).to be_instance_of(Petstore::ApiResponse)
end
end
describe "test attribute 'code'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute '_type'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'message'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
end

View File

@ -0,0 +1,38 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "../spec_helper"
require "json"
require "time"
# Unit tests for Petstore::Category
# Automatically generated by openapi-generator (https://openapi-generator.tech)
# Please update as you see appropriate
describe Petstore::Category do
describe "test an instance of Category" do
it "should create an instance of Category" do
#instance = Petstore::Category.new
#expect(instance).to be_instance_of(Petstore::Category)
end
end
describe "test attribute 'id'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'name'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
end

View File

@ -0,0 +1,66 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "../spec_helper"
require "json"
require "time"
# Unit tests for Petstore::Order
# Automatically generated by openapi-generator (https://openapi-generator.tech)
# Please update as you see appropriate
describe Petstore::Order do
describe "test an instance of Order" do
it "should create an instance of Order" do
#instance = Petstore::Order.new
#expect(instance).to be_instance_of(Petstore::Order)
end
end
describe "test attribute 'id'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'pet_id'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'quantity'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'ship_date'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'status'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
# validator = Petstore::EnumTest::EnumAttributeValidator.new("String", ["placed", "approved", "delivered"])
# validator.allowable_values.each do |value|
# expect { instance.status = value }.not_to raise_error
# end
end
end
describe "test attribute 'complete'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
end

View File

@ -0,0 +1,66 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "../spec_helper"
require "json"
require "time"
# Unit tests for Petstore::Pet
# Automatically generated by openapi-generator (https://openapi-generator.tech)
# Please update as you see appropriate
describe Petstore::Pet do
describe "test an instance of Pet" do
it "should create an instance of Pet" do
#instance = Petstore::Pet.new
#expect(instance).to be_instance_of(Petstore::Pet)
end
end
describe "test attribute 'id'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'category'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'name'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'photo_urls'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'tags'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'status'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
# validator = Petstore::EnumTest::EnumAttributeValidator.new("String", ["available", "pending", "sold"])
# validator.allowable_values.each do |value|
# expect { instance.status = value }.not_to raise_error
# end
end
end
end

View File

@ -0,0 +1,38 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "../spec_helper"
require "json"
require "time"
# Unit tests for Petstore::Tag
# Automatically generated by openapi-generator (https://openapi-generator.tech)
# Please update as you see appropriate
describe Petstore::Tag do
describe "test an instance of Tag" do
it "should create an instance of Tag" do
#instance = Petstore::Tag.new
#expect(instance).to be_instance_of(Petstore::Tag)
end
end
describe "test attribute 'id'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'name'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
end

View File

@ -0,0 +1,74 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "../spec_helper"
require "json"
require "time"
# Unit tests for Petstore::User
# Automatically generated by openapi-generator (https://openapi-generator.tech)
# Please update as you see appropriate
describe Petstore::User do
describe "test an instance of User" do
it "should create an instance of User" do
#instance = Petstore::User.new
#expect(instance).to be_instance_of(Petstore::User)
end
end
describe "test attribute 'id'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'username'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'first_name'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'last_name'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'email'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'password'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'phone'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
describe "test attribute 'user_status'" do
it "should work" do
# assertion here. ref: https://crystal-lang.org/reference/guides/testing.html
end
end
end

View File

@ -0,0 +1,14 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
# load modules
require "spec"
require "json"
require "../src/petstore"

View File

@ -0,0 +1,35 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
# Dependencies
require "crest"
require "log"
module Petstore
Log = ::Log.for("Petstore") # => Log for Petstore source
VERSION = {{ `shards version #{__DIR__}`.chomp.stringify }}
# Customize default settings for the SDK using block.
# Petstore.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 "./petstore/**"

View File

@ -0,0 +1,493 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "uri"
module Petstore
class PetApi
property api_client : ApiClient
def initialize(api_client = ApiClient.default)
@api_client = api_client
end
# Add a new pet to the store
# @param pet [Pet] Pet object that needs to be added to the store
# @return [Pet]
def add_pet(pet : Pet)
data, _status_code, _headers = add_pet_with_http_info(pet)
data
end
# Add a new pet to the store
# @param pet [Pet] Pet object that needs to be added to the store
# @return [Array<(Pet, Integer, Hash)>] Pet data, response status code and response headers
def add_pet_with_http_info(pet : Pet)
if @api_client.config.debugging
Log.debug {"Calling API: PetApi.add_pet ..."}
end
# verify the required parameter "pet" is set
if @api_client.config.client_side_validation && pet.nil?
raise ArgumentError.new("Missing the required parameter 'pet' when calling PetApi.add_pet")
end
# resource path
local_var_path = "/pet"
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/xml", "application/json"])
# HTTP header "Content-Type"
header_params["Content-Type"] = @api_client.select_header_content_type(["application/json", "application/xml"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = pet.to_json
# return_type
return_type = "Pet"
# auth_names
auth_names = ["petstore_auth"]
data, status_code, headers = @api_client.call_api(:POST,
local_var_path,
:"PetApi.add_pet",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: PetApi#add_pet\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return Pet.from_json(data), status_code, headers
end
# Deletes a pet
# @param pet_id [Int64] Pet id to delete
# @return [nil]
def delete_pet(pet_id : Int64, api_key : String?)
delete_pet_with_http_info(pet_id, api_key)
nil
end
# Deletes a pet
# @param pet_id [Int64] Pet id to delete
# @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
def delete_pet_with_http_info(pet_id : Int64, api_key : String?)
if @api_client.config.debugging
Log.debug {"Calling API: PetApi.delete_pet ..."}
end
# verify the required parameter "pet_id" is set
if @api_client.config.client_side_validation && pet_id.nil?
raise ArgumentError.new("Missing the required parameter 'pet_id' when calling PetApi.delete_pet")
end
# resource path
local_var_path = "/pet/{petId}".sub("{" + "petId" + "}", URI.encode(pet_id.to_s).gsub("%2F", "/"))
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
header_params["api_key"] = api_key
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = nil
# auth_names
auth_names = ["petstore_auth"]
data, status_code, headers = @api_client.call_api(:DELETE,
local_var_path,
:"PetApi.delete_pet",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: PetApi#delete_pet\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return nil, status_code, headers
end
# Finds Pets by status
# Multiple status values can be provided with comma separated strings
# @param status [Array(String)] Status values that need to be considered for filter
# @return [Array(Pet)]
def find_pets_by_status(status : Array(String))
data, _status_code, _headers = find_pets_by_status_with_http_info(status)
data
end
# Finds Pets by status
# Multiple status values can be provided with comma separated strings
# @param status [Array(String)] Status values that need to be considered for filter
# @return [Array<(Array(Pet), Integer, Hash)>] Array(Pet) data, response status code and response headers
def find_pets_by_status_with_http_info(status : Array(String))
if @api_client.config.debugging
Log.debug {"Calling API: PetApi.find_pets_by_status ..."}
end
# verify the required parameter "status" is set
if @api_client.config.client_side_validation && status.nil?
raise ArgumentError.new("Missing the required parameter 'status' when calling PetApi.find_pets_by_status")
end
# resource path
local_var_path = "/pet/findByStatus"
# query parameters
query_params = Hash(Symbol, String).new
query_params[:"status"] = @api_client.build_collection_param(status, :csv)
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/xml", "application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = "Array(Pet)"
# auth_names
auth_names = ["petstore_auth"]
data, status_code, headers = @api_client.call_api(:GET,
local_var_path,
:"PetApi.find_pets_by_status",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: PetApi#find_pets_by_status\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return Array(Pet).from_json(data), status_code, headers
end
# Finds Pets by tags
# Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
# @param tags [Array(String)] Tags to filter by
# @return [Array(Pet)]
def find_pets_by_tags(tags : Array(String))
data, _status_code, _headers = find_pets_by_tags_with_http_info(tags)
data
end
# Finds Pets by tags
# Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
# @param tags [Array(String)] Tags to filter by
# @return [Array<(Array(Pet), Integer, Hash)>] Array(Pet) data, response status code and response headers
def find_pets_by_tags_with_http_info(tags : Array(String))
if @api_client.config.debugging
Log.debug {"Calling API: PetApi.find_pets_by_tags ..."}
end
# verify the required parameter "tags" is set
if @api_client.config.client_side_validation && tags.nil?
raise ArgumentError.new("Missing the required parameter 'tags' when calling PetApi.find_pets_by_tags")
end
# resource path
local_var_path = "/pet/findByTags"
# query parameters
query_params = Hash(Symbol, String).new
query_params[:"tags"] = @api_client.build_collection_param(tags, :csv)
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/xml", "application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = "Array(Pet)"
# auth_names
auth_names = ["petstore_auth"]
data, status_code, headers = @api_client.call_api(:GET,
local_var_path,
:"PetApi.find_pets_by_tags",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: PetApi#find_pets_by_tags\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return Array(Pet).from_json(data), status_code, headers
end
# Find pet by ID
# Returns a single pet
# @param pet_id [Int64] ID of pet to return
# @return [Pet]
def get_pet_by_id(pet_id : Int64)
data, _status_code, _headers = get_pet_by_id_with_http_info(pet_id)
data
end
# Find pet by ID
# Returns a single pet
# @param pet_id [Int64] ID of pet to return
# @return [Array<(Pet, Integer, Hash)>] Pet data, response status code and response headers
def get_pet_by_id_with_http_info(pet_id : Int64)
if @api_client.config.debugging
Log.debug {"Calling API: PetApi.get_pet_by_id ..."}
end
# verify the required parameter "pet_id" is set
if @api_client.config.client_side_validation && pet_id.nil?
raise ArgumentError.new("Missing the required parameter 'pet_id' when calling PetApi.get_pet_by_id")
end
# resource path
local_var_path = "/pet/{petId}".sub("{" + "petId" + "}", URI.encode(pet_id.to_s).gsub("%2F", "/"))
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/xml", "application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = "Pet"
# auth_names
auth_names = ["api_key"]
data, status_code, headers = @api_client.call_api(:GET,
local_var_path,
:"PetApi.get_pet_by_id",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: PetApi#get_pet_by_id\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return Pet.from_json(data), status_code, headers
end
# Update an existing pet
# @param pet [Pet] Pet object that needs to be added to the store
# @return [Pet]
def update_pet(pet : Pet)
data, _status_code, _headers = update_pet_with_http_info(pet)
data
end
# Update an existing pet
# @param pet [Pet] Pet object that needs to be added to the store
# @return [Array<(Pet, Integer, Hash)>] Pet data, response status code and response headers
def update_pet_with_http_info(pet : Pet)
if @api_client.config.debugging
Log.debug {"Calling API: PetApi.update_pet ..."}
end
# verify the required parameter "pet" is set
if @api_client.config.client_side_validation && pet.nil?
raise ArgumentError.new("Missing the required parameter 'pet' when calling PetApi.update_pet")
end
# resource path
local_var_path = "/pet"
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/xml", "application/json"])
# HTTP header "Content-Type"
header_params["Content-Type"] = @api_client.select_header_content_type(["application/json", "application/xml"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = pet.to_json
# return_type
return_type = "Pet"
# auth_names
auth_names = ["petstore_auth"]
data, status_code, headers = @api_client.call_api(:PUT,
local_var_path,
:"PetApi.update_pet",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: PetApi#update_pet\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return Pet.from_json(data), status_code, headers
end
# Updates a pet in the store with form data
# @param pet_id [Int64] ID of pet that needs to be updated
# @return [nil]
def update_pet_with_form(pet_id : Int64, name : String?, status : String?)
update_pet_with_form_with_http_info(pet_id, name, status)
nil
end
# Updates a pet in the store with form data
# @param pet_id [Int64] ID of pet that needs to be updated
# @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
def update_pet_with_form_with_http_info(pet_id : Int64, name : String?, status : String?)
if @api_client.config.debugging
Log.debug {"Calling API: PetApi.update_pet_with_form ..."}
end
# verify the required parameter "pet_id" is set
if @api_client.config.client_side_validation && pet_id.nil?
raise ArgumentError.new("Missing the required parameter 'pet_id' when calling PetApi.update_pet_with_form")
end
# resource path
local_var_path = "/pet/{petId}".sub("{" + "petId" + "}", URI.encode(pet_id.to_s).gsub("%2F", "/"))
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Content-Type"
header_params["Content-Type"] = @api_client.select_header_content_type(["application/x-www-form-urlencoded"])
# form parameters
form_params = Hash(Symbol, String).new
form_params[:"name"] = name
form_params[:"status"] = status
# http body (model)
post_body = nil
# return_type
return_type = nil
# auth_names
auth_names = ["petstore_auth"]
data, status_code, headers = @api_client.call_api(:POST,
local_var_path,
:"PetApi.update_pet_with_form",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: PetApi#update_pet_with_form\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return nil, status_code, headers
end
# uploads an image
# @param pet_id [Int64] ID of pet to update
# @return [ApiResponse]
def upload_file(pet_id : Int64, additional_metadata : String?, file : File?)
data, _status_code, _headers = upload_file_with_http_info(pet_id, additional_metadata, file)
data
end
# uploads an image
# @param pet_id [Int64] ID of pet to update
# @return [Array<(ApiResponse, Integer, Hash)>] ApiResponse data, response status code and response headers
def upload_file_with_http_info(pet_id : Int64, additional_metadata : String?, file : File?)
if @api_client.config.debugging
Log.debug {"Calling API: PetApi.upload_file ..."}
end
# verify the required parameter "pet_id" is set
if @api_client.config.client_side_validation && pet_id.nil?
raise ArgumentError.new("Missing the required parameter 'pet_id' when calling PetApi.upload_file")
end
# resource path
local_var_path = "/pet/{petId}/uploadImage".sub("{" + "petId" + "}", URI.encode(pet_id.to_s).gsub("%2F", "/"))
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/json"])
# HTTP header "Content-Type"
header_params["Content-Type"] = @api_client.select_header_content_type(["multipart/form-data"])
# form parameters
form_params = Hash(Symbol, String).new
form_params[:"additionalMetadata"] = additional_metadata
form_params[:"file"] = file
# http body (model)
post_body = nil
# return_type
return_type = "ApiResponse"
# auth_names
auth_names = ["petstore_auth"]
data, status_code, headers = @api_client.call_api(:POST,
local_var_path,
:"PetApi.upload_file",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: PetApi#upload_file\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return ApiResponse.from_json(data), status_code, headers
end
end
end

View File

@ -0,0 +1,256 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "uri"
module Petstore
class StoreApi
property api_client : ApiClient
def initialize(api_client = ApiClient.default)
@api_client = api_client
end
# Delete purchase order by ID
# For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
# @param order_id [String] ID of the order that needs to be deleted
# @return [nil]
def delete_order(order_id : String)
delete_order_with_http_info(order_id)
nil
end
# Delete purchase order by ID
# For valid response try integer IDs with value &lt; 1000. Anything above 1000 or nonintegers will generate API errors
# @param order_id [String] ID of the order that needs to be deleted
# @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
def delete_order_with_http_info(order_id : String)
if @api_client.config.debugging
Log.debug {"Calling API: StoreApi.delete_order ..."}
end
# verify the required parameter "order_id" is set
if @api_client.config.client_side_validation && order_id.nil?
raise ArgumentError.new("Missing the required parameter 'order_id' when calling StoreApi.delete_order")
end
# resource path
local_var_path = "/store/order/{orderId}".sub("{" + "orderId" + "}", URI.encode(order_id.to_s).gsub("%2F", "/"))
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = nil
# auth_names
auth_names = [] of String
data, status_code, headers = @api_client.call_api(:DELETE,
local_var_path,
:"StoreApi.delete_order",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: StoreApi#delete_order\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return nil, status_code, headers
end
# Returns pet inventories by status
# Returns a map of status codes to quantities
# @return [Hash(String, Int32)]
def get_inventory()
data, _status_code, _headers = get_inventory_with_http_info()
data
end
# Returns pet inventories by status
# Returns a map of status codes to quantities
# @return [Array<(Hash(String, Int32), Integer, Hash)>] Hash(String, Int32) data, response status code and response headers
def get_inventory_with_http_info()
if @api_client.config.debugging
Log.debug {"Calling API: StoreApi.get_inventory ..."}
end
# resource path
local_var_path = "/store/inventory"
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = "Hash(String, Int32)"
# auth_names
auth_names = ["api_key"]
data, status_code, headers = @api_client.call_api(:GET,
local_var_path,
:"StoreApi.get_inventory",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: StoreApi#get_inventory\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return Hash(String, Int32).from_json(data), status_code, headers
end
# Find purchase order by ID
# For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
# @param order_id [Int64] ID of pet that needs to be fetched
# @return [Order]
def get_order_by_id(order_id : Int64)
data, _status_code, _headers = get_order_by_id_with_http_info(order_id)
data
end
# Find purchase order by ID
# For valid response try integer IDs with value &lt;&#x3D; 5 or &gt; 10. Other values will generated exceptions
# @param order_id [Int64] ID of pet that needs to be fetched
# @return [Array<(Order, Integer, Hash)>] Order data, response status code and response headers
def get_order_by_id_with_http_info(order_id : Int64)
if @api_client.config.debugging
Log.debug {"Calling API: StoreApi.get_order_by_id ..."}
end
# verify the required parameter "order_id" is set
if @api_client.config.client_side_validation && order_id.nil?
raise ArgumentError.new("Missing the required parameter 'order_id' when calling StoreApi.get_order_by_id")
end
if @api_client.config.client_side_validation && order_id > 5
raise ArgumentError.new("invalid value for \"order_id\" when calling StoreApi.get_order_by_id, must be smaller than or equal to 5.")
end
if @api_client.config.client_side_validation && order_id < 1
raise ArgumentError.new("invalid value for \"order_id\" when calling StoreApi.get_order_by_id, must be greater than or equal to 1.")
end
# resource path
local_var_path = "/store/order/{orderId}".sub("{" + "orderId" + "}", URI.encode(order_id.to_s).gsub("%2F", "/"))
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/xml", "application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = "Order"
# auth_names
auth_names = [] of String
data, status_code, headers = @api_client.call_api(:GET,
local_var_path,
:"StoreApi.get_order_by_id",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: StoreApi#get_order_by_id\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return Order.from_json(data), status_code, headers
end
# Place an order for a pet
# @param order [Order] order placed for purchasing the pet
# @return [Order]
def place_order(order : Order)
data, _status_code, _headers = place_order_with_http_info(order)
data
end
# Place an order for a pet
# @param order [Order] order placed for purchasing the pet
# @return [Array<(Order, Integer, Hash)>] Order data, response status code and response headers
def place_order_with_http_info(order : Order)
if @api_client.config.debugging
Log.debug {"Calling API: StoreApi.place_order ..."}
end
# verify the required parameter "order" is set
if @api_client.config.client_side_validation && order.nil?
raise ArgumentError.new("Missing the required parameter 'order' when calling StoreApi.place_order")
end
# resource path
local_var_path = "/store/order"
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/xml", "application/json"])
# HTTP header "Content-Type"
header_params["Content-Type"] = @api_client.select_header_content_type(["application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = order.to_json
# return_type
return_type = "Order"
# auth_names
auth_names = [] of String
data, status_code, headers = @api_client.call_api(:POST,
local_var_path,
:"StoreApi.place_order",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: StoreApi#place_order\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return Order.from_json(data), status_code, headers
end
end
end

View File

@ -0,0 +1,491 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "uri"
module Petstore
class UserApi
property api_client : ApiClient
def initialize(api_client = ApiClient.default)
@api_client = api_client
end
# Create user
# This can only be done by the logged in user.
# @param user [User] Created user object
# @return [nil]
def create_user(user : User)
create_user_with_http_info(user)
nil
end
# Create user
# This can only be done by the logged in user.
# @param user [User] Created user object
# @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
def create_user_with_http_info(user : User)
if @api_client.config.debugging
Log.debug {"Calling API: UserApi.create_user ..."}
end
# verify the required parameter "user" is set
if @api_client.config.client_side_validation && user.nil?
raise ArgumentError.new("Missing the required parameter 'user' when calling UserApi.create_user")
end
# resource path
local_var_path = "/user"
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Content-Type"
header_params["Content-Type"] = @api_client.select_header_content_type(["application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = user.to_json
# return_type
return_type = nil
# auth_names
auth_names = ["api_key"]
data, status_code, headers = @api_client.call_api(:POST,
local_var_path,
:"UserApi.create_user",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: UserApi#create_user\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return nil, status_code, headers
end
# Creates list of users with given input array
# @param user [Array(User)] List of user object
# @return [nil]
def create_users_with_array_input(user : Array(User))
create_users_with_array_input_with_http_info(user)
nil
end
# Creates list of users with given input array
# @param user [Array(User)] List of user object
# @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
def create_users_with_array_input_with_http_info(user : Array(User))
if @api_client.config.debugging
Log.debug {"Calling API: UserApi.create_users_with_array_input ..."}
end
# verify the required parameter "user" is set
if @api_client.config.client_side_validation && user.nil?
raise ArgumentError.new("Missing the required parameter 'user' when calling UserApi.create_users_with_array_input")
end
# resource path
local_var_path = "/user/createWithArray"
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Content-Type"
header_params["Content-Type"] = @api_client.select_header_content_type(["application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = user.to_json
# return_type
return_type = nil
# auth_names
auth_names = ["api_key"]
data, status_code, headers = @api_client.call_api(:POST,
local_var_path,
:"UserApi.create_users_with_array_input",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: UserApi#create_users_with_array_input\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return nil, status_code, headers
end
# Creates list of users with given input array
# @param user [Array(User)] List of user object
# @return [nil]
def create_users_with_list_input(user : Array(User))
create_users_with_list_input_with_http_info(user)
nil
end
# Creates list of users with given input array
# @param user [Array(User)] List of user object
# @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
def create_users_with_list_input_with_http_info(user : Array(User))
if @api_client.config.debugging
Log.debug {"Calling API: UserApi.create_users_with_list_input ..."}
end
# verify the required parameter "user" is set
if @api_client.config.client_side_validation && user.nil?
raise ArgumentError.new("Missing the required parameter 'user' when calling UserApi.create_users_with_list_input")
end
# resource path
local_var_path = "/user/createWithList"
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Content-Type"
header_params["Content-Type"] = @api_client.select_header_content_type(["application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = user.to_json
# return_type
return_type = nil
# auth_names
auth_names = ["api_key"]
data, status_code, headers = @api_client.call_api(:POST,
local_var_path,
:"UserApi.create_users_with_list_input",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: UserApi#create_users_with_list_input\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return nil, status_code, headers
end
# Delete user
# This can only be done by the logged in user.
# @param username [String] The name that needs to be deleted
# @return [nil]
def delete_user(username : String)
delete_user_with_http_info(username)
nil
end
# Delete user
# This can only be done by the logged in user.
# @param username [String] The name that needs to be deleted
# @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
def delete_user_with_http_info(username : String)
if @api_client.config.debugging
Log.debug {"Calling API: UserApi.delete_user ..."}
end
# verify the required parameter "username" is set
if @api_client.config.client_side_validation && username.nil?
raise ArgumentError.new("Missing the required parameter 'username' when calling UserApi.delete_user")
end
# resource path
local_var_path = "/user/{username}".sub("{" + "username" + "}", URI.encode(username.to_s).gsub("%2F", "/"))
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = nil
# auth_names
auth_names = ["api_key"]
data, status_code, headers = @api_client.call_api(:DELETE,
local_var_path,
:"UserApi.delete_user",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: UserApi#delete_user\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return nil, status_code, headers
end
# Get user by user name
# @param username [String] The name that needs to be fetched. Use user1 for testing.
# @return [User]
def get_user_by_name(username : String)
data, _status_code, _headers = get_user_by_name_with_http_info(username)
data
end
# Get user by user name
# @param username [String] The name that needs to be fetched. Use user1 for testing.
# @return [Array<(User, Integer, Hash)>] User data, response status code and response headers
def get_user_by_name_with_http_info(username : String)
if @api_client.config.debugging
Log.debug {"Calling API: UserApi.get_user_by_name ..."}
end
# verify the required parameter "username" is set
if @api_client.config.client_side_validation && username.nil?
raise ArgumentError.new("Missing the required parameter 'username' when calling UserApi.get_user_by_name")
end
# resource path
local_var_path = "/user/{username}".sub("{" + "username" + "}", URI.encode(username.to_s).gsub("%2F", "/"))
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/xml", "application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = "User"
# auth_names
auth_names = [] of String
data, status_code, headers = @api_client.call_api(:GET,
local_var_path,
:"UserApi.get_user_by_name",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: UserApi#get_user_by_name\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return User.from_json(data), status_code, headers
end
# Logs user into the system
# @param username [String] The user name for login
# @param password [String] The password for login in clear text
# @return [String]
def login_user(username : String, password : String)
data, _status_code, _headers = login_user_with_http_info(username, password)
data
end
# Logs user into the system
# @param username [String] The user name for login
# @param password [String] The password for login in clear text
# @return [Array<(String, Integer, Hash)>] String data, response status code and response headers
def login_user_with_http_info(username : String, password : String)
if @api_client.config.debugging
Log.debug {"Calling API: UserApi.login_user ..."}
end
# verify the required parameter "username" is set
if @api_client.config.client_side_validation && username.nil?
raise ArgumentError.new("Missing the required parameter 'username' when calling UserApi.login_user")
end
pattern = Regexp.new(/^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$/)
if @api_client.config.client_side_validation && username !~ pattern
raise ArgumentError.new("invalid value for \"username\" when calling UserApi.login_user, must conform to the pattern #{pattern}.")
end
# verify the required parameter "password" is set
if @api_client.config.client_side_validation && password.nil?
raise ArgumentError.new("Missing the required parameter 'password' when calling UserApi.login_user")
end
# resource path
local_var_path = "/user/login"
# query parameters
query_params = Hash(Symbol, String).new
query_params[:"username"] = username
query_params[:"password"] = password
# header parameters
header_params = Hash(String, String).new
# HTTP header "Accept" (if needed)
header_params["Accept"] = @api_client.select_header_accept(["application/xml", "application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = "String"
# auth_names
auth_names = [] of String
data, status_code, headers = @api_client.call_api(:GET,
local_var_path,
:"UserApi.login_user",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: UserApi#login_user\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return String.from_json(data), status_code, headers
end
# Logs out current logged in user session
# @return [nil]
def logout_user()
logout_user_with_http_info()
nil
end
# Logs out current logged in user session
# @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
def logout_user_with_http_info()
if @api_client.config.debugging
Log.debug {"Calling API: UserApi.logout_user ..."}
end
# resource path
local_var_path = "/user/logout"
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = nil
# return_type
return_type = nil
# auth_names
auth_names = ["api_key"]
data, status_code, headers = @api_client.call_api(:GET,
local_var_path,
:"UserApi.logout_user",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: UserApi#logout_user\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return nil, status_code, headers
end
# Updated user
# This can only be done by the logged in user.
# @param username [String] name that need to be deleted
# @param user [User] Updated user object
# @return [nil]
def update_user(username : String, user : User)
update_user_with_http_info(username, user)
nil
end
# Updated user
# This can only be done by the logged in user.
# @param username [String] name that need to be deleted
# @param user [User] Updated user object
# @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
def update_user_with_http_info(username : String, user : User)
if @api_client.config.debugging
Log.debug {"Calling API: UserApi.update_user ..."}
end
# verify the required parameter "username" is set
if @api_client.config.client_side_validation && username.nil?
raise ArgumentError.new("Missing the required parameter 'username' when calling UserApi.update_user")
end
# verify the required parameter "user" is set
if @api_client.config.client_side_validation && user.nil?
raise ArgumentError.new("Missing the required parameter 'user' when calling UserApi.update_user")
end
# resource path
local_var_path = "/user/{username}".sub("{" + "username" + "}", URI.encode(username.to_s).gsub("%2F", "/"))
# query parameters
query_params = Hash(Symbol, String).new
# header parameters
header_params = Hash(String, String).new
# HTTP header "Content-Type"
header_params["Content-Type"] = @api_client.select_header_content_type(["application/json"])
# form parameters
form_params = Hash(Symbol, String).new
# http body (model)
post_body = user.to_json
# return_type
return_type = nil
# auth_names
auth_names = ["api_key"]
data, status_code, headers = @api_client.call_api(:PUT,
local_var_path,
:"UserApi.update_user",
return_type,
post_body,
auth_names,
header_params,
query_params,
form_params)
if @api_client.config.debugging
Log.debug {"API called: UserApi#update_user\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"}
end
return nil, status_code, headers
end
end
end

View File

@ -0,0 +1,410 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "json"
require "time"
module Petstore
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 = "OpenAPI-Generator/#{VERSION}/crystal"
@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

View File

@ -0,0 +1,41 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
module Petstore
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

View File

@ -0,0 +1,271 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "log"
module Petstore
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 = "http"
@host = "petstore.swagger.io"
@base_path = "/v2"
@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{ "api_key" => {
type: "api_key",
in: "header",
key: "api_key",
value: api_key_with_prefix("api_key")
},
"petstore_auth" =>
{
type: "oauth2",
in: "header",
key: "Authorization",
value: "Bearer #{access_token}"
},
}
end
# Returns an array of Server setting
def server_settings
[
{
url: "http://petstore.swagger.io/v2",
description: "No description provided",
}
]
end
def operation_server_settings
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

View File

@ -0,0 +1,188 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "time"
module Petstore
# Describes the result of uploading an image resource
class ApiResponse include JSON::Serializable
include JSON::Serializable
@[JSON::Field(key: code, type: Int32)]
property code : Int32
@[JSON::Field(key: type, type: String)]
property _type : String
@[JSON::Field(key: message, type: String)]
property message : String
# Initializes the object
# @param [Hash] attributes Model attributes in the form of hash
def initialize(@code : Int32 | Nil, @_type : String | Nil, @message : String | Nil)
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 = Array.new
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?
true
end
# Checks equality by comparing each attribute.
# @param [Object] Object to be compared
def ==(o)
return true if self.equal?(o)
self.class == o.class &&
code == o.code &&
_type == o._type &&
message == o.message
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
[code, _type, message].hash
end
# 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)
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 = Petstore.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 = {} of Symbol => String
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
end
end

View File

@ -0,0 +1,200 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "time"
module Petstore
# A category for a pet
class Category include JSON::Serializable
include JSON::Serializable
@[JSON::Field(key: id, type: Int64)]
property id : Int64
@[JSON::Field(key: name, type: String)]
property name : String
# Initializes the object
# @param [Hash] attributes Model attributes in the form of hash
def initialize(@id : Int64 | Nil, @name : String | Nil)
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 = Array.new
pattern = Regexp.new(/^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$/)
if !@name.nil? && @name !~ pattern
invalid_properties.push("invalid value for \"name\", must conform to the pattern #{pattern}.")
end
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?
return false if !@name.nil? && @name !~ Regexp.new(/^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$/)
true
end
# Custom attribute writer method with validation
# @param [Object] name Value to be assigned
def name=(name)
pattern = Regexp.new(/^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$/)
if !name.nil? && name !~ pattern
raise ArgumentError.new("invalid value for \"name\", must conform to the pattern #{pattern}.")
end
@name = name
end
# Checks equality by comparing each attribute.
# @param [Object] Object to be compared
def ==(o)
return true if self.equal?(o)
self.class == o.class &&
id == o.id &&
name == o.name
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
[id, name].hash
end
# 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)
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 = Petstore.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 = {} of Symbol => String
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
end
end

View File

@ -0,0 +1,239 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "time"
module Petstore
# An order for a pets from the pet store
class Order include JSON::Serializable
include JSON::Serializable
@[JSON::Field(key: id, type: Int64)]
property id : Int64
@[JSON::Field(key: petId, type: Int64)]
property pet_id : Int64
@[JSON::Field(key: quantity, type: Int32)]
property quantity : Int32
@[JSON::Field(key: shipDate, type: Time)]
property ship_date : Time
# Order Status
@[JSON::Field(key: status, type: String)]
property status : String
@[JSON::Field(key: complete, type: Bool)]
property complete : Bool
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
# Initializes the object
# @param [Hash] attributes Model attributes in the form of hash
def initialize(@id : Int64 | Nil, @pet_id : Int64 | Nil, @quantity : Int32 | Nil, @ship_date : Time | Nil, @status : String | Nil, @complete : Bool | Nil)
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 = Array.new
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?
status_validator = EnumAttributeValidator.new("String", ["placed", "approved", "delivered"])
return false unless status_validator.valid?(@status)
true
end
# Custom attribute writer method checking allowed values (enum).
# @param [Object] status Object to be assigned
def status=(status)
validator = EnumAttributeValidator.new("String", ["placed", "approved", "delivered"])
unless validator.valid?(status)
raise ArgumentError.new("invalid value for \"status\", must be one of #{validator.allowable_values}.")
end
@status = status
end
# Checks equality by comparing each attribute.
# @param [Object] Object to be compared
def ==(o)
return true if self.equal?(o)
self.class == o.class &&
id == o.id &&
pet_id == o.pet_id &&
quantity == o.quantity &&
ship_date == o.ship_date &&
status == o.status &&
complete == o.complete
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
[id, pet_id, quantity, ship_date, status, complete].hash
end
# 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)
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 = Petstore.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 = {} of Symbol => String
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
end
end

View File

@ -0,0 +1,249 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "time"
module Petstore
# A pet for sale in the pet store
class Pet include JSON::Serializable
include JSON::Serializable
@[JSON::Field(key: id, type: Int64)]
property id : Int64
@[JSON::Field(key: category, type: Category)]
property category : Category
@[JSON::Field(key: name, type: String)]
property name : String
@[JSON::Field(key: photoUrls, type: Array(String))]
property photo_urls : Array(String)
@[JSON::Field(key: tags, type: Array(Tag))]
property tags : Array(Tag)
# pet status in the store
@[JSON::Field(key: status, type: String)]
property status : String
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
# Initializes the object
# @param [Hash] attributes Model attributes in the form of hash
def initialize(@id : Int64 | Nil, @category : Category | Nil, @name : String, @photo_urls : Array(String), @tags : Array(Tag) | Nil, @status : String | Nil)
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 = Array.new
if @name.nil?
invalid_properties.push("invalid value for \"name\", name cannot be nil.")
end
if @photo_urls.nil?
invalid_properties.push("invalid value for \"photo_urls\", photo_urls cannot be nil.")
end
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?
return false if @name.nil?
return false if @photo_urls.nil?
status_validator = EnumAttributeValidator.new("String", ["available", "pending", "sold"])
return false unless status_validator.valid?(@status)
true
end
# Custom attribute writer method checking allowed values (enum).
# @param [Object] status Object to be assigned
def status=(status)
validator = EnumAttributeValidator.new("String", ["available", "pending", "sold"])
unless validator.valid?(status)
raise ArgumentError.new("invalid value for \"status\", must be one of #{validator.allowable_values}.")
end
@status = status
end
# Checks equality by comparing each attribute.
# @param [Object] Object to be compared
def ==(o)
return true if self.equal?(o)
self.class == o.class &&
id == o.id &&
category == o.category &&
name == o.name &&
photo_urls == o.photo_urls &&
tags == o.tags &&
status == o.status
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
[id, category, name, photo_urls, tags, status].hash
end
# 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)
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 = Petstore.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 = {} of Symbol => String
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
end
end

View File

@ -0,0 +1,183 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "time"
module Petstore
# A tag for a pet
class Tag include JSON::Serializable
include JSON::Serializable
@[JSON::Field(key: id, type: Int64)]
property id : Int64
@[JSON::Field(key: name, type: String)]
property name : String
# Initializes the object
# @param [Hash] attributes Model attributes in the form of hash
def initialize(@id : Int64 | Nil, @name : String | Nil)
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 = Array.new
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?
true
end
# Checks equality by comparing each attribute.
# @param [Object] Object to be compared
def ==(o)
return true if self.equal?(o)
self.class == o.class &&
id == o.id &&
name == o.name
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
[id, name].hash
end
# 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)
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 = Petstore.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 = {} of Symbol => String
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
end
end

View File

@ -0,0 +1,214 @@
# #OpenAPI Petstore
#
##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
#
#The version of the OpenAPI document: 1.0.0
#
#Generated by: https://openapi-generator.tech
#OpenAPI Generator version: 5.0.1-SNAPSHOT
#
require "time"
module Petstore
# A User who is purchasing from the pet store
class User include JSON::Serializable
include JSON::Serializable
@[JSON::Field(key: id, type: Int64)]
property id : Int64
@[JSON::Field(key: username, type: String)]
property username : String
@[JSON::Field(key: firstName, type: String)]
property first_name : String
@[JSON::Field(key: lastName, type: String)]
property last_name : String
@[JSON::Field(key: email, type: String)]
property email : String
@[JSON::Field(key: password, type: String)]
property password : String
@[JSON::Field(key: phone, type: String)]
property phone : String
# User Status
@[JSON::Field(key: userStatus, type: Int32)]
property user_status : Int32
# Initializes the object
# @param [Hash] attributes Model attributes in the form of hash
def initialize(@id : Int64 | Nil, @username : String | Nil, @first_name : String | Nil, @last_name : String | Nil, @email : String | Nil, @password : String | Nil, @phone : String | Nil, @user_status : Int32 | Nil)
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 = Array.new
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?
true
end
# Checks equality by comparing each attribute.
# @param [Object] Object to be compared
def ==(o)
return true if self.equal?(o)
self.class == o.class &&
id == o.id &&
username == o.username &&
first_name == o.first_name &&
last_name == o.last_name &&
email == o.email &&
password == o.password &&
phone == o.phone &&
user_status == o.user_status
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
[id, username, first_name, last_name, email, password, phone, user_status].hash
end
# 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)
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 = Petstore.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 = {} of Symbol => String
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
end
end