From c9863998849667a448aabd65907006b40713ab5c Mon Sep 17 00:00:00 2001 From: Mauro Valota <7254293+valmoz@users.noreply.github.com> Date: Wed, 11 May 2022 17:00:40 +0200 Subject: [PATCH] fix: added oauth helpers to all sdks (#324) --- .github/workflows/check-custom-templates.yaml | 10 +- .../workflows/generate-csharp-netcore.yaml | 24 +- .github/workflows/generate-java.yaml | 20 +- .github/workflows/generate-javascript.yaml | 17 +- .github/workflows/generate-php.yaml | 30 +- .github/workflows/generate-python.yaml | 22 +- .github/workflows/generate-ruby.yaml | 22 +- .../workflows/generate-typescript-axios.yaml | 19 +- openapi-enriched.yaml | 1 + openapi.yaml | 32 +- scripts/enrich.js | 14 + scripts/generate-scopes.js | 55 + scripts/package.json | 1 + .../csharp-netcore/README.mustache | 0 .../csharp-netcore/modelGeneric.mustache | 0 .../csharp-netcore/netcore_project.mustache | 0 .../netcore_testproject.mustache | 0 .../openapi-generator/java/ApiClient.mustache | 1502 +++++++++++++++++ .../java/README.mustache | 0 templates/openapi-generator/java/api.mustache | 532 ++++++ .../java/api_doc.mustache | 0 .../java/build.gradle.mustache | 22 +- .../openapi-generator/java/build.sbt.mustache | 35 + templates/openapi-generator/java/pom.mustache | 416 +++++ .../javascript/README.mustache | 0 .../javascript/api_doc.mustache | 0 .../javascript/index.mustache | 66 + .../javascript/package.mustache | 5 +- .../php/README.mustache | 0 .../php/api_doc.mustache | 0 .../php/composer.mustache | 0 .../php/model_generic.mustache | 454 +++++ .../php/phpunit.xml.mustache | 0 .../python/README.mustache | 0 .../python/README_common.mustache | 0 .../python/model_templates/classvars.mustache | 0 .../python/python_doc_auth_partial.mustache | 0 .../python/requirements.mustache | 0 .../python/setup.mustache | 0 .../ruby/README.mustache | 0 .../ruby/base_object.mustache | 0 .../{ => openapi-generator}/ruby/gem.mustache | 4 + .../ruby/partial_model_generic_doc.mustache | 0 .../typescript-axios-docs/api_doc.mustache | 0 .../typescript-axios-docs/model_doc.mustache | 0 .../typescript-axios/README.mustache | 0 .../typescript-axios/apiInner.mustache | 0 .../typescript-axios/index.mustache | 9 + .../typescript-axios/package.mustache | 7 +- .../typescript-axios/tsconfig.mustache | 0 templates/scopes/csharp-netcore/scopes.liquid | 37 + templates/scopes/java/scopes.liquid | 18 + templates/scopes/javascript/scopes.liquid | 13 + templates/scopes/php/scopes.liquid | 24 + templates/scopes/python/scopes.liquid | 7 + templates/scopes/ruby/scopes.liquid | 9 + .../scopes/typescript-axios/scopes.liquid | 13 + 57 files changed, 3396 insertions(+), 44 deletions(-) create mode 100644 scripts/generate-scopes.js rename templates/{ => openapi-generator}/csharp-netcore/README.mustache (100%) rename templates/{ => openapi-generator}/csharp-netcore/modelGeneric.mustache (100%) rename templates/{ => openapi-generator}/csharp-netcore/netcore_project.mustache (100%) rename templates/{ => openapi-generator}/csharp-netcore/netcore_testproject.mustache (100%) create mode 100644 templates/openapi-generator/java/ApiClient.mustache rename templates/{ => openapi-generator}/java/README.mustache (100%) create mode 100644 templates/openapi-generator/java/api.mustache rename templates/{ => openapi-generator}/java/api_doc.mustache (100%) rename templates/{ => openapi-generator}/java/build.gradle.mustache (89%) create mode 100644 templates/openapi-generator/java/build.sbt.mustache create mode 100644 templates/openapi-generator/java/pom.mustache rename templates/{ => openapi-generator}/javascript/README.mustache (100%) rename templates/{ => openapi-generator}/javascript/api_doc.mustache (100%) rename templates/{ => openapi-generator}/javascript/index.mustache (62%) rename templates/{ => openapi-generator}/javascript/package.mustache (92%) rename templates/{ => openapi-generator}/php/README.mustache (100%) rename templates/{ => openapi-generator}/php/api_doc.mustache (100%) rename templates/{ => openapi-generator}/php/composer.mustache (100%) create mode 100644 templates/openapi-generator/php/model_generic.mustache rename templates/{ => openapi-generator}/php/phpunit.xml.mustache (100%) rename templates/{ => openapi-generator}/python/README.mustache (100%) rename templates/{ => openapi-generator}/python/README_common.mustache (100%) rename templates/{ => openapi-generator}/python/model_templates/classvars.mustache (100%) rename templates/{ => openapi-generator}/python/python_doc_auth_partial.mustache (100%) rename templates/{ => openapi-generator}/python/requirements.mustache (100%) rename templates/{ => openapi-generator}/python/setup.mustache (100%) rename templates/{ => openapi-generator}/ruby/README.mustache (100%) rename templates/{ => openapi-generator}/ruby/base_object.mustache (100%) rename templates/{ => openapi-generator}/ruby/gem.mustache (92%) rename templates/{ => openapi-generator}/ruby/partial_model_generic_doc.mustache (100%) rename templates/{ => openapi-generator}/typescript-axios-docs/api_doc.mustache (100%) rename templates/{ => openapi-generator}/typescript-axios-docs/model_doc.mustache (100%) rename templates/{ => openapi-generator}/typescript-axios/README.mustache (100%) rename templates/{ => openapi-generator}/typescript-axios/apiInner.mustache (100%) create mode 100644 templates/openapi-generator/typescript-axios/index.mustache rename templates/{ => openapi-generator}/typescript-axios/package.mustache (80%) rename templates/{ => openapi-generator}/typescript-axios/tsconfig.mustache (100%) create mode 100644 templates/scopes/csharp-netcore/scopes.liquid create mode 100644 templates/scopes/java/scopes.liquid create mode 100644 templates/scopes/javascript/scopes.liquid create mode 100644 templates/scopes/php/scopes.liquid create mode 100644 templates/scopes/python/scopes.liquid create mode 100644 templates/scopes/ruby/scopes.liquid create mode 100644 templates/scopes/typescript-axios/scopes.liquid diff --git a/.github/workflows/check-custom-templates.yaml b/.github/workflows/check-custom-templates.yaml index 1f811715..a4304036 100644 --- a/.github/workflows/check-custom-templates.yaml +++ b/.github/workflows/check-custom-templates.yaml @@ -46,16 +46,16 @@ jobs: - id: retrieve-templates name: Retrieve templates run: | - openapi-generator-cli author template -g ${{ matrix.sdk }} -o templates-temp/${{ matrix.sdk }} - for entry in "templates-temp/${{ matrix.sdk }}"/*; do - FILE="${entry/templates-temp/templates}" + openapi-generator-cli author template -g ${{ matrix.sdk }} -o templates-temp/openapi-generator/${{ matrix.sdk }} + for entry in "templates-temp/openapi-generator/${{ matrix.sdk }}"/*; do + FILE="${entry/templates-temp/openapi-generator/templates}" if test -f "$FILE"; then echo "Moving $entry to $FILE" mv $entry $FILE fi done - rm -rf templates-temp/${{ matrix.sdk }} - cd templates/${{ matrix.sdk }} + rm -rf templates-temp/openapi-generator/${{ matrix.sdk }} + cd templates/openapi-generator/${{ matrix.sdk }} git add . diff --git a/.github/workflows/generate-csharp-netcore.yaml b/.github/workflows/generate-csharp-netcore.yaml index 2c843551..9251aadc 100644 --- a/.github/workflows/generate-csharp-netcore.yaml +++ b/.github/workflows/generate-csharp-netcore.yaml @@ -45,6 +45,12 @@ jobs: distribution: 'adopt' java-version: '8' + - id: setup-dotnet + name: Setup dotnet + uses: actions/setup-dotnet@v2 + with: + dotnet-version: '2.1.x' + - id: setup-libraries name: Install libraries run: | @@ -90,7 +96,9 @@ jobs: name: Move custom files to backup run: | mkdir -p ./backup/csharp-netcore/src/It.FattureInCloud.Sdk/Filter + mkdir -p ./backup/csharp-netcore/src/It.FattureInCloud.Sdk/Oauth2 mv ./generated/csharp-netcore/src/It.FattureInCloud.Sdk/Filter ./backup/csharp-netcore/src/It.FattureInCloud.Sdk/ + mv ./generated/csharp-netcore/src/It.FattureInCloud.Sdk/Oauth2 ./backup/csharp-netcore/src/It.FattureInCloud.Sdk/ - id: delete-old-files name: Delete old files @@ -116,12 +124,26 @@ jobs: USER_AGENT="$APP_NAME/${{ env.sdk_version }}/csharp-SDK" - openapi-generator-cli generate -i ./openapi.yaml -g csharp-netcore -o generated/csharp-netcore/ -t ./templates/csharp-netcore --additional-properties=useDateTimeOffset=true,conditionalSerialization=true,packageName=${PACKAGE_NAME},packageAuthors=${PACKAGE_AUTHORS},packageCompany=${PACKAGE_COMPANY},packageTitle=${PACKAGE_TITLE},packageVersion=${SDK_VERSION},targetFramework=${TARGET_FRAMEWORK},testTargetFramework=${TEST_TARGET_FRAMEWORK},multiTarget=true,licenseId=MIT --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} + openapi-generator-cli generate -i ./openapi.yaml -g csharp-netcore -o generated/csharp-netcore/ -t ./templates/openapi-generator/csharp-netcore --additional-properties=useDateTimeOffset=true,conditionalSerialization=true,packageName=${PACKAGE_NAME},packageAuthors=${PACKAGE_AUTHORS},packageCompany=${PACKAGE_COMPANY},packageTitle=${PACKAGE_TITLE},packageVersion=${SDK_VERSION},targetFramework=${TARGET_FRAMEWORK},testTargetFramework=${TEST_TARGET_FRAMEWORK},multiTarget=true,licenseId=MIT --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} - id: move-custom-files-to-repo name: Move custom files to repo run: | mv ./backup/csharp-netcore/src/It.FattureInCloud.Sdk/Filter ./generated/csharp-netcore/src/It.FattureInCloud.Sdk/ + mv ./backup/csharp-netcore/src/It.FattureInCloud.Sdk/Oauth2 ./generated/csharp-netcore/src/It.FattureInCloud.Sdk/ + + - id: generate-additional-files + name: Generate Additional files + run: | + node ./scripts/generate-scopes.js csharp-netcore + + - id: lint-code + name: Lint Code Base + run: | + cd ./generated/csharp-netcore + dotnet new tool-manifest + dotnet tool install JetBrains.ReSharper.GlobalTools + dotnet jb cleanupcode It.FattureInCloud.Sdk.sln - id: create-pr name: Create Pull Request diff --git a/.github/workflows/generate-java.yaml b/.github/workflows/generate-java.yaml index f8168a18..f1c2861e 100644 --- a/.github/workflows/generate-java.yaml +++ b/.github/workflows/generate-java.yaml @@ -93,6 +93,13 @@ jobs: mkdir -p ./backup/java/src/main/java/it/fattureincloud/sdk/ mv ./generated/java/src/main/java/it/fattureincloud/sdk/filter ./backup/java/src/main/java/it/fattureincloud/sdk/filter + mkdir -p ./backup/java/src/main/java/it/fattureincloud/sdk/auth/ + mv ./generated/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeError.java ./backup/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeError.java + mv ./generated/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeManager.java ./backup/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeManager.java + mv ./generated/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeParams.java ./backup/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeParams.java + mv ./generated/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeResponse.java ./backup/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeResponse.java + mv ./generated/java/src/main/java/it/fattureincloud/sdk/auth/Scope.java ./backup/java/src/main/java/it/fattureincloud/sdk/auth/Scope.java + - id: delete-old-files name: Delete old files run: | @@ -141,13 +148,24 @@ jobs: USER_AGENT="$APP_NAME/${{ env.sdk_version }}/Java-SDK" - openapi-generator-cli generate -i ./openapi.yaml -g java -o ./generated/java/ -t ./templates/java --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=$ADDITIONAL_PROPERTIES + openapi-generator-cli generate -i ./openapi.yaml -g java -o ./generated/java/ -t ./templates/openapi-generator/java --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=$ADDITIONAL_PROPERTIES - id: move-custom-files-to-repo name: Move custom files to repo run: | mv ./backup/java/src/main/java/it/fattureincloud/sdk/filter ./generated/java/src/main/java/it/fattureincloud/sdk/filter + mv ./backup/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeError.java ./generated/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeError.java + mv ./backup/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeManager.java ./generated/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeManager.java + mv ./backup/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeParams.java ./generated/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeParams.java + mv ./backup/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeResponse.java ./generated/java/src/main/java/it/fattureincloud/sdk/auth/OAuth2AuthorizationCodeResponse.java + mv ./backup/java/src/main/java/it/fattureincloud/sdk/auth/Scope.java ./generated/java/src/main/java/it/fattureincloud/sdk/auth/Scope.java + + - id: generate-additional-files + name: Generate Additional files + run: | + node ./scripts/generate-scopes.js java + - id: download-linter name: Download Java Linter run: | diff --git a/.github/workflows/generate-javascript.yaml b/.github/workflows/generate-javascript.yaml index 8b6364e3..91c1b2ae 100644 --- a/.github/workflows/generate-javascript.yaml +++ b/.github/workflows/generate-javascript.yaml @@ -90,7 +90,9 @@ jobs: name: Move custom files to backup run: | mkdir -p ./backup/javascript/src/filter + mkdir -p ./backup/javascript/src/oauth2 mv ./generated/javascript/src/filter ./backup/javascript/src/ + mv ./generated/javascript/src/oauth2 ./backup/javascript/src/ - id: delete-old-files name: Delete old files @@ -114,12 +116,25 @@ jobs: USER_AGENT="$APP_NAME/${{ env.sdk_version }}/JavaScript-SDK" - openapi-generator-cli generate -i ./openapi.yaml -g javascript -o ./generated/javascript/ -t ./templates/javascript --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=projectVersion=$SDK_VERSION,projectName=$PROJECT_NAME,projectDescription=$PROJECT_DESCRIPTION,moduleName=$MODULE_NAME,usePromises=true + openapi-generator-cli generate -i ./openapi.yaml -g javascript -o ./generated/javascript/ -t ./templates/openapi-generator/javascript --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=projectVersion=$SDK_VERSION,projectName=$PROJECT_NAME,projectDescription=$PROJECT_DESCRIPTION,moduleName=$MODULE_NAME,usePromises=true - id: move-custom-files-to-repo name: Move custom files to repo run: | mv ./backup/javascript/src/filter ./generated/javascript/src/ + mv ./backup/javascript/src/oauth2 ./generated/javascript/oauth2/ + + - id: generate-additional-files + name: Generate Additional files + run: | + node ./scripts/generate-scopes.js javascript + + - id: lint-code + name: Lint Code Base + run: | + cd ./generated/javascript/fattureincloud-js-sdk + npm install + npx eslint --fix ./ - id: create-pr name: Create Pull Request diff --git a/.github/workflows/generate-php.yaml b/.github/workflows/generate-php.yaml index 78b89f46..6de8feb8 100644 --- a/.github/workflows/generate-php.yaml +++ b/.github/workflows/generate-php.yaml @@ -45,6 +45,19 @@ jobs: distribution: 'adopt' java-version: '8' + - id: setup-php + name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 7.4 + + - id: setup-composer + name: Setup Composer + run: | + php -v + wget -O composer-setup.php https://getcomposer.org/installer + sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer + - id: setup-libraries name: Install libraries run: | @@ -90,7 +103,9 @@ jobs: name: Move custom files to backup run: | mkdir -p ./backup/php/lib/Filter + mkdir -p ./backup/php/lib/OAuth2 mv ./generated/php/lib/Filter ./backup/php/lib/ + mv ./generated/php/lib/OAuth2 ./backup/php/lib/ - id: delete-old-files name: Delete old files @@ -113,7 +128,7 @@ jobs: USER_AGENT="$INVOKER_PACKAGE/${{ env.sdk_version }}/PHP-SDK" - openapi-generator-cli generate -i ./openapi.yaml -g php -o ./generated/php/ -t ./templates/php --package-name=${PACKAGE_NAME} --invoker-package=${INVOKER_PACKAGE} --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=composerPackageName=${COMPOSER_PACKAGE_NAME} + openapi-generator-cli generate -i ./openapi.yaml -g php -o ./generated/php/ -t ./templates/openapi-generator/php --package-name=${PACKAGE_NAME} --invoker-package=${INVOKER_PACKAGE} --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=composerPackageName=${COMPOSER_PACKAGE_NAME} node ./scripts/postprocess-php.js clean './generated/php/lib/' './generated/php/test/' @@ -121,6 +136,19 @@ jobs: name: Move custom files to repo run: | mv ./backup/php/lib/Filter ./generated/php/lib/Filter + mv ./backup/php/lib/OAuth2 ./generated/php/lib/OAuth2 + + - id: generate-additional-files + name: Generate Additional files + run: | + node ./scripts/generate-scopes.js php + + - id: lint-code + name: Lint Code Base + run: | + cd ./generated/php/ + composer install + ./vendor/bin/php-cs-fixer fix ./ --allow-risky=yes - id: create-pr name: Create Pull Request diff --git a/.github/workflows/generate-python.yaml b/.github/workflows/generate-python.yaml index 90c2343c..b2948b6d 100644 --- a/.github/workflows/generate-python.yaml +++ b/.github/workflows/generate-python.yaml @@ -45,6 +45,12 @@ jobs: distribution: 'adopt' java-version: '8' + - id: setup-python + name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: '3.10' + - id: setup-libraries name: Install libraries run: | @@ -90,7 +96,9 @@ jobs: name: Move custom files to backup run: | mkdir -p ./backup/python/fattureincloud_python_sdk/filter + mkdir -p ./backup/python/fattureincloud_python_sdk/oauth2 mv ./generated/python/fattureincloud_python_sdk/filter ./backup/python/fattureincloud_python_sdk/ + mv ./generated/python/fattureincloud_python_sdk/oauth2 ./backup/python/fattureincloud_python_sdk/ - id: delete-old-files name: Delete old files @@ -115,12 +123,24 @@ jobs: USER_AGENT="$APP_NAME/${{ env.sdk_version }}/Python-SDK" - openapi-generator-cli generate -i ./openapi.yaml -g python -o ./generated/python/ -t ./templates/python --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=packageVersion=${SDK_VERSION},packageName=${PACKAGE_NAME},packageUrl=${PACKAGE_URL},projectName=${PROJECT_NAME},infoName=${INFO_NAME} + openapi-generator-cli generate -i ./openapi.yaml -g python -o ./generated/python/ -t ./templates/openapi-generator/python --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=packageVersion=${SDK_VERSION},packageName=${PACKAGE_NAME},packageUrl=${PACKAGE_URL},projectName=${PROJECT_NAME},infoName=${INFO_NAME} - id: move-custom-files-to-repo name: Move custom files to repo run: | mv ./backup/python/fattureincloud_python_sdk/filter ./generated/python/fattureincloud_python_sdk/ + mv ./backup/python/fattureincloud_python_sdk/oauth2 ./generated/python/fattureincloud_python_sdk/ + + - id: generate-additional-files + name: Generate Additional files + run: | + node ./scripts/generate-scopes.js python + + - id: format + name: Format files + run: | + pip install black + black ./generated/python/ - id: create-pr name: Create Pull Request diff --git a/.github/workflows/generate-ruby.yaml b/.github/workflows/generate-ruby.yaml index f6fb6d13..ce1cf4c8 100644 --- a/.github/workflows/generate-ruby.yaml +++ b/.github/workflows/generate-ruby.yaml @@ -45,6 +45,12 @@ jobs: distribution: 'adopt' java-version: '8' + - id: setup-ruby + name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.1.0 + - id: setup-libraries name: Install libraries run: | @@ -90,7 +96,9 @@ jobs: name: Move custom files to backup run: | mkdir -p ./backup/ruby/lib/fattureincloud_ruby_sdk/filter + mkdir -p ./backup/ruby/lib/fattureincloud_ruby_sdk/oauth2 mv ./generated/ruby/lib/fattureincloud_ruby_sdk/filter ./backup/ruby/lib/fattureincloud_ruby_sdk/ + mv ./generated/ruby/lib/fattureincloud_ruby_sdk/oauth2 ./backup/ruby/lib/fattureincloud_ruby_sdk/ - id: delete-old-files name: Delete old files @@ -118,12 +126,24 @@ jobs: USER_AGENT="$APP_NAME/${{ env.sdk_version }}/Ruby-SDK" - openapi-generator-cli generate -i ./openapi.yaml -g ruby -o ./generated/ruby/ -t ./templates/ruby --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=gemVersion=${SDK_VERSION},gemAuthor=${GEM_AUTHOR},gemAuthorEmail=${GEM_AUTHOR_EMAIL},gemDescription=${GEM_DESCRIPTION},gemSummary=${GEM_DESCRIPTION},gemHomepage=${GEM_HOMEPAGE},gemLicense=${GEM_LICENSE},gemName=${GEM_NAME},gemSummary=${GEM_SUMMARY},moduleName=${MODULE_NAME} + openapi-generator-cli generate -i ./openapi.yaml -g ruby -o ./generated/ruby/ -t ./templates/openapi-generator/ruby --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=gemVersion=${SDK_VERSION},gemAuthor=${GEM_AUTHOR},gemAuthorEmail=${GEM_AUTHOR_EMAIL},gemDescription=${GEM_DESCRIPTION},gemSummary=${GEM_DESCRIPTION},gemHomepage=${GEM_HOMEPAGE},gemLicense=${GEM_LICENSE},gemName=${GEM_NAME},gemSummary=${GEM_SUMMARY},moduleName=${MODULE_NAME} - id: move-custom-files-to-repo name: Move custom files to repo run: | mv ./backup/ruby/lib/fattureincloud_ruby_sdk/filter ./generated/ruby/lib/fattureincloud_ruby_sdk/ + mv ./backup/ruby/lib/fattureincloud_ruby_sdk/oauth2 ./generated/ruby/lib/fattureincloud_ruby_sdk/ + + - id: generate-additional-files + name: Generate Additional files + run: | + node ./scripts/generate-scopes.js ruby + + - id: lint-code + name: Lint Code Base + run: | + cd ./generated/ruby/fattureincloud_ruby_sdk + bundle exec rubocop -a - id: create-pr name: Create Pull Request diff --git a/.github/workflows/generate-typescript-axios.yaml b/.github/workflows/generate-typescript-axios.yaml index fcceb3c6..cd7f6553 100644 --- a/.github/workflows/generate-typescript-axios.yaml +++ b/.github/workflows/generate-typescript-axios.yaml @@ -89,7 +89,9 @@ jobs: name: Move custom files to backup run: | mkdir -p ./backup/typescript-axios/src/filter + mkdir -p ./backup/typescript-axios/src/oauth2 mv ./generated/typescript-axios/src/filter ./backup/typescript-axios/src/ + mv ./generated/typescript-axios/src/oauth2 ./backup/typescript-axios/src/ - id: delete-old-files name: Delete old files @@ -111,11 +113,11 @@ jobs: USER_AGENT="$APP_NAME/${{ env.sdk_version }}/TypeScript-SDK" - openapi-generator-cli generate -i ./openapi.yaml -g typescript-axios -o generated/typescript-axios/ -t ./templates/typescript-axios --additional-properties=npmName=${PACKAGE_NAME},npmVersion=${SDK_VERSION},supportsES6=true,withNodeImports=true,withSeparateModelsAndApi=true,apiPackage=src/api,modelPackage=src/models,withInterfaces=true --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} + openapi-generator-cli generate -i ./openapi.yaml -g typescript-axios -o generated/typescript-axios/ -t ./templates/openapi-generator/typescript-axios --additional-properties=npmName=${PACKAGE_NAME},npmVersion=${SDK_VERSION},supportsES6=true,withNodeImports=true,withSeparateModelsAndApi=true,apiPackage=src/api,modelPackage=src/models,withInterfaces=true --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} - id: generate-typescript-axios-docs name: Generate Docs - run: openapi-generator-cli generate -i ./openapi.yaml -g javascript -o generated/typescript-axios-docs/ -t ./templates/typescript-axios-docs + run: openapi-generator-cli generate -i ./openapi.yaml -g javascript -o generated/typescript-axios-docs/ -t ./templates/openapi-generator/typescript-axios-docs - id: move-docs name: Moving Docs To The Right Folder @@ -125,6 +127,19 @@ jobs: name: Move custom files to repo run: | mv ./backup/typescript-axios/src/filter ./generated/typescript-axios/src/ + mv ./backup/typescript-axios/src/oauth2 ./generated/typescript-axios/src/ + + - id: generate-additional-files + name: Generate Additional files + run: | + node ./scripts/generate-scopes.js typescript-axios + + - id: lint-code + name: Lint Code Base + run: | + cd ./generated/typescript-axios/fattureincloud-ts-sdk + npm install + npx eslint --fix ./ - id: create-pr name: Create Pull Request diff --git a/openapi-enriched.yaml b/openapi-enriched.yaml index 55b5d125..97d87833 100644 --- a/openapi-enriched.yaml +++ b/openapi-enriched.yaml @@ -11129,6 +11129,7 @@ components: securitySchemes: OAuth2AuthenticationCodeFlow: type: oauth2 + x-receive-token-in: request-body flows: authorizationCode: tokenUrl: https://api-v2.fattureincloud.it/oauth/token diff --git a/openapi.yaml b/openapi.yaml index c2c907f0..1dce12b1 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -2887,22 +2887,22 @@ components: entity.suppliers:a: Write permission to the Suppliers registry products:r: Read permission to the Products products:a: Write permission to the Products - issued_documents.invoice:r: Read permission to the issued Invoices - issued_documents.credit_note:r: Read permission to the issued Credit Notes - issued_documents.receipt:r: Read permission to the issued Receipts - issued_documents.order:r: Read permission to the issued Orders - issued_documents.quote:r: Read permission to the issued Quotes - issued_documents.proforma:r: Read permission to the issued Proformas - issued_documents.delivery_note:r: Read permission to the issued Delivery Notes - issued_documents.invoice:a: Write permission to the issued Invoices - issued_documents.credit_note:a: Write permission to the issued Credit Notes - issued_documents.receipt:a: Write permission to the issued issued Receipts - issued_documents.order:a: Write permission to the issued Orders - issued_documents.quote:a: Write permission to the issued Quotes - issued_documents.proforma:a: Write permission to the issued Proformas - issued_documents.delivery_note:a: Write permission to the issued Delivery Notes - received_documents:r: Read permission to the issued Received Documents - received_documents:a: Write permission to the issued Received Documents + issued_documents.invoices:r: Read permission to the issued Invoices + issued_documents.credit_notes:r: Read permission to the issued Credit Notes + issued_documents.receipts:r: Read permission to the issued Receipts + issued_documents.orders:r: Read permission to the issued Orders + issued_documents.quotes:r: Read permission to the issued Quotes + issued_documents.proformas:r: Read permission to the issued Proformas + issued_documents.delivery_notes:r: Read permission to the issued Delivery Notes + issued_documents.invoices:a: Write permission to the issued Invoices + issued_documents.credit_notes:a: Write permission to the issued Credit Notes + issued_documents.receipts:a: Write permission to the issued issued Receipts + issued_documents.orders:a: Write permission to the issued Orders + issued_documents.quotes:a: Write permission to the issued Quotes + issued_documents.proformas:a: Write permission to the issued Proformas + issued_documents.delivery_notes:a: Write permission to the issued Delivery Notes + received_documents:r: Read permission to the Received Documents + received_documents:a: Write permission to the Received Documents stock:r: Read permission to the Stock movements stock:a: Write permission to the Stock movements receipts:r: Read permission to the Receipts diff --git a/scripts/enrich.js b/scripts/enrich.js index 1383a145..02730a79 100644 --- a/scripts/enrich.js +++ b/scripts/enrich.js @@ -99,6 +99,8 @@ function enrichFile(filePath, detailsPath) { }) }) + doc = addReceiveTokenInParam(doc) + fs.writeFileSync(filePath, yaml.dump(doc)) console.log("Done") } catch (e) { @@ -131,6 +133,18 @@ function enrichProperty(doc, path, schema) { return doc } +// Applies the following JSONata transformation: +// $ ~> | components.securitySchemes.OAuth2AuthenticationCodeFlow | {"x-receive-token-in": "request-body"} | +// It is necessary to select the proper option on RapiDOC TryIt +function addReceiveTokenInParam(doc) { + path = 'components.securitySchemes.OAuth2AuthenticationCodeFlow' + value = '{"x-receive-token-in": "request-body"}' + var transformation = `$ ~> | ${path} | ${value} | ` + var expression = jsonata(transformation); + var result = expression.evaluate(doc); + return result +} + // This function uses JSONata's transform operator to apply modifies to the selected path // https://docs.jsonata.org/other-operators#-------transform // The "path" param indicates the object that must be updated in the YAML structure diff --git a/scripts/generate-scopes.js b/scripts/generate-scopes.js new file mode 100644 index 00000000..cc090fa2 --- /dev/null +++ b/scripts/generate-scopes.js @@ -0,0 +1,55 @@ +var { Liquid } = require('liquidjs') +const yaml = require('js-yaml') +const fs = require('fs') +const path = require('path') + +const lang = process.argv[2] + +const languagesPaths = { + 'csharp-netcore': './generated/csharp-netcore/src/It.FattureInCloud.Sdk/Oauth2/Scope.cs', + 'java': './generated/java/src/main/java/it/fattureincloud/sdk/auth/Scope.java', + 'javascript': './generated/javascript/src/oauth2/Scope.js', + 'python': './generated/python/fattureincloud_python_sdk/oauth2/scopes.py', + 'php': './generated/php/lib/OAuth2/Scope.php', + 'ruby': './generated/ruby/lib/fattureincloud_ruby_sdk/oauth2/scope.rb', + 'typescript-axios': './generated/typescript-axios/src/oauth2/scope.ts' +} + +var engine = new Liquid({ + root: path.resolve(__dirname, `../templates/scopes/${lang}`), + extname: '.liquid' +}); + +function getScopesFromOpenAPI() { + const openapi = yaml.load(fs.readFileSync('openapi.yaml', 'utf8')) + var scopes = openapi.components.securitySchemes.OAuth2AuthenticationCodeFlow.flows.authorizationCode.scopes + var map = Object.entries(scopes).map(([k,v]) => { return {name: getNameFromScope(k), str: k, comment: v} }); + return map +} + +function getNameFromScope(scope) { + const scopeTypes = { + ':a': '_ALL', + ':r': '_READ' + } + var ext = scope + + Object.keys(scopeTypes).forEach(key => { + ext = ext.replace(key, scopeTypes[key]) + }) + return ext.toUpperCase().replace(".", "_") +} + +function main() { + var collection = { + scopes: getScopesFromOpenAPI() + } + + engine + .renderFile("scopes", collection) + .then((c) => { + fs.writeFileSync(languagesPaths[lang], c, 'utf8') + }) +} + +main() diff --git a/scripts/package.json b/scripts/package.json index 621ab27f..51bbba65 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -5,6 +5,7 @@ "glob": "^7.2.0", "js-yaml": "^4.1.0", "jsonata": "^1.8.6", + "liquidjs": "^9.37.0", "semver": "^7.3.5" } } diff --git a/templates/csharp-netcore/README.mustache b/templates/openapi-generator/csharp-netcore/README.mustache similarity index 100% rename from templates/csharp-netcore/README.mustache rename to templates/openapi-generator/csharp-netcore/README.mustache diff --git a/templates/csharp-netcore/modelGeneric.mustache b/templates/openapi-generator/csharp-netcore/modelGeneric.mustache similarity index 100% rename from templates/csharp-netcore/modelGeneric.mustache rename to templates/openapi-generator/csharp-netcore/modelGeneric.mustache diff --git a/templates/csharp-netcore/netcore_project.mustache b/templates/openapi-generator/csharp-netcore/netcore_project.mustache similarity index 100% rename from templates/csharp-netcore/netcore_project.mustache rename to templates/openapi-generator/csharp-netcore/netcore_project.mustache diff --git a/templates/csharp-netcore/netcore_testproject.mustache b/templates/openapi-generator/csharp-netcore/netcore_testproject.mustache similarity index 100% rename from templates/csharp-netcore/netcore_testproject.mustache rename to templates/openapi-generator/csharp-netcore/netcore_testproject.mustache diff --git a/templates/openapi-generator/java/ApiClient.mustache b/templates/openapi-generator/java/ApiClient.mustache new file mode 100644 index 00000000..b9e86e11 --- /dev/null +++ b/templates/openapi-generator/java/ApiClient.mustache @@ -0,0 +1,1502 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{#dynamicOperations}} +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum; +import io.swagger.v3.parser.OpenAPIV3Parser; +{{/dynamicOperations}} +import okhttp3.*; +import okhttp3.internal.http.HttpMethod; +import okhttp3.internal.tls.OkHostnameVerifier; +import okhttp3.logging.HttpLoggingInterceptor; +import okhttp3.logging.HttpLoggingInterceptor.Level; +import okio.Buffer; +import okio.BufferedSink; +import okio.Okio; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +{{/joda}} + +import javax.net.ssl.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Type; +import java.net.URI; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +{{/java8}} +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import {{invokerPackage}}.auth.Authentication; +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} + +/** + *

ApiClient class.

+ */ +public class ApiClient { + + private String basePath = "{{{basePath}}}"; + private boolean debugging = false; + private Map defaultHeaderMap = new HashMap(); + private Map defaultCookieMap = new HashMap(); + private String tempFolderPath = null; + + private Map authentications; + + private InputStream sslCaCert; + private boolean verifyingSsl; + private KeyManager[] keyManagers; + + private OkHttpClient httpClient; + private JSON json; + + private HttpLoggingInterceptor loggingInterceptor; + + {{#dynamicOperations}} + private Map operationLookupMap = new HashMap<>(); + + {{/dynamicOperations}} + /** + * Basic constructor for ApiClient + */ + public ApiClient() { + init(); + initHttpClient(); + + // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Basic constructor with custom OkHttpClient + * + * @param client a {@link okhttp3.OkHttpClient} object + */ + public ApiClient(OkHttpClient client) { + init(); + + httpClient = client; + + // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + + private void initHttpClient() { + initHttpClient(Collections.emptyList()); + } + + private void initHttpClient(List interceptors) { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.addNetworkInterceptor(getProgressInterceptor()); + for (Interceptor interceptor: interceptors) { + builder.addInterceptor(interceptor); + } + {{#useGzipFeature}} + // Enable gzip request compression + builder.addInterceptor(new GzipRequestInterceptor()); + {{/useGzipFeature}} + + httpClient = builder.build(); + } + + private void init() { + verifyingSsl = true; + + json = new JSON(); + + // Set default User-Agent. + setUserAgent("{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + authentications = new HashMap(); + {{#dynamicOperations}} + + OpenAPI openAPI = new OpenAPIV3Parser().read("openapi/openapi.yaml"); + createOperationLookupMap(openAPI); + {{/dynamicOperations}} + } + + /** + * Get base path + * + * @return Base path + */ + public String getBasePath() { + return basePath; + } + + /** + * Set base path + * + * @param basePath Base path of the URL (e.g {{{basePath}}} + * @return An instance of OkHttpClient + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get HTTP client + * + * @return An instance of OkHttpClient + */ + public OkHttpClient getHttpClient() { + return httpClient; + } + + /** + * Set HTTP client, which must never be null. + * + * @param newHttpClient An instance of OkHttpClient + * @return Api Client + * @throws java.lang.NullPointerException when newHttpClient is null + */ + public ApiClient setHttpClient(OkHttpClient newHttpClient) { + this.httpClient = Objects.requireNonNull(newHttpClient, "HttpClient must not be null!"); + return this; + } + + /** + * Get JSON + * + * @return JSON object + */ + public JSON getJSON() { + return json; + } + + /** + * Set JSON + * + * @param json JSON object + * @return Api client + */ + public ApiClient setJSON(JSON json) { + this.json = json; + return this; + } + + /** + * True if isVerifyingSsl flag is on + * + * @return True if isVerifySsl flag is on + */ + public boolean isVerifyingSsl() { + return verifyingSsl; + } + + /** + * Configure whether to verify certificate and hostname when making https requests. + * Default to true. + * NOTE: Do NOT set to false in production code, otherwise you would face multiple types of cryptographic attacks. + * + * @param verifyingSsl True to verify TLS/SSL connection + * @return ApiClient + */ + public ApiClient setVerifyingSsl(boolean verifyingSsl) { + this.verifyingSsl = verifyingSsl; + applySslSettings(); + return this; + } + + /** + * Get SSL CA cert. + * + * @return Input stream to the SSL CA cert + */ + public InputStream getSslCaCert() { + return sslCaCert; + } + + /** + * Configure the CA certificate to be trusted when making https requests. + * Use null to reset to default. + * + * @param sslCaCert input stream for SSL CA cert + * @return ApiClient + */ + public ApiClient setSslCaCert(InputStream sslCaCert) { + this.sslCaCert = sslCaCert; + applySslSettings(); + return this; + } + + /** + *

Getter for the field keyManagers.

+ * + * @return an array of {@link javax.net.ssl.KeyManager} objects + */ + public KeyManager[] getKeyManagers() { + return keyManagers; + } + + /** + * Configure client keys to use for authorization in an SSL session. + * Use null to reset to default. + * + * @param managers The KeyManagers to use + * @return ApiClient + */ + public ApiClient setKeyManagers(KeyManager[] managers) { + this.keyManagers = managers; + applySslSettings(); + return this; + } + + /** + *

Set LenientOnJson.

+ * + * @param lenientOnJson a boolean + * @return a {@link it.fattureincloud.sdk.ApiClient} object + */ + public ApiClient setLenientOnJson(boolean lenientOnJson) { + this.json.setLenientOnJson(lenientOnJson); + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * + * @return Map of authentication objects + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + {{#hasHttpBearerMethods}} + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + {{/hasHttpBearerMethods}} + + /** + * Helper method to set access token for the first OAuth2 authentication. + * + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + {{#hasOAuthMethods}} + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + {{/hasOAuthMethods}} + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + * + * @param userAgent HTTP request's user agent + * @return ApiClient + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + * @return ApiClient + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Add a default cookie. + * + * @param key The cookie's key + * @param value The cookie's value + * @return ApiClient + */ + public ApiClient addDefaultCookie(String key, String value) { + defaultCookieMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * + * @return True if debugging is enabled, false otherwise. + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return ApiClient + */ + public ApiClient setDebugging(boolean debugging) { + if (debugging != this.debugging) { + if (debugging) { + loggingInterceptor = new HttpLoggingInterceptor(); + loggingInterceptor.setLevel(Level.BODY); + httpClient = httpClient.newBuilder().addInterceptor(loggingInterceptor).build(); + } else { + final OkHttpClient.Builder builder = httpClient.newBuilder(); + builder.interceptors().remove(loggingInterceptor); + httpClient = builder.build(); + loggingInterceptor = null; + } + } + this.debugging = debugging; + return this; + } + + /** + * The path of temporary folder used to store downloaded files from endpoints + * with file response. The default value is null, i.e. using + * the system's default temporary folder. + * + * @see createTempFile + * @return Temporary folder path + */ + public String getTempFolderPath() { + return tempFolderPath; + } + + /** + * Set the temporary folder path (for downloading files) + * + * @param tempFolderPath Temporary folder path + * @return ApiClient + */ + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Get connection timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public int getConnectTimeout() { + return httpClient.connectTimeoutMillis(); + } + + /** + * Sets the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link java.lang.Integer#MAX_VALUE}. + * + * @param connectionTimeout connection timeout in milliseconds + * @return Api client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + httpClient = httpClient.newBuilder().connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build(); + return this; + } + + /** + * Get read timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public int getReadTimeout() { + return httpClient.readTimeoutMillis(); + } + + /** + * Sets the read timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link java.lang.Integer#MAX_VALUE}. + * + * @param readTimeout read timeout in milliseconds + * @return Api client + */ + public ApiClient setReadTimeout(int readTimeout) { + httpClient = httpClient.newBuilder().readTimeout(readTimeout, TimeUnit.MILLISECONDS).build(); + return this; + } + + /** + * Get write timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public int getWriteTimeout() { + return httpClient.writeTimeoutMillis(); + } + + /** + * Sets the write timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link java.lang.Integer#MAX_VALUE}. + * + * @param writeTimeout connection timeout in milliseconds + * @return Api client + */ + public ApiClient setWriteTimeout(int writeTimeout) { + httpClient = httpClient.newBuilder().writeTimeout(writeTimeout, TimeUnit.MILLISECONDS).build(); + return this; + } + + /** + * Format the given parameter object into string. + * + * @param param Parameter + * @return String representation of the parameter + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date {{#joda}}|| param instanceof DateTime || param instanceof LocalDate{{/joda}}{{#jsr310}}|| param instanceof OffsetDateTime || param instanceof LocalDate{{/jsr310}}) { + //Serialize to json string and remove the " enclosing characters + String jsonStr = json.serialize(param); + return jsonStr.substring(1, jsonStr.length() - 1); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for (Object o : (Collection) param) { + if (b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Formats the specified query parameter to a list containing a single {@code Pair} object. + * + * Note that {@code value} must not be a collection. + * + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list containing a single {@code Pair} object. + */ + public List parameterToPair(String name, Object value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null || value instanceof Collection) { + return params; + } + + params.add(new Pair(name, parameterToString(value))); + return params; + } + + {{^dynamicOperations}} + /** + * Formats the specified collection query parameters to a list of {@code Pair} objects. + * + * Note that the values of each of the returned Pair objects are percent-encoded. + * + * @param collectionFormat The collection format of the parameter. + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list of {@code Pair} objects. + */ + public List parameterToPairs(String collectionFormat, String name, Collection value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null || value.isEmpty()) { + return params; + } + + // create the params based on the collection format + if ("multi".equals(collectionFormat)) { + for (Object item : value) { + params.add(new Pair(name, escapeString(parameterToString(item)))); + } + return params; + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + // escape all delimiters except commas, which are URI reserved + // characters + if ("ssv".equals(collectionFormat)) { + delimiter = escapeString(" "); + } else if ("tsv".equals(collectionFormat)) { + delimiter = escapeString("\t"); + } else if ("pipes".equals(collectionFormat)) { + delimiter = escapeString("|"); + } + + StringBuilder sb = new StringBuilder(); + for (Object item : value) { + sb.append(delimiter); + sb.append(escapeString(parameterToString(item))); + } + + params.add(new Pair(name, sb.substring(delimiter.length()))); + + return params; + } + {{/dynamicOperations}} + {{#dynamicOperations}} + public List parameterToPairs(Parameter param, Collection value) { + List params = new ArrayList(); + + // preconditions + if (param == null || param.getName() == null || param.getName().isEmpty() || value == null) { + return params; + } + + // create the params based on the collection format + if (StyleEnum.FORM.equals(param.getStyle()) && Boolean.TRUE.equals(param.getExplode())) { + for (Object item : value) { + params.add(new Pair(param.getName(), escapeString(parameterToString(item)))); + } + return params; + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + // escape all delimiters except commas, which are URI reserved + // characters + if (StyleEnum.SPACEDELIMITED.equals(param.getStyle())) { + delimiter = escapeString(" "); + } else if (StyleEnum.PIPEDELIMITED.equals(param.getStyle())) { + delimiter = escapeString("|"); + } + + StringBuilder sb = new StringBuilder(); + for (Object item : value) { + sb.append(delimiter); + sb.append(escapeString(parameterToString(item))); + } + + params.add(new Pair(param.getName(), sb.substring(delimiter.length()))); + + return params; + } + {{/dynamicOperations}} + + /** + * Formats the specified collection path parameter to a string value. + * + * @param collectionFormat The collection format of the parameter. + * @param value The value of the parameter. + * @return String representation of the parameter + */ + public String collectionPathParameterToString(String collectionFormat, Collection value) { + // create the value based on the collection format + if ("multi".equals(collectionFormat)) { + // not valid for path params + return parameterToString(value); + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + if ("ssv".equals(collectionFormat)) { + delimiter = " "; + } else if ("tsv".equals(collectionFormat)) { + delimiter = "\t"; + } else if ("pipes".equals(collectionFormat)) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : value) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + return sb.substring(delimiter.length()); + } + + /** + * Sanitize filename by removing path. + * e.g. ../../sun.gif becomes sun.gif + * + * @param filename The filename to be sanitized + * @return The sanitized filename + */ + public String sanitizeFilename(String filename) { + return filename.replaceAll(".*[/\\\\]", ""); + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * "* / *" is also default to JSON + * @param mime MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * returns null. If it matches "any", JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return null; + } + + if (contentTypes[0].equals("*/*")) { + return "application/json"; + } + + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + * + * @param str String to be escaped + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Deserialize response body to Java object, according to the return type and + * the Content-Type response header. + * + * @param Type + * @param response HTTP response + * @param returnType The type of the Java object + * @return The deserialized Java object + * @throws {{invokerPackage}}.ApiException If fail to deserialize response body, i.e. cannot read response body + * or the Content-Type of the response is not supported. + */ + @SuppressWarnings("unchecked") + public T deserialize(Response response, Type returnType) throws ApiException { + if (response == null || returnType == null) { + return null; + } + + if ("byte[]".equals(returnType.toString())) { + // Handle binary response (byte array). + try { + return (T) response.body().bytes(); + } catch (IOException e) { + throw new ApiException(e); + } + } else if (returnType.equals(File.class)) { + // Handle file downloading. + return (T) downloadFileFromResponse(response); + } + + String respBody; + try { + if (response.body() != null) + respBody = response.body().string(); + else + respBody = null; + } catch (IOException e) { + throw new ApiException(e); + } + + if (respBody == null || "".equals(respBody)) { + return null; + } + + String contentType = response.headers().get("Content-Type"); + if (contentType == null) { + // ensuring a default content type + contentType = "application/json"; + } + if (isJsonMime(contentType)) { + return json.deserialize(respBody, returnType); + } else if (returnType.equals(String.class)) { + // Expecting string, return the raw response body. + return (T) respBody; + } else { + throw new ApiException( + "Content type \"" + contentType + "\" is not supported for type: " + returnType, + response.code(), + response.headers().toMultimap(), + respBody); + } + } + + /** + * Serialize the given Java object into request body according to the object's + * class and the request Content-Type. + * + * @param obj The Java object + * @param contentType The request Content-Type + * @return The serialized request body + * @throws {{invokerPackage}}.ApiException If fail to serialize the given object + */ + public RequestBody serialize(Object obj, String contentType) throws ApiException { + if (obj instanceof byte[]) { + // Binary (byte array) body parameter support. + return RequestBody.create((byte[]) obj, MediaType.parse(contentType)); + } else if (obj instanceof File) { + // File body parameter support. + return RequestBody.create((File) obj, MediaType.parse(contentType)); + } else if ("text/plain".equals(contentType) && obj instanceof String) { + return RequestBody.create((String) obj, MediaType.parse(contentType)); + } else if (isJsonMime(contentType)) { + String content; + if (obj != null) { + content = json.serialize(obj); + } else { + content = null; + } + return RequestBody.create(content, MediaType.parse(contentType)); + } else { + throw new ApiException("Content type \"" + contentType + "\" is not supported"); + } + } + + /** + * Download file from the given response. + * + * @param response An instance of the Response object + * @throws {{invokerPackage}}.ApiException If fail to read file content from response and write to disk + * @return Downloaded file + */ + public File downloadFileFromResponse(Response response) throws ApiException { + try { + File file = prepareDownloadFile(response); + BufferedSink sink = Okio.buffer(Okio.sink(file)); + sink.writeAll(response.body().source()); + sink.close(); + return file; + } catch (IOException e) { + throw new ApiException(e); + } + } + + /** + * Prepare file for download + * + * @param response An instance of the Response object + * @return Prepared file for the download + * @throws java.io.IOException If fail to prepare file for download + */ + public File prepareDownloadFile(Response response) throws IOException { + String filename = null; + String contentDisposition = response.header("Content-Disposition"); + if (contentDisposition != null && !"".equals(contentDisposition)) { + // Get filename from the Content-Disposition header. + Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + Matcher matcher = pattern.matcher(contentDisposition); + if (matcher.find()) { + filename = sanitizeFilename(matcher.group(1)); + } + } + + String prefix = null; + String suffix = null; + if (filename == null) { + prefix = "download-"; + suffix = ""; + } else { + int pos = filename.lastIndexOf("."); + if (pos == -1) { + prefix = filename + "-"; + } else { + prefix = filename.substring(0, pos) + "-"; + suffix = filename.substring(pos); + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length() < 3) + prefix = "download-"; + } + + if (tempFolderPath == null) + return Files.createTempFile(prefix, suffix).toFile(); + else + return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); + } + + /** + * {@link #execute(Call, Type)} + * + * @param Type + * @param call An instance of the Call object + * @return ApiResponse<T> + * @throws {{invokerPackage}}.ApiException If fail to execute the call + */ + public ApiResponse execute(Call call) throws ApiException { + return execute(call, null); + } + + /** + * Execute HTTP call and deserialize the HTTP response body into the given return type. + * + * @param returnType The return type used to deserialize HTTP response body + * @param The return type corresponding to (same with) returnType + * @param call Call + * @return ApiResponse object containing response status, headers and + * data, which is a Java object deserialized from response body and would be null + * when returnType is null. + * @throws {{invokerPackage}}.ApiException If fail to execute the call + */ + public ApiResponse execute(Call call, Type returnType) throws ApiException { + try { + Response response = call.execute(); + T data = handleResponse(response, returnType); + return new ApiResponse(response.code(), response.headers().toMultimap(), data); + } catch (IOException e) { + throw new ApiException(e); + } + } + + {{#supportStreaming}} + /** + *

Execute stream.

+ * + * @param call a {@link okhttp3.Call} object + * @param returnType a {@link java.lang.reflect.Type} object + * @return a {@link java.io.InputStream} object + * @throws {{invokerPackage}}.ApiException if any. + */ + public InputStream executeStream(Call call, Type returnType) throws ApiException { + try { + Response response = call.execute(); + if (!response.isSuccessful()) { + throw new ApiException(response.code(), response.message()); + } + if (response.body() == null) { + return null; + } + return response.body().byteStream(); + } catch (IOException e) { + throw new ApiException(e); + } + } + + {{/supportStreaming}} + /** + * {@link #executeAsync(Call, Type, ApiCallback)} + * + * @param Type + * @param call An instance of the Call object + * @param callback ApiCallback<T> + */ + public void executeAsync(Call call, ApiCallback callback) { + executeAsync(call, null, callback); + } + + /** + * Execute HTTP call asynchronously. + * + * @param Type + * @param call The callback to be executed when the API call finishes + * @param returnType Return type + * @param callback ApiCallback + * @see #execute(Call, Type) + */ + @SuppressWarnings("unchecked") + public void executeAsync(Call call, final Type returnType, final ApiCallback callback) { + call.enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + callback.onFailure(new ApiException(e), 0, null); + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + T result; + try { + result = (T) handleResponse(response, returnType); + } catch (ApiException e) { + callback.onFailure(e, response.code(), response.headers().toMultimap()); + return; + } catch (Exception e) { + callback.onFailure(new ApiException(e), response.code(), response.headers().toMultimap()); + return; + } + callback.onSuccess(result, response.code(), response.headers().toMultimap()); + } + }); + } + + /** + * Handle the given response, return the deserialized object when the response is successful. + * + * @param Type + * @param response Response + * @param returnType Return type + * @return Type + * @throws {{invokerPackage}}.ApiException If the response has an unsuccessful status code or + * fail to deserialize the response body + */ + public T handleResponse(Response response, Type returnType) throws ApiException { + if (response.isSuccessful()) { + if (returnType == null || response.code() == 204) { + // returning null if the returnType is not defined, + // or the status code is 204 (No Content) + if (response.body() != null) { + try { + response.body().close(); + } catch (Exception e) { + throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap()); + } + } + return null; + } else { + return deserialize(response, returnType); + } + } else { + String respBody = null; + if (response.body() != null) { + try { + respBody = response.body().string(); + } catch (IOException e) { + throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap()); + } + } + throw new ApiException(response.message(), response.code(), response.headers().toMultimap(), respBody); + } + } + + /** + * Build HTTP call with the given options. + * + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE" + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param cookieParams The cookie parameters + * @param formParams The form parameters + * @param authNames The authentications to apply + * @param callback Callback for upload/download progress + * @return The HTTP call + * @throws {{invokerPackage}}.ApiException If fail to serialize the request body object + */ + public Call buildCall(String baseUrl, String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { + Request request = buildRequest(baseUrl, path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, authNames, callback); + + return httpClient.newCall(request); + } + + /** + * Build an HTTP request with the given options. + * + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE" + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param cookieParams The cookie parameters + * @param formParams The form parameters + * @param authNames The authentications to apply + * @param callback Callback for upload/download progress + * @return The HTTP request + * @throws {{invokerPackage}}.ApiException If fail to serialize the request body object + */ + public Request buildRequest(String baseUrl, String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { + // aggregate queryParams (non-collection) and collectionQueryParams into allQueryParams + List allQueryParams = new ArrayList(queryParams); + allQueryParams.addAll(collectionQueryParams); + + final String url = buildUrl(baseUrl, path, queryParams, collectionQueryParams); + + // prepare HTTP request body + RequestBody reqBody; + String contentType = headerParams.get("Content-Type"); + + if (!HttpMethod.permitsRequestBody(method)) { + reqBody = null; + } else if ("application/x-www-form-urlencoded".equals(contentType)) { + reqBody = buildRequestBodyFormEncoding(formParams); + } else if ("multipart/form-data".equals(contentType)) { + reqBody = buildRequestBodyMultipart(formParams); + } else if (body == null) { + if ("DELETE".equals(method)) { + // allow calling DELETE without sending a request body + reqBody = null; + } else { + // use an empty request body (for POST, PUT and PATCH) + reqBody = RequestBody.create("", MediaType.parse(contentType)); + } + } else { + reqBody = serialize(body, contentType); + } + + // update parameters with authentication settings + updateParamsForAuth(authNames, allQueryParams, headerParams, cookieParams, requestBodyToString(reqBody), method, URI.create(url)); + + final Request.Builder reqBuilder = new Request.Builder().url(url); + processHeaderParams(headerParams, reqBuilder); + processCookieParams(cookieParams, reqBuilder); + + // Associate callback with request (if not null) so interceptor can + // access it when creating ProgressResponseBody + reqBuilder.tag(callback); + + Request request = null; + + if (callback != null && reqBody != null) { + ProgressRequestBody progressRequestBody = new ProgressRequestBody(reqBody, callback); + request = reqBuilder.method(method, progressRequestBody).build(); + } else { + request = reqBuilder.method(method, reqBody).build(); + } + + return request; + } + + /** + * Build full URL by concatenating base path, the given sub path and query parameters. + * + * @param path The sub path + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @return The full URL + */ + public String buildUrl(String baseUrl, String path, List queryParams, List collectionQueryParams) { + final StringBuilder url = new StringBuilder(); + if (baseUrl != null) { + url.append(baseUrl).append(path); + } else { + url.append(basePath).append(path); + } + + if (queryParams != null && !queryParams.isEmpty()) { + // support (constant) query string in `path`, e.g. "/posts?draft=1" + String prefix = path.contains("?") ? "&" : "?"; + for (Pair param : queryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + url.append(escapeString(param.getName())).append("=").append(escapeString(value)); + } + } + } + + if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) { + String prefix = url.toString().contains("?") ? "&" : "?"; + for (Pair param : collectionQueryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + // collection query parameter value already escaped as part of parameterToPairs + url.append(escapeString(param.getName())).append("=").append(value); + } + } + } + + return url.toString(); + } + + /** + * Set header parameters to the request builder, including default headers. + * + * @param headerParams Header parameters in the form of Map + * @param reqBuilder Request.Builder + */ + public void processHeaderParams(Map headerParams, Request.Builder reqBuilder) { + for (Entry param : headerParams.entrySet()) { + reqBuilder.header(param.getKey(), parameterToString(param.getValue())); + } + for (Entry header : defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(header.getKey())) { + reqBuilder.header(header.getKey(), parameterToString(header.getValue())); + } + } + } + + /** + * Set cookie parameters to the request builder, including default cookies. + * + * @param cookieParams Cookie parameters in the form of Map + * @param reqBuilder Request.Builder + */ + public void processCookieParams(Map cookieParams, Request.Builder reqBuilder) { + for (Entry param : cookieParams.entrySet()) { + reqBuilder.addHeader("Cookie", String.format("%s=%s", param.getKey(), param.getValue())); + } + for (Entry param : defaultCookieMap.entrySet()) { + if (!cookieParams.containsKey(param.getKey())) { + reqBuilder.addHeader("Cookie", String.format("%s=%s", param.getKey(), param.getValue())); + } + } + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + * @param cookieParams Map of cookie parameters + * @param payload HTTP request body + * @param method HTTP method + * @param uri URI + */ + public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, + Map cookieParams, String payload, String method, URI uri) throws ApiException { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) { + throw new RuntimeException("Authentication undefined: " + authName); + } + auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri); + } + } + + /** + * Build a form-encoding request body with the given form parameters. + * + * @param formParams Form parameters in the form of Map + * @return RequestBody + */ + public RequestBody buildRequestBodyFormEncoding(Map formParams) { + okhttp3.FormBody.Builder formBuilder = new okhttp3.FormBody.Builder(); + for (Entry param : formParams.entrySet()) { + formBuilder.add(param.getKey(), parameterToString(param.getValue())); + } + return formBuilder.build(); + } + + /** + * Build a multipart (file uploading) request body with the given form parameters, + * which could contain text fields and file fields. + * + * @param formParams Form parameters in the form of Map + * @return RequestBody + */ + public RequestBody buildRequestBodyMultipart(Map formParams) { + MultipartBody.Builder mpBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM); + for (Entry param : formParams.entrySet()) { + if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\"; filename=\"" + file.getName() + "\""); + MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file)); + mpBuilder.addPart(partHeaders, RequestBody.create(file, mediaType)); + } else { + Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\""); + mpBuilder.addPart(partHeaders, RequestBody.create(parameterToString(param.getValue()), null)); + } + } + return mpBuilder.build(); + } + + /** + * Guess Content-Type header from the given file (defaults to "application/octet-stream"). + * + * @param file The given file + * @return The guessed Content-Type + */ + public String guessContentTypeFromFile(File file) { + String contentType = URLConnection.guessContentTypeFromName(file.getName()); + if (contentType == null) { + return "application/octet-stream"; + } else { + return contentType; + } + } + + /** + * Get network interceptor to add it to the httpClient to track download progress for + * async requests. + */ + private Interceptor getProgressInterceptor() { + return new Interceptor() { + @Override + public Response intercept(Interceptor.Chain chain) throws IOException { + final Request request = chain.request(); + final Response originalResponse = chain.proceed(request); + if (request.tag() instanceof ApiCallback) { + final ApiCallback callback = (ApiCallback) request.tag(); + return originalResponse.newBuilder() + .body(new ProgressResponseBody(originalResponse.body(), callback)) + .build(); + } + return originalResponse; + } + }; + } + + /** + * Apply SSL related settings to httpClient according to the current values of + * verifyingSsl and sslCaCert. + */ + private void applySslSettings() { + try { + TrustManager[] trustManagers; + HostnameVerifier hostnameVerifier; + if (!verifyingSsl) { + trustManagers = new TrustManager[]{ + new X509TrustManager() { + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[]{}; + } + } + }; + hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + } else { + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + + if (sslCaCert == null) { + trustManagerFactory.init((KeyStore) null); + } else { + char[] password = null; // Any password will work. + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + Collection certificates = certificateFactory.generateCertificates(sslCaCert); + if (certificates.isEmpty()) { + throw new IllegalArgumentException("expected non-empty set of trusted certificates"); + } + KeyStore caKeyStore = newEmptyKeyStore(password); + int index = 0; + for (Certificate certificate : certificates) { + String certificateAlias = "ca" + Integer.toString(index++); + caKeyStore.setCertificateEntry(certificateAlias, certificate); + } + trustManagerFactory.init(caKeyStore); + } + trustManagers = trustManagerFactory.getTrustManagers(); + hostnameVerifier = OkHostnameVerifier.INSTANCE; + } + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagers, trustManagers, new SecureRandom()); + httpClient = httpClient.newBuilder() + .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0]) + .hostnameVerifier(hostnameVerifier) + .build(); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } + } + + private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException { + try { + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, password); + return keyStore; + } catch (IOException e) { + throw new AssertionError(e); + } + } + {{#dynamicOperations}} + + public ApiClient createOperationLookupMap(OpenAPI openAPI) { + operationLookupMap = new HashMap<>(); + for (Map.Entry pathItemEntry : openAPI.getPaths().entrySet()) { + String path = pathItemEntry.getKey(); + PathItem pathItem = pathItemEntry.getValue(); + addOperationLookupEntry(path, "GET", pathItem.getGet()); + addOperationLookupEntry(path, "PUT", pathItem.getPut()); + addOperationLookupEntry(path, "POST", pathItem.getPost()); + addOperationLookupEntry(path, "DELETE", pathItem.getDelete()); + addOperationLookupEntry(path, "OPTIONS", pathItem.getOptions()); + addOperationLookupEntry(path, "HEAD", pathItem.getHead()); + addOperationLookupEntry(path, "PATCH", pathItem.getPatch()); + addOperationLookupEntry(path, "TRACE", pathItem.getTrace()); + } + return this; + } + + private void addOperationLookupEntry(String path, String method, Operation operation) { + if ( operation != null && operation.getOperationId() != null) { + operationLookupMap.put( + operation.getOperationId(), + new ApiOperation(path, method, operation)); + } + } + + public Map getOperationLookupMap() { + return operationLookupMap; + } + + public String fillParametersFromOperation( + Operation operation, + Map paramMap, + String path, + List queryParams, + List collectionQueryParams, + Map headerParams, + Map cookieParams + ) { + for (Map.Entry entry : paramMap.entrySet()) { + Object value = entry.getValue(); + for (Parameter param : operation.getParameters()) { + if (entry.getKey().equals(param.getName())) { + switch (param.getIn()) { + case "path": + path = path.replaceAll("\\{" + param.getName() + "\\}", escapeString(value.toString())); + break; + case "query": + if (value instanceof Collection) { + collectionQueryParams.addAll(parameterToPairs(param, (Collection) value)); + } else { + queryParams.addAll(parameterToPair(param.getName(), value)); + } + break; + case "header": + headerParams.put(param.getName(), parameterToString(value)); + break; + case "cookie": + cookieParams.put(param.getName(), parameterToString(value)); + break; + default: + throw new IllegalStateException("Unexpected param in: " + param.getIn()); + } + + } + } + } + return path; + } + {{/dynamicOperations}} + + /** + * Convert the HTTP request body to a string. + * + * @param requestBody The HTTP request object + * @return The string representation of the HTTP request body + * @throws {{invokerPackage}}.ApiException If fail to serialize the request body object into a string + */ + private String requestBodyToString(RequestBody requestBody) throws ApiException { + if (requestBody != null) { + try { + final Buffer buffer = new Buffer(); + requestBody.writeTo(buffer); + return buffer.readUtf8(); + } catch (final IOException e) { + throw new ApiException(e); + } + } + + // empty http request body + return ""; + } +} diff --git a/templates/java/README.mustache b/templates/openapi-generator/java/README.mustache similarity index 100% rename from templates/java/README.mustache rename to templates/openapi-generator/java/README.mustache diff --git a/templates/openapi-generator/java/api.mustache b/templates/openapi-generator/java/api.mustache new file mode 100644 index 00000000..255a8173 --- /dev/null +++ b/templates/openapi-generator/java/api.mustache @@ -0,0 +1,532 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiCallback; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +{{#dynamicOperations}} +import {{invokerPackage}}.ApiOperation; +{{/dynamicOperations}} +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ProgressRequestBody; +import {{invokerPackage}}.ProgressResponseBody; +{{#performBeanValidation}} +import {{invokerPackage}}.BeanValidationException; +{{/performBeanValidation}} + +import com.google.gson.reflect.TypeToken; +{{#dynamicOperations}} +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.parameters.Parameter; +{{/dynamicOperations}} + +import java.io.IOException; + +{{#useBeanValidation}} +import javax.validation.constraints.*; +{{/useBeanValidation}} +{{#performBeanValidation}} +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; +import javax.validation.executable.ExecutableValidator; +import java.util.Set; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +{{/performBeanValidation}} + +{{#imports}}import {{import}}; +{{/imports}} + +import java.lang.reflect.Type; +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{#supportStreaming}} +import java.io.InputStream; +{{/supportStreaming}} +{{/fullJavaUtil}} + +{{#operations}} +public class {{classname}} { + private ApiClient localVarApiClient; + private int localHostIndex; + private String localCustomBaseUrl; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.localVarApiClient = apiClient; + } + + public ApiClient getApiClient() { + return localVarApiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.localVarApiClient = apiClient; + } + + public int getHostIndex() { + return localHostIndex; + } + + public void setHostIndex(int hostIndex) { + this.localHostIndex = hostIndex; + } + + public String getCustomBaseUrl() { + return localCustomBaseUrl; + } + + public void setCustomBaseUrl(String customBaseUrl) { + this.localCustomBaseUrl = customBaseUrl; + } + + {{#operation}} + {{^vendorExtensions.x-group-parameters}}/** + * Build call for {{operationId}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} + * @param _callback Callback for upload/download progress + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Response Details
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback _callback) throws ApiException { + String basePath = null; + + // Operation Servers + String[] localBasePaths = new String[] { {{#servers}}"{{{url}}}"{{^-last}}, {{/-last}}{{/servers}} }; + + // Determine Base Path to Use + if (localCustomBaseUrl != null){ + basePath = localCustomBaseUrl; + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[localHostIndex]; + } else { + basePath = null; + } + + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + + // create path and map variables + {{^dynamicOperations}} + String localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", localVarApiClient.escapeString({{#collectionFormat}}localVarApiClient.collectionPathParameterToString("{{{collectionFormat}}}", {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}.toString(){{/collectionFormat}})){{/pathParams}}; + {{/dynamicOperations}} + {{#dynamicOperations}} + ApiOperation apiOperation = localVarApiClient.getOperationLookupMap().get("{{{operationId}}}"); + if (apiOperation == null) { + throw new ApiException("Operation not found in OAS"); + } + Operation operation = apiOperation.getOperation(); + String localVarPath = apiOperation.getPath(); + Map paramMap = new HashMap<>(); + {{#allParams}} + {{^isFormParam}} + {{^isBodyParam}} + paramMap.put("{{baseName}}", {{paramName}}); + {{/isBodyParam}} + {{/isFormParam}} + {{/allParams}} + {{/dynamicOperations}} + + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#formParams}} + if ({{paramName}} != null) { + localVarFormParams.put("{{baseName}}", {{paramName}}); + } + + {{/formParams}} + {{^dynamicOperations}} + {{#queryParams}} + if ({{paramName}} != null) { + {{#collectionFormat}}localVarCollectionQueryParams.addAll(localVarApiClient.parameterToPairs("{{{.}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(localVarApiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + } + + {{/queryParams}} + {{#headerParams}} + if ({{paramName}} != null) { + localVarHeaderParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}})); + } + + {{/headerParams}} + {{#cookieParams}} + if ({{paramName}} != null) { + localVarCookieParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}})); + } + + {{/cookieParams}} + {{/dynamicOperations}} + {{#dynamicOperations}} + localVarPath = localVarApiClient.fillParametersFromOperation(operation, paramMap, localVarPath, localVarQueryParams, localVarCollectionQueryParams, localVarHeaderParams, localVarCookieParams); + + {{/dynamicOperations}} + final String[] localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + return localVarApiClient.buildCall(basePath, localVarPath, {{^dynamicOperations}}"{{httpMethod}}"{{/dynamicOperations}}{{#dynamicOperations}}apiOperation.getMethod(){{/dynamicOperations}}, localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + @SuppressWarnings("rawtypes") + private okhttp3.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback _callback) throws ApiException { + {{^performBeanValidation}} + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException("Missing the required parameter '{{paramName}}' when calling {{operationId}}(Async)"); + } + {{/required}}{{/allParams}} + + okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); + return localVarCall; + + {{/performBeanValidation}} + {{#performBeanValidation}} + try { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + ExecutableValidator executableValidator = factory.getValidator().forExecutables(); + + Object[] parameterValues = { {{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}} }; + Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isArray}}java.util.List{{/isArray}}{{#isMap}}java.util.Map{{/isMap}}{{^isArray}}{{^isMap}}{{{dataType}}}{{/isMap}}{{/isArray}}.class{{/allParams}}); + Set> violations = executableValidator.validateParameters(this, method, + parameterValues); + + if (violations.size() == 0) { + okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); + return localVarCall; + + } else { + throw new BeanValidationException((Set) violations); + } + } catch (NoSuchMethodException e) { + e.printStackTrace(); + throw new ApiException(e.getMessage()); + } catch (SecurityException e) { + e.printStackTrace(); + throw new ApiException(e.getMessage()); + } + + {{/performBeanValidation}} + } + + {{^vendorExtensions.x-group-parameters}} + /** + * {{summary}} + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}}{{#returnType}} + * @return {{.}}{{/returnType}} + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Response Details
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + {{#vendorExtensions.x-streaming}} + public {{#returnType}}InputStream {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#returnType}}InputStream localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} + return localVarResp;{{/returnType}} + } + {{/vendorExtensions.x-streaming}} + {{^vendorExtensions.x-streaming}} + public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#returnType}}ApiResponse<{{{.}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} + return localVarResp.getData();{{/returnType}} + } + {{/vendorExtensions.x-streaming}} + {{/vendorExtensions.x-group-parameters}} + + {{^vendorExtensions.x-group-parameters}}/** + * {{summary}} + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} + * @return ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Response Details
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-streaming}} InputStream {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null); + {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + return localVarApiClient.executeStream(localVarCall, localVarReturnType);{{/returnType}} + } + {{/vendorExtensions.x-streaming}}{{^vendorExtensions.x-streaming}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null); + {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType);{{/returnType}}{{^returnType}}return localVarApiClient.execute(localVarCall);{{/returnType}} + } + {{/vendorExtensions.x-streaming}} + + {{^vendorExtensions.x-group-parameters}}/** + * {{summary}} (asynchronously) + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} + * @param _callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Response Details
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{{returnType}}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException { + + okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}_callback); + {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback);{{/returnType}}{{^returnType}}localVarApiClient.executeAsync(localVarCall, _callback);{{/returnType}} + return localVarCall; + } + {{#vendorExtensions.x-group-parameters}} + + public class API{{operationId}}Request { + {{#requiredParams}} + private final {{{dataType}}} {{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{paramName}}; + {{/optionalParams}} + + private API{{operationId}}Request({{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}) { + {{#requiredParams}} + this.{{paramName}} = {{paramName}}; + {{/requiredParams}} + } + + {{#optionalParams}} + /** + * Set {{paramName}} + * @param {{paramName}} {{description}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}) + * @return API{{operationId}}Request + */ + public API{{operationId}}Request {{paramName}}({{{dataType}}} {{paramName}}) { + this.{{paramName}} = {{paramName}}; + return this; + } + + {{/optionalParams}} + /** + * Build call for {{operationId}} + * @param _callback ApiCallback API callback + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public okhttp3.Call buildCall(final ApiCallback _callback) throws ApiException { + return {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); + } + + /** + * Execute {{operationId}} request{{#returnType}} + * @return {{.}}{{/returnType}} + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{{returnType}}}{{^returnType}}void{{/returnType}} execute() throws ApiException { + {{#returnType}}ApiResponse<{{{.}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} + return localVarResp.getData();{{/returnType}} + } + + /** + * Execute {{operationId}} request with HTTP info returned + * @return ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + + /** + * Execute {{operationId}} request (asynchronously) + * @param _callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public okhttp3.Call executeAsync(final ApiCallback<{{{returnType}}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException { + return {{operationId}}Async({{#allParams}}{{paramName}}, {{/allParams}}_callback); + } + } + + /** + * {{summary}} + * {{notes}}{{#requiredParams}} + * @param {{paramName}} {{description}} (required){{/requiredParams}} + * @return API{{operationId}}Request + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Response Details
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public API{{operationId}}Request {{operationId}}({{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}) { + return new API{{operationId}}Request({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}); + } + {{/vendorExtensions.x-group-parameters}} + {{/operation}} +} +{{/operations}} diff --git a/templates/java/api_doc.mustache b/templates/openapi-generator/java/api_doc.mustache similarity index 100% rename from templates/java/api_doc.mustache rename to templates/openapi-generator/java/api_doc.mustache diff --git a/templates/java/build.gradle.mustache b/templates/openapi-generator/java/build.gradle.mustache similarity index 89% rename from templates/java/build.gradle.mustache rename to templates/openapi-generator/java/build.gradle.mustache index 07e4e898..c90a6fa4 100644 --- a/templates/java/build.gradle.mustache +++ b/templates/openapi-generator/java/build.gradle.mustache @@ -19,32 +19,28 @@ repositories { } dependencies { - implementation 'io.swagger:swagger-annotations:1.5.24' + implementation 'io.swagger:swagger-annotations:1.6.6' implementation "com.google.code.findbugs:jsr305:3.0.2" - implementation 'com.squareup.okhttp3:okhttp:4.9.1' - implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1' - implementation 'com.google.code.gson:gson:2.8.6' - implementation 'io.gsonfire:gson-fire:1.8.4' + implementation 'com.squareup.okhttp3:okhttp:4.9.3' + implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3' + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'io.gsonfire:gson-fire:1.8.5' {{#openApiNullable}} implementation 'org.openapitools:jackson-databind-nullable:0.2.2' {{/openApiNullable}} - {{#hasOAuthMethods}} - implementation group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' - {{/hasOAuthMethods}} implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' {{#joda}} implementation 'joda-time:joda-time:2.9.9' {{/joda}} - {{#threetenbp}} - implementation 'org.threeten:threetenbp:1.4.3' - {{/threetenbp}} {{#dynamicOperations}} implementation 'io.swagger.parser.v3:swagger-parser-v3:2.0.23' {{/dynamicOperations}} - implementation "jakarta.annotation:jakarta.annotation-api:1.3.5" + implementation 'jakarta.annotation:jakarta.annotation-api:1.3.5' + implementation "io.vavr:vavr:0.10.4" testImplementation(platform('org.junit:junit-bom:5.8.2')) testImplementation('org.junit.jupiter:junit-jupiter:5.8.2') - testImplementation 'org.mockito:mockito-core:4.1.0' + testImplementation 'org.mockito:mockito-core:4.5.1' + testImplementation 'com.squareup.okhttp3:mockwebserver:4.9.3' } publishing { diff --git a/templates/openapi-generator/java/build.sbt.mustache b/templates/openapi-generator/java/build.sbt.mustache new file mode 100644 index 00000000..60351447 --- /dev/null +++ b/templates/openapi-generator/java/build.sbt.mustache @@ -0,0 +1,35 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.6.6", + "com.squareup.okhttp3" % "okhttp" % "4.9.3", + "com.squareup.okhttp3" % "logging-interceptor" % "4.9.3", + "com.google.code.gson" % "gson" % "2.9.0", + "org.apache.commons" % "commons-lang3" % "3.10", + {{#openApiNullable}} + "org.openapitools" % "jackson-databind-nullable" % "0.2.2", + {{/openApiNullable}} + "io.vavr" % "vavr" % "0.10.4", + {{#joda}} + "joda-time" % "joda-time" % "2.9.9" % "compile", + {{/joda}} + {{#dynamicOperations}} + "io.swagger.parser.v3" % "swagger-parser-v3" "2.0.23" % "compile" + {{/dynamicOperations}} + "io.gsonfire" % "gson-fire" % "1.8.5" % "compile", + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", + "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", + "junit" % "junit" % "4.13.1" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + "com.squareup.okhttp3" % "mockwebserver" % "4.9.3" % "test" + ) + ) diff --git a/templates/openapi-generator/java/pom.mustache b/templates/openapi-generator/java/pom.mustache new file mode 100644 index 00000000..4f7be54a --- /dev/null +++ b/templates/openapi-generator/java/pom.mustache @@ -0,0 +1,416 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + true + 128m + 512m + + -Xlint:all + -J-Xss4m + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + 10 + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + test-jar + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + add_sources + generate-sources + + add-source + + + + {{{sourceFolder}}} + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.3.1 + + + attach-javadocs + + jar + + + + + none + + + http.response.details + a + Http Response Details: + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + + attach-sources + + jar-no-fork + + + + + + + com.diffplug.spotless + spotless-maven-plugin + ${spotless.version} + + + + + + + .gitignore + + + + + + true + 4 + + + + + + + + + + 1.8 + + true + + + + + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + + org.junit + junit-bom + ${junit-version} + pom + import + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + com.squareup.okhttp3 + okhttp + ${okhttp-version} + + + com.squareup.okhttp3 + logging-interceptor + ${okhttp-version} + + + com.google.code.gson + gson + ${gson-version} + + + io.gsonfire + gson-fire + ${gson-fire-version} + + + io.vavr + vavr + 0.10.4 + + + org.apache.commons + commons-lang3 + ${commons-lang3-version} + + {{#joda}} + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#dynamicOperations}} + + io.swagger.parser.v3 + swagger-parser-v3 + 2.0.28 + + {{/dynamicOperations}} + {{#useBeanValidation}} + + + jakarta.validation + jakarta.validation-api + ${beanvalidation-version} + provided + + {{/useBeanValidation}} + {{#performBeanValidation}} + + + org.hibernate + hibernate-validator + 5.4.3.Final + + + jakarta.el + jakarta.el-api + ${jakarta.el-version} + + {{/performBeanValidation}} + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} + + + org.junit.jupiter + junit-jupiter + ${junit-version} + test + + + org.mockito + mockito-core + 4.5.1 + test + + + com.squareup.okhttp3 + mockwebserver + 4.9.3 + test + + + + 1.8 + ${java.version} + ${java.version} + 1.8.5 + 1.6.6 + 4.9.3 + 2.9.0 + 3.12.0 + {{#openApiNullable}} + 0.2.2 + {{/openApiNullable}} + {{#joda}} + 2.10.9 + {{/joda}} + 1.3.5 +{{#performBeanValidation}} + 3.0.3 +{{/performBeanValidation}} +{{#useBeanValidation}} + 2.0.2 +{{/useBeanValidation}} + 5.8.2 + UTF-8 + 2.17.3 + + diff --git a/templates/javascript/README.mustache b/templates/openapi-generator/javascript/README.mustache similarity index 100% rename from templates/javascript/README.mustache rename to templates/openapi-generator/javascript/README.mustache diff --git a/templates/javascript/api_doc.mustache b/templates/openapi-generator/javascript/api_doc.mustache similarity index 100% rename from templates/javascript/api_doc.mustache rename to templates/openapi-generator/javascript/api_doc.mustache diff --git a/templates/javascript/index.mustache b/templates/openapi-generator/javascript/index.mustache similarity index 62% rename from templates/javascript/index.mustache rename to templates/openapi-generator/javascript/index.mustache index 10039bf7..9c2176c4 100644 --- a/templates/javascript/index.mustache +++ b/templates/openapi-generator/javascript/index.mustache @@ -12,6 +12,11 @@ import Conjunction from './filter/Conjunction'; import Disjunction from './filter/Disjunction'; import Operator from './filter/Operator'; +import OAuth2AuthorizationCodeManager from './oauth2/OAuth2'; +import OAuth2AuthorizationCodeTokenResponse from './oauth2/OAuth2AuthorizationCodeTokenResponse'; +import OAuth2AuthorizationCodeParams from './oauth2/OAuth2AuthorizationCodeParams'; +import Scope from './oauth2/Scope'; + {{#emitJSDoc}}/**{{#projectDescription}} * {{.}}.
{{/projectDescription}} @@ -63,4 +68,65 @@ export { * @property {module:<#invokerPackage>/<#apiPackage>/} */ + + /** + * The Condition service constructor. + * @property {module:filter/Condition} + */ + Condition, + + /** + * The Conjunction service constructor. + * @property {module:filter/Conjunction} + */ + Conjunction, + + /** + * The Disjunction service constructor. + * @property {module:filter/Disjunction} + */ + Disjunction, + + /** + * The Expression service constructor. + * @property {module:filter/Expression} + */ + Expression, + + /** + * The Filter service constructor. + * @property {module:filter/Filter} + */ + Filter, + + /** + * The Operator service constructor. + * @property {module:api/Operator} + */ + Operator, + + /** + * The OAuth2AuthorizationCodeManager service constructor. + * @property {module:api/OAuth2AuthorizationCodeManager} + */ + OAuth2AuthorizationCodeManager, + + /** + * The Scope service constructor. + * @property {module:api/Scope} + */ + Scope, + + /** + * The OAuth2AuthorizationCodeTokenResponse service constructor. + * @property {module:api/OAuth2AuthorizationCodeTokenResponse} + */ + OAuth2AuthorizationCodeTokenResponse, + + /** + * The OAuth2AuthorizationCodeParams service constructor. + * @property {module:api/OAuth2AuthorizationCodeParams} + */ + OAuth2AuthorizationCodeParams + };<={{ }}=> diff --git a/templates/javascript/package.mustache b/templates/openapi-generator/javascript/package.mustache similarity index 92% rename from templates/javascript/package.mustache rename to templates/openapi-generator/javascript/package.mustache index 2e7d9b1b..ea489bf8 100644 --- a/templates/javascript/package.mustache +++ b/templates/openapi-generator/javascript/package.mustache @@ -44,7 +44,10 @@ "expect.js": "^0.3.1", "mocha": "^8.0.1", "sinon": "^7.2.0", - "nyc": "^15.1.0" + "nyc": "^15.1.0", + "eslint": "^8.14.0", + "eslint-config-standard": "^17.0.0", + "eslint-plugin-unused-imports": "^2.0.0" }, "files": [ "dist" diff --git a/templates/php/README.mustache b/templates/openapi-generator/php/README.mustache similarity index 100% rename from templates/php/README.mustache rename to templates/openapi-generator/php/README.mustache diff --git a/templates/php/api_doc.mustache b/templates/openapi-generator/php/api_doc.mustache similarity index 100% rename from templates/php/api_doc.mustache rename to templates/openapi-generator/php/api_doc.mustache diff --git a/templates/php/composer.mustache b/templates/openapi-generator/php/composer.mustache similarity index 100% rename from templates/php/composer.mustache rename to templates/openapi-generator/php/composer.mustache diff --git a/templates/openapi-generator/php/model_generic.mustache b/templates/openapi-generator/php/model_generic.mustache new file mode 100644 index 00000000..11e402e0 --- /dev/null +++ b/templates/openapi-generator/php/model_generic.mustache @@ -0,0 +1,454 @@ +class {{classname}} {{#parentSchema}}extends {{{parent}}}{{/parentSchema}}{{^parentSchema}}implements ModelInterface, ArrayAccess, \JsonSerializable{{/parentSchema}} +{ + public const DISCRIMINATOR = {{#discriminator}}'{{discriminatorName}}'{{/discriminator}}{{^discriminator}}null{{/discriminator}}; + + /** + * The original name of the model. + * + * @var string + */ + protected static $openAPIModelName = '{{name}}'; + + /** + * Array of property to type mappings. Used for (de)serialization + * + * @var string[] + */ + protected static $openAPITypes = [ + {{#vars}}'{{name}}' => '{{{dataType}}}'{{^-last}}, + {{/-last}}{{/vars}} + ]; + + /** + * Array of property to format mappings. Used for (de)serialization + * + * @var string[] + * @phpstan-var array + * @psalm-var array + */ + protected static $openAPIFormats = [ + {{#vars}}'{{name}}' => {{#dataFormat}}'{{{.}}}'{{/dataFormat}}{{^dataFormat}}null{{/dataFormat}}{{^-last}}, + {{/-last}}{{/vars}} + ]; + + /** + * Array of property to type mappings. Used for (de)serialization + * + * @return array + */ + public static function openAPITypes() + { + return self::$openAPITypes{{#parentSchema}} + parent::openAPITypes(){{/parentSchema}}; + } + + /** + * Array of property to format mappings. Used for (de)serialization + * + * @return array + */ + public static function openAPIFormats() + { + return self::$openAPIFormats{{#parentSchema}} + parent::openAPIFormats(){{/parentSchema}}; + } + + /** + * Array of attributes where the key is the local name, + * and the value is the original name + * + * @var string[] + */ + protected static $attributeMap = [ + {{#vars}}'{{name}}' => '{{baseName}}'{{^-last}}, + {{/-last}}{{/vars}} + ]; + + /** + * Array of attributes to setter functions (for deserialization of responses) + * + * @var string[] + */ + protected static $setters = [ + {{#vars}}'{{name}}' => '{{setter}}'{{^-last}}, + {{/-last}}{{/vars}} + ]; + + /** + * Array of attributes to getter functions (for serialization of requests) + * + * @var string[] + */ + protected static $getters = [ + {{#vars}}'{{name}}' => '{{getter}}'{{^-last}}, + {{/-last}}{{/vars}} + ]; + + /** + * Array of attributes where the key is the local name, + * and the value is the original name + * + * @return array + */ + public static function attributeMap() + { + return {{#parentSchema}}parent::attributeMap() + {{/parentSchema}}self::$attributeMap; + } + + /** + * Array of attributes to setter functions (for deserialization of responses) + * + * @return array + */ + public static function setters() + { + return {{#parentSchema}}parent::setters() + {{/parentSchema}}self::$setters; + } + + /** + * Array of attributes to getter functions (for serialization of requests) + * + * @return array + */ + public static function getters() + { + return {{#parentSchema}}parent::getters() + {{/parentSchema}}self::$getters; + } + + /** + * The original name of the model. + * + * @return string + */ + public function getModelName() + { + return self::$openAPIModelName; + } + + {{#vars}} + {{#isEnum}} + {{#allowableValues}} + {{#enumVars}} + const {{enumName}}_{{{name}}} = {{{value}}}; + {{/enumVars}} + {{/allowableValues}} + {{/isEnum}} + {{/vars}} + + {{#vars}} + {{#isEnum}} + /** + * Gets allowable values of the enum + * + * @return string[] + */ + public function {{getter}}AllowableValues() + { + return [ + {{#allowableValues}}{{#enumVars}}self::{{enumName}}_{{{name}}},{{^-last}} + {{/-last}}{{/enumVars}}{{/allowableValues}} + ]; + } + + {{/isEnum}} + {{/vars}} + {{^parentSchema}} + /** + * Associative array for storing property values + * + * @var mixed[] + */ + protected $container = []; + {{/parentSchema}} + + /** + * Constructor + * + * @param mixed[] $data Associated array of property values + * initializing the model + */ + public function __construct(array $data = null) + { + {{#parentSchema}} + parent::__construct($data); + + {{/parentSchema}} + {{#vars}} + $this->container['{{name}}'] = $data['{{name}}'] ?? {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}}; + {{/vars}} + {{#discriminator}} + + // Initialize discriminator property with the model name. + $this->container['{{discriminatorName}}'] = static::$openAPIModelName; + {{/discriminator}} + } + + /** + * Show all the invalid properties with reasons. + * + * @return array invalid properties with reasons + */ + public function listInvalidProperties() + { + {{#parentSchema}} + $invalidProperties = parent::listInvalidProperties(); + {{/parentSchema}} + {{^parentSchema}} + $invalidProperties = []; + {{/parentSchema}} + + {{#vars}} + {{#required}} + if ($this->container['{{name}}'] === null) { + $invalidProperties[] = "'{{name}}' can't be null"; + } + {{/required}} + {{#isEnum}} + {{^isContainer}} + $allowedValues = $this->{{getter}}AllowableValues(); + if (!is_null($this->container['{{name}}']) && !in_array($this->container['{{name}}'], $allowedValues, true)) { + $invalidProperties[] = sprintf( + "invalid value '%s' for '{{name}}', must be one of '%s'", + $this->container['{{name}}'], + implode("', '", $allowedValues) + ); + } + + {{/isContainer}} + {{/isEnum}} + {{#hasValidation}} + {{#maxLength}} + if ({{^required}}!is_null($this->container['{{name}}']) && {{/required}}(mb_strlen($this->container['{{name}}']) > {{maxLength}})) { + $invalidProperties[] = "invalid value for '{{name}}', the character length must be smaller than or equal to {{{maxLength}}}."; + } + + {{/maxLength}} + {{#minLength}} + if ({{^required}}!is_null($this->container['{{name}}']) && {{/required}}(mb_strlen($this->container['{{name}}']) < {{minLength}})) { + $invalidProperties[] = "invalid value for '{{name}}', the character length must be bigger than or equal to {{{minLength}}}."; + } + + {{/minLength}} + {{#maximum}} + if ({{^required}}!is_null($this->container['{{name}}']) && {{/required}}($this->container['{{name}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}})) { + $invalidProperties[] = "invalid value for '{{name}}', must be smaller than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}{{maximum}}."; + } + + {{/maximum}} + {{#minimum}} + if ({{^required}}!is_null($this->container['{{name}}']) && {{/required}}($this->container['{{name}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}})) { + $invalidProperties[] = "invalid value for '{{name}}', must be bigger than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}{{minimum}}."; + } + + {{/minimum}} + {{#pattern}} + if ({{^required}}!is_null($this->container['{{name}}']) && {{/required}}!preg_match("{{{pattern}}}", $this->container['{{name}}'])) { + $invalidProperties[] = "invalid value for '{{name}}', must be conform to the pattern {{{pattern}}}."; + } + + {{/pattern}} + {{#maxItems}} + if ({{^required}}!is_null($this->container['{{name}}']) && {{/required}}(count($this->container['{{name}}']) > {{maxItems}})) { + $invalidProperties[] = "invalid value for '{{name}}', number of items must be less than or equal to {{{maxItems}}}."; + } + + {{/maxItems}} + {{#minItems}} + if ({{^required}}!is_null($this->container['{{name}}']) && {{/required}}(count($this->container['{{name}}']) < {{minItems}})) { + $invalidProperties[] = "invalid value for '{{name}}', number of items must be greater than or equal to {{{minItems}}}."; + } + + {{/minItems}} + {{/hasValidation}} + {{/vars}} + return $invalidProperties; + } + + /** + * Validate all the properties in the model + * return true if all passed + * + * @return bool True if all properties are valid + */ + public function valid() + { + return count($this->listInvalidProperties()) === 0; + } + + {{#vars}} + + /** + * Gets {{name}} + * + * @return {{#allowableValues}}string{{/allowableValues}}{{^allowableValues}}{{{dataType}}}{{/allowableValues}}{{^required}}|null{{/required}} + {{#deprecated}} + * @deprecated + {{/deprecated}} + */ + public function {{getter}}() + { + return $this->container['{{name}}']; + } + + /** + * Sets {{name}}{{#allowableValues}}, the accepted values are available in {{dataType}}{{/allowableValues}} + * + * @param {{#allowableValues}}string{{/allowableValues}}{{^allowableValues}}{{{dataType}}}{{/allowableValues}}{{^required}}|null{{/required}} ${{name}}{{#description}} {{{.}}}{{/description}}{{^description}} {{{name}}}{{/description}} + * + * @return self + {{#deprecated}} + * @deprecated + {{/deprecated}} + */ + public function {{setter}}(${{name}}) + { + {{#isEnum}} + $allowedValues = $this->{{getter}}AllowableValues(); + {{^isContainer}} + if ({{^required}}!is_null(${{name}}) && {{/required}}!in_array(${{{name}}}, $allowedValues, true)) { + throw new \InvalidArgumentException( + sprintf( + "Invalid value '%s' for '{{name}}', must be one of '%s'", + ${{{name}}}, + implode("', '", $allowedValues) + ) + ); + } + {{/isContainer}} + {{#isContainer}} + if ({{^required}}!is_null(${{name}}) && {{/required}}array_diff(${{{name}}}, $allowedValues)) { + throw new \InvalidArgumentException( + sprintf( + "Invalid value for '{{name}}', must be one of '%s'", + implode("', '", $allowedValues) + ) + ); + } + {{/isContainer}} + {{/isEnum}} + {{#hasValidation}} + {{#maxLength}} + if ({{^required}}!is_null(${{name}}) && {{/required}}(mb_strlen(${{name}}) > {{maxLength}})) { + throw new \InvalidArgumentException('invalid length for ${{name}} when calling {{classname}}.{{operationId}}, must be smaller than or equal to {{maxLength}}.'); + }{{/maxLength}} + {{#minLength}} + if ({{^required}}!is_null(${{name}}) && {{/required}}(mb_strlen(${{name}}) < {{minLength}})) { + throw new \InvalidArgumentException('invalid length for ${{name}} when calling {{classname}}.{{operationId}}, must be bigger than or equal to {{minLength}}.'); + } + {{/minLength}} + {{#maximum}} + if ({{^required}}!is_null(${{name}}) && {{/required}}(${{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}})) { + throw new \InvalidArgumentException('invalid value for ${{name}} when calling {{classname}}.{{operationId}}, must be smaller than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}{{maximum}}.'); + } + {{/maximum}} + {{#minimum}} + if ({{^required}}!is_null(${{name}}) && {{/required}}(${{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}})) { + throw new \InvalidArgumentException('invalid value for ${{name}} when calling {{classname}}.{{operationId}}, must be bigger than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}{{minimum}}.'); + } + {{/minimum}} + {{#pattern}} + if ({{^required}}!is_null(${{name}}) && {{/required}}(!preg_match("{{{pattern}}}", ${{name}}))) { + throw new \InvalidArgumentException("invalid value for ${{name}} when calling {{classname}}.{{operationId}}, must conform to the pattern {{{pattern}}}."); + } + {{/pattern}} + {{#maxItems}} + if ({{^required}}!is_null(${{name}}) && {{/required}}(count(${{name}}) > {{maxItems}})) { + throw new \InvalidArgumentException('invalid value for ${{name}} when calling {{classname}}.{{operationId}}, number of items must be less than or equal to {{maxItems}}.'); + }{{/maxItems}} + {{#minItems}} + if ({{^required}}!is_null(${{name}}) && {{/required}}(count(${{name}}) < {{minItems}})) { + throw new \InvalidArgumentException('invalid length for ${{name}} when calling {{classname}}.{{operationId}}, number of items must be greater than or equal to {{minItems}}.'); + } + {{/minItems}} + {{/hasValidation}} + $this->container['{{name}}'] = ${{name}}; + + return $this; + } + {{/vars}} + /** + * Returns true if offset exists. False otherwise. + * + * @param integer $offset Offset + * + * @return boolean + */ + public function offsetExists($offset) + { + return isset($this->container[$offset]); + } + + /** + * Gets offset. + * + * @param integer $offset Offset + * + * @return mixed|null + */ + public function offsetGet($offset) + { + return $this->container[$offset] ?? null; + } + + /** + * Sets value based on offset. + * + * @param int|null $offset Offset + * @param mixed $value Value to be set + * + * @return void + */ + public function offsetSet($offset, $value) + { + if (is_null($offset)) { + $this->container[] = $value; + } else { + $this->container[$offset] = $value; + } + } + + /** + * Unsets offset. + * + * @param integer $offset Offset + * + * @return void + */ + public function offsetUnset($offset) + { + unset($this->container[$offset]); + } + + /** + * Serializes the object to a value that can be serialized natively by json_encode(). + * @link https://www.php.net/manual/en/jsonserializable.jsonserialize.php + * + * @return mixed Returns data which can be serialized by json_encode(), which is a value + * of any type other than a resource. + */ + public function jsonSerialize() + { + return ObjectSerializer::sanitizeForSerialization($this); + } + + /** + * Gets the string presentation of the object + * + * @return string + */ + public function __toString() + { + return json_encode( + ObjectSerializer::sanitizeForSerialization($this), + JSON_PRETTY_PRINT + ); + } + + /** + * Gets a header-safe presentation of the object + * + * @return string + */ + public function toHeaderValue() + { + return json_encode(ObjectSerializer::sanitizeForSerialization($this)); + } +} diff --git a/templates/php/phpunit.xml.mustache b/templates/openapi-generator/php/phpunit.xml.mustache similarity index 100% rename from templates/php/phpunit.xml.mustache rename to templates/openapi-generator/php/phpunit.xml.mustache diff --git a/templates/python/README.mustache b/templates/openapi-generator/python/README.mustache similarity index 100% rename from templates/python/README.mustache rename to templates/openapi-generator/python/README.mustache diff --git a/templates/python/README_common.mustache b/templates/openapi-generator/python/README_common.mustache similarity index 100% rename from templates/python/README_common.mustache rename to templates/openapi-generator/python/README_common.mustache diff --git a/templates/python/model_templates/classvars.mustache b/templates/openapi-generator/python/model_templates/classvars.mustache similarity index 100% rename from templates/python/model_templates/classvars.mustache rename to templates/openapi-generator/python/model_templates/classvars.mustache diff --git a/templates/python/python_doc_auth_partial.mustache b/templates/openapi-generator/python/python_doc_auth_partial.mustache similarity index 100% rename from templates/python/python_doc_auth_partial.mustache rename to templates/openapi-generator/python/python_doc_auth_partial.mustache diff --git a/templates/python/requirements.mustache b/templates/openapi-generator/python/requirements.mustache similarity index 100% rename from templates/python/requirements.mustache rename to templates/openapi-generator/python/requirements.mustache diff --git a/templates/python/setup.mustache b/templates/openapi-generator/python/setup.mustache similarity index 100% rename from templates/python/setup.mustache rename to templates/openapi-generator/python/setup.mustache diff --git a/templates/ruby/README.mustache b/templates/openapi-generator/ruby/README.mustache similarity index 100% rename from templates/ruby/README.mustache rename to templates/openapi-generator/ruby/README.mustache diff --git a/templates/ruby/base_object.mustache b/templates/openapi-generator/ruby/base_object.mustache similarity index 100% rename from templates/ruby/base_object.mustache rename to templates/openapi-generator/ruby/base_object.mustache diff --git a/templates/ruby/gem.mustache b/templates/openapi-generator/ruby/gem.mustache similarity index 92% rename from templates/ruby/gem.mustache rename to templates/openapi-generator/ruby/gem.mustache index c3e20b9f..fef6aa60 100644 --- a/templates/ruby/gem.mustache +++ b/templates/openapi-generator/ruby/gem.mustache @@ -39,6 +39,10 @@ require 'fattureincloud_ruby_sdk/filter/disjunction' require 'fattureincloud_ruby_sdk/filter/filter' require 'fattureincloud_ruby_sdk/filter/expression' +#oauth +require 'fattureincloud_ruby_sdk/oauth2/oauth2' +require 'fattureincloud_ruby_sdk/oauth2/scope' + module {{moduleName}} class << self # Customize default settings for the SDK using block. diff --git a/templates/ruby/partial_model_generic_doc.mustache b/templates/openapi-generator/ruby/partial_model_generic_doc.mustache similarity index 100% rename from templates/ruby/partial_model_generic_doc.mustache rename to templates/openapi-generator/ruby/partial_model_generic_doc.mustache diff --git a/templates/typescript-axios-docs/api_doc.mustache b/templates/openapi-generator/typescript-axios-docs/api_doc.mustache similarity index 100% rename from templates/typescript-axios-docs/api_doc.mustache rename to templates/openapi-generator/typescript-axios-docs/api_doc.mustache diff --git a/templates/typescript-axios-docs/model_doc.mustache b/templates/openapi-generator/typescript-axios-docs/model_doc.mustache similarity index 100% rename from templates/typescript-axios-docs/model_doc.mustache rename to templates/openapi-generator/typescript-axios-docs/model_doc.mustache diff --git a/templates/typescript-axios/README.mustache b/templates/openapi-generator/typescript-axios/README.mustache similarity index 100% rename from templates/typescript-axios/README.mustache rename to templates/openapi-generator/typescript-axios/README.mustache diff --git a/templates/typescript-axios/apiInner.mustache b/templates/openapi-generator/typescript-axios/apiInner.mustache similarity index 100% rename from templates/typescript-axios/apiInner.mustache rename to templates/openapi-generator/typescript-axios/apiInner.mustache diff --git a/templates/openapi-generator/typescript-axios/index.mustache b/templates/openapi-generator/typescript-axios/index.mustache new file mode 100644 index 00000000..76de02d7 --- /dev/null +++ b/templates/openapi-generator/typescript-axios/index.mustache @@ -0,0 +1,9 @@ +/* tslint:disable */ +/* eslint-disable */ +{{>licenseInfo}} + +export * from "./api"; +export * from "./configuration"; +{{#withSeparateModelsAndApi}}export * from "./{{tsModelPackage}}";{{/withSeparateModelsAndApi}} +export * from "./src/filter"; +export * from "./src/oauth2"; diff --git a/templates/typescript-axios/package.mustache b/templates/openapi-generator/typescript-axios/package.mustache similarity index 80% rename from templates/typescript-axios/package.mustache rename to templates/openapi-generator/typescript-axios/package.mustache index a2f1a214..e0ec7974 100644 --- a/templates/typescript-axios/package.mustache +++ b/templates/openapi-generator/typescript-axios/package.mustache @@ -31,7 +31,12 @@ "mocha": "^8.0.1", "@types/mocha": "^9.1.0", "sinon": "^7.2.0", - "@types/sinon": "^10.0.11" + "@types/sinon": "^10.0.11", + "@typescript-eslint/eslint-plugin": "^5.22.0", + "@typescript-eslint/parser": "^5.22.0", + "eslint": "^8.14.0", + "eslint-config-standard": "^17.0.0", + "eslint-plugin-unused-imports": "^2.0.0" }{{#npmRepository}},{{/npmRepository}} {{#npmRepository}} "publishConfig": { diff --git a/templates/typescript-axios/tsconfig.mustache b/templates/openapi-generator/typescript-axios/tsconfig.mustache similarity index 100% rename from templates/typescript-axios/tsconfig.mustache rename to templates/openapi-generator/typescript-axios/tsconfig.mustache diff --git a/templates/scopes/csharp-netcore/scopes.liquid b/templates/scopes/csharp-netcore/scopes.liquid new file mode 100644 index 00000000..34381505 --- /dev/null +++ b/templates/scopes/csharp-netcore/scopes.liquid @@ -0,0 +1,37 @@ +namespace It.FattureInCloud.Sdk.OauthHelper +{ + /// + /// Scope enum + /// + public enum Scope + { + {% for scope in scopes %} + /// {{ scope.comment }} + {{ scope.name }}, + {% endfor %} + } + + /// + /// Scope Extensions Class + /// + public class ScopeExtensions + { + /// + /// Returns the Scope value. + /// + /// Scope + public static string GetScopeValue(Scope scope) + { + string stringScope = string.Empty; + switch (scope.ToString()) + { + {% for scope in scopes %} + case "{{ scope.name }}": + stringScope = "{{ scope.str }}"; + break; + {% endfor %} + } + return stringScope; + } + } +} \ No newline at end of file diff --git a/templates/scopes/java/scopes.liquid b/templates/scopes/java/scopes.liquid new file mode 100644 index 00000000..8a27b596 --- /dev/null +++ b/templates/scopes/java/scopes.liquid @@ -0,0 +1,18 @@ +package it.fattureincloud.sdk.auth; + +public enum Scope { +{% for scope in scopes %} + // {{ scope.comment }} + {{ scope.name }}("{{ scope.str }}"){% if forloop.last == true %};{% else %},{% endif %} +{% endfor %} + + private String scope; + + Scope(String scope) { + this.scope = scope; + } + + public String getScope() { + return scope; + } +} \ No newline at end of file diff --git a/templates/scopes/javascript/scopes.liquid b/templates/scopes/javascript/scopes.liquid new file mode 100644 index 00000000..269cc1a2 --- /dev/null +++ b/templates/scopes/javascript/scopes.liquid @@ -0,0 +1,13 @@ +/** + * The Scope oauth module. + * @module oauth/Scope + */ +export default class Scope { + {% for scope in scopes %} + /** + * {{ scope.comment }} + * @member {String} {{ scope.name }} + */ + static {{ scope.name }} = '{{ scope.str }}' + {% endfor %} +} \ No newline at end of file diff --git a/templates/scopes/php/scopes.liquid b/templates/scopes/php/scopes.liquid new file mode 100644 index 00000000..58dae31e --- /dev/null +++ b/templates/scopes/php/scopes.liquid @@ -0,0 +1,24 @@ +