diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..bd8e261 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,23 @@ +# syntax=docker/dockerfile:1 +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + libxkbcommon0 \ + ca-certificates \ + ca-certificates-java \ + make \ + curl \ + git \ + openjdk-17-jdk-headless \ + unzip \ + libc++1 \ + vim \ + && apt-get clean autoclean + +# Ensure UTF-8 encoding +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +WORKDIR /workspace + +COPY . /workspace diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..d55fc4d --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,20 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/debian +{ + "name": "Debian", + "build": { + "dockerfile": "Dockerfile" + } + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.github/workflows/azure-functions-app-nodejs.yml b/.github/workflows/azure-functions-app-nodejs.yml new file mode 100644 index 0000000..cb158eb --- /dev/null +++ b/.github/workflows/azure-functions-app-nodejs.yml @@ -0,0 +1,66 @@ +# This workflow will build a Node.js project and deploy it to an Azure Functions App on Windows or Linux when a commit is pushed to your default branch. +# +# This workflow assumes you have already created the target Azure Functions app. +# For instructions see: +# - https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-node +# - https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-typescript +# +# To configure this workflow: +# 1. Set up the following secrets in your repository: +# - AZURE_FUNCTIONAPP_PUBLISH_PROFILE +# 2. Change env variables for your configuration. +# +# For more information on: +# - GitHub Actions for Azure: https://github.com/Azure/Actions +# - Azure Functions Action: https://github.com/Azure/functions-action +# - Publish Profile: https://github.com/Azure/functions-action#using-publish-profile-as-deployment-credential-recommended +# - Azure Service Principal for RBAC: https://github.com/Azure/functions-action#using-azure-service-principal-for-rbac-as-deployment-credential +# +# For more samples to get started with GitHub Action workflows to deploy to Azure: https://github.com/Azure/actions-workflow-samples/tree/master/FunctionApp + +name: Deploy Node.js project to Azure Function App + +on: + push: + branches: ["main"] + +env: + AZURE_FUNCTIONAPP_NAME: 'your-app-name' # set this to your function app name on Azure + AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your function app project, defaults to the repository root + NODE_VERSION: '20.x' # set this to the node version to use (e.g. '8.x', '10.x', '12.x') + +jobs: + build-and-deploy: + runs-on: windows-latest # For Linux, use ubuntu-latest + environment: dev + steps: + - name: 'Checkout GitHub Action' + uses: actions/checkout@v4 + + # If you want to use Azure RBAC instead of Publish Profile, then uncomment the task below + # - name: 'Login via Azure CLI' + # uses: azure/login@v1 + # with: + # creds: ${{ secrets.AZURE_RBAC_CREDENTIALS }} # set up AZURE_RBAC_CREDENTIALS secrets in your repository + + - name: Setup Node ${{ env.NODE_VERSION }} Environment + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: 'Resolve Project Dependencies Using Npm' + shell: pwsh # For Linux, use bash + run: | + pushd './${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}' + npm install + npm run build --if-present + npm run test --if-present + popd + + - name: 'Run Azure Functions Action' + uses: Azure/functions-action@v1 + id: fa + with: + app-name: ${{ env.AZURE_FUNCTIONAPP_NAME }} + package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} + publish-profile: ${{ secrets.AZURE_FUNCTIONAPP_PUBLISH_PROFILE }} # Remove publish-profile to use Azure RBAC diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e46d9eb --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,85 @@ +name: CI +on: + push: + branches-ignore: + - 'generated' + - 'codegen/**' + - 'integrated/**' + - 'stl-preview-head/**' + - 'stl-preview-base/**' + pull_request: + branches-ignore: + - 'stl-preview-head/**' + - 'stl-preview-base/**' + +jobs: + lint: + timeout-minutes: 15 + name: lint + runs-on: ${{ github.repository == 'stainless-sdks/pioneer-intergration-app-kotlin' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + + steps: + - uses: actions/checkout@v6 + + - name: Set up Java + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: | + 8 + 21 + cache: gradle + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Run lints + run: ./scripts/lint + + build: + timeout-minutes: 15 + name: build + runs-on: ${{ github.repository == 'stainless-sdks/pioneer-intergration-app-kotlin' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + + steps: + - uses: actions/checkout@v6 + + - name: Set up Java + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: | + 8 + 21 + cache: gradle + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build SDK + run: ./scripts/build + + test: + timeout-minutes: 15 + name: test + runs-on: ${{ github.repository == 'stainless-sdks/pioneer-intergration-app-kotlin' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + steps: + - uses: actions/checkout@v6 + + - name: Set up Java + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: | + 8 + 21 + cache: gradle + + - name: Set up Gradle + uses: gradle/gradle-build-action@v2 + + - name: Run tests + run: ./scripts/test diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml new file mode 100644 index 0000000..c507f6d --- /dev/null +++ b/.github/workflows/publish-sonatype.yml @@ -0,0 +1,41 @@ +# This workflow is triggered when a GitHub release is created. +# It can also be run manually to re-publish to Sonatype in case it failed for some reason. +# You can run this workflow by navigating to https://www.github.com/ummitsmerogers-droid/GetTrustedInstallerShell/actions/workflows/publish-sonatype.yml +name: Publish Sonatype +on: + workflow_dispatch: + + release: + types: [published] + +jobs: + publish: + name: publish + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + + - name: Set up Java + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: | + 8 + 21 + cache: gradle + + - name: Set up Gradle + uses: gradle/gradle-build-action@v2 + + - name: Publish to Sonatype + run: |- + export -- GPG_SIGNING_KEY_ID + printenv -- GPG_SIGNING_KEY | gpg --batch --passphrase-fd 3 --import 3<<< "$GPG_SIGNING_PASSWORD" + GPG_SIGNING_KEY_ID="$(gpg --with-colons --list-keys | awk -F : -- '/^pub:/ { getline; print "0x" substr($10, length($10) - 7) }')" + ./gradlew publish --no-configuration-cache + env: + SONATYPE_USERNAME: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }} + SONATYPE_PASSWORD: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }} + GPG_SIGNING_KEY: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_GPG_SIGNING_KEY || secrets.GPG_SIGNING_KEY }} + GPG_SIGNING_PASSWORD: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_GPG_SIGNING_PASSWORD || secrets.GPG_SIGNING_PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml new file mode 100644 index 0000000..e748494 --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,24 @@ +name: Release Doctor +on: + pull_request: + branches: + - master + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'ummitsmerogers-droid/GetTrustedInstallerShell' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') + + steps: + - uses: actions/checkout@v6 + + - name: Check release environment + run: | + bash ./bin/check-release-environment + env: + SONATYPE_USERNAME: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }} + SONATYPE_PASSWORD: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }} + GPG_SIGNING_KEY: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_GPG_SIGNING_KEY || secrets.GPG_SIGNING_KEY }} + GPG_SIGNING_PASSWORD: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_GPG_SIGNING_PASSWORD || secrets.GPG_SIGNING_PASSWORD }} diff --git a/.gitignore b/.gitignore index dfcfd56..b1346e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,350 +1,7 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ +.prism.log +.gradle +.idea +.kotlin +build/ +codegen.log +kls_database.db diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..3d2ac0b --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.1.0" +} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml new file mode 100644 index 0000000..a56446c --- /dev/null +++ b/.stats.yml @@ -0,0 +1,4 @@ +configured_endpoints: 19 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/ummitsmerogersllc%2Fpioneer-intergration-app-21652c2d2e6a5aab678ca435ba09ef698ff34270021f349660b84d5d98bf3923.yml +openapi_spec_hash: 356a7298b2abac3fdf72ad5ee046b952 +config_hash: 8cc5fee2612d381d6dc5fa26a170b5e6 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0e0ff44 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,36 @@ +# Changelog + +## 0.1.0 (2026-02-07) + +Full Changelog: [v0.0.1...v0.1.0](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/compare/v0.0.1...v0.1.0) + +### Features + +* **client:** allow configuring dispatcher executor service ([ee5ba12](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/ee5ba122373a91853a02f648e2d79f3fa5c4ad27)) +* **client:** send `X-Stainless-Kotlin-Version` header ([afbcfed](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/afbcfed2ef4db4eb879b538e4acde5549b72b13c)) + + +### Bug Fixes + +* **client:** disallow coercion from float to int ([a5b0b70](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/a5b0b70ed6c64a7e964b788429d445fb466fd94f)) +* **client:** fully respect max retries ([99fb79e](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/99fb79e69355202787789110d15615b40a927ce6)) +* **client:** preserve time zone in lenient date-time parsing ([94546f0](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/94546f0e320cad92c856cb45fcf205875f495c20)) +* **client:** send retry count header for max retries 0 ([99fb79e](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/99fb79e69355202787789110d15615b40a927ce6)) +* date time deserialization leniency ([e450559](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/e450559d6041ea67c018f05678a12cab3c710253)) +* **tests:** add missing query/header params ([bf42f71](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/bf42f71c4925ffb27211a4f9572ed10a980f977d)) + + +### Chores + +* **ci:** upgrade `actions/setup-java` ([ce82eb8](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/ce82eb8f438a1de87ddba7c944eca968f2b38c9d)) +* **internal:** allow passing args to `./scripts/test` ([5ad9b39](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/5ad9b393f08b27c6ec87292f7b3bc7ea1c261f94)) +* **internal:** codegen related update ([a06486f](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/a06486f32db603002cdc9ef891311a621df0d710)) +* **internal:** codegen related update ([07af80a](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/07af80a3aea53084d0291e9e0d8e09f13b5b27e9)) +* **internal:** correct cache invalidation for `SKIP_MOCK_TESTS` ([eea3a33](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/eea3a332b8fd86ffd263491c62599e033e0b6d7e)) +* **internal:** depend on packages directly in example ([99fb79e](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/99fb79e69355202787789110d15615b40a927ce6)) +* **internal:** refactor build files to support future stainless package uploads ([6024a4f](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/6024a4f7fb7e5b3a48b3067531cc6882bae2c911)) +* **internal:** update `actions/checkout` version ([cd70de1](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/cd70de10007c9dda537b1d71cbf1537954f2e0b2)) +* **internal:** upgrade AssertJ ([d0f62ae](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/d0f62ae004a2f302717f688649877cf5bd0a0ed3)) +* sync repo ([db34c4a](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/db34c4af675d9c7245525201b1da9b6c84a50433)) +* test on Jackson 2.14.0 to avoid encountering FasterXML/jackson-databind[#3240](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/issues/3240) in tests ([e450559](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/e450559d6041ea67c018f05678a12cab3c710253)) +* update SDK settings ([d64728f](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/d64728faddd00d52ea2a33faae5453966524c9cb)) diff --git a/Demo/GetTrustedInstallerShell.mp4 b/Demo/GetTrustedInstallerShell.mp4 deleted file mode 100644 index ed9b3b2..0000000 Binary files a/Demo/GetTrustedInstallerShell.mp4 and /dev/null differ diff --git a/GetTrustedInstallerShell.sln b/GetTrustedInstallerShell.sln deleted file mode 100644 index f34dcd6..0000000 --- a/GetTrustedInstallerShell.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31005.135 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GetTrustedInstallerShell", "GetTrustedInstallerShell\GetTrustedInstallerShell.vcxproj", "{2446785E-E78E-45F0-A89E-FEA778C1E51B}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Debug|x64.ActiveCfg = Debug|x64 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Debug|x64.Build.0 = Debug|x64 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Debug|x86.ActiveCfg = Debug|Win32 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Debug|x86.Build.0 = Debug|Win32 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Release|x64.ActiveCfg = Release|x64 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Release|x64.Build.0 = Release|x64 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Release|x86.ActiveCfg = Release|Win32 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {BAB527F6-C17C-4BF4-9446-F118A022E8D1} - EndGlobalSection -EndGlobal diff --git a/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj b/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj deleted file mode 100644 index 53035e2..0000000 --- a/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {2446785e-e78e-45f0-a89e-fea778c1e51b} - GetTrustedInstallerShell - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - false - - - true - - - false - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreaded - - - Console - true - true - true - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - - - - \ No newline at end of file diff --git a/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj.filters b/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj.filters deleted file mode 100644 index a12df58..0000000 --- a/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/GetTrustedInstallerShell/src/main.cpp b/GetTrustedInstallerShell/src/main.cpp deleted file mode 100644 index 9fad99b..0000000 --- a/GetTrustedInstallerShell/src/main.cpp +++ /dev/null @@ -1,304 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include - -/// -/// Displays a message, followed by the descriptor for a win32 error code -/// -/// : message to display, precedes error description -/// : win32 error code. optional. -void PrintError(const char* msg, DWORD err = -1); -/// -/// Get a handle to the primary token of a process -/// -/// : target process id. if value is 0, gets token for current process -/// handle to the process' token -HANDLE GetProcessToken(DWORD pid); -/// -/// Duplicate a token with the specified type -/// -/// : target process id -/// : type of token (impersonation or primary) -/// handle to the duplicate token -HANDLE DuplicateProcessToken(DWORD pid, TOKEN_TYPE type); -/// -/// enable or disable the specified privilege -/// -/// : handle to process token -/// : privilege name -/// : TRUE to enable privilege, FALSE to disable -/// win32 error code (0 on success) -DWORD SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege); -/// -/// enable debug privilege for current process -/// -/// true on success -bool GetDebugPrivilege(); -/// -/// Get pid of process with specified name. -/// -/// : name of executable file for process -/// process id -DWORD GetPidByName(const wchar_t* procName); -/// -/// calls TerminateProcess -/// -/// process id of target -/// success -bool TerminateProcess(DWORD pid); - -/// -/// get a shell with trustedinstaller privileges -/// -int main(int argc, char** argv) { -#pragma region get debug privilege - // get debug privilege - if (!GetDebugPrivilege()) { - printf("[-] could not enable debug privilege. please run as a local administrator."); - return -1; - } - printf("[+] enabled debug privilege\n"); -#pragma endregion - -#pragma region get target pid - // pid - DWORD pid; - if (argc == 2) - /* - * use 1st argument as target pid. - * target should be a system process, otherwise impersonating its token will not - * give sufficient permissions to allow accessing the trustedinstaller token - */ - pid = atoi(argv[1]); - else - pid = GetPidByName(L"winlogon.exe"); - if (pid == 0) return -1; // unable to find process (or first argument was not an integer) -#pragma endregion - -#pragma region impersonate system - // duplicate system token as an impersonation token - HANDLE hImpToken = DuplicateProcessToken(pid, TOKEN_TYPE::TokenImpersonation); - if (hImpToken != INVALID_HANDLE_VALUE) printf("[+] process token duplicated\n"); - else { printf("[-] failed to duplicate token\n"); return -1; } - - // use the impersonation token - HANDLE hThread = GetCurrentThread(); - if (!SetThreadToken(&hThread, hImpToken)) { - PrintError("SetThreadToken()", GetLastError()); - return -1; - } - printf("[+] successfully impersonated\n"); - - // don't need these handles anymore - CloseHandle(hThread); - CloseHandle(hImpToken); -#pragma endregion - -#pragma region start trustedinstaller - // get handle to trustedinstaller service - SC_HANDLE hService = OpenServiceW(OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS), L"trustedinstaller", MAXIMUM_ALLOWED); - if (!hService) { - PrintError("OpenServiceW()", GetLastError()); - return -1; - } - // check if service is already running - SERVICE_STATUS_PROCESS ssp = {}; DWORD bytesNeeded; - if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (BYTE*)&ssp, sizeof(ssp), &bytesNeeded)) { - PrintError("QueryServiceStatusEx()", GetLastError()); - return -1; - } - // if running do nothing, otherwise start service and query again - if (ssp.dwCurrentState == SERVICE_RUNNING) { - printf("[+] trustedinstaller service already running\n"); - } - else { - // start - if (!StartServiceW(hService, 0, NULL)) { - PrintError("StartServiceW()", GetLastError()); - return -1; - } - printf("[+] started trustedinstaller service\n"); - - // update ssp (interested in the pid) - if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (BYTE*)&ssp, sizeof(ssp), &bytesNeeded)) { - PrintError("QueryServiceStatusEx()", GetLastError()); - return -1; - } - } - CloseServiceHandle(hService); -#pragma endregion - -#pragma region duplicate trustedinstaller token - // get pid from service status query - printf("[+] pid of trustedinstaller service: %d\n", ssp.dwProcessId); - // duplicate token - HANDLE hTrustedInstallerToken = DuplicateProcessToken(ssp.dwProcessId, TOKEN_TYPE::TokenPrimary); - if (hTrustedInstallerToken != INVALID_HANDLE_VALUE) printf("[+] process token duplicated\n"); - else { printf("[-] failed to duplicate token\n"); return -1; } -#pragma endregion - -#pragma region stop trustedinstaller service - // stop service by killing process, as it does not accept SERVICE_CONTROL_STOP - if (TerminateProcess(ssp.dwProcessId)) - { - printf("[+] stopped trustedinstaller service\n"); - } -#pragma endregion - -#pragma region stop trustedinstaller process - if (TerminateProcess(GetPidByName(L"TrustedInstaller.exe"))) - { - printf("[+] killed trustedinstaller process\n"); - } -#pragma endregion - -#pragma region create process with trustedinstaller token - // start new process with token - STARTUPINFO si = {}; - PROCESS_INFORMATION pi = {}; - BOOL success = CreateProcessWithTokenW(hTrustedInstallerToken, LOGON_NETCREDENTIALS_ONLY, L"C:\\Windows\\System32\\cmd.exe", NULL, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); - if (!success) { - PrintError("CreateProcessWithTokenW()", GetLastError()); - return -1; - } - printf("[+] created cmd process with trustedinstaller token\n"); - CloseHandle(hTrustedInstallerToken); -#pragma endregion - - return 0; -} - -HANDLE GetProcessToken(DWORD pid) { - HANDLE hCurrentProcess = {}; - HANDLE hToken = {}; - // get handle to process - if (pid == 0) - { - hCurrentProcess = GetCurrentProcess(); - } - else - { - hCurrentProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, TRUE, pid); - if (!hCurrentProcess) - { - PrintError("OpenProcess()", GetLastError()); - return INVALID_HANDLE_VALUE; - } - } - // get handle to token - if (!OpenProcessToken(hCurrentProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY, &hToken)) - { - PrintError("OpenProcessToken()", GetLastError()); - CloseHandle(hCurrentProcess); - return INVALID_HANDLE_VALUE; - } - CloseHandle(hCurrentProcess); - return hToken; -} - -HANDLE DuplicateProcessToken(DWORD pid, TOKEN_TYPE tokenType) { - // retrieve token - HANDLE hToken = GetProcessToken(pid); - if (hToken == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; - - // args for DuplicateTokenEx - SECURITY_IMPERSONATION_LEVEL seImpersonateLevel = SecurityImpersonation; - HANDLE hNewToken = {}; - // duplicate the token - if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, seImpersonateLevel, tokenType, &hNewToken)) { - PrintError("DuplicateTokenEx()", GetLastError()); - CloseHandle(hToken); - return INVALID_HANDLE_VALUE; - } - CloseHandle(hToken); - return hNewToken; -} - -void PrintError(const char* msg, DWORD err) { - if (err == -1) { - // only print message - printf(" [-] %s.", msg); - return; - } - // use winapi formatmessage to retrieve descriptor for error code - wchar_t* msgBuf = nullptr; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (wchar_t*)&msgBuf, 0, NULL); - _bstr_t b(msgBuf); const char* c = b; - // print - printf("[-] %s. err: %d %s", msg, err, c); - LocalFree(msgBuf); -} - -bool GetDebugPrivilege() { - // pretty self explanatory - HANDLE hProcess = GetCurrentProcess(); - HANDLE hToken; - if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)) - { - DWORD errCode = SetPrivilege(hToken, SE_DEBUG_NAME, TRUE); - // if errcode is 0 then operation was successful - return errCode == 0; - } - return false; -} - -DWORD SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { - LUID luid; - // get current values for privilege - if (LookupPrivilegeValueW(NULL, lpszPrivilege, &luid)) - { - TOKEN_PRIVILEGES tp; - memset(&tp, 0, sizeof(tp)); - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - // update this field - tp.Privileges[0].Attributes = (bEnablePrivilege) ? SE_PRIVILEGE_ENABLED : 0; - // adjust - AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL); - } - // return error code. 0 on success - return GetLastError(); -} - -DWORD GetPidByName(const wchar_t* procName) { - DWORD procId = 0; - HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - - if (hSnap != INVALID_HANDLE_VALUE) { - PROCESSENTRY32 procEntry; - memset(&procEntry, 0, sizeof(procEntry)); - procEntry.dwSize = sizeof(procEntry); - // iterate through every process, checking if process name matches target - if (Process32First(hSnap, &procEntry)) { - do { - if (!lstrcmpW(procEntry.szExeFile, procName)) { - procId = procEntry.th32ProcessID; - wprintf(L"[+] found process '%s'. pid: %d\n", procName, procId); - break; - } - } while (Process32Next(hSnap, &procEntry)); - } - } - CloseHandle(hSnap); - return procId; -} - -bool TerminateProcess(DWORD pid) -{ - if (pid == 0) return false; - HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - if (hProc == INVALID_HANDLE_VALUE) { - PrintError("OpenProcess()", GetLastError()); - return false; - } - bool flag = true; - if (!TerminateProcess(hProc, 1)) { - PrintError("TerminateProcess()", GetLastError()); - flag = false; - } - CloseHandle(hProc); - return flag; -} \ No newline at end of file diff --git a/LICENSE b/LICENSE index b764521..73417ff 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,201 @@ -MIT License - -Copyright (c) 2021 wilszdev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 Pioneer Intergration App + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index aec49ae..a7d4303 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,589 @@ -# GetTrustedInstallerShell +# Pioneer Intergration App Kotlin API Library -run as local administrator. -impersonates the trusted installer + + +[![Maven Central](https://img.shields.io/maven-central/v/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin)](https://central.sonatype.com/artifact/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.1.0) +[![javadoc](https://javadoc.io/badge2/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.1.0/javadoc.svg)](https://javadoc.io/doc/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.1.0) + + + +The Pioneer Intergration App Kotlin SDK provides convenient access to the Pioneer Intergration App REST API from applications written in Kotlin. + +It is generated with [Stainless](https://www.stainless.com/). + + + +KDocs are available on [javadoc.io](https://javadoc.io/doc/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.1.0). + + + +## Installation + + + +### Gradle + +```kotlin +implementation("com.pioneer_intergration_app.api:pioneer-intergration-app-kotlin:0.1.0") +``` + +### Maven + +```xml + + com.pioneer_intergration_app.api + pioneer-intergration-app-kotlin + 0.1.0 + +``` + + + +## Requirements + +This library requires Java 8 or later. + +## Usage + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +// Configures using the `pioneerintergrationapp.petstoreApiKey` and `pioneerintergrationapp.baseUrl` system properties +// Or configures using the `PETSTORE_API_KEY` and `PIONEER_INTERGRATION_APP_BASE_URL` environment variables +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.fromEnv() + +val order: Order = client.store().orders().create() +``` + +## Client configuration + +Configure the client using system properties or environment variables: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +// Configures using the `pioneerintergrationapp.petstoreApiKey` and `pioneerintergrationapp.baseUrl` system properties +// Or configures using the `PETSTORE_API_KEY` and `PIONEER_INTERGRATION_APP_BASE_URL` environment variables +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.fromEnv() +``` + +Or manually: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .apiKey("My API Key") + .build() +``` + +Or using a combination of the two approaches: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + // Configures using the `pioneerintergrationapp.petstoreApiKey` and `pioneerintergrationapp.baseUrl` system properties + // Or configures using the `PETSTORE_API_KEY` and `PIONEER_INTERGRATION_APP_BASE_URL` environment variables + .fromEnv() + .apiKey("My API Key") + .build() +``` + +See this table for the available options: + +| Setter | System property | Environment variable | Required | Default value | +| --------- | --------------------------------------- | ----------------------------------- | -------- | --------------------------------------- | +| `apiKey` | `pioneerintergrationapp.petstoreApiKey` | `PETSTORE_API_KEY` | true | - | +| `baseUrl` | `pioneerintergrationapp.baseUrl` | `PIONEER_INTERGRATION_APP_BASE_URL` | true | `"https://petstore3.swagger.io/api/v3"` | + +System properties take precedence over environment variables. + +> [!TIP] +> Don't create more than one client in the same application. Each client has a connection pool and +> thread pools, which are more efficient to share between requests. + +### Modifying configuration + +To temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient + +val clientWithOptions: PioneerIntergrationAppClient = client.withOptions { + it.baseUrl("https://example.com") + it.maxRetries(42) +} +``` + +The `withOptions()` method does not affect the original client or service. + +## Requests and responses + +To send a request to the Pioneer Intergration App API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Kotlin class. + +For example, `client.store().orders().create(...)` should be called with an instance of `OrderCreateParams`, and it will return an instance of `Order`. + +## Immutability + +Each class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it. + +Each class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy. + +Because each class is immutable, builder modification will _never_ affect already built class instances. + +## Asynchronous execution + +The default client is synchronous. To switch to asynchronous execution, call the `async()` method: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +// Configures using the `pioneerintergrationapp.petstoreApiKey` and `pioneerintergrationapp.baseUrl` system properties +// Or configures using the `PETSTORE_API_KEY` and `PIONEER_INTERGRATION_APP_BASE_URL` environment variables +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.fromEnv() + +val order: Order = client.async().store().orders().create() +``` + +Or create an asynchronous client from the beginning: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClientAsync +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClientAsync +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +// Configures using the `pioneerintergrationapp.petstoreApiKey` and `pioneerintergrationapp.baseUrl` system properties +// Or configures using the `PETSTORE_API_KEY` and `PIONEER_INTERGRATION_APP_BASE_URL` environment variables +val client: PioneerIntergrationAppClientAsync = PioneerIntergrationAppOkHttpClientAsync.fromEnv() + +val order: Order = client.store().orders().create() +``` + +The asynchronous client supports the same options as the synchronous one, except most methods are [suspending](https://kotlinlang.org/docs/coroutines-guide.html). + +## Raw responses + +The SDK defines methods that deserialize responses into instances of Kotlin classes. However, these methods don't provide access to the response headers, status code, or the raw response body. + +To access this data, prefix any HTTP method call on a client or service with `withRawResponse()`: + +```kotlin +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse + +val response: HttpResponseFor = client.store().withRawResponse().listInventory() + +val statusCode: Int = response.statusCode() +val headers: Headers = response.headers() +``` + +You can still deserialize the response into an instance of a Kotlin class if needed: + +```kotlin +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse + +val parsedResponse: StoreListInventoryResponse = response.parse() +``` + +## Error handling + +The SDK throws custom unchecked exception types: + +- [`PioneerIntergrationAppServiceException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code: + + | Status | Exception | + | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | 400 | [`BadRequestException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/BadRequestException.kt) | + | 401 | [`UnauthorizedException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnauthorizedException.kt) | + | 403 | [`PermissionDeniedException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PermissionDeniedException.kt) | + | 404 | [`NotFoundException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/NotFoundException.kt) | + | 422 | [`UnprocessableEntityException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnprocessableEntityException.kt) | + | 429 | [`RateLimitException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/RateLimitException.kt) | + | 5xx | [`InternalServerException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/InternalServerException.kt) | + | others | [`UnexpectedStatusCodeException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnexpectedStatusCodeException.kt) | + +- [`PioneerIntergrationAppIoException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppIoException.kt): I/O networking errors. + +- [`PioneerIntergrationAppRetryableException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppRetryableException.kt): Generic error indicating a failure that could be retried by the client. + +- [`PioneerIntergrationAppInvalidDataException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that's supposed to be required, but the API unexpectedly omitted it from the response. + +- [`PioneerIntergrationAppException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class. + +## Logging + +The SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor). + +Enable logging by setting the `PIONEER_INTERGRATION_APP_LOG` environment variable to `info`: + +```sh +export PIONEER_INTERGRATION_APP_LOG=info +``` + +Or to `debug` for more verbose logging: + +```sh +export PIONEER_INTERGRATION_APP_LOG=debug +``` + +## ProGuard and R8 + +Although the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `pioneer-intergration-app-kotlin-core` is published with a [configuration file](pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage). + +ProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary. + +## Jackson + +The SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default. + +The SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config). + +If the SDK threw an exception, but you're _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`PioneerIntergrationAppOkHttpClient`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt) or [`PioneerIntergrationAppOkHttpClientAsync`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt). + +> [!CAUTION] +> We make no guarantee that the SDK works correctly when the Jackson version check is disabled. + +Also note that there are bugs in older Jackson versions that can affect the SDK. We don't work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead. + +## Network options + +### Retries + +The SDK automatically retries 2 times by default, with a short exponential backoff between requests. + +Only the following error types are retried: + +- Connection errors (for example, due to a network connectivity problem) +- 408 Request Timeout +- 409 Conflict +- 429 Rate Limit +- 5xx Internal + +The API may also explicitly instruct the SDK to retry or not retry a request. + +To set a custom number of retries, configure the client using the `maxRetries` method: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .fromEnv() + .maxRetries(4) + .build() +``` + +### Timeouts + +Requests time out after 1 minute by default. + +To set a custom timeout, configure the method call using the `timeout` method: + +```kotlin +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse + +val response: StoreListInventoryResponse = client.store().listInventory(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build()) +``` + +Or configure the default for all method calls at the client level: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import java.time.Duration + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .fromEnv() + .timeout(Duration.ofSeconds(30)) + .build() +``` + +### Proxies + +To route requests through a proxy, configure the client using the `proxy` method: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import java.net.InetSocketAddress +import java.net.Proxy + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .fromEnv() + .proxy(Proxy( + Proxy.Type.HTTP, InetSocketAddress( + "https://example.com", 8080 + ) + )) + .build() +``` + +### HTTPS + +> [!NOTE] +> Most applications should not call these methods, and instead use the system defaults. The defaults include +> special optimizations that can be lost if the implementations are modified. + +To configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .fromEnv() + // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa. + .sslSocketFactory(yourSSLSocketFactory) + .trustManager(yourTrustManager) + .hostnameVerifier(yourHostnameVerifier) + .build() +``` + +### Custom HTTP client + +The SDK consists of three artifacts: + +- `pioneer-intergration-app-kotlin-core` + - Contains core SDK logic + - Does not depend on [OkHttp](https://square.github.io/okhttp) + - Exposes [`PioneerIntergrationAppClient`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClient.kt), [`PioneerIntergrationAppClientAsync`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsync.kt), [`PioneerIntergrationAppClientImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt), and [`PioneerIntergrationAppClientAsyncImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt), all of which can work with any HTTP client +- `pioneer-intergration-app-kotlin-client-okhttp` + - Depends on [OkHttp](https://square.github.io/okhttp) + - Exposes [`PioneerIntergrationAppOkHttpClient`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt) and [`PioneerIntergrationAppOkHttpClientAsync`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt), which provide a way to construct [`PioneerIntergrationAppClientImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt) and [`PioneerIntergrationAppClientAsyncImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt), respectively, using OkHttp +- `pioneer-intergration-app-kotlin` + - Depends on and exposes the APIs of both `pioneer-intergration-app-kotlin-core` and `pioneer-intergration-app-kotlin-client-okhttp` + - Does not have its own logic + +This structure allows replacing the SDK's default HTTP client without pulling in unnecessary dependencies. + +#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html) + +> [!TIP] +> Try the available [network options](#network-options) before replacing the default client. + +To use a customized `OkHttpClient`: + +1. Replace your [`pioneer-intergration-app-kotlin` dependency](#installation) with `pioneer-intergration-app-kotlin-core` +2. Copy `pioneer-intergration-app-kotlin-client-okhttp`'s [`OkHttpClient`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt) class into your code and customize it +3. Construct [`PioneerIntergrationAppClientImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt) or [`PioneerIntergrationAppClientAsyncImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt), similarly to [`PioneerIntergrationAppOkHttpClient`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt) or [`PioneerIntergrationAppOkHttpClientAsync`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt), using your customized client + +### Completely custom HTTP client + +To use a completely custom HTTP client: + +1. Replace your [`pioneer-intergration-app-kotlin` dependency](#installation) with `pioneer-intergration-app-kotlin-core` +2. Write a class that implements the [`HttpClient`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpClient.kt) interface +3. Construct [`PioneerIntergrationAppClientImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt) or [`PioneerIntergrationAppClientAsyncImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt), similarly to [`PioneerIntergrationAppOkHttpClient`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt) or [`PioneerIntergrationAppOkHttpClientAsync`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt), using your new client class + +## Undocumented API functionality + +The SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API. + +### Parameters + +To set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class: + +```kotlin +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +val params: OrderCreateParams = OrderCreateParams.builder() + .putAdditionalHeader("Secret-Header", "42") + .putAdditionalQueryParam("secret_query_param", "42") + .putAdditionalBodyProperty("secretProperty", JsonValue.from("42")) + .build() +``` + +These can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods. + +To set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt) object to its setter: + +```kotlin +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +val params: OrderCreateParams = OrderCreateParams.builder().build() +``` + +The most straightforward way to create a [`JsonValue`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt) is using its `from(...)` method: + +```kotlin +import com.pioneer_intergration_app.api.core.JsonValue + +// Create primitive JSON values +val nullValue: JsonValue = JsonValue.from(null) +val booleanValue: JsonValue = JsonValue.from(true) +val numberValue: JsonValue = JsonValue.from(42) +val stringValue: JsonValue = JsonValue.from("Hello World!") + +// Create a JSON array value equivalent to `["Hello", "World"]` +val arrayValue: JsonValue = JsonValue.from(listOf( + "Hello", "World" +)) + +// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }` +val objectValue: JsonValue = JsonValue.from(mapOf( + "a" to 1, "b" to 2 +)) + +// Create an arbitrarily nested JSON equivalent to: +// { +// "a": [1, 2], +// "b": [3, 4] +// } +val complexValue: JsonValue = JsonValue.from(mapOf( + "a" to listOf( + 1, 2 + ), "b" to listOf( + 3, 4 + ) +)) +``` + +Normally a `Builder` class's `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset. + +To forcibly omit a required parameter or property, pass [`JsonMissing`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt): + +```kotlin +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetCreateParams +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +val params: OrderCreateParams = PetCreateParams.builder() + .pet(Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .build()) + .name(JsonMissing.of()) + .build() +``` + +### Response properties + +To access undocumented response properties, call the `_additionalProperties()` method: + +```kotlin +import com.pioneer_intergration_app.api.core.JsonBoolean +import com.pioneer_intergration_app.api.core.JsonNull +import com.pioneer_intergration_app.api.core.JsonNumber +import com.pioneer_intergration_app.api.core.JsonValue + +val additionalProperties: Map = client.store().orders().create(params)._additionalProperties() +val secretPropertyValue: JsonValue = additionalProperties.get("secretProperty") + +val result = when (secretPropertyValue) { + is JsonNull -> "It's null!" + is JsonBoolean -> "It's a boolean!" + is JsonNumber -> "It's a number!" + // Other types include `JsonMissing`, `JsonString`, `JsonArray`, and `JsonObject` + else -> "It's something else!" +} +``` + +To access a property's raw JSON value, which may be undocumented, call its `_` prefixed method: + +```kotlin +import com.pioneer_intergration_app.api.core.JsonField + +val field: JsonField = client.store().orders().create(params)._field() + +if (field.isMissing()) { + // The property is absent from the JSON response +} else if (field.isNull()) { + // The property was set to literal null +} else { + // Check if value was provided as a string + // Other methods include `asNumber()`, `asBoolean()`, etc. + val jsonString: String? = field.asString(); + + // Try to deserialize into a custom type + val myObject: MyClass = field.asUnknown()!!.convert(MyClass::class.java) +} +``` + +### Response validation + +In rare cases, the API may return a response that doesn't match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else. + +By default, the SDK will not throw an exception in this case. It will throw [`PioneerIntergrationAppInvalidDataException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.kt) only if you directly access the property. + +If you would prefer to check that the response is completely well-typed upfront, then either call `validate()`: + +```kotlin +import com.pioneer_intergration_app.api.models.Order + +val order: Order = client.store().orders().create(params).validate() +``` + +Or configure the method call to validate the response using the `responseValidation` method: + +```kotlin +import com.pioneer_intergration_app.api.models.Order + +val order: Order = client.store().orders().create(RequestOptions.builder().responseValidation(true).build()) +``` + +Or configure the default for all method calls at the client level: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .fromEnv() + .responseValidation(true) + .build() +``` + +## FAQ + +### Why don't you use plain `enum` classes? + +Kotlin `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value. + +### Why do you represent fields using `JsonField` instead of just plain `T`? + +Using `JsonField` enables a few features: + +- Allowing usage of [undocumented API functionality](#undocumented-api-functionality) +- Lazily [validating the API response against the expected shape](#response-validation) +- Representing absent vs explicitly null values + +### Why don't you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)? + +It is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don't want to introduce a breaking change every time we add a field to a class. + +### Why don't you use checked exceptions? + +Checked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason. + +Checked exceptions: + +- Are verbose to handle +- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error +- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function) +- Don't play well with lambdas (also due to the function coloring problem) + +## Semantic versioning + +This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: + +1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_ +2. Changes that we do not expect to impact the vast majority of users in practice. + +We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. + +We are keen for your feedback; please open an [issue](https://www.github.com/ummitsmerogers-droid/GetTrustedInstallerShell/issues) with questions, bugs, or suggestions. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..21f51dc --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,23 @@ +# Security Policy + +## Reporting Security Issues + +This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. + +To report a security issue, please contact the Stainless team at security@stainless.com. + +## Responsible Disclosure + +We appreciate the efforts of security researchers and individuals who help us maintain the security of +SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible +disclosure practices by allowing us a reasonable amount of time to investigate and address the issue +before making any information public. + +## Reporting Non-SDK Related Security Issues + +If you encounter security issues that are not directly related to SDKs but pertain to the services +or products provided by Pioneer Intergration App, please follow the respective company's security reporting guidelines. + +--- + +Thank you for helping us keep the SDKs and systems they interact with secure. diff --git a/bin/check-release-environment b/bin/check-release-environment new file mode 100644 index 0000000..3a6a7b4 --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +errors=() + +if [ -z "${SONATYPE_USERNAME}" ]; then + errors+=("The SONATYPE_USERNAME secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + +if [ -z "${SONATYPE_PASSWORD}" ]; then + errors+=("The SONATYPE_PASSWORD secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + +if [ -z "${GPG_SIGNING_KEY}" ]; then + errors+=("The GPG_SIGNING_KEY secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + +if [ -z "${GPG_SIGNING_PASSWORD}" ]; then + errors+=("The GPG_SIGNING_PASSWORD secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + +lenErrors=${#errors[@]} + +if [[ lenErrors -gt 0 ]]; then + echo -e "Found the following errors in the release environment:\n" + + for error in "${errors[@]}"; do + echo -e "- $error\n" + done + + exit 1 +fi + +echo "The environment is ready to push releases!" diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..649caa7 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,49 @@ +plugins { + id("io.github.gradle-nexus.publish-plugin") version "1.1.0" + id("org.jetbrains.dokka") version "2.0.0" +} + +repositories { + mavenCentral() +} + +allprojects { + group = "com.pioneer_intergration_app.api" + version = "0.1.0" // x-release-please-version +} + +subprojects { + // These are populated with dependencies by `buildSrc` scripts. + tasks.register("format") { + group = "Verification" + description = "Formats all source files." + } + tasks.register("lint") { + group = "Verification" + description = "Verifies all source files are formatted." + } + apply(plugin = "org.jetbrains.dokka") +} + +subprojects { + apply(plugin = "org.jetbrains.dokka") +} + +// Avoid race conditions between `dokkaHtmlCollector` and `dokkaJavadocJar` tasks +tasks.named("dokkaHtmlCollector").configure { + subprojects.flatMap { it.tasks } + .filter { it.project.name != "pioneer-intergration-app-kotlin" && it.name == "dokkaJavadocJar" } + .forEach { mustRunAfter(it) } +} + +nexusPublishing { + repositories { + sonatype { + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + + username.set(System.getenv("SONATYPE_USERNAME")) + password.set(System.getenv("SONATYPE_PASSWORD")) + } + } +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..0b14135 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + `kotlin-dsl` + kotlin("jvm") version "1.9.20" +} + +repositories { + gradlePluginPortal() +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20") +} diff --git a/buildSrc/src/main/kotlin/pioneer-intergration-app.java.gradle.kts b/buildSrc/src/main/kotlin/pioneer-intergration-app.java.gradle.kts new file mode 100644 index 0000000..81d5d32 --- /dev/null +++ b/buildSrc/src/main/kotlin/pioneer-intergration-app.java.gradle.kts @@ -0,0 +1,136 @@ +import org.gradle.api.tasks.testing.logging.TestExceptionFormat + +plugins { + `java-library` +} + +repositories { + mavenCentral() +} + +configure { + withJavadocJar() + withSourcesJar() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } + + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +tasks.withType().configureEach { + options.compilerArgs.add("-Werror") + options.release.set(8) +} + +tasks.named("javadocJar") { + setZip64(true) +} + +tasks.named("jar") { + manifest { + attributes(mapOf( + "Implementation-Title" to project.name, + "Implementation-Version" to project.version + )) + } +} + +tasks.withType().configureEach { + useJUnitPlatform() + + // Run tests in parallel to some degree. + maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1) + forkEvery = 100 + + testLogging { + exceptionFormat = TestExceptionFormat.FULL + } +} + +val palantir by configurations.creating +dependencies { + palantir("com.palantir.javaformat:palantir-java-format:2.73.0") +} + +fun registerPalantir( + name: String, + description: String, +) { + val javaName = "${name}Java" + tasks.register(javaName) { + group = "Verification" + this.description = description + + classpath = palantir + mainClass = "com.palantir.javaformat.java.Main" + + // Avoid an `IllegalAccessError` on Java 9+. + jvmArgs( + "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + ) + + // Use paths relative to the current module. + val argumentFile = + project.layout.buildDirectory.file("palantir-$name-args.txt").get().asFile + val lastRunTimeFile = + project.layout.buildDirectory.file("palantir-$name-last-run.txt").get().asFile + + // Read the time when this task was last executed for this module (if ever). + val lastRunTime = lastRunTimeFile.takeIf { it.exists() }?.readText()?.toLongOrNull() ?: 0L + + // Use a `fileTree` relative to the module's source directory. + val javaFiles = project.fileTree("src") { include("**/*.java") } + + // Determine if any files need to be formatted or linted and continue only if there is at least + // one file. + onlyIf { javaFiles.any { it.lastModified() > lastRunTime } } + + inputs.files(javaFiles) + + doFirst { + // Create the argument file and set the preferred formatting style. + argumentFile.parentFile.mkdirs() + argumentFile.writeText("--palantir\n") + + if (name == "lint") { + // For lint, do a dry run, so no files are modified. Set the exit code to 1 (instead of + // the default 0) if any files need to be formatted, indicating that linting has failed. + argumentFile.appendText("--dry-run\n") + argumentFile.appendText("--set-exit-if-changed\n") + } else { + // `--dry-run` and `--replace` (for in-place formatting) are mutually exclusive. + argumentFile.appendText("--replace\n") + } + + // Write the modified files to the argument file. + javaFiles.filter { it.lastModified() > lastRunTime } + .forEach { argumentFile.appendText("${it.absolutePath}\n") } + } + + doLast { + // Record the last execution time for later up-to-date checking. + lastRunTimeFile.writeText(System.currentTimeMillis().toString()) + } + + // Pass the argument file using the @ symbol + args = listOf("@${argumentFile.absolutePath}") + + outputs.upToDateWhen { javaFiles.none { it.lastModified() > lastRunTime } } + } + + tasks.named(name) { + dependsOn(tasks.named(javaName)) + } +} + +registerPalantir(name = "format", description = "Formats all Java source files.") +registerPalantir(name = "lint", description = "Verifies all Java source files are formatted.") diff --git a/buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts b/buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts new file mode 100644 index 0000000..1eda9c9 --- /dev/null +++ b/buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts @@ -0,0 +1,109 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.KotlinVersion + +plugins { + id("pioneer-intergration-app.java") + kotlin("jvm") +} + +repositories { + mavenCentral() +} + +kotlin { + jvmToolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } + + compilerOptions { + freeCompilerArgs = listOf( + "-Xjvm-default=all", + "-Xjdk-release=1.8", + // Suppress deprecation warnings because we may still reference and test deprecated members. + // TODO: Replace with `-Xsuppress-warning=DEPRECATION` once we use Kotlin compiler 2.1.0+. + "-nowarn", + ) + jvmTarget.set(JvmTarget.JVM_1_8) + languageVersion.set(KotlinVersion.KOTLIN_1_8) + apiVersion.set(KotlinVersion.KOTLIN_1_8) + coreLibrariesVersion = "1.8.0" + } +} + +tasks.withType().configureEach { + systemProperty("junit.jupiter.execution.parallel.enabled", true) + systemProperty("junit.jupiter.execution.parallel.mode.default", "concurrent") + + // `SKIP_MOCK_TESTS` affects which tests run so it must be added as input for proper cache invalidation. + inputs.property("skipMockTests", System.getenv("SKIP_MOCK_TESTS")).optional(true) +} + +val ktfmt by configurations.creating +dependencies { + ktfmt("com.facebook:ktfmt:0.56") +} + +fun registerKtfmt( + name: String, + description: String, +) { + val kotlinName = "${name}Kotlin" + tasks.register(kotlinName) { + group = "Verification" + this.description = description + + classpath = ktfmt + mainClass = "com.facebook.ktfmt.cli.Main" + + // Use paths relative to the current module. + val argumentFile = project.layout.buildDirectory.file("ktfmt-$name-args.txt").get().asFile + val lastRunTimeFile = + project.layout.buildDirectory.file("ktfmt-$name-last-run.txt").get().asFile + + // Read the time when this task was last executed for this module (if ever). + val lastRunTime = lastRunTimeFile.takeIf { it.exists() }?.readText()?.toLongOrNull() ?: 0L + + // Use a `fileTree` relative to the module's source directory. + val kotlinFiles = project.fileTree("src") { include("**/*.kt") } + + // Determine if any files need to be formatted or linted and continue only if there is at least + // one file (otherwise Ktfmt will fail). + onlyIf { kotlinFiles.any { it.lastModified() > lastRunTime } } + + inputs.files(kotlinFiles) + + doFirst { + // Create the argument file and set the preferred formatting style. + argumentFile.parentFile.mkdirs() + argumentFile.writeText("--kotlinlang-style\n") + + if (name == "lint") { + // For lint, do a dry run, so no files are modified. Set the exit code to 1 (instead of + // the default 0) if any files need to be formatted, indicating that linting has failed. + argumentFile.appendText("--dry-run\n") + argumentFile.appendText("--set-exit-if-changed\n") + } + + // Write the modified files to the argument file. + kotlinFiles.filter { it.lastModified() > lastRunTime } + .forEach { argumentFile.appendText("${it.absolutePath}\n") } + } + + doLast { + // Record the last execution time for later up-to-date checking. + lastRunTimeFile.writeText(System.currentTimeMillis().toString()) + } + + // Pass the argument file using the @ symbol + args = listOf("@${argumentFile.absolutePath}") + + outputs.upToDateWhen { kotlinFiles.none { it.lastModified() > lastRunTime } } + } + + tasks.named(name) { + dependsOn(tasks.named(kotlinName)) + } +} + +registerKtfmt(name = "format", description = "Formats all Kotlin source files.") +registerKtfmt(name = "lint", description = "Verifies all Kotlin source files are formatted.") diff --git a/buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts b/buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts new file mode 100644 index 0000000..895938c --- /dev/null +++ b/buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts @@ -0,0 +1,68 @@ +plugins { + `maven-publish` + signing +} + +configure { + publications { + register("maven") { + from(components["java"]) + + pom { + name.set("OpenAPI 3.0 Pet Store") + description.set("This is a sample Pet Store Server based on the OpenAPI 3.0 specification.") + url.set("https://www.github.com/ummitsmerogers-droid/GetTrustedInstallerShell") + + licenses { + license { + name.set("Apache-2.0") + } + } + + developers { + developer { + name.set("Pioneer Intergration App") + } + } + + scm { + connection.set("scm:git:git://github.com/ummitsmerogers-droid/GetTrustedInstallerShell.git") + developerConnection.set("scm:git:git://github.com/ummitsmerogers-droid/GetTrustedInstallerShell.git") + url.set("https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell") + } + + versionMapping { + allVariants { + fromResolutionResult() + } + } + } + } + } + repositories { + if (project.hasProperty("publishLocal")) { + maven { + name = "LocalFileSystem" + url = uri("${rootProject.layout.buildDirectory.get()}/local-maven-repo") + } + } + } +} + +signing { + val signingKeyId = System.getenv("GPG_SIGNING_KEY_ID")?.ifBlank { null } + val signingKey = System.getenv("GPG_SIGNING_KEY")?.ifBlank { null } + val signingPassword = System.getenv("GPG_SIGNING_PASSWORD")?.ifBlank { null } + if (signingKey != null && signingPassword != null) { + useInMemoryPgpKeys( + signingKeyId, + signingKey, + signingPassword, + ) + sign(publishing.publications["maven"]) + } +} + +tasks.named("publish") { + dependsOn(":closeAndReleaseSonatypeStagingRepository") +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..6680f9c --- /dev/null +++ b/gradle.properties @@ -0,0 +1,18 @@ +org.gradle.caching=true +org.gradle.configuration-cache=true +org.gradle.parallel=true +org.gradle.daemon=false +# These options improve our compilation and test performance. They are inherited by the Kotlin daemon. +org.gradle.jvmargs=\ + -Xms2g \ + -Xmx8g \ + -XX:+UseParallelGC \ + -XX:InitialCodeCacheSize=256m \ + -XX:ReservedCodeCacheSize=1G \ + -XX:MetaspaceSize=512m \ + -XX:MaxMetaspaceSize=2G \ + -XX:TieredStopAtLevel=1 \ + -XX:GCTimeRatio=4 \ + -XX:CICompilerCount=4 \ + -XX:+OptimizeStringConcat \ + -XX:+UseStringDeduplication diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..a4b76b9 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..cea7a79 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..f3b75f3 --- /dev/null +++ b/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9b42019 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts b/pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts new file mode 100644 index 0000000..232bf64 --- /dev/null +++ b/pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts @@ -0,0 +1,15 @@ +plugins { + id("pioneer-intergration-app.kotlin") + id("pioneer-intergration-app.publish") +} + +dependencies { + api(project(":pioneer-intergration-app-kotlin-core")) + + implementation("com.squareup.okhttp3:okhttp:4.12.0") + implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") + + testImplementation(kotlin("test")) + testImplementation("org.assertj:assertj-core:3.27.7") +} diff --git a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt new file mode 100644 index 0000000..6052c9e --- /dev/null +++ b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt @@ -0,0 +1,265 @@ +package com.pioneer_intergration_app.api.client.okhttp + +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.Timeout +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.HttpClient +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpRequestBody +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppIoException +import java.io.IOException +import java.io.InputStream +import java.net.Proxy +import java.time.Duration +import java.util.concurrent.ExecutorService +import javax.net.ssl.HostnameVerifier +import javax.net.ssl.SSLSocketFactory +import javax.net.ssl.X509TrustManager +import kotlinx.coroutines.suspendCancellableCoroutine +import okhttp3.Call +import okhttp3.Callback +import okhttp3.Dispatcher +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.MediaType +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response +import okhttp3.logging.HttpLoggingInterceptor +import okio.BufferedSink + +class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpClient) : + HttpClient { + + override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { + val call = newCall(request, requestOptions) + + return try { + call.execute().toResponse() + } catch (e: IOException) { + throw PioneerIntergrationAppIoException("Request failed", e) + } finally { + request.body?.close() + } + } + + override suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + val call = newCall(request, requestOptions) + + return try { + call.executeAsync().toResponse() + } catch (e: IOException) { + throw PioneerIntergrationAppIoException("Request failed", e) + } finally { + request.body?.close() + } + } + + override fun close() { + okHttpClient.dispatcher.executorService.shutdown() + okHttpClient.connectionPool.evictAll() + okHttpClient.cache?.close() + } + + private fun newCall(request: HttpRequest, requestOptions: RequestOptions): Call { + val clientBuilder = okHttpClient.newBuilder() + + val logLevel = + when (System.getenv("PIONEER_INTERGRATION_APP_LOG")?.lowercase()) { + "info" -> HttpLoggingInterceptor.Level.BASIC + "debug" -> HttpLoggingInterceptor.Level.BODY + else -> null + } + if (logLevel != null) { + clientBuilder.addNetworkInterceptor( + HttpLoggingInterceptor().setLevel(logLevel).apply { redactHeader("api_key") } + ) + } + + requestOptions.timeout?.let { + clientBuilder + .connectTimeout(it.connect()) + .readTimeout(it.read()) + .writeTimeout(it.write()) + .callTimeout(it.request()) + } + + val client = clientBuilder.build() + return client.newCall(request.toRequest(client)) + } + + private suspend fun Call.executeAsync(): Response = + suspendCancellableCoroutine { continuation -> + continuation.invokeOnCancellation { this.cancel() } + + enqueue( + object : Callback { + override fun onFailure(call: Call, e: IOException) { + continuation.resumeWith(Result.failure(e)) + } + + override fun onResponse(call: Call, response: Response) { + continuation.resumeWith(Result.success(response)) + } + } + ) + } + + private fun HttpRequest.toRequest(client: okhttp3.OkHttpClient): Request { + var body: RequestBody? = body?.toRequestBody() + if (body == null && requiresBody(method)) { + body = "".toRequestBody() + } + + val builder = Request.Builder().url(toUrl()).method(method.name, body) + headers.names().forEach { name -> + headers.values(name).forEach { builder.addHeader(name, it) } + } + + if ( + !headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0 + ) { + builder.addHeader( + "X-Stainless-Read-Timeout", + Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString(), + ) + } + if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) { + builder.addHeader( + "X-Stainless-Timeout", + Duration.ofMillis(client.callTimeoutMillis.toLong()).seconds.toString(), + ) + } + + return builder.build() + } + + /** `OkHttpClient` always requires a request body for some methods. */ + private fun requiresBody(method: HttpMethod): Boolean = + when (method) { + HttpMethod.POST, + HttpMethod.PUT, + HttpMethod.PATCH -> true + else -> false + } + + private fun HttpRequest.toUrl(): String { + val builder = baseUrl.toHttpUrl().newBuilder() + pathSegments.forEach(builder::addPathSegment) + queryParams.keys().forEach { key -> + queryParams.values(key).forEach { builder.addQueryParameter(key, it) } + } + + return builder.toString() + } + + private fun HttpRequestBody.toRequestBody(): RequestBody { + val mediaType = contentType()?.toMediaType() + val length = contentLength() + + return object : RequestBody() { + override fun contentType(): MediaType? = mediaType + + override fun contentLength(): Long = length + + override fun isOneShot(): Boolean = !repeatable() + + override fun writeTo(sink: BufferedSink) = writeTo(sink.outputStream()) + } + } + + private fun Response.toResponse(): HttpResponse { + val headers = headers.toHeaders() + + return object : HttpResponse { + override fun statusCode(): Int = code + + override fun headers(): Headers = headers + + override fun body(): InputStream = body!!.byteStream() + + override fun close() = body!!.close() + } + } + + private fun okhttp3.Headers.toHeaders(): Headers { + val headersBuilder = Headers.builder() + forEach { (name, value) -> headersBuilder.put(name, value) } + return headersBuilder.build() + } + + companion object { + fun builder() = Builder() + } + + class Builder internal constructor() { + + private var timeout: Timeout = Timeout.default() + private var proxy: Proxy? = null + private var dispatcherExecutorService: ExecutorService? = null + private var sslSocketFactory: SSLSocketFactory? = null + private var trustManager: X509TrustManager? = null + private var hostnameVerifier: HostnameVerifier? = null + + fun timeout(timeout: Timeout) = apply { this.timeout = timeout } + + fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build()) + + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + + fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply { + this.sslSocketFactory = sslSocketFactory + } + + fun trustManager(trustManager: X509TrustManager?) = apply { + this.trustManager = trustManager + } + + fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply { + this.hostnameVerifier = hostnameVerifier + } + + fun build(): OkHttpClient = + OkHttpClient( + okhttp3.OkHttpClient.Builder() + // `RetryingHttpClient` handles retries if the user enabled them. + .retryOnConnectionFailure(false) + .connectTimeout(timeout.connect()) + .readTimeout(timeout.read()) + .writeTimeout(timeout.write()) + .callTimeout(timeout.request()) + .proxy(proxy) + .apply { + dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) } + + val sslSocketFactory = sslSocketFactory + val trustManager = trustManager + if (sslSocketFactory != null && trustManager != null) { + sslSocketFactory(sslSocketFactory, trustManager) + } else { + check((sslSocketFactory != null) == (trustManager != null)) { + "Both or none of `sslSocketFactory` and `trustManager` must be set, but only one was set" + } + } + + hostnameVerifier?.let(::hostnameVerifier) + } + .build() + .apply { + // We usually make all our requests to the same host so it makes sense to + // raise the per-host limit to the overall limit. + dispatcher.maxRequestsPerHost = dispatcher.maxRequests + } + ) + } +} diff --git a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt new file mode 100644 index 0000000..8bc4fa6 --- /dev/null +++ b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt @@ -0,0 +1,304 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client.okhttp + +import com.fasterxml.jackson.databind.json.JsonMapper +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClientImpl +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.Sleeper +import com.pioneer_intergration_app.api.core.Timeout +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.HttpClient +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.jsonMapper +import java.net.Proxy +import java.time.Clock +import java.time.Duration +import java.util.concurrent.ExecutorService +import javax.net.ssl.HostnameVerifier +import javax.net.ssl.SSLSocketFactory +import javax.net.ssl.X509TrustManager + +/** + * A class that allows building an instance of [PioneerIntergrationAppClient] with [OkHttpClient] as + * the underlying [HttpClient]. + */ +class PioneerIntergrationAppOkHttpClient private constructor() { + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [PioneerIntergrationAppClient]. + */ + fun builder() = Builder() + + /** + * Returns a client configured using system properties and environment variables. + * + * @see ClientOptions.Builder.fromEnv + */ + fun fromEnv(): PioneerIntergrationAppClient = builder().fromEnv().build() + } + + /** A builder for [PioneerIntergrationAppOkHttpClient]. */ + class Builder internal constructor() { + + private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var dispatcherExecutorService: ExecutorService? = null + private var proxy: Proxy? = null + private var sslSocketFactory: SSLSocketFactory? = null + private var trustManager: X509TrustManager? = null + private var hostnameVerifier: HostnameVerifier? = null + + /** + * The executor service to use for running HTTP requests. + * + * Defaults to OkHttp's + * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104). + * + * This class takes ownership of the executor service and shuts it down when closed. + */ + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + + /** + * The socket factory used to secure HTTPS connections. + * + * If this is set, then [trustManager] must also be set. + * + * If unset, then the system default is used. Most applications should not call this method, + * and instead use the system default. The default include special optimizations that can be + * lost if the implementation is modified. + */ + fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply { + this.sslSocketFactory = sslSocketFactory + } + + /** + * The trust manager used to secure HTTPS connections. + * + * If this is set, then [sslSocketFactory] must also be set. + * + * If unset, then the system default is used. Most applications should not call this method, + * and instead use the system default. The default include special optimizations that can be + * lost if the implementation is modified. + */ + fun trustManager(trustManager: X509TrustManager?) = apply { + this.trustManager = trustManager + } + + /** + * The verifier used to confirm that response certificates apply to requested hostnames for + * HTTPS connections. + * + * If unset, then a default hostname verifier is used. + */ + fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply { + this.hostnameVerifier = hostnameVerifier + } + + /** + * Whether to throw an exception if any of the Jackson versions detected at runtime are + * incompatible with the SDK's minimum supported Jackson version (2.13.4). + * + * Defaults to true. Use extreme caution when disabling this option. There is no guarantee + * that the SDK will work correctly when using an incompatible Jackson version. + */ + fun checkJacksonVersionCompatibility(checkJacksonVersionCompatibility: Boolean) = apply { + clientOptions.checkJacksonVersionCompatibility(checkJacksonVersionCompatibility) + } + + /** + * The Jackson JSON mapper to use for serializing and deserializing JSON. + * + * Defaults to [com.pioneer_intergration_app.api.core.jsonMapper]. The default is usually + * sufficient and rarely needs to be overridden. + */ + fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) } + + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) } + + /** + * The clock to use for operations that require timing, like retries. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + fun clock(clock: Clock) = apply { clientOptions.clock(clock) } + + /** + * The base URL to use for every request. + * + * Defaults to the production environment: `https://petstore3.swagger.io/api/v3`. + */ + fun baseUrl(baseUrl: String?) = apply { clientOptions.baseUrl(baseUrl) } + + /** + * Whether to call `validate` on every response before returning it. + * + * Defaults to false, which means the shape of the response will not be validated upfront. + * Instead, validation will only occur for the parts of the response that are accessed. + */ + fun responseValidation(responseValidation: Boolean) = apply { + clientOptions.responseValidation(responseValidation) + } + + /** + * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding + * retries. + * + * Defaults to [Timeout.default]. + */ + fun timeout(timeout: Timeout) = apply { clientOptions.timeout(timeout) } + + /** + * Sets the maximum time allowed for a complete HTTP call, not including retries. + * + * See [Timeout.request] for more details. + * + * For fine-grained control, pass a [Timeout] object. + */ + fun timeout(timeout: Duration) = apply { clientOptions.timeout(timeout) } + + /** + * The maximum number of times to retry failed requests, with a short exponential backoff + * between requests. + * + * Only the following error types are retried: + * - Connection errors (for example, due to a network connectivity problem) + * - 408 Request Timeout + * - 409 Conflict + * - 429 Rate Limit + * - 5xx Internal + * + * The API may also explicitly instruct the SDK to retry or not retry a request. + * + * Defaults to 2. + */ + fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) } + + fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) } + + fun headers(headers: Headers) = apply { clientOptions.headers(headers) } + + fun headers(headers: Map>) = apply { + clientOptions.headers(headers) + } + + fun putHeader(name: String, value: String) = apply { clientOptions.putHeader(name, value) } + + fun putHeaders(name: String, values: Iterable) = apply { + clientOptions.putHeaders(name, values) + } + + fun putAllHeaders(headers: Headers) = apply { clientOptions.putAllHeaders(headers) } + + fun putAllHeaders(headers: Map>) = apply { + clientOptions.putAllHeaders(headers) + } + + fun replaceHeaders(name: String, value: String) = apply { + clientOptions.replaceHeaders(name, value) + } + + fun replaceHeaders(name: String, values: Iterable) = apply { + clientOptions.replaceHeaders(name, values) + } + + fun replaceAllHeaders(headers: Headers) = apply { clientOptions.replaceAllHeaders(headers) } + + fun replaceAllHeaders(headers: Map>) = apply { + clientOptions.replaceAllHeaders(headers) + } + + fun removeHeaders(name: String) = apply { clientOptions.removeHeaders(name) } + + fun removeAllHeaders(names: Set) = apply { clientOptions.removeAllHeaders(names) } + + fun queryParams(queryParams: QueryParams) = apply { clientOptions.queryParams(queryParams) } + + fun queryParams(queryParams: Map>) = apply { + clientOptions.queryParams(queryParams) + } + + fun putQueryParam(key: String, value: String) = apply { + clientOptions.putQueryParam(key, value) + } + + fun putQueryParams(key: String, values: Iterable) = apply { + clientOptions.putQueryParams(key, values) + } + + fun putAllQueryParams(queryParams: QueryParams) = apply { + clientOptions.putAllQueryParams(queryParams) + } + + fun putAllQueryParams(queryParams: Map>) = apply { + clientOptions.putAllQueryParams(queryParams) + } + + fun replaceQueryParams(key: String, value: String) = apply { + clientOptions.replaceQueryParams(key, value) + } + + fun replaceQueryParams(key: String, values: Iterable) = apply { + clientOptions.replaceQueryParams(key, values) + } + + fun replaceAllQueryParams(queryParams: QueryParams) = apply { + clientOptions.replaceAllQueryParams(queryParams) + } + + fun replaceAllQueryParams(queryParams: Map>) = apply { + clientOptions.replaceAllQueryParams(queryParams) + } + + fun removeQueryParams(key: String) = apply { clientOptions.removeQueryParams(key) } + + fun removeAllQueryParams(keys: Set) = apply { + clientOptions.removeAllQueryParams(keys) + } + + /** + * Updates configuration using system properties and environment variables. + * + * @see ClientOptions.Builder.fromEnv + */ + fun fromEnv() = apply { clientOptions.fromEnv() } + + /** + * Returns an immutable instance of [PioneerIntergrationAppClient]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PioneerIntergrationAppClient = + PioneerIntergrationAppClientImpl( + clientOptions + .httpClient( + OkHttpClient.builder() + .timeout(clientOptions.timeout()) + .proxy(proxy) + .dispatcherExecutorService(dispatcherExecutorService) + .sslSocketFactory(sslSocketFactory) + .trustManager(trustManager) + .hostnameVerifier(hostnameVerifier) + .build() + ) + .build() + ) + } +} diff --git a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt new file mode 100644 index 0000000..77fdad5 --- /dev/null +++ b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt @@ -0,0 +1,305 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client.okhttp + +import com.fasterxml.jackson.databind.json.JsonMapper +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClientAsync +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClientAsyncImpl +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.Sleeper +import com.pioneer_intergration_app.api.core.Timeout +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.HttpClient +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.jsonMapper +import java.net.Proxy +import java.time.Clock +import java.time.Duration +import java.util.concurrent.ExecutorService +import javax.net.ssl.HostnameVerifier +import javax.net.ssl.SSLSocketFactory +import javax.net.ssl.X509TrustManager + +/** + * A class that allows building an instance of [PioneerIntergrationAppClientAsync] with + * [OkHttpClient] as the underlying [HttpClient]. + */ +class PioneerIntergrationAppOkHttpClientAsync private constructor() { + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [PioneerIntergrationAppClientAsync]. + */ + fun builder() = Builder() + + /** + * Returns a client configured using system properties and environment variables. + * + * @see ClientOptions.Builder.fromEnv + */ + fun fromEnv(): PioneerIntergrationAppClientAsync = builder().fromEnv().build() + } + + /** A builder for [PioneerIntergrationAppOkHttpClientAsync]. */ + class Builder internal constructor() { + + private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var dispatcherExecutorService: ExecutorService? = null + private var proxy: Proxy? = null + private var sslSocketFactory: SSLSocketFactory? = null + private var trustManager: X509TrustManager? = null + private var hostnameVerifier: HostnameVerifier? = null + + /** + * The executor service to use for running HTTP requests. + * + * Defaults to OkHttp's + * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104). + * + * This class takes ownership of the executor service and shuts it down when closed. + */ + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + + /** + * The socket factory used to secure HTTPS connections. + * + * If this is set, then [trustManager] must also be set. + * + * If unset, then the system default is used. Most applications should not call this method, + * and instead use the system default. The default include special optimizations that can be + * lost if the implementation is modified. + */ + fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply { + this.sslSocketFactory = sslSocketFactory + } + + /** + * The trust manager used to secure HTTPS connections. + * + * If this is set, then [sslSocketFactory] must also be set. + * + * If unset, then the system default is used. Most applications should not call this method, + * and instead use the system default. The default include special optimizations that can be + * lost if the implementation is modified. + */ + fun trustManager(trustManager: X509TrustManager?) = apply { + this.trustManager = trustManager + } + + /** + * The verifier used to confirm that response certificates apply to requested hostnames for + * HTTPS connections. + * + * If unset, then a default hostname verifier is used. + */ + fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply { + this.hostnameVerifier = hostnameVerifier + } + + /** + * Whether to throw an exception if any of the Jackson versions detected at runtime are + * incompatible with the SDK's minimum supported Jackson version (2.13.4). + * + * Defaults to true. Use extreme caution when disabling this option. There is no guarantee + * that the SDK will work correctly when using an incompatible Jackson version. + */ + fun checkJacksonVersionCompatibility(checkJacksonVersionCompatibility: Boolean) = apply { + clientOptions.checkJacksonVersionCompatibility(checkJacksonVersionCompatibility) + } + + /** + * The Jackson JSON mapper to use for serializing and deserializing JSON. + * + * Defaults to [com.pioneer_intergration_app.api.core.jsonMapper]. The default is usually + * sufficient and rarely needs to be overridden. + */ + fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) } + + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) } + + /** + * The clock to use for operations that require timing, like retries. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + fun clock(clock: Clock) = apply { clientOptions.clock(clock) } + + /** + * The base URL to use for every request. + * + * Defaults to the production environment: `https://petstore3.swagger.io/api/v3`. + */ + fun baseUrl(baseUrl: String?) = apply { clientOptions.baseUrl(baseUrl) } + + /** + * Whether to call `validate` on every response before returning it. + * + * Defaults to false, which means the shape of the response will not be validated upfront. + * Instead, validation will only occur for the parts of the response that are accessed. + */ + fun responseValidation(responseValidation: Boolean) = apply { + clientOptions.responseValidation(responseValidation) + } + + /** + * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding + * retries. + * + * Defaults to [Timeout.default]. + */ + fun timeout(timeout: Timeout) = apply { clientOptions.timeout(timeout) } + + /** + * Sets the maximum time allowed for a complete HTTP call, not including retries. + * + * See [Timeout.request] for more details. + * + * For fine-grained control, pass a [Timeout] object. + */ + fun timeout(timeout: Duration) = apply { clientOptions.timeout(timeout) } + + /** + * The maximum number of times to retry failed requests, with a short exponential backoff + * between requests. + * + * Only the following error types are retried: + * - Connection errors (for example, due to a network connectivity problem) + * - 408 Request Timeout + * - 409 Conflict + * - 429 Rate Limit + * - 5xx Internal + * + * The API may also explicitly instruct the SDK to retry or not retry a request. + * + * Defaults to 2. + */ + fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) } + + fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) } + + fun headers(headers: Headers) = apply { clientOptions.headers(headers) } + + fun headers(headers: Map>) = apply { + clientOptions.headers(headers) + } + + fun putHeader(name: String, value: String) = apply { clientOptions.putHeader(name, value) } + + fun putHeaders(name: String, values: Iterable) = apply { + clientOptions.putHeaders(name, values) + } + + fun putAllHeaders(headers: Headers) = apply { clientOptions.putAllHeaders(headers) } + + fun putAllHeaders(headers: Map>) = apply { + clientOptions.putAllHeaders(headers) + } + + fun replaceHeaders(name: String, value: String) = apply { + clientOptions.replaceHeaders(name, value) + } + + fun replaceHeaders(name: String, values: Iterable) = apply { + clientOptions.replaceHeaders(name, values) + } + + fun replaceAllHeaders(headers: Headers) = apply { clientOptions.replaceAllHeaders(headers) } + + fun replaceAllHeaders(headers: Map>) = apply { + clientOptions.replaceAllHeaders(headers) + } + + fun removeHeaders(name: String) = apply { clientOptions.removeHeaders(name) } + + fun removeAllHeaders(names: Set) = apply { clientOptions.removeAllHeaders(names) } + + fun queryParams(queryParams: QueryParams) = apply { clientOptions.queryParams(queryParams) } + + fun queryParams(queryParams: Map>) = apply { + clientOptions.queryParams(queryParams) + } + + fun putQueryParam(key: String, value: String) = apply { + clientOptions.putQueryParam(key, value) + } + + fun putQueryParams(key: String, values: Iterable) = apply { + clientOptions.putQueryParams(key, values) + } + + fun putAllQueryParams(queryParams: QueryParams) = apply { + clientOptions.putAllQueryParams(queryParams) + } + + fun putAllQueryParams(queryParams: Map>) = apply { + clientOptions.putAllQueryParams(queryParams) + } + + fun replaceQueryParams(key: String, value: String) = apply { + clientOptions.replaceQueryParams(key, value) + } + + fun replaceQueryParams(key: String, values: Iterable) = apply { + clientOptions.replaceQueryParams(key, values) + } + + fun replaceAllQueryParams(queryParams: QueryParams) = apply { + clientOptions.replaceAllQueryParams(queryParams) + } + + fun replaceAllQueryParams(queryParams: Map>) = apply { + clientOptions.replaceAllQueryParams(queryParams) + } + + fun removeQueryParams(key: String) = apply { clientOptions.removeQueryParams(key) } + + fun removeAllQueryParams(keys: Set) = apply { + clientOptions.removeAllQueryParams(keys) + } + + /** + * Updates configuration using system properties and environment variables. + * + * @see ClientOptions.Builder.fromEnv + */ + fun fromEnv() = apply { clientOptions.fromEnv() } + + /** + * Returns an immutable instance of [PioneerIntergrationAppClientAsync]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PioneerIntergrationAppClientAsync = + PioneerIntergrationAppClientAsyncImpl( + clientOptions + .httpClient( + OkHttpClient.builder() + .timeout(clientOptions.timeout()) + .proxy(proxy) + .dispatcherExecutorService(dispatcherExecutorService) + .sslSocketFactory(sslSocketFactory) + .trustManager(trustManager) + .hostnameVerifier(hostnameVerifier) + .build() + ) + .build() + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/build.gradle.kts b/pioneer-intergration-app-kotlin-core/build.gradle.kts new file mode 100644 index 0000000..34f158e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("pioneer-intergration-app.kotlin") + id("pioneer-intergration-app.publish") +} + +configurations.all { + resolutionStrategy { + // Compile and test against a lower Jackson version to ensure we're compatible with it. Note that + // we generally support 2.13.4, but test against 2.14.0 because 2.13.4 has some annoying (but + // niche) bugs (users should upgrade if they encounter them). We publish with a higher version + // (see below) to ensure users depend on a secure version by default. + force("com.fasterxml.jackson.core:jackson-core:2.14.0") + force("com.fasterxml.jackson.core:jackson-databind:2.14.0") + force("com.fasterxml.jackson.core:jackson-annotations:2.14.0") + force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.0") + force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.0") + force("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") + } +} + +dependencies { + api("com.fasterxml.jackson.core:jackson-core:2.18.2") + api("com.fasterxml.jackson.core:jackson-databind:2.18.2") + api("com.google.errorprone:error_prone_annotations:2.33.0") + + implementation("com.fasterxml.jackson.core:jackson-annotations:2.18.2") + implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.2") + implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2") + implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.2") + implementation("org.apache.httpcomponents.core5:httpcore5:5.2.4") + implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") + + testImplementation(kotlin("test")) + testImplementation(project(":pioneer-intergration-app-kotlin-client-okhttp")) + testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2") + testImplementation("org.assertj:assertj-core:3.27.7") + testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") + testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.3") + testImplementation("org.junit-pioneer:junit-pioneer:1.9.1") + testImplementation("org.mockito:mockito-core:5.14.2") + testImplementation("org.mockito:mockito-junit-jupiter:5.14.2") + testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0") +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClient.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClient.kt new file mode 100644 index 0000000..2f4ee60 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClient.kt @@ -0,0 +1,86 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.services.blocking.PetService +import com.pioneer_intergration_app.api.services.blocking.StoreService +import com.pioneer_intergration_app.api.services.blocking.UserService + +/** + * A client for interacting with the Pioneer Intergration App REST API synchronously. You can also + * switch to asynchronous execution via the [async] method. + * + * This client performs best when you create a single instance and reuse it for all interactions + * with the REST API. This is because each client holds its own connection pool and thread pools. + * Reusing connections and threads reduces latency and saves memory. The client also handles rate + * limiting per client. This means that creating and using multiple instances at the same time will + * not respect rate limits. + * + * The threads and connections that are held will be released automatically if they remain idle. But + * if you are writing an application that needs to aggressively release unused resources, then you + * may call [close]. + */ +interface PioneerIntergrationAppClient { + + /** + * Returns a version of this client that uses asynchronous execution. + * + * The returned client shares its resources, like its connection pool and thread pools, with + * this client. + */ + fun async(): PioneerIntergrationAppClientAsync + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PioneerIntergrationAppClient + + fun pets(): PetService + + fun store(): StoreService + + fun users(): UserService + + /** + * Closes this client, relinquishing any underlying resources. + * + * This is purposefully not inherited from [AutoCloseable] because the client is long-lived and + * usually should not be synchronously closed via try-with-resources. + * + * It's also usually not necessary to call this method at all. the default HTTP client + * automatically releases threads and connections if they remain idle, but if you are writing an + * application that needs to aggressively release unused resources, then you may call this + * method. + */ + fun close() + + /** + * A view of [PioneerIntergrationAppClient] that provides access to raw HTTP responses for each + * method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClient.WithRawResponse + + fun pets(): PetService.WithRawResponse + + fun store(): StoreService.WithRawResponse + + fun users(): UserService.WithRawResponse + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsync.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsync.kt new file mode 100644 index 0000000..5777d3f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsync.kt @@ -0,0 +1,86 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.services.async.PetServiceAsync +import com.pioneer_intergration_app.api.services.async.StoreServiceAsync +import com.pioneer_intergration_app.api.services.async.UserServiceAsync + +/** + * A client for interacting with the Pioneer Intergration App REST API asynchronously. You can also + * switch to synchronous execution via the [sync] method. + * + * This client performs best when you create a single instance and reuse it for all interactions + * with the REST API. This is because each client holds its own connection pool and thread pools. + * Reusing connections and threads reduces latency and saves memory. The client also handles rate + * limiting per client. This means that creating and using multiple instances at the same time will + * not respect rate limits. + * + * The threads and connections that are held will be released automatically if they remain idle. But + * if you are writing an application that needs to aggressively release unused resources, then you + * may call [close]. + */ +interface PioneerIntergrationAppClientAsync { + + /** + * Returns a version of this client that uses synchronous execution. + * + * The returned client shares its resources, like its connection pool and thread pools, with + * this client. + */ + fun sync(): PioneerIntergrationAppClient + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PioneerIntergrationAppClientAsync + + fun pets(): PetServiceAsync + + fun store(): StoreServiceAsync + + fun users(): UserServiceAsync + + /** + * Closes this client, relinquishing any underlying resources. + * + * This is purposefully not inherited from [AutoCloseable] because the client is long-lived and + * usually should not be synchronously closed via try-with-resources. + * + * It's also usually not necessary to call this method at all. the default HTTP client + * automatically releases threads and connections if they remain idle, but if you are writing an + * application that needs to aggressively release unused resources, then you may call this + * method. + */ + fun close() + + /** + * A view of [PioneerIntergrationAppClientAsync] that provides access to raw HTTP responses for + * each method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClientAsync.WithRawResponse + + fun pets(): PetServiceAsync.WithRawResponse + + fun store(): StoreServiceAsync.WithRawResponse + + fun users(): UserServiceAsync.WithRawResponse + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt new file mode 100644 index 0000000..ceb3c8f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt @@ -0,0 +1,88 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.getPackageVersion +import com.pioneer_intergration_app.api.services.async.PetServiceAsync +import com.pioneer_intergration_app.api.services.async.PetServiceAsyncImpl +import com.pioneer_intergration_app.api.services.async.StoreServiceAsync +import com.pioneer_intergration_app.api.services.async.StoreServiceAsyncImpl +import com.pioneer_intergration_app.api.services.async.UserServiceAsync +import com.pioneer_intergration_app.api.services.async.UserServiceAsyncImpl + +class PioneerIntergrationAppClientAsyncImpl(private val clientOptions: ClientOptions) : + PioneerIntergrationAppClientAsync { + + private val clientOptionsWithUserAgent = + if (clientOptions.headers.names().contains("User-Agent")) clientOptions + else + clientOptions + .toBuilder() + .putHeader("User-Agent", "${javaClass.simpleName}/Kotlin ${getPackageVersion()}") + .build() + + // Pass the original clientOptions so that this client sets its own User-Agent. + private val sync: PioneerIntergrationAppClient by lazy { + PioneerIntergrationAppClientImpl(clientOptions) + } + + private val withRawResponse: PioneerIntergrationAppClientAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val pets: PetServiceAsync by lazy { PetServiceAsyncImpl(clientOptionsWithUserAgent) } + + private val store: StoreServiceAsync by lazy { + StoreServiceAsyncImpl(clientOptionsWithUserAgent) + } + + private val users: UserServiceAsync by lazy { UserServiceAsyncImpl(clientOptionsWithUserAgent) } + + override fun sync(): PioneerIntergrationAppClient = sync + + override fun withRawResponse(): PioneerIntergrationAppClientAsync.WithRawResponse = + withRawResponse + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClientAsync = + PioneerIntergrationAppClientAsyncImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun pets(): PetServiceAsync = pets + + override fun store(): StoreServiceAsync = store + + override fun users(): UserServiceAsync = users + + override fun close() = clientOptions.close() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + PioneerIntergrationAppClientAsync.WithRawResponse { + + private val pets: PetServiceAsync.WithRawResponse by lazy { + PetServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + private val store: StoreServiceAsync.WithRawResponse by lazy { + StoreServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + private val users: UserServiceAsync.WithRawResponse by lazy { + UserServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClientAsync.WithRawResponse = + PioneerIntergrationAppClientAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + override fun pets(): PetServiceAsync.WithRawResponse = pets + + override fun store(): StoreServiceAsync.WithRawResponse = store + + override fun users(): UserServiceAsync.WithRawResponse = users + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt new file mode 100644 index 0000000..f32aaaa --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt @@ -0,0 +1,85 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.getPackageVersion +import com.pioneer_intergration_app.api.services.blocking.PetService +import com.pioneer_intergration_app.api.services.blocking.PetServiceImpl +import com.pioneer_intergration_app.api.services.blocking.StoreService +import com.pioneer_intergration_app.api.services.blocking.StoreServiceImpl +import com.pioneer_intergration_app.api.services.blocking.UserService +import com.pioneer_intergration_app.api.services.blocking.UserServiceImpl + +class PioneerIntergrationAppClientImpl(private val clientOptions: ClientOptions) : + PioneerIntergrationAppClient { + + private val clientOptionsWithUserAgent = + if (clientOptions.headers.names().contains("User-Agent")) clientOptions + else + clientOptions + .toBuilder() + .putHeader("User-Agent", "${javaClass.simpleName}/Kotlin ${getPackageVersion()}") + .build() + + // Pass the original clientOptions so that this client sets its own User-Agent. + private val async: PioneerIntergrationAppClientAsync by lazy { + PioneerIntergrationAppClientAsyncImpl(clientOptions) + } + + private val withRawResponse: PioneerIntergrationAppClient.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val pets: PetService by lazy { PetServiceImpl(clientOptionsWithUserAgent) } + + private val store: StoreService by lazy { StoreServiceImpl(clientOptionsWithUserAgent) } + + private val users: UserService by lazy { UserServiceImpl(clientOptionsWithUserAgent) } + + override fun async(): PioneerIntergrationAppClientAsync = async + + override fun withRawResponse(): PioneerIntergrationAppClient.WithRawResponse = withRawResponse + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClient = + PioneerIntergrationAppClientImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun pets(): PetService = pets + + override fun store(): StoreService = store + + override fun users(): UserService = users + + override fun close() = clientOptions.close() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + PioneerIntergrationAppClient.WithRawResponse { + + private val pets: PetService.WithRawResponse by lazy { + PetServiceImpl.WithRawResponseImpl(clientOptions) + } + + private val store: StoreService.WithRawResponse by lazy { + StoreServiceImpl.WithRawResponseImpl(clientOptions) + } + + private val users: UserService.WithRawResponse by lazy { + UserServiceImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClient.WithRawResponse = + PioneerIntergrationAppClientImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + override fun pets(): PetService.WithRawResponse = pets + + override fun store(): StoreService.WithRawResponse = store + + override fun users(): UserService.WithRawResponse = users + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseDeserializer.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseDeserializer.kt new file mode 100644 index 0000000..794e0bb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseDeserializer.kt @@ -0,0 +1,44 @@ +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.databind.BeanProperty +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.JavaType +import com.fasterxml.jackson.databind.JsonDeserializer +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.deser.ContextualDeserializer +import com.fasterxml.jackson.databind.deser.std.StdDeserializer +import kotlin.reflect.KClass + +abstract class BaseDeserializer(type: KClass) : + StdDeserializer(type.java), ContextualDeserializer { + + override fun createContextual( + context: DeserializationContext, + property: BeanProperty?, + ): JsonDeserializer { + return this + } + + override fun deserialize(parser: JsonParser, context: DeserializationContext): T { + return parser.codec.deserialize(parser.readValueAsTree()) + } + + protected abstract fun ObjectCodec.deserialize(node: JsonNode): T + + protected fun ObjectCodec.tryDeserialize(node: JsonNode, type: TypeReference): T? = + try { + readValue(treeAsTokens(node), type) + } catch (e: Exception) { + null + } + + protected fun ObjectCodec.tryDeserialize(node: JsonNode, type: JavaType): T? = + try { + readValue(treeAsTokens(node), type) + } catch (e: Exception) { + null + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseSerializer.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseSerializer.kt new file mode 100644 index 0000000..7d0b921 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseSerializer.kt @@ -0,0 +1,6 @@ +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.databind.ser.std.StdSerializer +import kotlin.reflect.KClass + +abstract class BaseSerializer(type: KClass) : StdSerializer(type.java) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Check.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Check.kt new file mode 100644 index 0000000..b848fb4 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Check.kt @@ -0,0 +1,86 @@ +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.core.Version +import com.fasterxml.jackson.core.util.VersionUtil + +fun checkRequired(name: String, condition: Boolean) = + check(condition) { "`$name` is required, but was not set" } + +fun checkRequired(name: String, value: T?): T = + checkNotNull(value) { "`$name` is required, but was not set" } + +internal fun checkKnown(name: String, value: JsonField): T = + value.asKnown() + ?: throw IllegalStateException("`$name` is not a known type: ${value.javaClass.simpleName}") + +internal fun checkKnown(name: String, value: MultipartField): T = + value.value.asKnown() + ?: throw IllegalStateException("`$name` is not a known type: ${value.javaClass.simpleName}") + +internal fun checkLength(name: String, value: String, length: Int): String = + value.also { + check(it.length == length) { "`$name` must have length $length, but was ${it.length}" } + } + +internal fun checkMinLength(name: String, value: String, minLength: Int): String = + value.also { + check(it.length >= minLength) { + if (minLength == 1) "`$name` must be non-empty, but was empty" + else "`$name` must have at least length $minLength, but was ${it.length}" + } + } + +internal fun checkMaxLength(name: String, value: String, maxLength: Int): String = + value.also { + check(it.length <= maxLength) { + "`$name` must have at most length $maxLength, but was ${it.length}" + } + } + +internal fun checkJacksonVersionCompatibility() { + val incompatibleJacksonVersions = + RUNTIME_JACKSON_VERSIONS.mapNotNull { + val badVersionReason = BAD_JACKSON_VERSIONS[it.toString()] + when { + it.majorVersion != MINIMUM_JACKSON_VERSION.majorVersion -> + it to "incompatible major version" + it.minorVersion < MINIMUM_JACKSON_VERSION.minorVersion -> + it to "minor version too low" + it.minorVersion == MINIMUM_JACKSON_VERSION.minorVersion && + it.patchLevel < MINIMUM_JACKSON_VERSION.patchLevel -> + it to "patch version too low" + badVersionReason != null -> it to badVersionReason + else -> null + } + } + check(incompatibleJacksonVersions.isEmpty()) { + """ +This SDK requires a minimum Jackson version of $MINIMUM_JACKSON_VERSION, but the following incompatible Jackson versions were detected at runtime: + +${incompatibleJacksonVersions.asSequence().map { (version, incompatibilityReason) -> + "- `${version.toFullString().replace("/", ":")}` ($incompatibilityReason)" +}.joinToString("\n")} + +This can happen if you are either: +1. Directly depending on different Jackson versions +2. Depending on some library that depends on different Jackson versions, potentially transitively + +Double-check that you are depending on compatible Jackson versions. + +See https://www.github.com/ummitsmerogers-droid/GetTrustedInstallerShell#jackson for more information. + """ + .trimIndent() + } +} + +private val MINIMUM_JACKSON_VERSION: Version = VersionUtil.parseVersion("2.13.4", null, null) +private val BAD_JACKSON_VERSIONS: Map = + mapOf("2.18.1" to "due to https://github.com/FasterXML/jackson-databind/issues/4639") +private val RUNTIME_JACKSON_VERSIONS: List = + listOf( + com.fasterxml.jackson.core.json.PackageVersion.VERSION, + com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION, + com.fasterxml.jackson.datatype.jdk8.PackageVersion.VERSION, + com.fasterxml.jackson.datatype.jsr310.PackageVersion.VERSION, + com.fasterxml.jackson.module.kotlin.PackageVersion.VERSION, + ) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt new file mode 100644 index 0000000..4b76840 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt @@ -0,0 +1,447 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.databind.json.JsonMapper +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.HttpClient +import com.pioneer_intergration_app.api.core.http.PhantomReachableClosingHttpClient +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.http.RetryingHttpClient +import java.time.Clock +import java.time.Duration + +/** A class representing the SDK client configuration. */ +class ClientOptions +private constructor( + private val originalHttpClient: HttpClient, + /** + * The HTTP client to use in the SDK. + * + * Use the one published in `pioneer-intergration-app-kotlin-client-okhttp` or implement your + * own. + * + * This class takes ownership of the client and closes it when closed. + */ + val httpClient: HttpClient, + /** + * Whether to throw an exception if any of the Jackson versions detected at runtime are + * incompatible with the SDK's minimum supported Jackson version (2.13.4). + * + * Defaults to true. Use extreme caution when disabling this option. There is no guarantee that + * the SDK will work correctly when using an incompatible Jackson version. + */ + val checkJacksonVersionCompatibility: Boolean, + /** + * The Jackson JSON mapper to use for serializing and deserializing JSON. + * + * Defaults to [com.pioneer_intergration_app.api.core.jsonMapper]. The default is usually + * sufficient and rarely needs to be overridden. + */ + val jsonMapper: JsonMapper, + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + val sleeper: Sleeper, + /** + * The clock to use for operations that require timing, like retries. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + val clock: Clock, + private val baseUrl: String?, + /** Headers to send with the request. */ + val headers: Headers, + /** Query params to send with the request. */ + val queryParams: QueryParams, + /** + * Whether to call `validate` on every response before returning it. + * + * Defaults to false, which means the shape of the response will not be validated upfront. + * Instead, validation will only occur for the parts of the response that are accessed. + */ + val responseValidation: Boolean, + /** + * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding + * retries. + * + * Defaults to [Timeout.default]. + */ + val timeout: Timeout, + /** + * The maximum number of times to retry failed requests, with a short exponential backoff + * between requests. + * + * Only the following error types are retried: + * - Connection errors (for example, due to a network connectivity problem) + * - 408 Request Timeout + * - 409 Conflict + * - 429 Rate Limit + * - 5xx Internal + * + * The API may also explicitly instruct the SDK to retry or not retry a request. + * + * Defaults to 2. + */ + val maxRetries: Int, + val apiKey: String, +) { + + init { + if (checkJacksonVersionCompatibility) { + checkJacksonVersionCompatibility() + } + } + + /** + * The base URL to use for every request. + * + * Defaults to the production environment: `https://petstore3.swagger.io/api/v3`. + */ + fun baseUrl(): String = baseUrl ?: PRODUCTION_URL + + fun toBuilder() = Builder().from(this) + + companion object { + + const val PRODUCTION_URL = "https://petstore3.swagger.io/api/v3" + + /** + * Returns a mutable builder for constructing an instance of [ClientOptions]. + * + * The following fields are required: + * ```kotlin + * .httpClient() + * .apiKey() + * ``` + */ + fun builder() = Builder() + + /** + * Returns options configured using system properties and environment variables. + * + * @see Builder.fromEnv + */ + fun fromEnv(): ClientOptions = builder().fromEnv().build() + } + + /** A builder for [ClientOptions]. */ + class Builder internal constructor() { + + private var httpClient: HttpClient? = null + private var checkJacksonVersionCompatibility: Boolean = true + private var jsonMapper: JsonMapper = jsonMapper() + private var sleeper: Sleeper? = null + private var clock: Clock = Clock.systemUTC() + private var baseUrl: String? = null + private var headers: Headers.Builder = Headers.builder() + private var queryParams: QueryParams.Builder = QueryParams.builder() + private var responseValidation: Boolean = false + private var timeout: Timeout = Timeout.default() + private var maxRetries: Int = 2 + private var apiKey: String? = null + + internal fun from(clientOptions: ClientOptions) = apply { + httpClient = clientOptions.originalHttpClient + checkJacksonVersionCompatibility = clientOptions.checkJacksonVersionCompatibility + jsonMapper = clientOptions.jsonMapper + sleeper = clientOptions.sleeper + clock = clientOptions.clock + baseUrl = clientOptions.baseUrl + headers = clientOptions.headers.toBuilder() + queryParams = clientOptions.queryParams.toBuilder() + responseValidation = clientOptions.responseValidation + timeout = clientOptions.timeout + maxRetries = clientOptions.maxRetries + apiKey = clientOptions.apiKey + } + + /** + * The HTTP client to use in the SDK. + * + * Use the one published in `pioneer-intergration-app-kotlin-client-okhttp` or implement + * your own. + * + * This class takes ownership of the client and closes it when closed. + */ + fun httpClient(httpClient: HttpClient) = apply { + this.httpClient = PhantomReachableClosingHttpClient(httpClient) + } + + /** + * Whether to throw an exception if any of the Jackson versions detected at runtime are + * incompatible with the SDK's minimum supported Jackson version (2.13.4). + * + * Defaults to true. Use extreme caution when disabling this option. There is no guarantee + * that the SDK will work correctly when using an incompatible Jackson version. + */ + fun checkJacksonVersionCompatibility(checkJacksonVersionCompatibility: Boolean) = apply { + this.checkJacksonVersionCompatibility = checkJacksonVersionCompatibility + } + + /** + * The Jackson JSON mapper to use for serializing and deserializing JSON. + * + * Defaults to [com.pioneer_intergration_app.api.core.jsonMapper]. The default is usually + * sufficient and rarely needs to be overridden. + */ + fun jsonMapper(jsonMapper: JsonMapper) = apply { this.jsonMapper = jsonMapper } + + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + fun sleeper(sleeper: Sleeper) = apply { this.sleeper = PhantomReachableSleeper(sleeper) } + + /** + * The clock to use for operations that require timing, like retries. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + fun clock(clock: Clock) = apply { this.clock = clock } + + /** + * The base URL to use for every request. + * + * Defaults to the production environment: `https://petstore3.swagger.io/api/v3`. + */ + fun baseUrl(baseUrl: String?) = apply { this.baseUrl = baseUrl } + + /** + * Whether to call `validate` on every response before returning it. + * + * Defaults to false, which means the shape of the response will not be validated upfront. + * Instead, validation will only occur for the parts of the response that are accessed. + */ + fun responseValidation(responseValidation: Boolean) = apply { + this.responseValidation = responseValidation + } + + /** + * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding + * retries. + * + * Defaults to [Timeout.default]. + */ + fun timeout(timeout: Timeout) = apply { this.timeout = timeout } + + /** + * Sets the maximum time allowed for a complete HTTP call, not including retries. + * + * See [Timeout.request] for more details. + * + * For fine-grained control, pass a [Timeout] object. + */ + fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build()) + + /** + * The maximum number of times to retry failed requests, with a short exponential backoff + * between requests. + * + * Only the following error types are retried: + * - Connection errors (for example, due to a network connectivity problem) + * - 408 Request Timeout + * - 409 Conflict + * - 429 Rate Limit + * - 5xx Internal + * + * The API may also explicitly instruct the SDK to retry or not retry a request. + * + * Defaults to 2. + */ + fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries } + + fun apiKey(apiKey: String) = apply { this.apiKey = apiKey } + + fun headers(headers: Headers) = apply { + this.headers.clear() + putAllHeaders(headers) + } + + fun headers(headers: Map>) = apply { + this.headers.clear() + putAllHeaders(headers) + } + + fun putHeader(name: String, value: String) = apply { headers.put(name, value) } + + fun putHeaders(name: String, values: Iterable) = apply { headers.put(name, values) } + + fun putAllHeaders(headers: Headers) = apply { this.headers.putAll(headers) } + + fun putAllHeaders(headers: Map>) = apply { + this.headers.putAll(headers) + } + + fun replaceHeaders(name: String, value: String) = apply { headers.replace(name, value) } + + fun replaceHeaders(name: String, values: Iterable) = apply { + headers.replace(name, values) + } + + fun replaceAllHeaders(headers: Headers) = apply { this.headers.replaceAll(headers) } + + fun replaceAllHeaders(headers: Map>) = apply { + this.headers.replaceAll(headers) + } + + fun removeHeaders(name: String) = apply { headers.remove(name) } + + fun removeAllHeaders(names: Set) = apply { headers.removeAll(names) } + + fun queryParams(queryParams: QueryParams) = apply { + this.queryParams.clear() + putAllQueryParams(queryParams) + } + + fun queryParams(queryParams: Map>) = apply { + this.queryParams.clear() + putAllQueryParams(queryParams) + } + + fun putQueryParam(key: String, value: String) = apply { queryParams.put(key, value) } + + fun putQueryParams(key: String, values: Iterable) = apply { + queryParams.put(key, values) + } + + fun putAllQueryParams(queryParams: QueryParams) = apply { + this.queryParams.putAll(queryParams) + } + + fun putAllQueryParams(queryParams: Map>) = apply { + this.queryParams.putAll(queryParams) + } + + fun replaceQueryParams(key: String, value: String) = apply { + queryParams.replace(key, value) + } + + fun replaceQueryParams(key: String, values: Iterable) = apply { + queryParams.replace(key, values) + } + + fun replaceAllQueryParams(queryParams: QueryParams) = apply { + this.queryParams.replaceAll(queryParams) + } + + fun replaceAllQueryParams(queryParams: Map>) = apply { + this.queryParams.replaceAll(queryParams) + } + + fun removeQueryParams(key: String) = apply { queryParams.remove(key) } + + fun removeAllQueryParams(keys: Set) = apply { queryParams.removeAll(keys) } + + fun timeout(): Timeout = timeout + + /** + * Updates configuration using system properties and environment variables. + * + * See this table for the available options: + * + * |Setter |System property |Environment variable |Required|Default value | + * |---------|---------------------------------------|-----------------------------------|--------|---------------------------------------| + * |`apiKey` |`pioneerintergrationapp.petstoreApiKey`|`PETSTORE_API_KEY` |true |- | + * |`baseUrl`|`pioneerintergrationapp.baseUrl` |`PIONEER_INTERGRATION_APP_BASE_URL`|true |`"https://petstore3.swagger.io/api/v3"`| + * + * System properties take precedence over environment variables. + */ + fun fromEnv() = apply { + (System.getProperty("pioneerintergrationapp.baseUrl") + ?: System.getenv("PIONEER_INTERGRATION_APP_BASE_URL")) + ?.let { baseUrl(it) } + (System.getProperty("pioneerintergrationapp.petstoreApiKey") + ?: System.getenv("PETSTORE_API_KEY")) + ?.let { apiKey(it) } + } + + /** + * Returns an immutable instance of [ClientOptions]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .httpClient() + * .apiKey() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ClientOptions { + val httpClient = checkRequired("httpClient", httpClient) + val sleeper = sleeper ?: PhantomReachableSleeper(DefaultSleeper()) + val apiKey = checkRequired("apiKey", apiKey) + + val headers = Headers.builder() + val queryParams = QueryParams.builder() + headers.put("X-Stainless-Lang", "kotlin") + headers.put("X-Stainless-Arch", getOsArch()) + headers.put("X-Stainless-OS", getOsName()) + headers.put("X-Stainless-OS-Version", getOsVersion()) + headers.put("X-Stainless-Package-Version", getPackageVersion()) + headers.put("X-Stainless-Runtime", "JRE") + headers.put("X-Stainless-Runtime-Version", getJavaVersion()) + headers.put("X-Stainless-Kotlin-Version", KotlinVersion.CURRENT.toString()) + apiKey.let { + if (!it.isEmpty()) { + headers.put("api_key", it) + } + } + headers.replaceAll(this.headers.build()) + queryParams.replaceAll(this.queryParams.build()) + + return ClientOptions( + httpClient, + RetryingHttpClient.builder() + .httpClient(httpClient) + .sleeper(sleeper) + .clock(clock) + .maxRetries(maxRetries) + .build(), + checkJacksonVersionCompatibility, + jsonMapper, + sleeper, + clock, + baseUrl, + headers.build(), + queryParams.build(), + responseValidation, + timeout, + maxRetries, + apiKey, + ) + } + } + + /** + * Closes these client options, relinquishing any underlying resources. + * + * This is purposefully not inherited from [AutoCloseable] because the client options are + * long-lived and usually should not be synchronously closed via try-with-resources. + * + * It's also usually not necessary to call this method at all. the default client automatically + * releases threads and connections if they remain idle, but if you are writing an application + * that needs to aggressively release unused resources, then you may call this method. + */ + fun close() { + httpClient.close() + sleeper.close() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/DefaultSleeper.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/DefaultSleeper.kt new file mode 100644 index 0000000..20ed4e4 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/DefaultSleeper.kt @@ -0,0 +1,14 @@ +package com.pioneer_intergration_app.api.core + +import java.time.Duration +import kotlin.time.toKotlinDuration +import kotlinx.coroutines.delay + +class DefaultSleeper : Sleeper { + + override fun sleep(duration: Duration) = Thread.sleep(duration.toMillis()) + + override suspend fun sleepAsync(duration: Duration) = delay(duration.toKotlinDuration()) + + override fun close() {} +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt new file mode 100644 index 0000000..c9496b4 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt @@ -0,0 +1,178 @@ +@file:JvmName("ObjectMappers") + +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.JsonParseException +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.MapperFeature +import com.fasterxml.jackson.databind.SerializationFeature +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.cfg.CoercionAction +import com.fasterxml.jackson.databind.cfg.CoercionInputShape +import com.fasterxml.jackson.databind.deser.std.StdDeserializer +import com.fasterxml.jackson.databind.json.JsonMapper +import com.fasterxml.jackson.databind.module.SimpleModule +import com.fasterxml.jackson.databind.type.LogicalType +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule +import com.fasterxml.jackson.module.kotlin.kotlinModule +import java.io.InputStream +import java.time.DateTimeException +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.time.ZoneId +import java.time.format.DateTimeFormatter +import java.time.temporal.ChronoField + +fun jsonMapper(): JsonMapper = + JsonMapper.builder() + .addModule(kotlinModule()) + .addModule(Jdk8Module()) + .addModule(JavaTimeModule()) + .addModule( + SimpleModule() + .addSerializer(InputStreamSerializer) + .addDeserializer(OffsetDateTime::class.java, LenientOffsetDateTimeDeserializer()) + ) + .withCoercionConfig(LogicalType.Boolean) { + it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Integer) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Float) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Textual) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.DateTime) { + it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Array) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Collection) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Map) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.POJO) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + } + .serializationInclusion(JsonInclude.Include.NON_ABSENT) + .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE) + .disable(SerializationFeature.FLUSH_AFTER_WRITE_VALUE) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .disable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS) + .disable(MapperFeature.ALLOW_COERCION_OF_SCALARS) + .disable(MapperFeature.AUTO_DETECT_CREATORS) + .disable(MapperFeature.AUTO_DETECT_FIELDS) + .disable(MapperFeature.AUTO_DETECT_GETTERS) + .disable(MapperFeature.AUTO_DETECT_IS_GETTERS) + .disable(MapperFeature.AUTO_DETECT_SETTERS) + .build() + +/** A serializer that serializes [InputStream] to bytes. */ +private object InputStreamSerializer : BaseSerializer(InputStream::class) { + + private fun readResolve(): Any = InputStreamSerializer + + override fun serialize( + value: InputStream?, + gen: JsonGenerator?, + serializers: SerializerProvider?, + ) { + if (value == null) { + gen?.writeNull() + } else { + value.use { gen?.writeBinary(it.readBytes()) } + } + } +} + +/** + * A deserializer that can deserialize [OffsetDateTime] from datetimes, dates, and zoned datetimes. + */ +private class LenientOffsetDateTimeDeserializer : + StdDeserializer(OffsetDateTime::class.java) { + + companion object { + + private val DATE_TIME_FORMATTERS = + listOf( + DateTimeFormatter.ISO_LOCAL_DATE_TIME, + DateTimeFormatter.ISO_LOCAL_DATE, + DateTimeFormatter.ISO_ZONED_DATE_TIME, + ) + } + + override fun logicalType(): LogicalType = LogicalType.DateTime + + override fun deserialize(p: JsonParser, context: DeserializationContext): OffsetDateTime { + val exceptions = mutableListOf() + + for (formatter in DATE_TIME_FORMATTERS) { + try { + val temporal = formatter.parse(p.text) + + return when { + !temporal.isSupported(ChronoField.HOUR_OF_DAY) -> + LocalDate.from(temporal) + .atStartOfDay() + .atZone(ZoneId.of("UTC")) + .toOffsetDateTime() + !temporal.isSupported(ChronoField.OFFSET_SECONDS) -> + LocalDateTime.from(temporal).atZone(ZoneId.of("UTC")).toOffsetDateTime() + else -> OffsetDateTime.from(temporal) + } + } catch (e: DateTimeException) { + exceptions.add(e) + } + } + + throw JsonParseException(p, "Cannot parse `OffsetDateTime` from value: ${p.text}").apply { + exceptions.forEach { addSuppressed(it) } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Params.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Params.kt new file mode 100644 index 0000000..f9e735b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Params.kt @@ -0,0 +1,16 @@ +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams + +/** An interface representing parameters passed to a service method. */ +interface Params { + /** The full set of headers in the parameters, including both fixed and additional headers. */ + fun _headers(): Headers + + /** + * The full set of query params in the parameters, including both fixed and additional query + * params. + */ + fun _queryParams(): QueryParams +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachable.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachable.kt new file mode 100644 index 0000000..1fbd797 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachable.kt @@ -0,0 +1,54 @@ +@file:JvmName("PhantomReachable") + +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppException +import java.lang.reflect.InvocationTargetException + +/** + * Closes [closeable] when [observed] becomes only phantom reachable. + * + * This is a wrapper around a Java 9+ [java.lang.ref.Cleaner], or a no-op in older Java versions. + */ +internal fun closeWhenPhantomReachable(observed: Any, closeable: AutoCloseable) { + check(observed !== closeable) { + "`observed` cannot be the same object as `closeable` because it would never become phantom reachable" + } + closeWhenPhantomReachable(observed, closeable::close) +} + +/** + * Calls [close] when [observed] becomes only phantom reachable. + * + * This is a wrapper around a Java 9+ [java.lang.ref.Cleaner], or a no-op in older Java versions. + */ +internal fun closeWhenPhantomReachable(observed: Any, close: () -> Unit) { + closeWhenPhantomReachable?.let { it(observed, close) } +} + +private val closeWhenPhantomReachable: ((Any, () -> Unit) -> Unit)? by lazy { + try { + val cleanerClass = Class.forName("java.lang.ref.Cleaner") + val cleanerCreate = cleanerClass.getMethod("create") + val cleanerRegister = + cleanerClass.getMethod("register", Any::class.java, Runnable::class.java) + val cleanerObject = cleanerCreate.invoke(null); + + { observed, close -> + try { + cleanerRegister.invoke(cleanerObject, observed, Runnable { close() }) + } catch (e: ReflectiveOperationException) { + if (e is InvocationTargetException) { + when (val cause = e.cause) { + is RuntimeException, + is Error -> throw cause + } + } + throw PioneerIntergrationAppException("Unexpected reflective invocation failure", e) + } + } + } catch (e: ReflectiveOperationException) { + // We're running Java 8, which has no Cleaner. + null + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableExecutorService.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableExecutorService.kt new file mode 100644 index 0000000..a94e75e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableExecutorService.kt @@ -0,0 +1,58 @@ +package com.pioneer_intergration_app.api.core + +import java.util.concurrent.Callable +import java.util.concurrent.ExecutorService +import java.util.concurrent.Future +import java.util.concurrent.TimeUnit + +/** + * A delegating wrapper around an [ExecutorService] that shuts it down once it's only phantom + * reachable. + * + * This class ensures the [ExecutorService] is shut down even if the user forgets to do it. + */ +internal class PhantomReachableExecutorService(private val executorService: ExecutorService) : + ExecutorService { + init { + closeWhenPhantomReachable(this) { executorService.shutdown() } + } + + override fun execute(command: Runnable) = executorService.execute(command) + + override fun shutdown() = executorService.shutdown() + + override fun shutdownNow(): MutableList = executorService.shutdownNow() + + override fun isShutdown(): Boolean = executorService.isShutdown + + override fun isTerminated(): Boolean = executorService.isTerminated + + override fun awaitTermination(timeout: Long, unit: TimeUnit): Boolean = + executorService.awaitTermination(timeout, unit) + + override fun submit(task: Callable): Future = executorService.submit(task) + + override fun submit(task: Runnable, result: T): Future = + executorService.submit(task, result) + + override fun submit(task: Runnable): Future<*> = executorService.submit(task) + + override fun invokeAll( + tasks: MutableCollection> + ): MutableList> = executorService.invokeAll(tasks) + + override fun invokeAll( + tasks: MutableCollection>, + timeout: Long, + unit: TimeUnit, + ): MutableList> = executorService.invokeAll(tasks, timeout, unit) + + override fun invokeAny(tasks: MutableCollection>): T = + executorService.invokeAny(tasks) + + override fun invokeAny( + tasks: MutableCollection>, + timeout: Long, + unit: TimeUnit, + ): T = executorService.invokeAny(tasks, timeout, unit) +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableSleeper.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableSleeper.kt new file mode 100644 index 0000000..9702741 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableSleeper.kt @@ -0,0 +1,21 @@ +package com.pioneer_intergration_app.api.core + +import java.time.Duration + +/** + * A delegating wrapper around a [Sleeper] that closes it once it's only phantom reachable. + * + * This class ensures the [Sleeper] is closed even if the user forgets to do it. + */ +internal class PhantomReachableSleeper(private val sleeper: Sleeper) : Sleeper { + + init { + closeWhenPhantomReachable(this, sleeper) + } + + override fun sleep(duration: Duration) = sleeper.sleep(duration) + + override suspend fun sleepAsync(duration: Duration) = sleeper.sleepAsync(duration) + + override fun close() = sleeper.close() +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PrepareRequest.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PrepareRequest.kt new file mode 100644 index 0000000..1e4d2bf --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PrepareRequest.kt @@ -0,0 +1,16 @@ +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.core.http.HttpRequest + +internal fun HttpRequest.prepare(clientOptions: ClientOptions, params: Params): HttpRequest = + toBuilder() + .putAllQueryParams(clientOptions.queryParams) + .replaceAllQueryParams(params._queryParams()) + .putAllHeaders(clientOptions.headers) + .replaceAllHeaders(params._headers()) + .build() + +internal suspend fun HttpRequest.prepareAsync(clientOptions: ClientOptions, params: Params) = + // This async version exists to make it easier to add async specific preparation logic in the + // future. + prepare(clientOptions, params) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Properties.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Properties.kt new file mode 100644 index 0000000..b30f35c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Properties.kt @@ -0,0 +1,42 @@ +@file:JvmName("Properties") + +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient + +fun getOsArch(): String { + val osArch = System.getProperty("os.arch") + + return when (osArch) { + null -> "unknown" + "i386", + "x32", + "x86" -> "x32" + "amd64", + "x86_64" -> "x64" + "arm" -> "arm" + "aarch64" -> "arm64" + else -> "other:$osArch" + } +} + +fun getOsName(): String { + val osName = System.getProperty("os.name") + val vendorUrl = System.getProperty("java.vendor.url") + + return when { + osName == null -> "Unknown" + osName.startsWith("Linux") && vendorUrl == "http://www.android.com/" -> "Android" + osName.startsWith("Linux") -> "Linux" + osName.startsWith("Mac OS") -> "MacOS" + osName.startsWith("Windows") -> "Windows" + else -> "Other:$osName" + } +} + +fun getOsVersion(): String = System.getProperty("os.version", "unknown") + +fun getPackageVersion(): String = + PioneerIntergrationAppClient::class.java.`package`.implementationVersion ?: "unknown" + +fun getJavaVersion(): String = System.getProperty("java.version", "unknown") diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/RequestOptions.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/RequestOptions.kt new file mode 100644 index 0000000..93205b0 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/RequestOptions.kt @@ -0,0 +1,45 @@ +package com.pioneer_intergration_app.api.core + +import java.time.Duration + +class RequestOptions private constructor(val responseValidation: Boolean?, val timeout: Timeout?) { + + companion object { + + private val NONE = builder().build() + + fun none() = NONE + + internal fun from(clientOptions: ClientOptions): RequestOptions = + builder() + .responseValidation(clientOptions.responseValidation) + .timeout(clientOptions.timeout) + .build() + + fun builder() = Builder() + } + + fun applyDefaults(options: RequestOptions): RequestOptions = + RequestOptions( + responseValidation = responseValidation ?: options.responseValidation, + timeout = + if (options.timeout != null && timeout != null) timeout.assign(options.timeout) + else timeout ?: options.timeout, + ) + + class Builder internal constructor() { + + private var responseValidation: Boolean? = null + private var timeout: Timeout? = null + + fun responseValidation(responseValidation: Boolean) = apply { + this.responseValidation = responseValidation + } + + fun timeout(timeout: Timeout) = apply { this.timeout = timeout } + + fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build()) + + fun build(): RequestOptions = RequestOptions(responseValidation, timeout) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Sleeper.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Sleeper.kt new file mode 100644 index 0000000..412b016 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Sleeper.kt @@ -0,0 +1,17 @@ +package com.pioneer_intergration_app.api.core + +import java.time.Duration + +/** + * An interface for delaying execution for a specified amount of time. + * + * Useful for testing and cleaning up resources. + */ +interface Sleeper : AutoCloseable { + + /** Synchronously pauses execution for the given [duration]. */ + fun sleep(duration: Duration) + + /** Asynchronously pauses execution for the given [duration]. */ + suspend fun sleepAsync(duration: Duration) +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Timeout.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Timeout.kt new file mode 100644 index 0000000..328e47b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Timeout.kt @@ -0,0 +1,155 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core + +import java.time.Duration +import java.util.Objects + +/** A class containing timeouts for various processing phases of a request. */ +class Timeout +private constructor( + private val connect: Duration?, + private val read: Duration?, + private val write: Duration?, + private val request: Duration?, +) { + + /** + * The maximum time allowed to establish a connection with a host. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `Duration.ofMinutes(1)`. + */ + fun connect(): Duration = connect ?: Duration.ofMinutes(1) + + /** + * The maximum time allowed between two data packets when waiting for the server’s response. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `request()`. + */ + fun read(): Duration = read ?: request() + + /** + * The maximum time allowed between two data packets when sending the request to the server. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `request()`. + */ + fun write(): Duration = write ?: request() + + /** + * The maximum time allowed for a complete HTTP call, not including retries. + * + * This includes resolving DNS, connecting, writing the request body, server processing, as well + * as reading the response body. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `Duration.ofMinutes(1)`. + */ + fun request(): Duration = request ?: Duration.ofMinutes(1) + + fun toBuilder() = Builder().from(this) + + companion object { + + fun default() = builder().build() + + /** Returns a mutable builder for constructing an instance of [Timeout]. */ + fun builder() = Builder() + } + + /** A builder for [Timeout]. */ + class Builder internal constructor() { + + private var connect: Duration? = null + private var read: Duration? = null + private var write: Duration? = null + private var request: Duration? = null + + internal fun from(timeout: Timeout) = apply { + connect = timeout.connect + read = timeout.read + write = timeout.write + request = timeout.request + } + + /** + * The maximum time allowed to establish a connection with a host. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `Duration.ofMinutes(1)`. + */ + fun connect(connect: Duration?) = apply { this.connect = connect } + + /** + * The maximum time allowed between two data packets when waiting for the server’s response. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `request()`. + */ + fun read(read: Duration?) = apply { this.read = read } + + /** + * The maximum time allowed between two data packets when sending the request to the server. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `request()`. + */ + fun write(write: Duration?) = apply { this.write = write } + + /** + * The maximum time allowed for a complete HTTP call, not including retries. + * + * This includes resolving DNS, connecting, writing the request body, server processing, as + * well as reading the response body. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `Duration.ofMinutes(1)`. + */ + fun request(request: Duration?) = apply { this.request = request } + + /** + * Returns an immutable instance of [Timeout]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Timeout = Timeout(connect, read, write, request) + } + + internal fun assign(target: Timeout): Timeout = + target + .toBuilder() + .apply { + connect?.let(this::connect) + read?.let(this::read) + write?.let(this::write) + request?.let(this::request) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Timeout && + connect == other.connect && + read == other.read && + write == other.write && + request == other.request + } + + override fun hashCode(): Int = Objects.hash(connect, read, write, request) + + override fun toString() = + "Timeout{connect=$connect, read=$read, write=$write, request=$request}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Utils.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Utils.kt new file mode 100644 index 0000000..2f1fed0 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Utils.kt @@ -0,0 +1,102 @@ +@file:JvmName("Utils") + +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Collections +import java.util.SortedMap +import java.util.concurrent.locks.Lock + +internal fun T?.getOrThrow(name: String): T = + this ?: throw PioneerIntergrationAppInvalidDataException("`${name}` is not present") + +internal fun List.toImmutable(): List = + if (isEmpty()) Collections.emptyList() else Collections.unmodifiableList(toList()) + +internal fun Map.toImmutable(): Map = + if (isEmpty()) immutableEmptyMap() else Collections.unmodifiableMap(toMap()) + +internal fun immutableEmptyMap(): Map = Collections.emptyMap() + +internal fun , V> SortedMap.toImmutable(): SortedMap = + if (isEmpty()) Collections.emptySortedMap() + else Collections.unmodifiableSortedMap(toSortedMap(comparator())) + +/** + * Returns all elements that yield the largest value for the given function, or an empty list if + * there are zero elements. + * + * This is similar to [Sequence.maxByOrNull] except it returns _all_ elements that yield the largest + * value; not just the first one. + */ +internal fun > Sequence.allMaxBy(selector: (T) -> R): List { + var maxValue: R? = null + val maxElements = mutableListOf() + + val iterator = iterator() + while (iterator.hasNext()) { + val element = iterator.next() + val value = selector(element) + if (maxValue == null || value > maxValue) { + maxValue = value + maxElements.clear() + maxElements.add(element) + } else if (value == maxValue) { + maxElements.add(element) + } + } + + return maxElements +} + +/** + * Returns whether [this] is equal to [other]. + * + * This differs from [Object.equals] because it also deeply equates arrays based on their contents, + * even when there are arrays directly nested within other arrays. + */ +internal infix fun Any?.contentEquals(other: Any?): Boolean = + arrayOf(this).contentDeepEquals(arrayOf(other)) + +/** + * Returns a hash of the given sequence of [values]. + * + * This differs from [java.util.Objects.hash] because it also deeply hashes arrays based on their + * contents, even when there are arrays directly nested within other arrays. + */ +internal fun contentHash(vararg values: Any?): Int = values.contentDeepHashCode() + +/** + * Returns a [String] representation of [this]. + * + * This differs from [Object.toString] because it also deeply stringifies arrays based on their + * contents, even when there are arrays directly nested within other arrays. + */ +internal fun Any?.contentToString(): String { + var string = arrayOf(this).contentDeepToString() + if (string.startsWith('[')) { + string = string.substring(1) + } + if (string.endsWith(']')) { + string = string.substring(0, string.length - 1) + } + return string +} + +internal interface Enum + +/** + * Executes a suspending block of code while holding this lock. + * + * @param T the return type of the action + * @param action the suspending function to execute while holding the lock + * @return the result of executing the action + */ +internal suspend fun Lock.withLockAsync(action: suspend () -> T): T { + lock() + return try { + action() + } finally { + unlock() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt new file mode 100644 index 0000000..01f6f79 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt @@ -0,0 +1,700 @@ +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.databind.BeanProperty +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.JavaType +import com.fasterxml.jackson.databind.JsonDeserializer +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.node.JsonNodeType.ARRAY +import com.fasterxml.jackson.databind.node.JsonNodeType.BINARY +import com.fasterxml.jackson.databind.node.JsonNodeType.BOOLEAN +import com.fasterxml.jackson.databind.node.JsonNodeType.MISSING +import com.fasterxml.jackson.databind.node.JsonNodeType.NULL +import com.fasterxml.jackson.databind.node.JsonNodeType.NUMBER +import com.fasterxml.jackson.databind.node.JsonNodeType.OBJECT +import com.fasterxml.jackson.databind.node.JsonNodeType.POJO +import com.fasterxml.jackson.databind.node.JsonNodeType.STRING +import com.fasterxml.jackson.databind.ser.std.NullSerializer +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.io.InputStream +import java.util.* +import kotlin.reflect.KClass + +/** + * A class representing a serializable JSON field. + * + * It can either be a [KnownValue] value of type [T], matching the type the SDK expects, or an + * arbitrary JSON value that bypasses the type system (via [JsonValue]). + */ +@JsonDeserialize(using = JsonField.Deserializer::class) +sealed class JsonField { + + /** + * Returns whether this field is missing, which means it will be omitted from the serialized + * JSON entirely. + */ + fun isMissing(): Boolean = this is JsonMissing + + /** Whether this field is explicitly set to `null`. */ + fun isNull(): Boolean = this is JsonNull + + /** + * Returns this field's "known" value, meaning it matches the type the SDK expects, or null if + * this field contains an arbitrary [JsonValue]. + * + * This is the opposite of [asUnknown]. + */ + fun asKnown(): T? = (this as? KnownValue)?.value + + /** + * Returns this field's arbitrary [JsonValue], meaning it mismatches the type the SDK expects, + * or null if this field contains a "known" value. + * + * This is the opposite of [asKnown]. + */ + fun asUnknown(): JsonValue? = this as? JsonValue + + /** + * Returns this field's boolean value, or null if it doesn't contain a boolean. + * + * This method checks for both a [KnownValue] containing a boolean and for [JsonBoolean]. + */ + fun asBoolean(): Boolean? = + when (this) { + is JsonBoolean -> value + is KnownValue -> value as? Boolean + else -> null + } + + /** + * Returns this field's numerical value, or null if it doesn't contain a number. + * + * This method checks for both a [KnownValue] containing a number and for [JsonNumber]. + */ + fun asNumber(): Number? = + when (this) { + is JsonNumber -> value + is KnownValue -> value as? Number + else -> null + } + + /** + * Returns this field's string value, or null if it doesn't contain a string. + * + * This method checks for both a [KnownValue] containing a string and for [JsonString]. + */ + fun asString(): String? = + when (this) { + is JsonString -> value + is KnownValue -> value as? String + else -> null + } + + fun asStringOrThrow(): String = + asString() ?: throw PioneerIntergrationAppInvalidDataException("Value is not a string") + + /** + * Returns this field's list value, or null if it doesn't contain a list. + * + * This method checks for both a [KnownValue] containing a list and for [JsonArray]. + */ + fun asArray(): List? = + when (this) { + is JsonArray -> values + is KnownValue -> + (value as? List<*>)?.map { + try { + JsonValue.from(it) + } catch (e: IllegalArgumentException) { + // The known value is a list, but not all items are convertible to + // `JsonValue`. + return null + } + } + else -> null + } + + /** + * Returns this field's map value, or null if it doesn't contain a map. + * + * This method checks for both a [KnownValue] containing a map and for [JsonObject]. + */ + fun asObject(): Map? = + when (this) { + is JsonObject -> values + is KnownValue -> + (value as? Map<*, *>) + ?.map { (key, value) -> + if (key !is String) { + return null + } + + val jsonValue = + try { + JsonValue.from(value) + } catch (e: IllegalArgumentException) { + // The known value is a map, but not all values are convertible to + // `JsonValue`. + return null + } + + key to jsonValue + } + ?.toMap() + else -> null + } + + internal fun getRequired(name: String): T = + when (this) { + is KnownValue -> value + is JsonMissing -> throw PioneerIntergrationAppInvalidDataException("`$name` is not set") + is JsonNull -> throw PioneerIntergrationAppInvalidDataException("`$name` is null") + else -> + throw PioneerIntergrationAppInvalidDataException( + "`$name` is invalid, received $this" + ) + } + + internal fun getNullable(name: String): T? = + when (this) { + is KnownValue -> value + is JsonMissing -> null + is JsonNull -> null + else -> + throw PioneerIntergrationAppInvalidDataException( + "`$name` is invalid, received $this" + ) + } + + internal fun map(transform: (T) -> R): JsonField = + when (this) { + is KnownValue -> KnownValue.of(transform(value)) + is JsonValue -> this + } + + internal fun accept(consume: (T) -> Unit) { + asKnown()?.let(consume) + } + + /** Returns the result of calling the [visitor] method corresponding to this field's state. */ + fun accept(visitor: Visitor): R = + when (this) { + is KnownValue -> visitor.visitKnown(value) + is JsonValue -> accept(visitor as JsonValue.Visitor) + } + + /** + * An interface that defines how to map each possible state of a `JsonField` to a value of + * type [R]. + */ + interface Visitor : JsonValue.Visitor { + + fun visitKnown(value: T): R = visitDefault() + } + + companion object { + + /** Returns a [JsonField] containing the given "known" [value]. */ + fun of(value: T): JsonField = KnownValue.of(value) + + /** + * Returns a [JsonField] containing the given "known" [value], or [JsonNull] if [value] is + * null. + */ + fun ofNullable(value: T?): JsonField = + when (value) { + null -> JsonNull.of() + else -> KnownValue.of(value) + } + } + + /** + * This class is a Jackson filter that can be used to exclude missing properties from objects. + * This filter should not be used directly and should instead use the @ExcludeMissing + * annotation. + */ + class IsMissing { + + override fun equals(other: Any?): Boolean = other is JsonMissing + + override fun hashCode(): Int = Objects.hash() + } + + class Deserializer(private val type: JavaType? = null) : + BaseDeserializer>(JsonField::class) { + + override fun createContextual( + context: DeserializationContext, + property: BeanProperty?, + ): JsonDeserializer> = Deserializer(context.contextualType?.containedType(0)) + + override fun ObjectCodec.deserialize(node: JsonNode): JsonField<*> = + type?.let { tryDeserialize(node, type) }?.let { of(it) } + ?: JsonValue.fromJsonNode(node) + + override fun getNullValue(context: DeserializationContext): JsonField<*> = JsonNull.of() + } +} + +/** + * A class representing an arbitrary JSON value. + * + * It is immutable and assignable to any [JsonField], regardless of its expected type (i.e. its + * generic type argument). + */ +@JsonDeserialize(using = JsonValue.Deserializer::class) +sealed class JsonValue : JsonField() { + + inline fun convert(): R? = convert(jacksonTypeRef()) + + fun convert(type: TypeReference): R? = JSON_MAPPER.convertValue(this, type) + + fun convert(type: KClass): R? = JSON_MAPPER.convertValue(this, type.java) + + /** Returns the result of calling the [visitor] method corresponding to this value's variant. */ + fun accept(visitor: Visitor): R = + when (this) { + is JsonMissing -> visitor.visitMissing() + is JsonNull -> visitor.visitNull() + is JsonBoolean -> visitor.visitBoolean(value) + is JsonNumber -> visitor.visitNumber(value) + is JsonString -> visitor.visitString(value) + is JsonArray -> visitor.visitArray(values) + is JsonObject -> visitor.visitObject(values) + } + + /** + * An interface that defines how to map each variant state of a [JsonValue] to a value of type + * [R]. + */ + interface Visitor { + + fun visitNull(): R = visitDefault() + + fun visitMissing(): R = visitDefault() + + fun visitBoolean(value: Boolean): R = visitDefault() + + fun visitNumber(value: Number): R = visitDefault() + + fun visitString(value: String): R = visitDefault() + + fun visitArray(values: List): R = visitDefault() + + fun visitObject(values: Map): R = visitDefault() + + /** + * The default implementation for unimplemented visitor methods. + * + * @throws IllegalArgumentException in the default implementation. + */ + fun visitDefault(): R = throw IllegalArgumentException("Unexpected value") + } + + companion object { + + private val JSON_MAPPER = jsonMapper() + + /** + * Converts the given [value] to a [JsonValue]. + * + * This method works best on primitive types, [List] values, [Map] values, and nested + * combinations of these. For example: + * ```kotlin + * // Create primitive JSON values + * val nullValue: JsonValue = JsonValue.from(null) + * val booleanValue: JsonValue = JsonValue.from(true) + * val numberValue: JsonValue = JsonValue.from(42) + * val stringValue: JsonValue = JsonValue.from("Hello World!") + * + * // Create a JSON array value equivalent to `["Hello", "World"]` + * val arrayValue: JsonValue = JsonValue.from(listOf("Hello", "World")) + * + * // Create a JSON object value equivalent to `{ "a": 1, "b": 2 }` + * val objectValue: JsonValue = JsonValue.from(mapOf( + * "a" to 1, + * "b" to 2, + * )) + * + * // Create an arbitrarily nested JSON equivalent to: + * // { + * // "a": [1, 2], + * // "b": [3, 4] + * // } + * val complexValue: JsonValue = JsonValue.from(mapOf( + * "a" to listOf(1, 2), + * "b" to listOf(3, 4), + * )) + * ``` + * + * @throws IllegalArgumentException if [value] is not JSON serializable. + */ + fun from(value: Any?): JsonValue = + when (value) { + null -> JsonNull.of() + is JsonValue -> value + else -> JSON_MAPPER.convertValue(value, JsonValue::class.java) + } + + /** + * Returns a [JsonValue] converted from the given Jackson [JsonNode]. + * + * @throws IllegalStateException for unsupported node types. + */ + fun fromJsonNode(node: JsonNode): JsonValue = + when (node.nodeType) { + MISSING -> JsonMissing.of() + NULL -> JsonNull.of() + BOOLEAN -> JsonBoolean.of(node.booleanValue()) + NUMBER -> JsonNumber.of(node.numberValue()) + STRING -> JsonString.of(node.textValue()) + ARRAY -> + JsonArray.of(node.elements().asSequence().map { fromJsonNode(it) }.toList()) + OBJECT -> + JsonObject.of( + node.fields().asSequence().map { it.key to fromJsonNode(it.value) }.toMap() + ) + BINARY, + POJO, + null -> throw IllegalStateException("Unexpected JsonNode type: ${node.nodeType}") + } + } + + class Deserializer : BaseDeserializer(JsonValue::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): JsonValue = fromJsonNode(node) + + override fun getNullValue(context: DeserializationContext?): JsonValue = JsonNull.of() + } +} + +/** + * A class representing a "known" JSON serializable value of type [T], matching the type the SDK + * expects. + * + * It is assignable to `JsonField`. + */ +class KnownValue +private constructor( + @com.fasterxml.jackson.annotation.JsonValue @get:JvmName("value") val value: T +) : JsonField() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is KnownValue<*> && value contentEquals other.value + } + + override fun hashCode() = contentHash(value) + + override fun toString() = value.contentToString() + + companion object { + + /** Returns a [KnownValue] containing the given [value]. */ + @JsonCreator fun of(value: T) = KnownValue(value) + } +} + +/** + * A [JsonValue] representing an omitted JSON field. + * + * An instance of this class will cause a JSON field to be omitted from the serialized JSON + * entirely. + */ +@JsonSerialize(using = JsonMissing.Serializer::class) +class JsonMissing : JsonValue() { + + override fun toString() = "" + + companion object { + + private val INSTANCE: JsonMissing = JsonMissing() + + /** Returns the singleton instance of [JsonMissing]. */ + fun of() = INSTANCE + } + + class Serializer : BaseSerializer(JsonMissing::class) { + + override fun serialize( + value: JsonMissing, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + throw IllegalStateException("JsonMissing cannot be serialized") + } + } +} + +/** A [JsonValue] representing a JSON `null` value. */ +@JsonSerialize(using = NullSerializer::class) +class JsonNull : JsonValue() { + + override fun toString() = "null" + + companion object { + + private val INSTANCE: JsonNull = JsonNull() + + /** Returns the singleton instance of [JsonMissing]. */ + @JsonCreator fun of() = INSTANCE + } +} + +/** A [JsonValue] representing a JSON boolean value. */ +class JsonBoolean +private constructor( + @get:com.fasterxml.jackson.annotation.JsonValue @get:JvmName("value") val value: Boolean +) : JsonValue() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JsonBoolean && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + + companion object { + + /** Returns a [JsonBoolean] containing the given [value]. */ + @JsonCreator fun of(value: Boolean) = JsonBoolean(value) + } +} + +/** A [JsonValue] representing a JSON number value. */ +class JsonNumber +private constructor( + @get:com.fasterxml.jackson.annotation.JsonValue @get:JvmName("value") val value: Number +) : JsonValue() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JsonNumber && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + + companion object { + + /** Returns a [JsonNumber] containing the given [value]. */ + @JsonCreator fun of(value: Number) = JsonNumber(value) + } +} + +/** A [JsonValue] representing a JSON string value. */ +class JsonString +private constructor( + @get:com.fasterxml.jackson.annotation.JsonValue @get:JvmName("value") val value: String +) : JsonValue() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JsonString && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value + + companion object { + + /** Returns a [JsonString] containing the given [value]. */ + @JsonCreator fun of(value: String) = JsonString(value) + } +} + +/** A [JsonValue] representing a JSON array value. */ +class JsonArray +private constructor( + @get:com.fasterxml.jackson.annotation.JsonValue + @get:JvmName("values") + val values: List +) : JsonValue() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JsonArray && values == other.values + } + + override fun hashCode() = values.hashCode() + + override fun toString() = values.toString() + + companion object { + + /** Returns a [JsonArray] containing the given [values]. */ + @JsonCreator fun of(values: List) = JsonArray(values.toImmutable()) + } +} + +/** A [JsonValue] representing a JSON object value. */ +class JsonObject +private constructor( + @get:com.fasterxml.jackson.annotation.JsonValue + @get:JvmName("values") + val values: Map +) : JsonValue() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JsonObject && values == other.values + } + + override fun hashCode() = values.hashCode() + + override fun toString() = values.toString() + + companion object { + + /** Returns a [JsonObject] containing the given [values]. */ + @JsonCreator fun of(values: Map) = JsonObject(values.toImmutable()) + } +} + +/** A Jackson annotation for excluding fields set to [JsonMissing] from the serialized JSON. */ +@JacksonAnnotationsInside +@JsonInclude(JsonInclude.Include.CUSTOM, valueFilter = JsonField.IsMissing::class) +annotation class ExcludeMissing + +/** A class representing a field in a `multipart/form-data` request. */ +class MultipartField +private constructor( + /** A [JsonField] value, which will be serialized to zero or more parts. */ + @get:com.fasterxml.jackson.annotation.JsonValue val value: JsonField, + /** A content type for the serialized parts. */ + val contentType: String, + /** Returns the filename directive that will be included in the serialized field. */ + val filename: String?, +) { + + companion object { + + /** + * Returns a [MultipartField] containing the given [value] as a [KnownValue]. + * + * [contentType] will be set to `application/octet-stream` if [value] is binary data, or + * `text/plain; charset=utf-8` otherwise. + */ + fun of(value: T?) = builder().value(value).build() + + /** + * Returns a [MultipartField] containing the given [value]. + * + * [contentType] will be set to `application/octet-stream` if [value] is binary data, or + * `text/plain; charset=utf-8` otherwise. + */ + fun of(value: JsonField) = builder().value(value).build() + + /** + * Returns a mutable builder for constructing an instance of [MultipartField]. + * + * The following fields are required: + * ```kotlin + * .value() + * ``` + * + * If [contentType] is unset, then it will be set to `application/octet-stream` if [value] + * is binary data, or `text/plain; charset=utf-8` otherwise. + */ + fun builder() = Builder() + } + + internal fun map(transform: (T) -> R): MultipartField = + builder().value(value.map(transform)).contentType(contentType).filename(filename).build() + + /** A builder for [MultipartField]. */ + class Builder internal constructor() { + + private var value: JsonField? = null + private var contentType: String? = null + private var filename: String? = null + + fun value(value: JsonField) = apply { this.value = value } + + fun value(value: T?) = value(JsonField.ofNullable(value)) + + fun contentType(contentType: String) = apply { this.contentType = contentType } + + fun filename(filename: String?) = apply { this.filename = filename } + + /** + * Returns an immutable instance of [MultipartField]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .value() + * ``` + * + * If [contentType] is unset, then it will be set to `application/octet-stream` if [value] + * is binary data, or `text/plain; charset=utf-8` otherwise. + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): MultipartField { + val value = checkRequired("value", value) + return MultipartField( + value, + contentType + ?: if ( + value is KnownValue && + (value.value is InputStream || value.value is ByteArray) + ) + "application/octet-stream" + else "text/plain; charset=utf-8", + filename, + ) + } + } + + private val hashCode: Int by lazy { contentHash(value, contentType, filename) } + + override fun hashCode(): Int = hashCode + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MultipartField<*> && + value == other.value && + contentType == other.contentType && + filename == other.filename + } + + override fun toString(): String = + "MultipartField{value=$value, contentType=$contentType, filename=$filename}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/EmptyHandler.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/EmptyHandler.kt new file mode 100644 index 0000000..10211dd --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/EmptyHandler.kt @@ -0,0 +1,12 @@ +@file:JvmName("EmptyHandler") + +package com.pioneer_intergration_app.api.core.handlers + +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler + +internal fun emptyHandler(): Handler = EmptyHandlerInternal + +private object EmptyHandlerInternal : Handler { + override fun handle(response: HttpResponse): Void? = null +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/ErrorHandler.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/ErrorHandler.kt new file mode 100644 index 0000000..aed4f8e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/ErrorHandler.kt @@ -0,0 +1,80 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core.handlers + +import com.fasterxml.jackson.databind.json.JsonMapper +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.errors.BadRequestException +import com.pioneer_intergration_app.api.errors.InternalServerException +import com.pioneer_intergration_app.api.errors.NotFoundException +import com.pioneer_intergration_app.api.errors.PermissionDeniedException +import com.pioneer_intergration_app.api.errors.RateLimitException +import com.pioneer_intergration_app.api.errors.UnauthorizedException +import com.pioneer_intergration_app.api.errors.UnexpectedStatusCodeException +import com.pioneer_intergration_app.api.errors.UnprocessableEntityException + +internal fun errorBodyHandler(jsonMapper: JsonMapper): Handler { + val handler = jsonHandler(jsonMapper) + + return object : Handler { + override fun handle(response: HttpResponse): JsonValue = + try { + handler.handle(response) + } catch (e: Exception) { + JsonMissing.of() + } + } +} + +internal fun errorHandler(errorBodyHandler: Handler): Handler = + object : Handler { + override fun handle(response: HttpResponse): HttpResponse = + when (val statusCode = response.statusCode()) { + in 200..299 -> response + 400 -> + throw BadRequestException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + 401 -> + throw UnauthorizedException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + 403 -> + throw PermissionDeniedException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + 404 -> + throw NotFoundException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + 422 -> + throw UnprocessableEntityException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + 429 -> + throw RateLimitException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + in 500..599 -> + throw InternalServerException.builder() + .statusCode(statusCode) + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + else -> + throw UnexpectedStatusCodeException.builder() + .statusCode(statusCode) + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + } + } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/JsonHandler.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/JsonHandler.kt new file mode 100644 index 0000000..0a30484 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/JsonHandler.kt @@ -0,0 +1,20 @@ +@file:JvmName("JsonHandler") + +package com.pioneer_intergration_app.api.core.handlers + +import com.fasterxml.jackson.databind.json.JsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException + +internal inline fun jsonHandler(jsonMapper: JsonMapper): Handler = + object : Handler { + override fun handle(response: HttpResponse): T { + try { + return jsonMapper.readValue(response.body(), jacksonTypeRef()) + } catch (e: Exception) { + throw PioneerIntergrationAppInvalidDataException("Error reading response", e) + } + } + } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/StringHandler.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/StringHandler.kt new file mode 100644 index 0000000..e93a77f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/StringHandler.kt @@ -0,0 +1,13 @@ +@file:JvmName("StringHandler") + +package com.pioneer_intergration_app.api.core.handlers + +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler + +internal fun stringHandler(): Handler = StringHandlerInternal + +private object StringHandlerInternal : Handler { + override fun handle(response: HttpResponse): String = + response.body().readBytes().toString(Charsets.UTF_8) +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/Headers.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/Headers.kt new file mode 100644 index 0000000..7dc82b3 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/Headers.kt @@ -0,0 +1,111 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.JsonArray +import com.pioneer_intergration_app.api.core.JsonBoolean +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonNull +import com.pioneer_intergration_app.api.core.JsonNumber +import com.pioneer_intergration_app.api.core.JsonObject +import com.pioneer_intergration_app.api.core.JsonString +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.TreeMap + +class Headers private constructor(private val map: Map>, val size: Int) { + + fun isEmpty(): Boolean = map.isEmpty() + + fun names(): Set = map.keys + + fun values(name: String): List = map[name].orEmpty() + + fun toBuilder(): Builder = Builder().putAll(map) + + companion object { + + fun builder() = Builder() + } + + class Builder internal constructor() { + + private val map: MutableMap> = + TreeMap(String.CASE_INSENSITIVE_ORDER) + private var size: Int = 0 + + fun put(name: String, value: JsonValue): Builder = apply { + when (value) { + is JsonMissing, + is JsonNull -> {} + is JsonBoolean -> put(name, value.value.toString()) + is JsonNumber -> put(name, value.value.toString()) + is JsonString -> put(name, value.value) + is JsonArray -> value.values.forEach { put(name, it) } + is JsonObject -> + value.values.forEach { (nestedName, value) -> put("$name.$nestedName", value) } + } + } + + fun put(name: String, value: String) = apply { + map.getOrPut(name) { mutableListOf() }.add(value) + size++ + } + + fun put(name: String, values: Iterable) = apply { values.forEach { put(name, it) } } + + fun putAll(headers: Map>) = apply { headers.forEach(::put) } + + fun putAll(headers: Headers) = apply { + headers.names().forEach { put(it, headers.values(it)) } + } + + fun replace(name: String, value: String) = apply { + remove(name) + put(name, value) + } + + fun replace(name: String, values: Iterable) = apply { + remove(name) + put(name, values) + } + + fun replaceAll(headers: Map>) = apply { + headers.forEach(::replace) + } + + fun replaceAll(headers: Headers) = apply { + headers.names().forEach { replace(it, headers.values(it)) } + } + + fun remove(name: String) = apply { size -= map.remove(name).orEmpty().size } + + fun removeAll(names: Set) = apply { names.forEach(::remove) } + + fun clear() = apply { + map.clear() + size = 0 + } + + fun build() = + Headers( + map.mapValuesTo(TreeMap(String.CASE_INSENSITIVE_ORDER)) { (_, values) -> + values.toImmutable() + } + .toImmutable(), + size, + ) + } + + override fun hashCode(): Int = map.hashCode() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Headers && map == other.map + } + + override fun toString(): String = "Headers{map=$map}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpClient.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpClient.kt new file mode 100644 index 0000000..ae5773b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpClient.kt @@ -0,0 +1,17 @@ +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.RequestOptions +import java.lang.AutoCloseable + +interface HttpClient : AutoCloseable { + + fun execute( + request: HttpRequest, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpMethod.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpMethod.kt new file mode 100644 index 0000000..a7b82d7 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpMethod.kt @@ -0,0 +1,13 @@ +package com.pioneer_intergration_app.api.core.http + +enum class HttpMethod { + GET, + HEAD, + POST, + PUT, + DELETE, + CONNECT, + OPTIONS, + TRACE, + PATCH, +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequest.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequest.kt new file mode 100644 index 0000000..83db170 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequest.kt @@ -0,0 +1,175 @@ +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.toImmutable +import java.net.URLEncoder + +class HttpRequest +private constructor( + val method: HttpMethod, + val baseUrl: String, + val pathSegments: List, + val headers: Headers, + val queryParams: QueryParams, + val body: HttpRequestBody?, +) { + + fun url(): String = buildString { + append(baseUrl) + + pathSegments.forEach { segment -> + if (!endsWith("/")) { + append("/") + } + append(URLEncoder.encode(segment, "UTF-8")) + } + + if (queryParams.isEmpty()) { + return@buildString + } + + append("?") + var isFirst = true + queryParams.keys().forEach { key -> + queryParams.values(key).forEach { value -> + if (!isFirst) { + append("&") + } + append(URLEncoder.encode(key, "UTF-8")) + append("=") + append(URLEncoder.encode(value, "UTF-8")) + isFirst = false + } + } + } + + fun toBuilder(): Builder = Builder().from(this) + + override fun toString(): String = + "HttpRequest{method=$method, baseUrl=$baseUrl, pathSegments=$pathSegments, headers=$headers, queryParams=$queryParams, body=$body}" + + companion object { + fun builder() = Builder() + } + + class Builder internal constructor() { + + private var method: HttpMethod? = null + private var baseUrl: String? = null + private var pathSegments: MutableList = mutableListOf() + private var headers: Headers.Builder = Headers.builder() + private var queryParams: QueryParams.Builder = QueryParams.builder() + private var body: HttpRequestBody? = null + + internal fun from(request: HttpRequest) = apply { + method = request.method + baseUrl = request.baseUrl + pathSegments = request.pathSegments.toMutableList() + headers = request.headers.toBuilder() + queryParams = request.queryParams.toBuilder() + body = request.body + } + + fun method(method: HttpMethod) = apply { this.method = method } + + fun baseUrl(baseUrl: String) = apply { this.baseUrl = baseUrl } + + fun addPathSegment(pathSegment: String) = apply { pathSegments.add(pathSegment) } + + fun addPathSegments(vararg pathSegments: String) = apply { + this.pathSegments.addAll(pathSegments) + } + + fun headers(headers: Headers) = apply { + this.headers.clear() + putAllHeaders(headers) + } + + fun headers(headers: Map>) = apply { + this.headers.clear() + putAllHeaders(headers) + } + + fun putHeader(name: String, value: String) = apply { headers.put(name, value) } + + fun putHeaders(name: String, values: Iterable) = apply { headers.put(name, values) } + + fun putAllHeaders(headers: Headers) = apply { this.headers.putAll(headers) } + + fun putAllHeaders(headers: Map>) = apply { + this.headers.putAll(headers) + } + + fun replaceHeaders(name: String, value: String) = apply { headers.replace(name, value) } + + fun replaceHeaders(name: String, values: Iterable) = apply { + headers.replace(name, values) + } + + fun replaceAllHeaders(headers: Headers) = apply { this.headers.replaceAll(headers) } + + fun replaceAllHeaders(headers: Map>) = apply { + this.headers.replaceAll(headers) + } + + fun removeHeaders(name: String) = apply { headers.remove(name) } + + fun removeAllHeaders(names: Set) = apply { headers.removeAll(names) } + + fun queryParams(queryParams: QueryParams) = apply { + this.queryParams.clear() + putAllQueryParams(queryParams) + } + + fun queryParams(queryParams: Map>) = apply { + this.queryParams.clear() + putAllQueryParams(queryParams) + } + + fun putQueryParam(key: String, value: String) = apply { queryParams.put(key, value) } + + fun putQueryParams(key: String, values: Iterable) = apply { + queryParams.put(key, values) + } + + fun putAllQueryParams(queryParams: QueryParams) = apply { + this.queryParams.putAll(queryParams) + } + + fun putAllQueryParams(queryParams: Map>) = apply { + this.queryParams.putAll(queryParams) + } + + fun replaceQueryParams(key: String, value: String) = apply { + queryParams.replace(key, value) + } + + fun replaceQueryParams(key: String, values: Iterable) = apply { + queryParams.replace(key, values) + } + + fun replaceAllQueryParams(queryParams: QueryParams) = apply { + this.queryParams.replaceAll(queryParams) + } + + fun replaceAllQueryParams(queryParams: Map>) = apply { + this.queryParams.replaceAll(queryParams) + } + + fun removeQueryParams(key: String) = apply { queryParams.remove(key) } + + fun removeAllQueryParams(keys: Set) = apply { queryParams.removeAll(keys) } + + fun body(body: HttpRequestBody) = apply { this.body = body } + + fun build(): HttpRequest = + HttpRequest( + checkRequired("method", method), + checkRequired("baseUrl", baseUrl), + pathSegments.toImmutable(), + headers.build(), + queryParams.build(), + body, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBodies.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBodies.kt new file mode 100644 index 0000000..4e0c6a5 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBodies.kt @@ -0,0 +1,125 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core.http + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.json.JsonMapper +import com.fasterxml.jackson.databind.node.JsonNodeType +import com.pioneer_intergration_app.api.core.MultipartField +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.io.InputStream +import java.io.OutputStream +import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder +import org.apache.hc.core5.http.ContentType +import org.apache.hc.core5.http.HttpEntity + +internal inline fun json(jsonMapper: JsonMapper, value: T): HttpRequestBody = + object : HttpRequestBody { + private val bytes: ByteArray by lazy { jsonMapper.writeValueAsBytes(value) } + + override fun writeTo(outputStream: OutputStream) = outputStream.write(bytes) + + override fun contentType(): String = "application/json" + + override fun contentLength(): Long = bytes.size.toLong() + + override fun repeatable(): Boolean = true + + override fun close() {} + } + +internal fun multipartFormData( + jsonMapper: JsonMapper, + fields: Map>, +): HttpRequestBody = + object : HttpRequestBody { + private val entity: HttpEntity by lazy { + MultipartEntityBuilder.create() + .apply { + fields.forEach { (name, field) -> + val knownValue = field.value.asKnown() + val parts = + if (knownValue is InputStream) { + // Read directly from the `InputStream` instead of reading it all + // into memory due to the `jsonMapper` serialization below. + sequenceOf(name to knownValue) + } else { + val node = jsonMapper.valueToTree(field.value) + serializePart(name, node) + } + + parts.forEach { (name, bytes) -> + addBinaryBody( + name, + bytes, + ContentType.parseLenient(field.contentType), + field.filename, + ) + } + } + } + .build() + } + + private fun serializePart( + name: String, + node: JsonNode, + ): Sequence> = + when (node.nodeType) { + JsonNodeType.MISSING, + JsonNodeType.NULL -> emptySequence() + JsonNodeType.BINARY -> sequenceOf(name to node.binaryValue().inputStream()) + JsonNodeType.STRING -> sequenceOf(name to node.textValue().inputStream()) + JsonNodeType.BOOLEAN -> + sequenceOf(name to node.booleanValue().toString().inputStream()) + JsonNodeType.NUMBER -> + sequenceOf(name to node.numberValue().toString().inputStream()) + JsonNodeType.ARRAY -> + sequenceOf( + name to + node + .elements() + .asSequence() + .mapNotNull { element -> + when (element.nodeType) { + JsonNodeType.MISSING, + JsonNodeType.NULL -> null + JsonNodeType.STRING -> node.textValue() + JsonNodeType.BOOLEAN -> node.booleanValue().toString() + JsonNodeType.NUMBER -> node.numberValue().toString() + null, + JsonNodeType.BINARY, + JsonNodeType.ARRAY, + JsonNodeType.OBJECT, + JsonNodeType.POJO -> + throw PioneerIntergrationAppInvalidDataException( + "Unexpected JsonNode type in array: ${node.nodeType}" + ) + } + } + .joinToString(",") + .inputStream() + ) + JsonNodeType.OBJECT -> + node.fields().asSequence().flatMap { (key, value) -> + serializePart("$name[$key]", value) + } + JsonNodeType.POJO, + null -> + throw PioneerIntergrationAppInvalidDataException( + "Unexpected JsonNode type: ${node.nodeType}" + ) + } + + private fun String.inputStream(): InputStream = toByteArray().inputStream() + + override fun writeTo(outputStream: OutputStream) = entity.writeTo(outputStream) + + override fun contentType(): String = entity.contentType + + override fun contentLength(): Long = entity.contentLength + + override fun repeatable(): Boolean = entity.isRepeatable + + override fun close() = entity.close() + } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBody.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBody.kt new file mode 100644 index 0000000..71b845a --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBody.kt @@ -0,0 +1,22 @@ +package com.pioneer_intergration_app.api.core.http + +import java.io.OutputStream +import java.lang.AutoCloseable + +interface HttpRequestBody : AutoCloseable { + + fun writeTo(outputStream: OutputStream) + + fun contentType(): String? + + fun contentLength(): Long + + /** + * Determines if a request can be repeated in a meaningful way, for example before doing a + * retry. + * + * The most typical case when a request can't be retried is if the request body is being + * streamed. In this case the body data isn't available on subsequent attempts. + */ + fun repeatable(): Boolean +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponse.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponse.kt new file mode 100644 index 0000000..a01def6 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponse.kt @@ -0,0 +1,19 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core.http + +import java.io.InputStream + +interface HttpResponse : AutoCloseable { + + fun statusCode(): Int + + fun headers(): Headers + + fun body(): InputStream + + interface Handler { + + fun handle(response: HttpResponse): T + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponseFor.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponseFor.kt new file mode 100644 index 0000000..b091b8d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponseFor.kt @@ -0,0 +1,24 @@ +package com.pioneer_intergration_app.api.core.http + +import java.io.InputStream + +interface HttpResponseFor : HttpResponse { + + fun parse(): T +} + +internal fun HttpResponse.parseable(parse: () -> T): HttpResponseFor = + object : HttpResponseFor { + + private val parsed: T by lazy { parse() } + + override fun parse(): T = parsed + + override fun statusCode(): Int = this@parseable.statusCode() + + override fun headers(): Headers = this@parseable.headers() + + override fun body(): InputStream = this@parseable.body() + + override fun close() = this@parseable.close() + } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingHttpClient.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingHttpClient.kt new file mode 100644 index 0000000..0c442c8 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingHttpClient.kt @@ -0,0 +1,25 @@ +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.closeWhenPhantomReachable + +/** + * A delegating wrapper around an `HttpClient` that closes it once it's only phantom reachable. + * + * This class ensures the `HttpClient` is closed even if the user forgets to close it. + */ +internal class PhantomReachableClosingHttpClient(private val httpClient: HttpClient) : HttpClient { + init { + closeWhenPhantomReachable(this, httpClient) + } + + override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse = + httpClient.execute(request, requestOptions) + + override suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse = httpClient.executeAsync(request, requestOptions) + + override fun close() = httpClient.close() +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingStreamResponse.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingStreamResponse.kt new file mode 100644 index 0000000..ff6c2bb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingStreamResponse.kt @@ -0,0 +1,20 @@ +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.closeWhenPhantomReachable + +/** + * A delegating wrapper around a `StreamResponse` that closes it once it's only phantom reachable. + * + * This class ensures the `StreamResponse` is closed even if the user forgets to close it. + */ +internal class PhantomReachableClosingStreamResponse( + private val streamResponse: StreamResponse +) : StreamResponse { + init { + closeWhenPhantomReachable(this, streamResponse) + } + + override fun asSequence(): Sequence = streamResponse.asSequence() + + override fun close() = streamResponse.close() +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/QueryParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/QueryParams.kt new file mode 100644 index 0000000..58081ab --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/QueryParams.kt @@ -0,0 +1,125 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.JsonArray +import com.pioneer_intergration_app.api.core.JsonBoolean +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonNull +import com.pioneer_intergration_app.api.core.JsonNumber +import com.pioneer_intergration_app.api.core.JsonObject +import com.pioneer_intergration_app.api.core.JsonString +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.toImmutable + +class QueryParams private constructor(private val map: Map>, val size: Int) { + + fun isEmpty(): Boolean = map.isEmpty() + + fun keys(): Set = map.keys + + fun values(key: String): List = map[key].orEmpty() + + fun toBuilder(): Builder = Builder().putAll(map) + + companion object { + + fun builder() = Builder() + } + + class Builder internal constructor() { + + private val map: MutableMap> = mutableMapOf() + private var size: Int = 0 + + fun put(key: String, value: JsonValue): Builder = apply { + when (value) { + is JsonMissing, + is JsonNull -> {} + is JsonBoolean -> put(key, value.value.toString()) + is JsonNumber -> put(key, value.value.toString()) + is JsonString -> put(key, value.value) + is JsonArray -> + put( + key, + value.values + .asSequence() + .mapNotNull { + when (it) { + is JsonMissing, + is JsonNull -> null + is JsonBoolean -> it.value.toString() + is JsonNumber -> it.value.toString() + is JsonString -> it.value + is JsonArray, + is JsonObject -> + throw IllegalArgumentException( + "Cannot comma separate non-primitives in query params" + ) + } + } + .joinToString(","), + ) + is JsonObject -> + value.values.forEach { (nestedKey, value) -> put("$key[$nestedKey]", value) } + } + } + + fun put(key: String, value: String) = apply { + map.getOrPut(key) { mutableListOf() }.add(value) + size++ + } + + fun put(key: String, values: Iterable) = apply { values.forEach { put(key, it) } } + + fun putAll(queryParams: Map>) = apply { + queryParams.forEach(::put) + } + + fun putAll(queryParams: QueryParams) = apply { + queryParams.keys().forEach { put(it, queryParams.values(it)) } + } + + fun replace(key: String, value: String) = apply { + remove(key) + put(key, value) + } + + fun replace(key: String, values: Iterable) = apply { + remove(key) + put(key, values) + } + + fun replaceAll(queryParams: Map>) = apply { + queryParams.forEach(::replace) + } + + fun replaceAll(queryParams: QueryParams) = apply { + queryParams.keys().forEach { replace(it, queryParams.values(it)) } + } + + fun remove(key: String) = apply { size -= map.remove(key).orEmpty().size } + + fun removeAll(keys: Set) = apply { keys.forEach(::remove) } + + fun clear() = apply { + map.clear() + size = 0 + } + + fun build() = + QueryParams(map.mapValues { (_, values) -> values.toImmutable() }.toImmutable(), size) + } + + override fun hashCode(): Int = map.hashCode() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is QueryParams && map == other.map + } + + override fun toString(): String = "QueryParams{map=$map}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt new file mode 100644 index 0000000..4a36544 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt @@ -0,0 +1,248 @@ +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.DefaultSleeper +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.Sleeper +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppIoException +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppRetryableException +import java.io.IOException +import java.time.Clock +import java.time.Duration +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter +import java.time.format.DateTimeParseException +import java.time.temporal.ChronoUnit +import java.util.UUID +import java.util.concurrent.ThreadLocalRandom +import java.util.concurrent.TimeUnit +import kotlin.math.min +import kotlin.math.pow + +class RetryingHttpClient +private constructor( + private val httpClient: HttpClient, + private val sleeper: Sleeper, + private val clock: Clock, + private val maxRetries: Int, + private val idempotencyHeader: String?, +) : HttpClient { + + override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { + var modifiedRequest = maybeAddIdempotencyHeader(request) + + // Don't send the current retry count in the headers if the caller set their own value. + val shouldSendRetryCount = + !modifiedRequest.headers.names().contains("X-Stainless-Retry-Count") + + var retries = 0 + + while (true) { + if (shouldSendRetryCount) { + modifiedRequest = setRetryCountHeader(modifiedRequest, retries) + } + + if (!isRetryable(modifiedRequest)) { + return httpClient.execute(modifiedRequest, requestOptions) + } + + val response = + try { + val response = httpClient.execute(modifiedRequest, requestOptions) + if (++retries > maxRetries || !shouldRetry(response)) { + return response + } + + response + } catch (throwable: Throwable) { + if (++retries > maxRetries || !shouldRetry(throwable)) { + throw throwable + } + + null + } + + val backoffDuration = getRetryBackoffDuration(retries, response) + // All responses must be closed, so close the failed one before retrying. + response?.close() + sleeper.sleep(backoffDuration) + } + } + + override suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + var modifiedRequest = maybeAddIdempotencyHeader(request) + + // Don't send the current retry count in the headers if the caller set their own value. + val shouldSendRetryCount = + !modifiedRequest.headers.names().contains("X-Stainless-Retry-Count") + + var retries = 0 + + while (true) { + if (shouldSendRetryCount) { + modifiedRequest = setRetryCountHeader(modifiedRequest, retries) + } + + if (!isRetryable(modifiedRequest)) { + return httpClient.executeAsync(modifiedRequest, requestOptions) + } + + val response = + try { + val response = httpClient.execute(modifiedRequest, requestOptions) + if (++retries > maxRetries || !shouldRetry(response)) { + return response + } + + response + } catch (throwable: Throwable) { + if (++retries > maxRetries || !shouldRetry(throwable)) { + throw throwable + } + + null + } + + val backoffDuration = getRetryBackoffDuration(retries, response) + // All responses must be closed, so close the failed one before retrying. + response?.close() + sleeper.sleepAsync(backoffDuration) + } + } + + override fun close() { + httpClient.close() + sleeper.close() + } + + private fun isRetryable(request: HttpRequest): Boolean = + // Some requests, such as when a request body is being streamed, cannot be retried because + // the body data aren't available on subsequent attempts. + request.body?.repeatable() ?: true + + private fun setRetryCountHeader(request: HttpRequest, retries: Int): HttpRequest = + request.toBuilder().replaceHeaders("X-Stainless-Retry-Count", retries.toString()).build() + + private fun idempotencyKey(): String = "stainless-java-retry-${UUID.randomUUID()}" + + private fun maybeAddIdempotencyHeader(request: HttpRequest): HttpRequest { + if (idempotencyHeader == null || request.headers.names().contains(idempotencyHeader)) { + return request + } + + return request + .toBuilder() + // Set a header to uniquely identify the request when retried + .putHeader(idempotencyHeader, idempotencyKey()) + .build() + } + + private fun shouldRetry(response: HttpResponse): Boolean { + // Note: this is not a standard header + val shouldRetryHeader = response.headers().values("X-Should-Retry").getOrNull(0) + val statusCode = response.statusCode() + + return when { + // If the server explicitly says whether to retry, obey + shouldRetryHeader == "true" -> true + shouldRetryHeader == "false" -> false + + // Retry on request timeouts + statusCode == 408 -> true + // Retry on lock timeouts + statusCode == 409 -> true + // Retry on rate limits + statusCode == 429 -> true + // Retry internal errors + statusCode >= 500 -> true + else -> false + } + } + + private fun shouldRetry(throwable: Throwable): Boolean = + // Only retry known retryable exceptions, other exceptions are not intended to be retried. + throwable is IOException || + throwable is PioneerIntergrationAppIoException || + throwable is PioneerIntergrationAppRetryableException + + private fun getRetryBackoffDuration(retries: Int, response: HttpResponse?): Duration { + // About the Retry-After header: + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + response + ?.headers() + ?.let { headers -> + headers + .values("Retry-After-Ms") + .getOrNull(0) + ?.toFloatOrNull() + ?.times(TimeUnit.MILLISECONDS.toNanos(1)) + ?: headers.values("Retry-After").getOrNull(0)?.let { retryAfter -> + retryAfter.toFloatOrNull()?.times(TimeUnit.SECONDS.toNanos(1)) + ?: try { + ChronoUnit.MILLIS.between( + OffsetDateTime.now(clock), + OffsetDateTime.parse( + retryAfter, + DateTimeFormatter.RFC_1123_DATE_TIME, + ), + ) + } catch (e: DateTimeParseException) { + null + } + } + } + ?.let { retryAfterNanos -> + // If the API asks us to wait a certain amount of time (and it's a reasonable + // amount), just + // do what it says. + val retryAfter = Duration.ofNanos(retryAfterNanos.toLong()) + if (retryAfter in Duration.ofNanos(0)..Duration.ofMinutes(1)) { + return retryAfter + } + } + + // Apply exponential backoff, but not more than the max. + val backoffSeconds = min(0.5 * 2.0.pow(retries - 1), 8.0) + + // Apply some jitter + val jitter = 1.0 - 0.25 * ThreadLocalRandom.current().nextDouble() + + return Duration.ofNanos((TimeUnit.SECONDS.toNanos(1) * backoffSeconds * jitter).toLong()) + } + + companion object { + + fun builder() = Builder() + } + + class Builder internal constructor() { + + private var httpClient: HttpClient? = null + private var sleeper: Sleeper? = null + private var clock: Clock = Clock.systemUTC() + private var maxRetries: Int = 2 + private var idempotencyHeader: String? = null + + fun httpClient(httpClient: HttpClient) = apply { this.httpClient = httpClient } + + fun sleeper(sleeper: Sleeper) = apply { this.sleeper = sleeper } + + fun clock(clock: Clock) = apply { this.clock = clock } + + fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries } + + fun idempotencyHeader(header: String) = apply { this.idempotencyHeader = header } + + fun build(): HttpClient = + RetryingHttpClient( + checkRequired("httpClient", httpClient), + sleeper ?: DefaultSleeper(), + clock, + maxRetries, + idempotencyHeader, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/StreamResponse.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/StreamResponse.kt new file mode 100644 index 0000000..6b984f6 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/StreamResponse.kt @@ -0,0 +1,13 @@ +package com.pioneer_intergration_app.api.core.http + +interface StreamResponse : AutoCloseable { + + fun asSequence(): Sequence +} + +internal fun StreamResponse.map(transform: (T) -> R): StreamResponse = + object : StreamResponse { + override fun asSequence(): Sequence = this@map.asSequence().map(transform) + + override fun close() = this@map.close() + } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/BadRequestException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/BadRequestException.kt new file mode 100644 index 0000000..edc6559 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/BadRequestException.kt @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class BadRequestException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("400: $body", cause) { + + override fun statusCode(): Int = 400 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [BadRequestException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [BadRequestException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(badRequestException: BadRequestException) = apply { + headers = badRequestException.headers + body = badRequestException.body + cause = badRequestException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [BadRequestException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): BadRequestException = + BadRequestException( + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/InternalServerException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/InternalServerException.kt new file mode 100644 index 0000000..73c61e8 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/InternalServerException.kt @@ -0,0 +1,85 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class InternalServerException +private constructor( + private val statusCode: Int, + private val headers: Headers, + private val body: JsonValue, + cause: Throwable?, +) : PioneerIntergrationAppServiceException("$statusCode: $body", cause) { + + override fun statusCode(): Int = statusCode + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [InternalServerException]. + * + * The following fields are required: + * ```kotlin + * .statusCode() + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [InternalServerException]. */ + class Builder internal constructor() { + + private var statusCode: Int? = null + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(internalServerException: InternalServerException) = apply { + statusCode = internalServerException.statusCode + headers = internalServerException.headers + body = internalServerException.body + cause = internalServerException.cause + } + + fun statusCode(statusCode: Int) = apply { this.statusCode = statusCode } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [InternalServerException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .statusCode() + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): InternalServerException = + InternalServerException( + checkRequired("statusCode", statusCode), + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/NotFoundException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/NotFoundException.kt new file mode 100644 index 0000000..6761c18 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/NotFoundException.kt @@ -0,0 +1,70 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class NotFoundException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("404: $body", cause) { + + override fun statusCode(): Int = 404 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [NotFoundException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [NotFoundException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(notFoundException: NotFoundException) = apply { + headers = notFoundException.headers + body = notFoundException.body + cause = notFoundException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [NotFoundException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): NotFoundException = + NotFoundException(checkRequired("headers", headers), checkRequired("body", body), cause) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PermissionDeniedException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PermissionDeniedException.kt new file mode 100644 index 0000000..73812ac --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PermissionDeniedException.kt @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class PermissionDeniedException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("403: $body", cause) { + + override fun statusCode(): Int = 403 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [PermissionDeniedException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [PermissionDeniedException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(permissionDeniedException: PermissionDeniedException) = apply { + headers = permissionDeniedException.headers + body = permissionDeniedException.body + cause = permissionDeniedException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [PermissionDeniedException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): PermissionDeniedException = + PermissionDeniedException( + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppException.kt new file mode 100644 index 0000000..c573765 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppException.kt @@ -0,0 +1,4 @@ +package com.pioneer_intergration_app.api.errors + +open class PioneerIntergrationAppException(message: String? = null, cause: Throwable? = null) : + RuntimeException(message, cause) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.kt new file mode 100644 index 0000000..e5ccb27 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.kt @@ -0,0 +1,6 @@ +package com.pioneer_intergration_app.api.errors + +class PioneerIntergrationAppInvalidDataException( + message: String? = null, + cause: Throwable? = null, +) : PioneerIntergrationAppException(message, cause) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppIoException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppIoException.kt new file mode 100644 index 0000000..cc510dd --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppIoException.kt @@ -0,0 +1,4 @@ +package com.pioneer_intergration_app.api.errors + +class PioneerIntergrationAppIoException(message: String? = null, cause: Throwable? = null) : + PioneerIntergrationAppException(message, cause) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppRetryableException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppRetryableException.kt new file mode 100644 index 0000000..35c0377 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppRetryableException.kt @@ -0,0 +1,14 @@ +package com.pioneer_intergration_app.api.errors + +/** + * Exception that indicates a transient error that can be retried. + * + * When this exception is thrown during an HTTP request, the SDK will automatically retry the + * request up to the maximum number of retries. + * + * @param message A descriptive error message + * @param cause The underlying cause of this exception, if any + */ +class PioneerIntergrationAppRetryableException +constructor(message: String? = null, cause: Throwable? = null) : + PioneerIntergrationAppException(message, cause) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppServiceException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppServiceException.kt new file mode 100644 index 0000000..d6a1afb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppServiceException.kt @@ -0,0 +1,17 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.http.Headers + +abstract class PioneerIntergrationAppServiceException +protected constructor(message: String, cause: Throwable? = null) : + PioneerIntergrationAppException(message, cause) { + + abstract fun statusCode(): Int + + abstract fun headers(): Headers + + abstract fun body(): JsonValue +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/RateLimitException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/RateLimitException.kt new file mode 100644 index 0000000..0da4d02 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/RateLimitException.kt @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class RateLimitException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("429: $body", cause) { + + override fun statusCode(): Int = 429 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [RateLimitException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [RateLimitException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(rateLimitException: RateLimitException) = apply { + headers = rateLimitException.headers + body = rateLimitException.body + cause = rateLimitException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [RateLimitException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): RateLimitException = + RateLimitException( + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnauthorizedException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnauthorizedException.kt new file mode 100644 index 0000000..aee9969 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnauthorizedException.kt @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class UnauthorizedException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("401: $body", cause) { + + override fun statusCode(): Int = 401 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [UnauthorizedException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [UnauthorizedException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(unauthorizedException: UnauthorizedException) = apply { + headers = unauthorizedException.headers + body = unauthorizedException.body + cause = unauthorizedException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [UnauthorizedException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UnauthorizedException = + UnauthorizedException( + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnexpectedStatusCodeException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnexpectedStatusCodeException.kt new file mode 100644 index 0000000..535bf2a --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnexpectedStatusCodeException.kt @@ -0,0 +1,86 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class UnexpectedStatusCodeException +private constructor( + private val statusCode: Int, + private val headers: Headers, + private val body: JsonValue, + cause: Throwable?, +) : PioneerIntergrationAppServiceException("$statusCode: $body", cause) { + + override fun statusCode(): Int = statusCode + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [UnexpectedStatusCodeException]. + * + * The following fields are required: + * ```kotlin + * .statusCode() + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [UnexpectedStatusCodeException]. */ + class Builder internal constructor() { + + private var statusCode: Int? = null + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(unexpectedStatusCodeException: UnexpectedStatusCodeException) = apply { + statusCode = unexpectedStatusCodeException.statusCode + headers = unexpectedStatusCodeException.headers + body = unexpectedStatusCodeException.body + cause = unexpectedStatusCodeException.cause + } + + fun statusCode(statusCode: Int) = apply { this.statusCode = statusCode } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [UnexpectedStatusCodeException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .statusCode() + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UnexpectedStatusCodeException = + UnexpectedStatusCodeException( + checkRequired("statusCode", statusCode), + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnprocessableEntityException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnprocessableEntityException.kt new file mode 100644 index 0000000..349796d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnprocessableEntityException.kt @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class UnprocessableEntityException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("422: $body", cause) { + + override fun statusCode(): Int = 422 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [UnprocessableEntityException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [UnprocessableEntityException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(unprocessableEntityException: UnprocessableEntityException) = apply { + headers = unprocessableEntityException.headers + body = unprocessableEntityException.body + cause = unprocessableEntityException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [UnprocessableEntityException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UnprocessableEntityException = + UnprocessableEntityException( + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/Order.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/Order.kt new file mode 100644 index 0000000..1ebbfcd --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/Order.kt @@ -0,0 +1,454 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.pioneer_intergration_app.api.core.Enum +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.time.OffsetDateTime +import java.util.Collections +import java.util.Objects + +class Order +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val id: JsonField, + private val complete: JsonField, + private val petId: JsonField, + private val quantity: JsonField, + private val shipDate: JsonField, + private val status: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("complete") @ExcludeMissing complete: JsonField = JsonMissing.of(), + @JsonProperty("petId") @ExcludeMissing petId: JsonField = JsonMissing.of(), + @JsonProperty("quantity") @ExcludeMissing quantity: JsonField = JsonMissing.of(), + @JsonProperty("shipDate") + @ExcludeMissing + shipDate: JsonField = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + ) : this(id, complete, petId, quantity, shipDate, status, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun id(): Long? = id.getNullable("id") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun complete(): Boolean? = complete.getNullable("complete") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun petId(): Long? = petId.getNullable("petId") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun quantity(): Int? = quantity.getNullable("quantity") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun shipDate(): OffsetDateTime? = shipDate.getNullable("shipDate") + + /** + * Order Status + * + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun status(): Status? = status.getNullable("status") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [complete]. + * + * Unlike [complete], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("complete") @ExcludeMissing fun _complete(): JsonField = complete + + /** + * Returns the raw JSON value of [petId]. + * + * Unlike [petId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("petId") @ExcludeMissing fun _petId(): JsonField = petId + + /** + * Returns the raw JSON value of [quantity]. + * + * Unlike [quantity], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("quantity") @ExcludeMissing fun _quantity(): JsonField = quantity + + /** + * Returns the raw JSON value of [shipDate]. + * + * Unlike [shipDate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("shipDate") @ExcludeMissing fun _shipDate(): JsonField = shipDate + + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Order]. */ + fun builder() = Builder() + } + + /** A builder for [Order]. */ + class Builder internal constructor() { + + private var id: JsonField = JsonMissing.of() + private var complete: JsonField = JsonMissing.of() + private var petId: JsonField = JsonMissing.of() + private var quantity: JsonField = JsonMissing.of() + private var shipDate: JsonField = JsonMissing.of() + private var status: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(order: Order) = apply { + id = order.id + complete = order.complete + petId = order.petId + quantity = order.quantity + shipDate = order.shipDate + status = order.status + additionalProperties = order.additionalProperties.toMutableMap() + } + + fun id(id: Long) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [Long] value instead. This method + * is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun complete(complete: Boolean) = complete(JsonField.of(complete)) + + /** + * Sets [Builder.complete] to an arbitrary JSON value. + * + * You should usually call [Builder.complete] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun complete(complete: JsonField) = apply { this.complete = complete } + + fun petId(petId: Long) = petId(JsonField.of(petId)) + + /** + * Sets [Builder.petId] to an arbitrary JSON value. + * + * You should usually call [Builder.petId] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun petId(petId: JsonField) = apply { this.petId = petId } + + fun quantity(quantity: Int) = quantity(JsonField.of(quantity)) + + /** + * Sets [Builder.quantity] to an arbitrary JSON value. + * + * You should usually call [Builder.quantity] with a well-typed [Int] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun quantity(quantity: JsonField) = apply { this.quantity = quantity } + + fun shipDate(shipDate: OffsetDateTime) = shipDate(JsonField.of(shipDate)) + + /** + * Sets [Builder.shipDate] to an arbitrary JSON value. + * + * You should usually call [Builder.shipDate] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun shipDate(shipDate: JsonField) = apply { this.shipDate = shipDate } + + /** Order Status */ + fun status(status: Status) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Status] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Order]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Order = + Order( + id, + complete, + petId, + quantity, + shipDate, + status, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Order = apply { + if (validated) { + return@apply + } + + id() + complete() + petId() + quantity() + shipDate() + status()?.validate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (id.asKnown() == null) 0 else 1) + + (if (complete.asKnown() == null) 0 else 1) + + (if (petId.asKnown() == null) 0 else 1) + + (if (quantity.asKnown() == null) 0 else 1) + + (if (shipDate.asKnown() == null) 0 else 1) + + (status.asKnown()?.validity() ?: 0) + + /** Order Status */ + class Status @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + val PLACED = of("placed") + + val APPROVED = of("approved") + + val DELIVERED = of("delivered") + + fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + PLACED, + APPROVED, + DELIVERED, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PLACED, + APPROVED, + DELIVERED, + /** An enum member indicating that [Status] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PLACED -> Value.PLACED + APPROVED -> Value.APPROVED + DELIVERED -> Value.DELIVERED + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws PioneerIntergrationAppInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + PLACED -> Known.PLACED + APPROVED -> Known.APPROVED + DELIVERED -> Known.DELIVERED + else -> throw PioneerIntergrationAppInvalidDataException("Unknown Status: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws PioneerIntergrationAppInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString() + ?: throw PioneerIntergrationAppInvalidDataException("Value is not a String") + + private var validated: Boolean = false + + fun validate(): Status = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Status && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Order && + id == other.id && + complete == other.complete && + petId == other.petId && + quantity == other.quantity && + shipDate == other.shipDate && + status == other.status && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, complete, petId, quantity, shipDate, status, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Order{id=$id, complete=$complete, petId=$petId, quantity=$quantity, shipDate=$shipDate, status=$status, additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Category.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Category.kt new file mode 100644 index 0000000..b18051c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Category.kt @@ -0,0 +1,180 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Collections +import java.util.Objects + +class Category +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val id: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(id, name, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun id(): Long? = id.getNullable("id") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun name(): String? = name.getNullable("name") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Category]. */ + fun builder() = Builder() + } + + /** A builder for [Category]. */ + class Builder internal constructor() { + + private var id: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(category: Category) = apply { + id = category.id + name = category.name + additionalProperties = category.additionalProperties.toMutableMap() + } + + fun id(id: Long) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [Long] value instead. This method + * is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Category]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Category = Category(id, name, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Category = apply { + if (validated) { + return@apply + } + + id() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (id.asKnown() == null) 0 else 1) + (if (name.asKnown() == null) 0 else 1) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Category && + id == other.id && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Category{id=$id, name=$name, additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Pet.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Pet.kt new file mode 100644 index 0000000..2fb2c5d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Pet.kt @@ -0,0 +1,663 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.pioneer_intergration_app.api.core.Enum +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkKnown +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.toImmutable +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Collections +import java.util.Objects + +class Pet +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val name: JsonField, + private val photoUrls: JsonField>, + private val id: JsonField, + private val category: JsonField, + private val status: JsonField, + private val tags: JsonField>, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("photoUrls") + @ExcludeMissing + photoUrls: JsonField> = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("category") @ExcludeMissing category: JsonField = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(), + ) : this(name, photoUrls, id, category, status, tags, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * or is unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun name(): String = name.getRequired("name") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * or is unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun photoUrls(): List = photoUrls.getRequired("photoUrls") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun id(): Long? = id.getNullable("id") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun category(): Category? = category.getNullable("category") + + /** + * pet status in the store + * + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun status(): Status? = status.getNullable("status") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun tags(): List? = tags.getNullable("tags") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [photoUrls]. + * + * Unlike [photoUrls], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("photoUrls") @ExcludeMissing fun _photoUrls(): JsonField> = photoUrls + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [category]. + * + * Unlike [category], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("category") @ExcludeMissing fun _category(): JsonField = category + + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + + /** + * Returns the raw JSON value of [tags]. + * + * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField> = tags + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Pet]. + * + * The following fields are required: + * ```kotlin + * .name() + * .photoUrls() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [Pet]. */ + class Builder internal constructor() { + + private var name: JsonField? = null + private var photoUrls: JsonField>? = null + private var id: JsonField = JsonMissing.of() + private var category: JsonField = JsonMissing.of() + private var status: JsonField = JsonMissing.of() + private var tags: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(pet: Pet) = apply { + name = pet.name + photoUrls = pet.photoUrls.map { it.toMutableList() } + id = pet.id + category = pet.category + status = pet.status + tags = pet.tags.map { it.toMutableList() } + additionalProperties = pet.additionalProperties.toMutableMap() + } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun photoUrls(photoUrls: List) = photoUrls(JsonField.of(photoUrls)) + + /** + * Sets [Builder.photoUrls] to an arbitrary JSON value. + * + * You should usually call [Builder.photoUrls] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun photoUrls(photoUrls: JsonField>) = apply { + this.photoUrls = photoUrls.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [photoUrls]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addPhotoUrl(photoUrl: String) = apply { + photoUrls = + (photoUrls ?: JsonField.of(mutableListOf())).also { + checkKnown("photoUrls", it).add(photoUrl) + } + } + + fun id(id: Long) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [Long] value instead. This method + * is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun category(category: Category) = category(JsonField.of(category)) + + /** + * Sets [Builder.category] to an arbitrary JSON value. + * + * You should usually call [Builder.category] with a well-typed [Category] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun category(category: JsonField) = apply { this.category = category } + + /** pet status in the store */ + fun status(status: Status) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Status] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + + fun tags(tags: List) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed `List` value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun tags(tags: JsonField>) = apply { this.tags = tags.map { it.toMutableList() } } + + /** + * Adds a single [Tag] to [tags]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTag(tag: Tag) = apply { + tags = (tags ?: JsonField.of(mutableListOf())).also { checkKnown("tags", it).add(tag) } + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Pet]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .name() + * .photoUrls() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Pet = + Pet( + checkRequired("name", name), + checkRequired("photoUrls", photoUrls).map { it.toImmutable() }, + id, + category, + status, + (tags ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Pet = apply { + if (validated) { + return@apply + } + + name() + photoUrls() + id() + category()?.validate() + status()?.validate() + tags()?.forEach { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (name.asKnown() == null) 0 else 1) + + (photoUrls.asKnown()?.size ?: 0) + + (if (id.asKnown() == null) 0 else 1) + + (category.asKnown()?.validity() ?: 0) + + (status.asKnown()?.validity() ?: 0) + + (tags.asKnown()?.sumOf { it.validity().toInt() } ?: 0) + + /** pet status in the store */ + class Status @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + val AVAILABLE = of("available") + + val PENDING = of("pending") + + val SOLD = of("sold") + + fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + AVAILABLE, + PENDING, + SOLD, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AVAILABLE, + PENDING, + SOLD, + /** An enum member indicating that [Status] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AVAILABLE -> Value.AVAILABLE + PENDING -> Value.PENDING + SOLD -> Value.SOLD + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws PioneerIntergrationAppInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + AVAILABLE -> Known.AVAILABLE + PENDING -> Known.PENDING + SOLD -> Known.SOLD + else -> throw PioneerIntergrationAppInvalidDataException("Unknown Status: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws PioneerIntergrationAppInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString() + ?: throw PioneerIntergrationAppInvalidDataException("Value is not a String") + + private var validated: Boolean = false + + fun validate(): Status = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Status && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Tag + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val id: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(id, name, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun id(): Long? = id.getNullable("id") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun name(): String? = name.getNullable("name") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Tag]. */ + fun builder() = Builder() + } + + /** A builder for [Tag]. */ + class Builder internal constructor() { + + private var id: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(tag: Tag) = apply { + id = tag.id + name = tag.name + additionalProperties = tag.additionalProperties.toMutableMap() + } + + fun id(id: Long) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Tag]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Tag = Tag(id, name, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Tag = apply { + if (validated) { + return@apply + } + + id() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (id.asKnown() == null) 0 else 1) + (if (name.asKnown() == null) 0 else 1) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Tag && + id == other.id && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Tag{id=$id, name=$name, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Pet && + name == other.name && + photoUrls == other.photoUrls && + id == other.id && + category == other.category && + status == other.status && + tags == other.tags && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(name, photoUrls, id, category, status, tags, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Pet{name=$name, photoUrls=$photoUrls, id=$id, category=$category, status=$status, tags=$tags, additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParams.kt new file mode 100644 index 0000000..03b309b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParams.kt @@ -0,0 +1,199 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Add a new pet to the store */ +class PetCreateParams +private constructor( + private val pet: Pet, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun pet(): Pet = pet + + fun _additionalBodyProperties(): Map = pet._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [PetCreateParams]. + * + * The following fields are required: + * ```kotlin + * .pet() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [PetCreateParams]. */ + class Builder internal constructor() { + + private var pet: Pet? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petCreateParams: PetCreateParams) = apply { + pet = petCreateParams.pet + additionalHeaders = petCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = petCreateParams.additionalQueryParams.toBuilder() + } + + fun pet(pet: Pet) = apply { this.pet = pet } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .pet() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): PetCreateParams = + PetCreateParams( + checkRequired("pet", pet), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Pet = pet + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetCreateParams && + pet == other.pet && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(pet, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetCreateParams{pet=$pet, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParams.kt new file mode 100644 index 0000000..141949a --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParams.kt @@ -0,0 +1,229 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** delete a pet */ +class PetDeleteParams +private constructor( + private val petId: Long?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun petId(): Long? = petId + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetDeleteParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetDeleteParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetDeleteParams]. */ + class Builder internal constructor() { + + private var petId: Long? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + internal fun from(petDeleteParams: PetDeleteParams) = apply { + petId = petDeleteParams.petId + additionalHeaders = petDeleteParams.additionalHeaders.toBuilder() + additionalQueryParams = petDeleteParams.additionalQueryParams.toBuilder() + additionalBodyProperties = petDeleteParams.additionalBodyProperties.toMutableMap() + } + + fun petId(petId: Long?) = apply { this.petId = petId } + + /** + * Alias for [Builder.petId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun petId(petId: Long) = petId(petId as Long?) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [PetDeleteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetDeleteParams = + PetDeleteParams( + petId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Map? = additionalBodyProperties.ifEmpty { null } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> petId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetDeleteParams && + petId == other.petId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash(petId, additionalHeaders, additionalQueryParams, additionalBodyProperties) + + override fun toString() = + "PetDeleteParams{petId=$petId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParams.kt new file mode 100644 index 0000000..e3f92ea --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParams.kt @@ -0,0 +1,322 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.annotation.JsonCreator +import com.pioneer_intergration_app.api.core.Enum +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Objects + +/** Multiple status values can be provided with comma separated strings */ +class PetFindByStatusParams +private constructor( + private val status: Status?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Status values that need to be considered for filter */ + fun status(): Status? = status + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetFindByStatusParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetFindByStatusParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetFindByStatusParams]. */ + class Builder internal constructor() { + + private var status: Status? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petFindByStatusParams: PetFindByStatusParams) = apply { + status = petFindByStatusParams.status + additionalHeaders = petFindByStatusParams.additionalHeaders.toBuilder() + additionalQueryParams = petFindByStatusParams.additionalQueryParams.toBuilder() + } + + /** Status values that need to be considered for filter */ + fun status(status: Status?) = apply { this.status = status } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetFindByStatusParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetFindByStatusParams = + PetFindByStatusParams(status, additionalHeaders.build(), additionalQueryParams.build()) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + status?.let { put("status", it.toString()) } + putAll(additionalQueryParams) + } + .build() + + /** Status values that need to be considered for filter */ + class Status @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + val AVAILABLE = of("available") + + val PENDING = of("pending") + + val SOLD = of("sold") + + fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + AVAILABLE, + PENDING, + SOLD, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AVAILABLE, + PENDING, + SOLD, + /** An enum member indicating that [Status] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AVAILABLE -> Value.AVAILABLE + PENDING -> Value.PENDING + SOLD -> Value.SOLD + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws PioneerIntergrationAppInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + AVAILABLE -> Known.AVAILABLE + PENDING -> Known.PENDING + SOLD -> Known.SOLD + else -> throw PioneerIntergrationAppInvalidDataException("Unknown Status: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws PioneerIntergrationAppInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString() + ?: throw PioneerIntergrationAppInvalidDataException("Value is not a String") + + private var validated: Boolean = false + + fun validate(): Status = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Status && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetFindByStatusParams && + status == other.status && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(status, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetFindByStatusParams{status=$status, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParams.kt new file mode 100644 index 0000000..cc8a749 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParams.kt @@ -0,0 +1,197 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. */ +class PetFindByTagsParams +private constructor( + private val tags: List?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Tags to filter by */ + fun tags(): List? = tags + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetFindByTagsParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetFindByTagsParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetFindByTagsParams]. */ + class Builder internal constructor() { + + private var tags: MutableList? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petFindByTagsParams: PetFindByTagsParams) = apply { + tags = petFindByTagsParams.tags?.toMutableList() + additionalHeaders = petFindByTagsParams.additionalHeaders.toBuilder() + additionalQueryParams = petFindByTagsParams.additionalQueryParams.toBuilder() + } + + /** Tags to filter by */ + fun tags(tags: List?) = apply { this.tags = tags?.toMutableList() } + + /** + * Adds a single [String] to [tags]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTag(tag: String) = apply { tags = (tags ?: mutableListOf()).apply { add(tag) } } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetFindByTagsParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetFindByTagsParams = + PetFindByTagsParams( + tags?.toImmutable(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + tags?.let { put("tags", it.joinToString(",")) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetFindByTagsParams && + tags == other.tags && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(tags, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetFindByTagsParams{tags=$tags, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParams.kt new file mode 100644 index 0000000..830b00f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParams.kt @@ -0,0 +1,190 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Returns a single pet */ +class PetRetrieveParams +private constructor( + private val petId: Long?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun petId(): Long? = petId + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetRetrieveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetRetrieveParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetRetrieveParams]. */ + class Builder internal constructor() { + + private var petId: Long? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petRetrieveParams: PetRetrieveParams) = apply { + petId = petRetrieveParams.petId + additionalHeaders = petRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = petRetrieveParams.additionalQueryParams.toBuilder() + } + + fun petId(petId: Long?) = apply { this.petId = petId } + + /** + * Alias for [Builder.petId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun petId(petId: Long) = petId(petId as Long?) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetRetrieveParams = + PetRetrieveParams(petId, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> petId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetRetrieveParams && + petId == other.petId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(petId, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetRetrieveParams{petId=$petId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParams.kt new file mode 100644 index 0000000..489ca8c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParams.kt @@ -0,0 +1,265 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** Updates a pet in the store with form data */ +class PetUpdateByIdParams +private constructor( + private val petId: Long?, + private val name: String?, + private val status: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun petId(): Long? = petId + + /** Name of pet that needs to be updated */ + fun name(): String? = name + + /** Status of pet that needs to be updated */ + fun status(): String? = status + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetUpdateByIdParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetUpdateByIdParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetUpdateByIdParams]. */ + class Builder internal constructor() { + + private var petId: Long? = null + private var name: String? = null + private var status: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + internal fun from(petUpdateByIdParams: PetUpdateByIdParams) = apply { + petId = petUpdateByIdParams.petId + name = petUpdateByIdParams.name + status = petUpdateByIdParams.status + additionalHeaders = petUpdateByIdParams.additionalHeaders.toBuilder() + additionalQueryParams = petUpdateByIdParams.additionalQueryParams.toBuilder() + additionalBodyProperties = petUpdateByIdParams.additionalBodyProperties.toMutableMap() + } + + fun petId(petId: Long?) = apply { this.petId = petId } + + /** + * Alias for [Builder.petId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun petId(petId: Long) = petId(petId as Long?) + + /** Name of pet that needs to be updated */ + fun name(name: String?) = apply { this.name = name } + + /** Status of pet that needs to be updated */ + fun status(status: String?) = apply { this.status = status } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [PetUpdateByIdParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetUpdateByIdParams = + PetUpdateByIdParams( + petId, + name, + status, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Map? = additionalBodyProperties.ifEmpty { null } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> petId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + name?.let { put("name", it) } + status?.let { put("status", it) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetUpdateByIdParams && + petId == other.petId && + name == other.name && + status == other.status && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash( + petId, + name, + status, + additionalHeaders, + additionalQueryParams, + additionalBodyProperties, + ) + + override fun toString() = + "PetUpdateByIdParams{petId=$petId, name=$name, status=$status, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParams.kt new file mode 100644 index 0000000..32576e6 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParams.kt @@ -0,0 +1,199 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Update an existing pet by Id */ +class PetUpdateParams +private constructor( + private val pet: Pet, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun pet(): Pet = pet + + fun _additionalBodyProperties(): Map = pet._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [PetUpdateParams]. + * + * The following fields are required: + * ```kotlin + * .pet() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [PetUpdateParams]. */ + class Builder internal constructor() { + + private var pet: Pet? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petUpdateParams: PetUpdateParams) = apply { + pet = petUpdateParams.pet + additionalHeaders = petUpdateParams.additionalHeaders.toBuilder() + additionalQueryParams = petUpdateParams.additionalQueryParams.toBuilder() + } + + fun pet(pet: Pet) = apply { this.pet = pet } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetUpdateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .pet() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): PetUpdateParams = + PetUpdateParams( + checkRequired("pet", pet), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Pet = pet + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetUpdateParams && + pet == other.pet && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(pet, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetUpdateParams{pet=$pet, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParams.kt new file mode 100644 index 0000000..1187384 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParams.kt @@ -0,0 +1,225 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** uploads an image */ +class PetUploadImageParams +private constructor( + private val petId: Long?, + private val additionalMetadata: String?, + private val image: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun petId(): Long? = petId + + /** Additional Metadata */ + fun additionalMetadata(): String? = additionalMetadata + + fun image(): String? = image + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetUploadImageParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetUploadImageParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetUploadImageParams]. */ + class Builder internal constructor() { + + private var petId: Long? = null + private var additionalMetadata: String? = null + private var image: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petUploadImageParams: PetUploadImageParams) = apply { + petId = petUploadImageParams.petId + additionalMetadata = petUploadImageParams.additionalMetadata + image = petUploadImageParams.image + additionalHeaders = petUploadImageParams.additionalHeaders.toBuilder() + additionalQueryParams = petUploadImageParams.additionalQueryParams.toBuilder() + } + + fun petId(petId: Long?) = apply { this.petId = petId } + + /** + * Alias for [Builder.petId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun petId(petId: Long) = petId(petId as Long?) + + /** Additional Metadata */ + fun additionalMetadata(additionalMetadata: String?) = apply { + this.additionalMetadata = additionalMetadata + } + + fun image(image: String?) = apply { this.image = image } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetUploadImageParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetUploadImageParams = + PetUploadImageParams( + petId, + additionalMetadata, + image, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): String? = image + + fun _pathParam(index: Int): String = + when (index) { + 0 -> petId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + additionalMetadata?.let { put("additionalMetadata", it) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetUploadImageParams && + petId == other.petId && + additionalMetadata == other.additionalMetadata && + image == other.image && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(petId, additionalMetadata, image, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetUploadImageParams{petId=$petId, additionalMetadata=$additionalMetadata, image=$image, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponse.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponse.kt new file mode 100644 index 0000000..fca736b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponse.kt @@ -0,0 +1,212 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Collections +import java.util.Objects + +class PetUploadImageResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val code: JsonField, + private val message: JsonField, + private val type: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("code") @ExcludeMissing code: JsonField = JsonMissing.of(), + @JsonProperty("message") @ExcludeMissing message: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + ) : this(code, message, type, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun code(): Int? = code.getNullable("code") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun message(): String? = message.getNullable("message") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun type(): String? = type.getNullable("type") + + /** + * Returns the raw JSON value of [code]. + * + * Unlike [code], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("code") @ExcludeMissing fun _code(): JsonField = code + + /** + * Returns the raw JSON value of [message]. + * + * Unlike [message], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("message") @ExcludeMissing fun _message(): JsonField = message + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [PetUploadImageResponse]. */ + fun builder() = Builder() + } + + /** A builder for [PetUploadImageResponse]. */ + class Builder internal constructor() { + + private var code: JsonField = JsonMissing.of() + private var message: JsonField = JsonMissing.of() + private var type: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(petUploadImageResponse: PetUploadImageResponse) = apply { + code = petUploadImageResponse.code + message = petUploadImageResponse.message + type = petUploadImageResponse.type + additionalProperties = petUploadImageResponse.additionalProperties.toMutableMap() + } + + fun code(code: Int) = code(JsonField.of(code)) + + /** + * Sets [Builder.code] to an arbitrary JSON value. + * + * You should usually call [Builder.code] with a well-typed [Int] value instead. This method + * is primarily for setting the field to an undocumented or not yet supported value. + */ + fun code(code: JsonField) = apply { this.code = code } + + fun message(message: String) = message(JsonField.of(message)) + + /** + * Sets [Builder.message] to an arbitrary JSON value. + * + * You should usually call [Builder.message] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun message(message: JsonField) = apply { this.message = message } + + fun type(type: String) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [PetUploadImageResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetUploadImageResponse = + PetUploadImageResponse(code, message, type, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): PetUploadImageResponse = apply { + if (validated) { + return@apply + } + + code() + message() + type() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (code.asKnown() == null) 0 else 1) + + (if (message.asKnown() == null) 0 else 1) + + (if (type.asKnown() == null) 0 else 1) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetUploadImageResponse && + code == other.code && + message == other.message && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(code, message, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "PetUploadImageResponse{code=$code, message=$message, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParams.kt new file mode 100644 index 0000000..fef124d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParams.kt @@ -0,0 +1,169 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Returns a map of status codes to quantities */ +class StoreListInventoryParams +private constructor( + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): StoreListInventoryParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [StoreListInventoryParams]. */ + fun builder() = Builder() + } + + /** A builder for [StoreListInventoryParams]. */ + class Builder internal constructor() { + + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(storeListInventoryParams: StoreListInventoryParams) = apply { + additionalHeaders = storeListInventoryParams.additionalHeaders.toBuilder() + additionalQueryParams = storeListInventoryParams.additionalQueryParams.toBuilder() + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [StoreListInventoryParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): StoreListInventoryParams = + StoreListInventoryParams(additionalHeaders.build(), additionalQueryParams.build()) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is StoreListInventoryParams && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(additionalHeaders, additionalQueryParams) + + override fun toString() = + "StoreListInventoryParams{additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponse.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponse.kt new file mode 100644 index 0000000..b2f7d96 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponse.kt @@ -0,0 +1,112 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.toImmutable +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Objects + +class StoreListInventoryResponse +@JsonCreator +private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map +) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [StoreListInventoryResponse]. + */ + fun builder() = Builder() + } + + /** A builder for [StoreListInventoryResponse]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(storeListInventoryResponse: StoreListInventoryResponse) = apply { + additionalProperties = storeListInventoryResponse.additionalProperties.toMutableMap() + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [StoreListInventoryResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): StoreListInventoryResponse = + StoreListInventoryResponse(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + fun validate(): StoreListInventoryResponse = apply { + if (validated) { + return@apply + } + + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is StoreListInventoryResponse && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "StoreListInventoryResponse{additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParams.kt new file mode 100644 index 0000000..c7cc400 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParams.kt @@ -0,0 +1,185 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.immutableEmptyMap +import com.pioneer_intergration_app.api.models.Order +import java.util.Objects + +/** Place a new order in the store */ +class OrderCreateParams +private constructor( + private val order: Order?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun order(): Order? = order + + fun _additionalBodyProperties(): Map = + order?._additionalProperties() ?: immutableEmptyMap() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): OrderCreateParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [OrderCreateParams]. */ + fun builder() = Builder() + } + + /** A builder for [OrderCreateParams]. */ + class Builder internal constructor() { + + private var order: Order? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(orderCreateParams: OrderCreateParams) = apply { + order = orderCreateParams.order + additionalHeaders = orderCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = orderCreateParams.additionalQueryParams.toBuilder() + } + + fun order(order: Order?) = apply { this.order = order } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [OrderCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): OrderCreateParams = + OrderCreateParams(order, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _body(): Order? = order + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OrderCreateParams && + order == other.order && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(order, additionalHeaders, additionalQueryParams) + + override fun toString() = + "OrderCreateParams{order=$order, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParams.kt new file mode 100644 index 0000000..c38db95 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParams.kt @@ -0,0 +1,232 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will + * generate API errors + */ +class OrderDeleteParams +private constructor( + private val orderId: Long?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun orderId(): Long? = orderId + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): OrderDeleteParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [OrderDeleteParams]. */ + fun builder() = Builder() + } + + /** A builder for [OrderDeleteParams]. */ + class Builder internal constructor() { + + private var orderId: Long? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + internal fun from(orderDeleteParams: OrderDeleteParams) = apply { + orderId = orderDeleteParams.orderId + additionalHeaders = orderDeleteParams.additionalHeaders.toBuilder() + additionalQueryParams = orderDeleteParams.additionalQueryParams.toBuilder() + additionalBodyProperties = orderDeleteParams.additionalBodyProperties.toMutableMap() + } + + fun orderId(orderId: Long?) = apply { this.orderId = orderId } + + /** + * Alias for [Builder.orderId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun orderId(orderId: Long) = orderId(orderId as Long?) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [OrderDeleteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): OrderDeleteParams = + OrderDeleteParams( + orderId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Map? = additionalBodyProperties.ifEmpty { null } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> orderId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OrderDeleteParams && + orderId == other.orderId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash(orderId, additionalHeaders, additionalQueryParams, additionalBodyProperties) + + override fun toString() = + "OrderDeleteParams{orderId=$orderId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParams.kt new file mode 100644 index 0000000..591ab90 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParams.kt @@ -0,0 +1,193 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** + * For valid response try integer IDs with value <= 5 or > 10. Other values will generate + * exceptions. + */ +class OrderRetrieveParams +private constructor( + private val orderId: Long?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun orderId(): Long? = orderId + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): OrderRetrieveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [OrderRetrieveParams]. */ + fun builder() = Builder() + } + + /** A builder for [OrderRetrieveParams]. */ + class Builder internal constructor() { + + private var orderId: Long? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(orderRetrieveParams: OrderRetrieveParams) = apply { + orderId = orderRetrieveParams.orderId + additionalHeaders = orderRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = orderRetrieveParams.additionalQueryParams.toBuilder() + } + + fun orderId(orderId: Long?) = apply { this.orderId = orderId } + + /** + * Alias for [Builder.orderId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun orderId(orderId: Long) = orderId(orderId as Long?) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [OrderRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): OrderRetrieveParams = + OrderRetrieveParams(orderId, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> orderId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OrderRetrieveParams && + orderId == other.orderId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(orderId, additionalHeaders, additionalQueryParams) + + override fun toString() = + "OrderRetrieveParams{orderId=$orderId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/User.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/User.kt new file mode 100644 index 0000000..1a411b8 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/User.kt @@ -0,0 +1,388 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Collections +import java.util.Objects + +class User +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val id: JsonField, + private val email: JsonField, + private val firstName: JsonField, + private val lastName: JsonField, + private val password: JsonField, + private val phone: JsonField, + private val username: JsonField, + private val userStatus: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("email") @ExcludeMissing email: JsonField = JsonMissing.of(), + @JsonProperty("firstName") @ExcludeMissing firstName: JsonField = JsonMissing.of(), + @JsonProperty("lastName") @ExcludeMissing lastName: JsonField = JsonMissing.of(), + @JsonProperty("password") @ExcludeMissing password: JsonField = JsonMissing.of(), + @JsonProperty("phone") @ExcludeMissing phone: JsonField = JsonMissing.of(), + @JsonProperty("username") @ExcludeMissing username: JsonField = JsonMissing.of(), + @JsonProperty("userStatus") @ExcludeMissing userStatus: JsonField = JsonMissing.of(), + ) : this(id, email, firstName, lastName, password, phone, username, userStatus, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun id(): Long? = id.getNullable("id") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun email(): String? = email.getNullable("email") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun firstName(): String? = firstName.getNullable("firstName") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun lastName(): String? = lastName.getNullable("lastName") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun password(): String? = password.getNullable("password") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun phone(): String? = phone.getNullable("phone") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun username(): String? = username.getNullable("username") + + /** + * User Status + * + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun userStatus(): Int? = userStatus.getNullable("userStatus") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [email]. + * + * Unlike [email], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("email") @ExcludeMissing fun _email(): JsonField = email + + /** + * Returns the raw JSON value of [firstName]. + * + * Unlike [firstName], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("firstName") @ExcludeMissing fun _firstName(): JsonField = firstName + + /** + * Returns the raw JSON value of [lastName]. + * + * Unlike [lastName], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("lastName") @ExcludeMissing fun _lastName(): JsonField = lastName + + /** + * Returns the raw JSON value of [password]. + * + * Unlike [password], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("password") @ExcludeMissing fun _password(): JsonField = password + + /** + * Returns the raw JSON value of [phone]. + * + * Unlike [phone], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("phone") @ExcludeMissing fun _phone(): JsonField = phone + + /** + * Returns the raw JSON value of [username]. + * + * Unlike [username], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("username") @ExcludeMissing fun _username(): JsonField = username + + /** + * Returns the raw JSON value of [userStatus]. + * + * Unlike [userStatus], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("userStatus") @ExcludeMissing fun _userStatus(): JsonField = userStatus + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [User]. */ + fun builder() = Builder() + } + + /** A builder for [User]. */ + class Builder internal constructor() { + + private var id: JsonField = JsonMissing.of() + private var email: JsonField = JsonMissing.of() + private var firstName: JsonField = JsonMissing.of() + private var lastName: JsonField = JsonMissing.of() + private var password: JsonField = JsonMissing.of() + private var phone: JsonField = JsonMissing.of() + private var username: JsonField = JsonMissing.of() + private var userStatus: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(user: User) = apply { + id = user.id + email = user.email + firstName = user.firstName + lastName = user.lastName + password = user.password + phone = user.phone + username = user.username + userStatus = user.userStatus + additionalProperties = user.additionalProperties.toMutableMap() + } + + fun id(id: Long) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [Long] value instead. This method + * is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun email(email: String) = email(JsonField.of(email)) + + /** + * Sets [Builder.email] to an arbitrary JSON value. + * + * You should usually call [Builder.email] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun email(email: JsonField) = apply { this.email = email } + + fun firstName(firstName: String) = firstName(JsonField.of(firstName)) + + /** + * Sets [Builder.firstName] to an arbitrary JSON value. + * + * You should usually call [Builder.firstName] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun firstName(firstName: JsonField) = apply { this.firstName = firstName } + + fun lastName(lastName: String) = lastName(JsonField.of(lastName)) + + /** + * Sets [Builder.lastName] to an arbitrary JSON value. + * + * You should usually call [Builder.lastName] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun lastName(lastName: JsonField) = apply { this.lastName = lastName } + + fun password(password: String) = password(JsonField.of(password)) + + /** + * Sets [Builder.password] to an arbitrary JSON value. + * + * You should usually call [Builder.password] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun password(password: JsonField) = apply { this.password = password } + + fun phone(phone: String) = phone(JsonField.of(phone)) + + /** + * Sets [Builder.phone] to an arbitrary JSON value. + * + * You should usually call [Builder.phone] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun phone(phone: JsonField) = apply { this.phone = phone } + + fun username(username: String) = username(JsonField.of(username)) + + /** + * Sets [Builder.username] to an arbitrary JSON value. + * + * You should usually call [Builder.username] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun username(username: JsonField) = apply { this.username = username } + + /** User Status */ + fun userStatus(userStatus: Int) = userStatus(JsonField.of(userStatus)) + + /** + * Sets [Builder.userStatus] to an arbitrary JSON value. + * + * You should usually call [Builder.userStatus] with a well-typed [Int] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun userStatus(userStatus: JsonField) = apply { this.userStatus = userStatus } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [User]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): User = + User( + id, + email, + firstName, + lastName, + password, + phone, + username, + userStatus, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): User = apply { + if (validated) { + return@apply + } + + id() + email() + firstName() + lastName() + password() + phone() + username() + userStatus() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (id.asKnown() == null) 0 else 1) + + (if (email.asKnown() == null) 0 else 1) + + (if (firstName.asKnown() == null) 0 else 1) + + (if (lastName.asKnown() == null) 0 else 1) + + (if (password.asKnown() == null) 0 else 1) + + (if (phone.asKnown() == null) 0 else 1) + + (if (username.asKnown() == null) 0 else 1) + + (if (userStatus.asKnown() == null) 0 else 1) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is User && + id == other.id && + email == other.email && + firstName == other.firstName && + lastName == other.lastName && + password == other.password && + phone == other.phone && + username == other.username && + userStatus == other.userStatus && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + id, + email, + firstName, + lastName, + password, + phone, + username, + userStatus, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "User{id=$id, email=$email, firstName=$firstName, lastName=$lastName, password=$password, phone=$phone, username=$username, userStatus=$userStatus, additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParams.kt new file mode 100644 index 0000000..4bf2c4b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParams.kt @@ -0,0 +1,184 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.immutableEmptyMap +import java.util.Objects + +/** This can only be done by the logged in user. */ +class UserCreateParams +private constructor( + private val user: User?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun user(): User? = user + + fun _additionalBodyProperties(): Map = + user?._additionalProperties() ?: immutableEmptyMap() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserCreateParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserCreateParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserCreateParams]. */ + class Builder internal constructor() { + + private var user: User? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userCreateParams: UserCreateParams) = apply { + user = userCreateParams.user + additionalHeaders = userCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = userCreateParams.additionalQueryParams.toBuilder() + } + + fun user(user: User?) = apply { this.user = user } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserCreateParams = + UserCreateParams(user, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _body(): User? = user + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserCreateParams && + user == other.user && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(user, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserCreateParams{user=$user, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParams.kt new file mode 100644 index 0000000..391fbb3 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParams.kt @@ -0,0 +1,191 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** Creates list of users with given input array */ +class UserCreateWithListParams +private constructor( + private val items: List?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun items(): List? = items + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserCreateWithListParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserCreateWithListParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserCreateWithListParams]. */ + class Builder internal constructor() { + + private var items: MutableList? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userCreateWithListParams: UserCreateWithListParams) = apply { + items = userCreateWithListParams.items?.toMutableList() + additionalHeaders = userCreateWithListParams.additionalHeaders.toBuilder() + additionalQueryParams = userCreateWithListParams.additionalQueryParams.toBuilder() + } + + fun items(items: List?) = apply { this.items = items?.toMutableList() } + + /** + * Adds a single [User] to [items]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addItem(item: User) = apply { items = (items ?: mutableListOf()).apply { add(item) } } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserCreateWithListParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserCreateWithListParams = + UserCreateWithListParams( + items?.toImmutable(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): List? = items + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserCreateWithListParams && + items == other.items && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(items, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserCreateWithListParams{items=$items, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParams.kt new file mode 100644 index 0000000..6a4b771 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParams.kt @@ -0,0 +1,222 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** This can only be done by the logged in user. */ +class UserDeleteParams +private constructor( + private val username: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun username(): String? = username + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserDeleteParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserDeleteParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserDeleteParams]. */ + class Builder internal constructor() { + + private var username: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + internal fun from(userDeleteParams: UserDeleteParams) = apply { + username = userDeleteParams.username + additionalHeaders = userDeleteParams.additionalHeaders.toBuilder() + additionalQueryParams = userDeleteParams.additionalQueryParams.toBuilder() + additionalBodyProperties = userDeleteParams.additionalBodyProperties.toMutableMap() + } + + fun username(username: String?) = apply { this.username = username } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [UserDeleteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserDeleteParams = + UserDeleteParams( + username, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Map? = additionalBodyProperties.ifEmpty { null } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> username ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserDeleteParams && + username == other.username && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash(username, additionalHeaders, additionalQueryParams, additionalBodyProperties) + + override fun toString() = + "UserDeleteParams{username=$username, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParams.kt new file mode 100644 index 0000000..f4c3abb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParams.kt @@ -0,0 +1,202 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Logs user into the system */ +class UserLoginParams +private constructor( + private val password: String?, + private val username: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** The password for login in clear text */ + fun password(): String? = password + + /** The user name for login */ + fun username(): String? = username + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserLoginParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserLoginParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserLoginParams]. */ + class Builder internal constructor() { + + private var password: String? = null + private var username: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userLoginParams: UserLoginParams) = apply { + password = userLoginParams.password + username = userLoginParams.username + additionalHeaders = userLoginParams.additionalHeaders.toBuilder() + additionalQueryParams = userLoginParams.additionalQueryParams.toBuilder() + } + + /** The password for login in clear text */ + fun password(password: String?) = apply { this.password = password } + + /** The user name for login */ + fun username(username: String?) = apply { this.username = username } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserLoginParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserLoginParams = + UserLoginParams( + password, + username, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + password?.let { put("password", it) } + username?.let { put("username", it) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserLoginParams && + password == other.password && + username == other.username && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(password, username, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserLoginParams{password=$password, username=$username, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParams.kt new file mode 100644 index 0000000..23b884c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParams.kt @@ -0,0 +1,169 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Logs out current logged in user session */ +class UserLogoutParams +private constructor( + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserLogoutParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserLogoutParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserLogoutParams]. */ + class Builder internal constructor() { + + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userLogoutParams: UserLogoutParams) = apply { + additionalHeaders = userLogoutParams.additionalHeaders.toBuilder() + additionalQueryParams = userLogoutParams.additionalQueryParams.toBuilder() + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserLogoutParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserLogoutParams = + UserLogoutParams(additionalHeaders.build(), additionalQueryParams.build()) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserLogoutParams && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserLogoutParams{additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParams.kt new file mode 100644 index 0000000..6e6d293 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParams.kt @@ -0,0 +1,183 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Get user by user name */ +class UserRetrieveParams +private constructor( + private val username: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun username(): String? = username + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserRetrieveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserRetrieveParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserRetrieveParams]. */ + class Builder internal constructor() { + + private var username: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userRetrieveParams: UserRetrieveParams) = apply { + username = userRetrieveParams.username + additionalHeaders = userRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = userRetrieveParams.additionalQueryParams.toBuilder() + } + + fun username(username: String?) = apply { this.username = username } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserRetrieveParams = + UserRetrieveParams(username, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> username ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserRetrieveParams && + username == other.username && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(username, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserRetrieveParams{username=$username, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParams.kt new file mode 100644 index 0000000..d4d6199 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParams.kt @@ -0,0 +1,206 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.immutableEmptyMap +import java.util.Objects + +/** This can only be done by the logged in user. */ +class UserUpdateParams +private constructor( + private val existingUsername: String?, + private val user: User?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun existingUsername(): String? = existingUsername + + fun user(): User? = user + + fun _additionalBodyProperties(): Map = + user?._additionalProperties() ?: immutableEmptyMap() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserUpdateParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserUpdateParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserUpdateParams]. */ + class Builder internal constructor() { + + private var existingUsername: String? = null + private var user: User? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userUpdateParams: UserUpdateParams) = apply { + existingUsername = userUpdateParams.existingUsername + user = userUpdateParams.user + additionalHeaders = userUpdateParams.additionalHeaders.toBuilder() + additionalQueryParams = userUpdateParams.additionalQueryParams.toBuilder() + } + + fun existingUsername(existingUsername: String?) = apply { + this.existingUsername = existingUsername + } + + fun user(user: User?) = apply { this.user = user } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserUpdateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserUpdateParams = + UserUpdateParams( + existingUsername, + user, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): User? = user + + fun _pathParam(index: Int): String = + when (index) { + 0 -> existingUsername ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserUpdateParams && + existingUsername == other.existingUsername && + user == other.user && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(existingUsername, user, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserUpdateParams{existingUsername=$existingUsername, user=$user, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsync.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsync.kt new file mode 100644 index 0000000..3839b7d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsync.kt @@ -0,0 +1,323 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetCreateParams +import com.pioneer_intergration_app.api.models.pets.PetDeleteParams +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetRetrieveParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageResponse + +interface PetServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetServiceAsync + + /** Add a new pet to the store */ + suspend fun create( + params: PetCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet + + /** @see create */ + suspend fun create(pet: Pet, requestOptions: RequestOptions = RequestOptions.none()): Pet = + create(PetCreateParams.builder().pet(pet).build(), requestOptions) + + /** Returns a single pet */ + suspend fun retrieve( + petId: Long, + params: PetRetrieveParams = PetRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet = retrieve(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see retrieve */ + suspend fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet + + /** @see retrieve */ + suspend fun retrieve(petId: Long, requestOptions: RequestOptions): Pet = + retrieve(petId, PetRetrieveParams.none(), requestOptions) + + /** Update an existing pet by Id */ + suspend fun update( + params: PetUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet + + /** @see update */ + suspend fun update(pet: Pet, requestOptions: RequestOptions = RequestOptions.none()): Pet = + update(PetUpdateParams.builder().pet(pet).build(), requestOptions) + + /** delete a pet */ + suspend fun delete( + petId: Long, + params: PetDeleteParams = PetDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see delete */ + suspend fun delete( + params: PetDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see delete */ + suspend fun delete(petId: Long, requestOptions: RequestOptions) = + delete(petId, PetDeleteParams.none(), requestOptions) + + /** Multiple status values can be provided with comma separated strings */ + suspend fun findByStatus( + params: PetFindByStatusParams = PetFindByStatusParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): List + + /** @see findByStatus */ + suspend fun findByStatus(requestOptions: RequestOptions): List = + findByStatus(PetFindByStatusParams.none(), requestOptions) + + /** + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + */ + suspend fun findByTags( + params: PetFindByTagsParams = PetFindByTagsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): List + + /** @see findByTags */ + suspend fun findByTags(requestOptions: RequestOptions): List = + findByTags(PetFindByTagsParams.none(), requestOptions) + + /** Updates a pet in the store with form data */ + suspend fun updateById( + petId: Long, + params: PetUpdateByIdParams = PetUpdateByIdParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = updateById(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see updateById */ + suspend fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see updateById */ + suspend fun updateById(petId: Long, requestOptions: RequestOptions) = + updateById(petId, PetUpdateByIdParams.none(), requestOptions) + + /** uploads an image */ + suspend fun uploadImage( + petId: Long, + image: String, + params: PetUploadImageParams = PetUploadImageParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): PetUploadImageResponse = + uploadImage(params.toBuilder().petId(petId).image(image).build(), requestOptions) + + /** @see uploadImage */ + suspend fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): PetUploadImageResponse + + /** @see uploadImage */ + suspend fun uploadImage( + petId: Long, + image: String, + requestOptions: RequestOptions, + ): PetUploadImageResponse = + uploadImage(petId, image, PetUploadImageParams.none(), requestOptions) + + /** A view of [PetServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /pet`, but is otherwise the same as + * [PetServiceAsync.create]. + */ + @MustBeClosed + suspend fun create( + params: PetCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + suspend fun create( + pet: Pet, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = create(PetCreateParams.builder().pet(pet).build(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/{petId}`, but is otherwise the same as + * [PetServiceAsync.retrieve]. + */ + @MustBeClosed + suspend fun retrieve( + petId: Long, + params: PetRetrieveParams = PetRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = retrieve(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve(petId: Long, requestOptions: RequestOptions): HttpResponseFor = + retrieve(petId, PetRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /pet`, but is otherwise the same as + * [PetServiceAsync.update]. + */ + @MustBeClosed + suspend fun update( + params: PetUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see update */ + @MustBeClosed + suspend fun update( + pet: Pet, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = update(PetUpdateParams.builder().pet(pet).build(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /pet/{petId}`, but is otherwise the same as + * [PetServiceAsync.delete]. + */ + @MustBeClosed + suspend fun delete( + petId: Long, + params: PetDeleteParams = PetDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + suspend fun delete( + params: PetDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + suspend fun delete(petId: Long, requestOptions: RequestOptions): HttpResponse = + delete(petId, PetDeleteParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/findByStatus`, but is otherwise the same as + * [PetServiceAsync.findByStatus]. + */ + @MustBeClosed + suspend fun findByStatus( + params: PetFindByStatusParams = PetFindByStatusParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + + /** @see findByStatus */ + @MustBeClosed + suspend fun findByStatus(requestOptions: RequestOptions): HttpResponseFor> = + findByStatus(PetFindByStatusParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/findByTags`, but is otherwise the same as + * [PetServiceAsync.findByTags]. + */ + @MustBeClosed + suspend fun findByTags( + params: PetFindByTagsParams = PetFindByTagsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + + /** @see findByTags */ + @MustBeClosed + suspend fun findByTags(requestOptions: RequestOptions): HttpResponseFor> = + findByTags(PetFindByTagsParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /pet/{petId}`, but is otherwise the same as + * [PetServiceAsync.updateById]. + */ + @MustBeClosed + suspend fun updateById( + petId: Long, + params: PetUpdateByIdParams = PetUpdateByIdParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = updateById(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see updateById */ + @MustBeClosed + suspend fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see updateById */ + @MustBeClosed + suspend fun updateById(petId: Long, requestOptions: RequestOptions): HttpResponse = + updateById(petId, PetUpdateByIdParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /pet/{petId}/uploadImage`, but is otherwise the + * same as [PetServiceAsync.uploadImage]. + */ + @MustBeClosed + suspend fun uploadImage( + petId: Long, + image: String, + params: PetUploadImageParams = PetUploadImageParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + uploadImage(params.toBuilder().petId(petId).image(image).build(), requestOptions) + + /** @see uploadImage */ + @MustBeClosed + suspend fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see uploadImage */ + @MustBeClosed + suspend fun uploadImage( + petId: Long, + image: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + uploadImage(petId, image, PetUploadImageParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncImpl.kt new file mode 100644 index 0000000..4ff6ca2 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncImpl.kt @@ -0,0 +1,316 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepareAsync +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetCreateParams +import com.pioneer_intergration_app.api.models.pets.PetDeleteParams +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetRetrieveParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageResponse + +class PetServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + PetServiceAsync { + + private val withRawResponse: PetServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): PetServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetServiceAsync = + PetServiceAsyncImpl(clientOptions.toBuilder().apply(modifier).build()) + + override suspend fun create(params: PetCreateParams, requestOptions: RequestOptions): Pet = + // post /pet + withRawResponse().create(params, requestOptions).parse() + + override suspend fun retrieve(params: PetRetrieveParams, requestOptions: RequestOptions): Pet = + // get /pet/{petId} + withRawResponse().retrieve(params, requestOptions).parse() + + override suspend fun update(params: PetUpdateParams, requestOptions: RequestOptions): Pet = + // put /pet + withRawResponse().update(params, requestOptions).parse() + + override suspend fun delete(params: PetDeleteParams, requestOptions: RequestOptions) { + // delete /pet/{petId} + withRawResponse().delete(params, requestOptions) + } + + override suspend fun findByStatus( + params: PetFindByStatusParams, + requestOptions: RequestOptions, + ): List = + // get /pet/findByStatus + withRawResponse().findByStatus(params, requestOptions).parse() + + override suspend fun findByTags( + params: PetFindByTagsParams, + requestOptions: RequestOptions, + ): List = + // get /pet/findByTags + withRawResponse().findByTags(params, requestOptions).parse() + + override suspend fun updateById(params: PetUpdateByIdParams, requestOptions: RequestOptions) { + // post /pet/{petId} + withRawResponse().updateById(params, requestOptions) + } + + override suspend fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions, + ): PetUploadImageResponse = + // post /pet/{petId}/uploadImage + withRawResponse().uploadImage(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + PetServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PetServiceAsync.WithRawResponse = + PetServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun create( + params: PetCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val updateHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun update( + params: PetUpdateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { updateHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override suspend fun delete( + params: PetDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + + private val findByStatusHandler: Handler> = + jsonHandler>(clientOptions.jsonMapper) + + override suspend fun findByStatus( + params: PetFindByStatusParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", "findByStatus") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { findByStatusHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.forEach { it.validate() } + } + } + } + } + + private val findByTagsHandler: Handler> = + jsonHandler>(clientOptions.jsonMapper) + + override suspend fun findByTags( + params: PetFindByTagsParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", "findByTags") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { findByTagsHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.forEach { it.validate() } + } + } + } + } + + private val updateByIdHandler: Handler = emptyHandler() + + override suspend fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { updateByIdHandler.handle(it) } + } + } + + private val uploadImageHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override suspend fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + checkRequired("image", params._body()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0), "uploadImage") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { uploadImageHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsync.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsync.kt new file mode 100644 index 0000000..96ae910 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsync.kt @@ -0,0 +1,70 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse +import com.pioneer_intergration_app.api.services.async.store.OrderServiceAsync + +interface StoreServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): StoreServiceAsync + + fun orders(): OrderServiceAsync + + /** Returns a map of status codes to quantities */ + suspend fun listInventory( + params: StoreListInventoryParams = StoreListInventoryParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): StoreListInventoryResponse + + /** @see listInventory */ + suspend fun listInventory(requestOptions: RequestOptions): StoreListInventoryResponse = + listInventory(StoreListInventoryParams.none(), requestOptions) + + /** A view of [StoreServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): StoreServiceAsync.WithRawResponse + + fun orders(): OrderServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `get /store/inventory`, but is otherwise the same as + * [StoreServiceAsync.listInventory]. + */ + @MustBeClosed + suspend fun listInventory( + params: StoreListInventoryParams = StoreListInventoryParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see listInventory */ + @MustBeClosed + suspend fun listInventory( + requestOptions: RequestOptions + ): HttpResponseFor = + listInventory(StoreListInventoryParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncImpl.kt new file mode 100644 index 0000000..a6b22cb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncImpl.kt @@ -0,0 +1,91 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepareAsync +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse +import com.pioneer_intergration_app.api.services.async.store.OrderServiceAsync +import com.pioneer_intergration_app.api.services.async.store.OrderServiceAsyncImpl + +class StoreServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + StoreServiceAsync { + + private val withRawResponse: StoreServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val orders: OrderServiceAsync by lazy { OrderServiceAsyncImpl(clientOptions) } + + override fun withRawResponse(): StoreServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): StoreServiceAsync = + StoreServiceAsyncImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun orders(): OrderServiceAsync = orders + + override suspend fun listInventory( + params: StoreListInventoryParams, + requestOptions: RequestOptions, + ): StoreListInventoryResponse = + // get /store/inventory + withRawResponse().listInventory(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + StoreServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + private val orders: OrderServiceAsync.WithRawResponse by lazy { + OrderServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): StoreServiceAsync.WithRawResponse = + StoreServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + override fun orders(): OrderServiceAsync.WithRawResponse = orders + + private val listInventoryHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override suspend fun listInventory( + params: StoreListInventoryParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "inventory") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listInventoryHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsync.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsync.kt new file mode 100644 index 0000000..1e7fb40 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsync.kt @@ -0,0 +1,279 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateParams +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserDeleteParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserLogoutParams +import com.pioneer_intergration_app.api.models.users.UserRetrieveParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams + +interface UserServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserServiceAsync + + /** This can only be done by the logged in user. */ + suspend fun create( + params: UserCreateParams = UserCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see create */ + suspend fun create(user: User, requestOptions: RequestOptions = RequestOptions.none()): User = + create(UserCreateParams.builder().user(user).build(), requestOptions) + + /** @see create */ + suspend fun create(requestOptions: RequestOptions): User = + create(UserCreateParams.none(), requestOptions) + + /** Get user by user name */ + suspend fun retrieve( + username: String, + params: UserRetrieveParams = UserRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User = retrieve(params.toBuilder().username(username).build(), requestOptions) + + /** @see retrieve */ + suspend fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see retrieve */ + suspend fun retrieve(username: String, requestOptions: RequestOptions): User = + retrieve(username, UserRetrieveParams.none(), requestOptions) + + /** This can only be done by the logged in user. */ + suspend fun update( + existingUsername: String, + params: UserUpdateParams = UserUpdateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = update(params.toBuilder().existingUsername(existingUsername).build(), requestOptions) + + /** @see update */ + suspend fun update( + params: UserUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see update */ + suspend fun update(existingUsername: String, requestOptions: RequestOptions) = + update(existingUsername, UserUpdateParams.none(), requestOptions) + + /** This can only be done by the logged in user. */ + suspend fun delete( + username: String, + params: UserDeleteParams = UserDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().username(username).build(), requestOptions) + + /** @see delete */ + suspend fun delete( + params: UserDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see delete */ + suspend fun delete(username: String, requestOptions: RequestOptions) = + delete(username, UserDeleteParams.none(), requestOptions) + + /** Creates list of users with given input array */ + suspend fun createWithList( + params: UserCreateWithListParams = UserCreateWithListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see createWithList */ + suspend fun createWithList(requestOptions: RequestOptions): User = + createWithList(UserCreateWithListParams.none(), requestOptions) + + /** Logs user into the system */ + suspend fun login( + params: UserLoginParams = UserLoginParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): String + + /** @see login */ + suspend fun login(requestOptions: RequestOptions): String = + login(UserLoginParams.none(), requestOptions) + + /** Logs out current logged in user session */ + suspend fun logout( + params: UserLogoutParams = UserLogoutParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see logout */ + suspend fun logout(requestOptions: RequestOptions) = + logout(UserLogoutParams.none(), requestOptions) + + /** A view of [UserServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /user`, but is otherwise the same as + * [UserServiceAsync.create]. + */ + @MustBeClosed + suspend fun create( + params: UserCreateParams = UserCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + suspend fun create( + user: User, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(UserCreateParams.builder().user(user).build(), requestOptions) + + /** @see create */ + @MustBeClosed + suspend fun create(requestOptions: RequestOptions): HttpResponseFor = + create(UserCreateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/{username}`, but is otherwise the same as + * [UserServiceAsync.retrieve]. + */ + @MustBeClosed + suspend fun retrieve( + username: String, + params: UserRetrieveParams = UserRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().username(username).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve( + username: String, + requestOptions: RequestOptions, + ): HttpResponseFor = retrieve(username, UserRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /user/{username}`, but is otherwise the same as + * [UserServiceAsync.update]. + */ + @MustBeClosed + suspend fun update( + existingUsername: String, + params: UserUpdateParams = UserUpdateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = + update(params.toBuilder().existingUsername(existingUsername).build(), requestOptions) + + /** @see update */ + @MustBeClosed + suspend fun update( + params: UserUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see update */ + @MustBeClosed + suspend fun update(existingUsername: String, requestOptions: RequestOptions): HttpResponse = + update(existingUsername, UserUpdateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /user/{username}`, but is otherwise the same as + * [UserServiceAsync.delete]. + */ + @MustBeClosed + suspend fun delete( + username: String, + params: UserDeleteParams = UserDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().username(username).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + suspend fun delete( + params: UserDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + suspend fun delete(username: String, requestOptions: RequestOptions): HttpResponse = + delete(username, UserDeleteParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /user/createWithList`, but is otherwise the same as + * [UserServiceAsync.createWithList]. + */ + @MustBeClosed + suspend fun createWithList( + params: UserCreateWithListParams = UserCreateWithListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see createWithList */ + @MustBeClosed + suspend fun createWithList(requestOptions: RequestOptions): HttpResponseFor = + createWithList(UserCreateWithListParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/login`, but is otherwise the same as + * [UserServiceAsync.login]. + */ + @MustBeClosed + suspend fun login( + params: UserLoginParams = UserLoginParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see login */ + @MustBeClosed + suspend fun login(requestOptions: RequestOptions): HttpResponseFor = + login(UserLoginParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/logout`, but is otherwise the same as + * [UserServiceAsync.logout]. + */ + @MustBeClosed + suspend fun logout( + params: UserLogoutParams = UserLogoutParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see logout */ + @MustBeClosed + suspend fun logout(requestOptions: RequestOptions): HttpResponse = + logout(UserLogoutParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncImpl.kt new file mode 100644 index 0000000..3fbb60e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncImpl.kt @@ -0,0 +1,264 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.handlers.stringHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepareAsync +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateParams +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserDeleteParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserLogoutParams +import com.pioneer_intergration_app.api.models.users.UserRetrieveParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams + +class UserServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + UserServiceAsync { + + private val withRawResponse: UserServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): UserServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserServiceAsync = + UserServiceAsyncImpl(clientOptions.toBuilder().apply(modifier).build()) + + override suspend fun create(params: UserCreateParams, requestOptions: RequestOptions): User = + // post /user + withRawResponse().create(params, requestOptions).parse() + + override suspend fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions, + ): User = + // get /user/{username} + withRawResponse().retrieve(params, requestOptions).parse() + + override suspend fun update(params: UserUpdateParams, requestOptions: RequestOptions) { + // put /user/{username} + withRawResponse().update(params, requestOptions) + } + + override suspend fun delete(params: UserDeleteParams, requestOptions: RequestOptions) { + // delete /user/{username} + withRawResponse().delete(params, requestOptions) + } + + override suspend fun createWithList( + params: UserCreateWithListParams, + requestOptions: RequestOptions, + ): User = + // post /user/createWithList + withRawResponse().createWithList(params, requestOptions).parse() + + override suspend fun login(params: UserLoginParams, requestOptions: RequestOptions): String = + // get /user/login + withRawResponse().login(params, requestOptions).parse() + + override suspend fun logout(params: UserLogoutParams, requestOptions: RequestOptions) { + // get /user/logout + withRawResponse().logout(params, requestOptions) + } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + UserServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): UserServiceAsync.WithRawResponse = + UserServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun create( + params: UserCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("username", params.username()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val updateHandler: Handler = emptyHandler() + + override suspend fun update( + params: UserUpdateParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("existingUsername", params.existingUsername()) + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { updateHandler.handle(it) } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override suspend fun delete( + params: UserDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("username", params.username()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + + private val createWithListHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override suspend fun createWithList( + params: UserCreateWithListParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "createWithList") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createWithListHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val loginHandler: Handler = stringHandler() + + override suspend fun login( + params: UserLoginParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "login") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { loginHandler.handle(it) } + } + } + + private val logoutHandler: Handler = emptyHandler() + + override suspend fun logout( + params: UserLogoutParams, + requestOptions: RequestOptions, + ): HttpResponse { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "logout") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { logoutHandler.handle(it) } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsync.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsync.kt new file mode 100644 index 0000000..e1ef420 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsync.kt @@ -0,0 +1,169 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async.store + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams +import com.pioneer_intergration_app.api.models.store.orders.OrderDeleteParams +import com.pioneer_intergration_app.api.models.store.orders.OrderRetrieveParams + +interface OrderServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): OrderServiceAsync + + /** Place a new order in the store */ + suspend fun create( + params: OrderCreateParams = OrderCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Order + + /** @see create */ + suspend fun create( + order: Order, + requestOptions: RequestOptions = RequestOptions.none(), + ): Order = create(OrderCreateParams.builder().order(order).build(), requestOptions) + + /** @see create */ + suspend fun create(requestOptions: RequestOptions): Order = + create(OrderCreateParams.none(), requestOptions) + + /** + * For valid response try integer IDs with value <= 5 or > 10. Other values will generate + * exceptions. + */ + suspend fun retrieve( + orderId: Long, + params: OrderRetrieveParams = OrderRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Order = retrieve(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see retrieve */ + suspend fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Order + + /** @see retrieve */ + suspend fun retrieve(orderId: Long, requestOptions: RequestOptions): Order = + retrieve(orderId, OrderRetrieveParams.none(), requestOptions) + + /** + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will + * generate API errors + */ + suspend fun delete( + orderId: Long, + params: OrderDeleteParams = OrderDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see delete */ + suspend fun delete( + params: OrderDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see delete */ + suspend fun delete(orderId: Long, requestOptions: RequestOptions) = + delete(orderId, OrderDeleteParams.none(), requestOptions) + + /** A view of [OrderServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): OrderServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /store/order`, but is otherwise the same as + * [OrderServiceAsync.create]. + */ + @MustBeClosed + suspend fun create( + params: OrderCreateParams = OrderCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + suspend fun create( + order: Order, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(OrderCreateParams.builder().order(order).build(), requestOptions) + + /** @see create */ + @MustBeClosed + suspend fun create(requestOptions: RequestOptions): HttpResponseFor = + create(OrderCreateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /store/order/{orderId}`, but is otherwise the same + * as [OrderServiceAsync.retrieve]. + */ + @MustBeClosed + suspend fun retrieve( + orderId: Long, + params: OrderRetrieveParams = OrderRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve( + orderId: Long, + requestOptions: RequestOptions, + ): HttpResponseFor = retrieve(orderId, OrderRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /store/order/{orderId}`, but is otherwise the + * same as [OrderServiceAsync.delete]. + */ + @MustBeClosed + suspend fun delete( + orderId: Long, + params: OrderDeleteParams = OrderDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + suspend fun delete( + params: OrderDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + suspend fun delete(orderId: Long, requestOptions: RequestOptions): HttpResponse = + delete(orderId, OrderDeleteParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncImpl.kt new file mode 100644 index 0000000..dd039f4 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncImpl.kt @@ -0,0 +1,146 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async.store + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepareAsync +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams +import com.pioneer_intergration_app.api.models.store.orders.OrderDeleteParams +import com.pioneer_intergration_app.api.models.store.orders.OrderRetrieveParams + +class OrderServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + OrderServiceAsync { + + private val withRawResponse: OrderServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): OrderServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): OrderServiceAsync = + OrderServiceAsyncImpl(clientOptions.toBuilder().apply(modifier).build()) + + override suspend fun create(params: OrderCreateParams, requestOptions: RequestOptions): Order = + // post /store/order + withRawResponse().create(params, requestOptions).parse() + + override suspend fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions, + ): Order = + // get /store/order/{orderId} + withRawResponse().retrieve(params, requestOptions).parse() + + override suspend fun delete(params: OrderDeleteParams, requestOptions: RequestOptions) { + // delete /store/order/{orderId} + withRawResponse().delete(params, requestOptions) + } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + OrderServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): OrderServiceAsync.WithRawResponse = + OrderServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun create( + params: OrderCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("orderId", params.orderId()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order", params._pathParam(0)) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override suspend fun delete( + params: OrderDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("orderId", params.orderId()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetService.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetService.kt new file mode 100644 index 0000000..9dabb5b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetService.kt @@ -0,0 +1,314 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetCreateParams +import com.pioneer_intergration_app.api.models.pets.PetDeleteParams +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetRetrieveParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageResponse + +interface PetService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetService + + /** Add a new pet to the store */ + fun create(params: PetCreateParams, requestOptions: RequestOptions = RequestOptions.none()): Pet + + /** @see create */ + fun create(pet: Pet, requestOptions: RequestOptions = RequestOptions.none()): Pet = + create(PetCreateParams.builder().pet(pet).build(), requestOptions) + + /** Returns a single pet */ + fun retrieve( + petId: Long, + params: PetRetrieveParams = PetRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet = retrieve(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet + + /** @see retrieve */ + fun retrieve(petId: Long, requestOptions: RequestOptions): Pet = + retrieve(petId, PetRetrieveParams.none(), requestOptions) + + /** Update an existing pet by Id */ + fun update(params: PetUpdateParams, requestOptions: RequestOptions = RequestOptions.none()): Pet + + /** @see update */ + fun update(pet: Pet, requestOptions: RequestOptions = RequestOptions.none()): Pet = + update(PetUpdateParams.builder().pet(pet).build(), requestOptions) + + /** delete a pet */ + fun delete( + petId: Long, + params: PetDeleteParams = PetDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see delete */ + fun delete(params: PetDeleteParams, requestOptions: RequestOptions = RequestOptions.none()) + + /** @see delete */ + fun delete(petId: Long, requestOptions: RequestOptions) = + delete(petId, PetDeleteParams.none(), requestOptions) + + /** Multiple status values can be provided with comma separated strings */ + fun findByStatus( + params: PetFindByStatusParams = PetFindByStatusParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): List + + /** @see findByStatus */ + fun findByStatus(requestOptions: RequestOptions): List = + findByStatus(PetFindByStatusParams.none(), requestOptions) + + /** + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + */ + fun findByTags( + params: PetFindByTagsParams = PetFindByTagsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): List + + /** @see findByTags */ + fun findByTags(requestOptions: RequestOptions): List = + findByTags(PetFindByTagsParams.none(), requestOptions) + + /** Updates a pet in the store with form data */ + fun updateById( + petId: Long, + params: PetUpdateByIdParams = PetUpdateByIdParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = updateById(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see updateById */ + fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see updateById */ + fun updateById(petId: Long, requestOptions: RequestOptions) = + updateById(petId, PetUpdateByIdParams.none(), requestOptions) + + /** uploads an image */ + fun uploadImage( + petId: Long, + image: String, + params: PetUploadImageParams = PetUploadImageParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): PetUploadImageResponse = + uploadImage(params.toBuilder().petId(petId).image(image).build(), requestOptions) + + /** @see uploadImage */ + fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): PetUploadImageResponse + + /** @see uploadImage */ + fun uploadImage( + petId: Long, + image: String, + requestOptions: RequestOptions, + ): PetUploadImageResponse = + uploadImage(petId, image, PetUploadImageParams.none(), requestOptions) + + /** A view of [PetService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /pet`, but is otherwise the same as + * [PetService.create]. + */ + @MustBeClosed + fun create( + params: PetCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + fun create( + pet: Pet, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = create(PetCreateParams.builder().pet(pet).build(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/{petId}`, but is otherwise the same as + * [PetService.retrieve]. + */ + @MustBeClosed + fun retrieve( + petId: Long, + params: PetRetrieveParams = PetRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = retrieve(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve(petId: Long, requestOptions: RequestOptions): HttpResponseFor = + retrieve(petId, PetRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /pet`, but is otherwise the same as + * [PetService.update]. + */ + @MustBeClosed + fun update( + params: PetUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see update */ + @MustBeClosed + fun update( + pet: Pet, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = update(PetUpdateParams.builder().pet(pet).build(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /pet/{petId}`, but is otherwise the same as + * [PetService.delete]. + */ + @MustBeClosed + fun delete( + petId: Long, + params: PetDeleteParams = PetDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + fun delete( + params: PetDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + fun delete(petId: Long, requestOptions: RequestOptions): HttpResponse = + delete(petId, PetDeleteParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/findByStatus`, but is otherwise the same as + * [PetService.findByStatus]. + */ + @MustBeClosed + fun findByStatus( + params: PetFindByStatusParams = PetFindByStatusParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + + /** @see findByStatus */ + @MustBeClosed + fun findByStatus(requestOptions: RequestOptions): HttpResponseFor> = + findByStatus(PetFindByStatusParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/findByTags`, but is otherwise the same as + * [PetService.findByTags]. + */ + @MustBeClosed + fun findByTags( + params: PetFindByTagsParams = PetFindByTagsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + + /** @see findByTags */ + @MustBeClosed + fun findByTags(requestOptions: RequestOptions): HttpResponseFor> = + findByTags(PetFindByTagsParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /pet/{petId}`, but is otherwise the same as + * [PetService.updateById]. + */ + @MustBeClosed + fun updateById( + petId: Long, + params: PetUpdateByIdParams = PetUpdateByIdParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = updateById(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see updateById */ + @MustBeClosed + fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see updateById */ + @MustBeClosed + fun updateById(petId: Long, requestOptions: RequestOptions): HttpResponse = + updateById(petId, PetUpdateByIdParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /pet/{petId}/uploadImage`, but is otherwise the + * same as [PetService.uploadImage]. + */ + @MustBeClosed + fun uploadImage( + petId: Long, + image: String, + params: PetUploadImageParams = PetUploadImageParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + uploadImage(params.toBuilder().petId(petId).image(image).build(), requestOptions) + + /** @see uploadImage */ + @MustBeClosed + fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see uploadImage */ + @MustBeClosed + fun uploadImage( + petId: Long, + image: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + uploadImage(petId, image, PetUploadImageParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceImpl.kt new file mode 100644 index 0000000..0fe1c4f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceImpl.kt @@ -0,0 +1,310 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepare +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetCreateParams +import com.pioneer_intergration_app.api.models.pets.PetDeleteParams +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetRetrieveParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageResponse + +class PetServiceImpl internal constructor(private val clientOptions: ClientOptions) : PetService { + + private val withRawResponse: PetService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): PetService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetService = + PetServiceImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun create(params: PetCreateParams, requestOptions: RequestOptions): Pet = + // post /pet + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve(params: PetRetrieveParams, requestOptions: RequestOptions): Pet = + // get /pet/{petId} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun update(params: PetUpdateParams, requestOptions: RequestOptions): Pet = + // put /pet + withRawResponse().update(params, requestOptions).parse() + + override fun delete(params: PetDeleteParams, requestOptions: RequestOptions) { + // delete /pet/{petId} + withRawResponse().delete(params, requestOptions) + } + + override fun findByStatus( + params: PetFindByStatusParams, + requestOptions: RequestOptions, + ): List = + // get /pet/findByStatus + withRawResponse().findByStatus(params, requestOptions).parse() + + override fun findByTags( + params: PetFindByTagsParams, + requestOptions: RequestOptions, + ): List = + // get /pet/findByTags + withRawResponse().findByTags(params, requestOptions).parse() + + override fun updateById(params: PetUpdateByIdParams, requestOptions: RequestOptions) { + // post /pet/{petId} + withRawResponse().updateById(params, requestOptions) + } + + override fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions, + ): PetUploadImageResponse = + // post /pet/{petId}/uploadImage + withRawResponse().uploadImage(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + PetService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PetService.WithRawResponse = + PetServiceImpl.WithRawResponseImpl(clientOptions.toBuilder().apply(modifier).build()) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: PetCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val updateHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun update( + params: PetUpdateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { updateHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override fun delete(params: PetDeleteParams, requestOptions: RequestOptions): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + + private val findByStatusHandler: Handler> = + jsonHandler>(clientOptions.jsonMapper) + + override fun findByStatus( + params: PetFindByStatusParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", "findByStatus") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { findByStatusHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.forEach { it.validate() } + } + } + } + } + + private val findByTagsHandler: Handler> = + jsonHandler>(clientOptions.jsonMapper) + + override fun findByTags( + params: PetFindByTagsParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", "findByTags") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { findByTagsHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.forEach { it.validate() } + } + } + } + } + + private val updateByIdHandler: Handler = emptyHandler() + + override fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { updateByIdHandler.handle(it) } + } + } + + private val uploadImageHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + checkRequired("image", params._body()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0), "uploadImage") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { uploadImageHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreService.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreService.kt new file mode 100644 index 0000000..cb479a2 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreService.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse +import com.pioneer_intergration_app.api.services.blocking.store.OrderService + +interface StoreService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): StoreService + + fun orders(): OrderService + + /** Returns a map of status codes to quantities */ + fun listInventory( + params: StoreListInventoryParams = StoreListInventoryParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): StoreListInventoryResponse + + /** @see listInventory */ + fun listInventory(requestOptions: RequestOptions): StoreListInventoryResponse = + listInventory(StoreListInventoryParams.none(), requestOptions) + + /** A view of [StoreService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): StoreService.WithRawResponse + + fun orders(): OrderService.WithRawResponse + + /** + * Returns a raw HTTP response for `get /store/inventory`, but is otherwise the same as + * [StoreService.listInventory]. + */ + @MustBeClosed + fun listInventory( + params: StoreListInventoryParams = StoreListInventoryParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see listInventory */ + @MustBeClosed + fun listInventory( + requestOptions: RequestOptions + ): HttpResponseFor = + listInventory(StoreListInventoryParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceImpl.kt new file mode 100644 index 0000000..54334c8 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceImpl.kt @@ -0,0 +1,89 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepare +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse +import com.pioneer_intergration_app.api.services.blocking.store.OrderService +import com.pioneer_intergration_app.api.services.blocking.store.OrderServiceImpl + +class StoreServiceImpl internal constructor(private val clientOptions: ClientOptions) : + StoreService { + + private val withRawResponse: StoreService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val orders: OrderService by lazy { OrderServiceImpl(clientOptions) } + + override fun withRawResponse(): StoreService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): StoreService = + StoreServiceImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun orders(): OrderService = orders + + override fun listInventory( + params: StoreListInventoryParams, + requestOptions: RequestOptions, + ): StoreListInventoryResponse = + // get /store/inventory + withRawResponse().listInventory(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + StoreService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + private val orders: OrderService.WithRawResponse by lazy { + OrderServiceImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): StoreService.WithRawResponse = + StoreServiceImpl.WithRawResponseImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun orders(): OrderService.WithRawResponse = orders + + private val listInventoryHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun listInventory( + params: StoreListInventoryParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "inventory") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listInventoryHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserService.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserService.kt new file mode 100644 index 0000000..fed3a18 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserService.kt @@ -0,0 +1,270 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateParams +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserDeleteParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserLogoutParams +import com.pioneer_intergration_app.api.models.users.UserRetrieveParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams + +interface UserService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserService + + /** This can only be done by the logged in user. */ + fun create( + params: UserCreateParams = UserCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see create */ + fun create(user: User, requestOptions: RequestOptions = RequestOptions.none()): User = + create(UserCreateParams.builder().user(user).build(), requestOptions) + + /** @see create */ + fun create(requestOptions: RequestOptions): User = + create(UserCreateParams.none(), requestOptions) + + /** Get user by user name */ + fun retrieve( + username: String, + params: UserRetrieveParams = UserRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User = retrieve(params.toBuilder().username(username).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see retrieve */ + fun retrieve(username: String, requestOptions: RequestOptions): User = + retrieve(username, UserRetrieveParams.none(), requestOptions) + + /** This can only be done by the logged in user. */ + fun update( + existingUsername: String, + params: UserUpdateParams = UserUpdateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = update(params.toBuilder().existingUsername(existingUsername).build(), requestOptions) + + /** @see update */ + fun update(params: UserUpdateParams, requestOptions: RequestOptions = RequestOptions.none()) + + /** @see update */ + fun update(existingUsername: String, requestOptions: RequestOptions) = + update(existingUsername, UserUpdateParams.none(), requestOptions) + + /** This can only be done by the logged in user. */ + fun delete( + username: String, + params: UserDeleteParams = UserDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().username(username).build(), requestOptions) + + /** @see delete */ + fun delete(params: UserDeleteParams, requestOptions: RequestOptions = RequestOptions.none()) + + /** @see delete */ + fun delete(username: String, requestOptions: RequestOptions) = + delete(username, UserDeleteParams.none(), requestOptions) + + /** Creates list of users with given input array */ + fun createWithList( + params: UserCreateWithListParams = UserCreateWithListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see createWithList */ + fun createWithList(requestOptions: RequestOptions): User = + createWithList(UserCreateWithListParams.none(), requestOptions) + + /** Logs user into the system */ + fun login( + params: UserLoginParams = UserLoginParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): String + + /** @see login */ + fun login(requestOptions: RequestOptions): String = + login(UserLoginParams.none(), requestOptions) + + /** Logs out current logged in user session */ + fun logout( + params: UserLogoutParams = UserLogoutParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see logout */ + fun logout(requestOptions: RequestOptions) = logout(UserLogoutParams.none(), requestOptions) + + /** A view of [UserService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /user`, but is otherwise the same as + * [UserService.create]. + */ + @MustBeClosed + fun create( + params: UserCreateParams = UserCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + fun create( + user: User, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(UserCreateParams.builder().user(user).build(), requestOptions) + + /** @see create */ + @MustBeClosed + fun create(requestOptions: RequestOptions): HttpResponseFor = + create(UserCreateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/{username}`, but is otherwise the same as + * [UserService.retrieve]. + */ + @MustBeClosed + fun retrieve( + username: String, + params: UserRetrieveParams = UserRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().username(username).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve(username: String, requestOptions: RequestOptions): HttpResponseFor = + retrieve(username, UserRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /user/{username}`, but is otherwise the same as + * [UserService.update]. + */ + @MustBeClosed + fun update( + existingUsername: String, + params: UserUpdateParams = UserUpdateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = + update(params.toBuilder().existingUsername(existingUsername).build(), requestOptions) + + /** @see update */ + @MustBeClosed + fun update( + params: UserUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see update */ + @MustBeClosed + fun update(existingUsername: String, requestOptions: RequestOptions): HttpResponse = + update(existingUsername, UserUpdateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /user/{username}`, but is otherwise the same as + * [UserService.delete]. + */ + @MustBeClosed + fun delete( + username: String, + params: UserDeleteParams = UserDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().username(username).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + fun delete( + params: UserDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + fun delete(username: String, requestOptions: RequestOptions): HttpResponse = + delete(username, UserDeleteParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /user/createWithList`, but is otherwise the same as + * [UserService.createWithList]. + */ + @MustBeClosed + fun createWithList( + params: UserCreateWithListParams = UserCreateWithListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see createWithList */ + @MustBeClosed + fun createWithList(requestOptions: RequestOptions): HttpResponseFor = + createWithList(UserCreateWithListParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/login`, but is otherwise the same as + * [UserService.login]. + */ + @MustBeClosed + fun login( + params: UserLoginParams = UserLoginParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see login */ + @MustBeClosed + fun login(requestOptions: RequestOptions): HttpResponseFor = + login(UserLoginParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/logout`, but is otherwise the same as + * [UserService.logout]. + */ + @MustBeClosed + fun logout( + params: UserLogoutParams = UserLogoutParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see logout */ + @MustBeClosed + fun logout(requestOptions: RequestOptions): HttpResponse = + logout(UserLogoutParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceImpl.kt new file mode 100644 index 0000000..fb2501a --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceImpl.kt @@ -0,0 +1,258 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.handlers.stringHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepare +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateParams +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserDeleteParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserLogoutParams +import com.pioneer_intergration_app.api.models.users.UserRetrieveParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams + +class UserServiceImpl internal constructor(private val clientOptions: ClientOptions) : UserService { + + private val withRawResponse: UserService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): UserService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserService = + UserServiceImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun create(params: UserCreateParams, requestOptions: RequestOptions): User = + // post /user + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve(params: UserRetrieveParams, requestOptions: RequestOptions): User = + // get /user/{username} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun update(params: UserUpdateParams, requestOptions: RequestOptions) { + // put /user/{username} + withRawResponse().update(params, requestOptions) + } + + override fun delete(params: UserDeleteParams, requestOptions: RequestOptions) { + // delete /user/{username} + withRawResponse().delete(params, requestOptions) + } + + override fun createWithList( + params: UserCreateWithListParams, + requestOptions: RequestOptions, + ): User = + // post /user/createWithList + withRawResponse().createWithList(params, requestOptions).parse() + + override fun login(params: UserLoginParams, requestOptions: RequestOptions): String = + // get /user/login + withRawResponse().login(params, requestOptions).parse() + + override fun logout(params: UserLogoutParams, requestOptions: RequestOptions) { + // get /user/logout + withRawResponse().logout(params, requestOptions) + } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + UserService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): UserService.WithRawResponse = + UserServiceImpl.WithRawResponseImpl(clientOptions.toBuilder().apply(modifier).build()) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: UserCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("username", params.username()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val updateHandler: Handler = emptyHandler() + + override fun update( + params: UserUpdateParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("existingUsername", params.existingUsername()) + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { updateHandler.handle(it) } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override fun delete( + params: UserDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("username", params.username()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + + private val createWithListHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun createWithList( + params: UserCreateWithListParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "createWithList") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createWithListHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val loginHandler: Handler = stringHandler() + + override fun login( + params: UserLoginParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "login") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { loginHandler.handle(it) } + } + } + + private val logoutHandler: Handler = emptyHandler() + + override fun logout( + params: UserLogoutParams, + requestOptions: RequestOptions, + ): HttpResponse { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "logout") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { logoutHandler.handle(it) } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderService.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderService.kt new file mode 100644 index 0000000..452a29e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderService.kt @@ -0,0 +1,160 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking.store + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams +import com.pioneer_intergration_app.api.models.store.orders.OrderDeleteParams +import com.pioneer_intergration_app.api.models.store.orders.OrderRetrieveParams + +interface OrderService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): OrderService + + /** Place a new order in the store */ + fun create( + params: OrderCreateParams = OrderCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Order + + /** @see create */ + fun create(order: Order, requestOptions: RequestOptions = RequestOptions.none()): Order = + create(OrderCreateParams.builder().order(order).build(), requestOptions) + + /** @see create */ + fun create(requestOptions: RequestOptions): Order = + create(OrderCreateParams.none(), requestOptions) + + /** + * For valid response try integer IDs with value <= 5 or > 10. Other values will generate + * exceptions. + */ + fun retrieve( + orderId: Long, + params: OrderRetrieveParams = OrderRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Order = retrieve(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Order + + /** @see retrieve */ + fun retrieve(orderId: Long, requestOptions: RequestOptions): Order = + retrieve(orderId, OrderRetrieveParams.none(), requestOptions) + + /** + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will + * generate API errors + */ + fun delete( + orderId: Long, + params: OrderDeleteParams = OrderDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see delete */ + fun delete(params: OrderDeleteParams, requestOptions: RequestOptions = RequestOptions.none()) + + /** @see delete */ + fun delete(orderId: Long, requestOptions: RequestOptions) = + delete(orderId, OrderDeleteParams.none(), requestOptions) + + /** A view of [OrderService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): OrderService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /store/order`, but is otherwise the same as + * [OrderService.create]. + */ + @MustBeClosed + fun create( + params: OrderCreateParams = OrderCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + fun create( + order: Order, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(OrderCreateParams.builder().order(order).build(), requestOptions) + + /** @see create */ + @MustBeClosed + fun create(requestOptions: RequestOptions): HttpResponseFor = + create(OrderCreateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /store/order/{orderId}`, but is otherwise the same + * as [OrderService.retrieve]. + */ + @MustBeClosed + fun retrieve( + orderId: Long, + params: OrderRetrieveParams = OrderRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve(orderId: Long, requestOptions: RequestOptions): HttpResponseFor = + retrieve(orderId, OrderRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /store/order/{orderId}`, but is otherwise the + * same as [OrderService.delete]. + */ + @MustBeClosed + fun delete( + orderId: Long, + params: OrderDeleteParams = OrderDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + fun delete( + params: OrderDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + fun delete(orderId: Long, requestOptions: RequestOptions): HttpResponse = + delete(orderId, OrderDeleteParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceImpl.kt new file mode 100644 index 0000000..4626113 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceImpl.kt @@ -0,0 +1,141 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking.store + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepare +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams +import com.pioneer_intergration_app.api.models.store.orders.OrderDeleteParams +import com.pioneer_intergration_app.api.models.store.orders.OrderRetrieveParams + +class OrderServiceImpl internal constructor(private val clientOptions: ClientOptions) : + OrderService { + + private val withRawResponse: OrderService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): OrderService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): OrderService = + OrderServiceImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun create(params: OrderCreateParams, requestOptions: RequestOptions): Order = + // post /store/order + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve(params: OrderRetrieveParams, requestOptions: RequestOptions): Order = + // get /store/order/{orderId} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun delete(params: OrderDeleteParams, requestOptions: RequestOptions) { + // delete /store/order/{orderId} + withRawResponse().delete(params, requestOptions) + } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + OrderService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): OrderService.WithRawResponse = + OrderServiceImpl.WithRawResponseImpl(clientOptions.toBuilder().apply(modifier).build()) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: OrderCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("orderId", params.orderId()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order", params._pathParam(0)) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override fun delete( + params: OrderDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("orderId", params.orderId()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro b/pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro new file mode 100644 index 0000000..a944ff3 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro @@ -0,0 +1,32 @@ +# Jackson uses reflection and depends heavily on runtime attributes. +-keepattributes Exceptions,InnerClasses,Signature,Deprecated,*Annotation* + +# Jackson uses Kotlin reflection utilities, which themselves use reflection to access things. +-keep class kotlin.reflect.** { *; } +-keep class kotlin.Metadata { *; } + +# Jackson uses reflection to access enum members (e.g. via `java.lang.Class.getEnumConstants()`). +-keepclassmembers class com.fasterxml.jackson.** extends java.lang.Enum { + ; + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +# Jackson uses reflection to access annotation members. +-keepclassmembers @interface com.fasterxml.jackson.annotation.** { + *; +} + +# Jackson uses reified type information to serialize and deserialize our classes (via `TypeReference`). +-keep class com.fasterxml.jackson.core.type.TypeReference { *; } +-keep class * extends com.fasterxml.jackson.core.type.TypeReference { *; } + +# Jackson uses reflection to access our class serializers and deserializers. +-keep @com.fasterxml.jackson.databind.annotation.JsonSerialize class com.pioneer_intergration_app.api.** { *; } +-keep @com.fasterxml.jackson.databind.annotation.JsonDeserialize class com.pioneer_intergration_app.api.** { *; } + +# Jackson uses reflection to serialize and deserialize our classes based on their constructors and annotated members. +-keepclassmembers class com.pioneer_intergration_app.api.** { + (...); + @com.fasterxml.jackson.annotation.* *; +} \ No newline at end of file diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/TestServerExtension.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/TestServerExtension.kt new file mode 100644 index 0000000..3f4deac --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/TestServerExtension.kt @@ -0,0 +1,62 @@ +package com.pioneer_intergration_app.api + +import java.lang.RuntimeException +import java.net.URL +import org.junit.jupiter.api.extension.BeforeAllCallback +import org.junit.jupiter.api.extension.ConditionEvaluationResult +import org.junit.jupiter.api.extension.ExecutionCondition +import org.junit.jupiter.api.extension.ExtensionContext + +class TestServerExtension : BeforeAllCallback, ExecutionCondition { + + override fun beforeAll(context: ExtensionContext?) { + try { + URL(BASE_URL).openConnection().connect() + } catch (e: Exception) { + throw RuntimeException( + """ + The test suite will not run without a mock Prism server running against your OpenAPI spec. + + You can set the environment variable `SKIP_MOCK_TESTS` to `true` to skip running any tests + that require the mock server. + + To fix: + + 1. Install Prism (requires Node 16+): + + With npm: + $ npm install -g @stoplight/prism-cli + + With yarn: + $ yarn global add @stoplight/prism-cli + + 2. Run the mock server + + To run the server, pass in the path of your OpenAPI spec to the prism command: + $ prism mock path/to/your.openapi.yml + """ + .trimIndent(), + e, + ) + } + } + + override fun evaluateExecutionCondition(context: ExtensionContext): ConditionEvaluationResult { + return if (System.getenv(SKIP_TESTS_ENV).toBoolean()) { + ConditionEvaluationResult.disabled( + "Environment variable $SKIP_TESTS_ENV is set to true" + ) + } else { + ConditionEvaluationResult.enabled( + "Environment variable $SKIP_TESTS_ENV is not set to true" + ) + } + } + + companion object { + + val BASE_URL = System.getenv("TEST_API_BASE_URL") ?: "http://localhost:4010" + + const val SKIP_TESTS_ENV: String = "SKIP_MOCK_TESTS" + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ClientOptionsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ClientOptionsTest.kt new file mode 100644 index 0000000..1c5dd0f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ClientOptionsTest.kt @@ -0,0 +1,34 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.core.http.HttpClient +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.verify + +@ExtendWith(MockitoExtension::class) +internal class ClientOptionsTest { + + private val httpClient = mock() + + @Test + fun toBuilder_whenOriginalClientOptionsGarbageCollected_doesNotCloseOriginalClient() { + var clientOptions = + ClientOptions.builder().httpClient(httpClient).apiKey("My API Key").build() + verify(httpClient, never()).close() + + // Overwrite the `clientOptions` variable so that the original `ClientOptions` is GC'd. + clientOptions = clientOptions.toBuilder().build() + System.gc() + Thread.sleep(100) + + verify(httpClient, never()).close() + // This exists so that `clientOptions` is still reachable. + assertThat(clientOptions).isEqualTo(clientOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt new file mode 100644 index 0000000..1648da8 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt @@ -0,0 +1,117 @@ +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.databind.exc.MismatchedInputException +import com.fasterxml.jackson.module.kotlin.readValue +import java.time.LocalDate +import java.time.LocalTime +import java.time.OffsetDateTime +import java.time.ZoneOffset +import kotlin.reflect.KClass +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.catchThrowable +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource +import org.junitpioneer.jupiter.cartesian.CartesianTest + +internal class ObjectMappersTest { + + internal class ClassWithBooleanFieldPrefixedWithIs(private val isActive: JsonField) { + + @JsonProperty("is_active") @ExcludeMissing fun _isActive() = isActive + } + + @Test + fun write_whenFieldPrefixedWithIs_keepsPrefix() { + val value = ClassWithBooleanFieldPrefixedWithIs(JsonField.of(true)) + + val json = jsonMapper().writeValueAsString(value) + + assertThat(json).isEqualTo("{\"is_active\":true}") + } + + internal class Class(@get:JsonProperty("field") @JsonProperty("field") val field: String) + + enum class ShapeTestCase(val value: Any, val kClass: KClass<*>) { + STRING("Hello World!", String::class), + BOOLEAN(true, Boolean::class), + FLOAT(3.14F, Float::class), + DOUBLE(3.14, Double::class), + INTEGER(42, Int::class), + LONG(42L, Long::class), + MAP(mapOf("property" to "value"), Map::class), + CLASS(Class("Hello World!"), Class::class), + LIST(listOf(1, 2, 3), List::class); + + companion object { + val VALID_CONVERSIONS = + listOf( + FLOAT to DOUBLE, + DOUBLE to FLOAT, + INTEGER to FLOAT, + INTEGER to DOUBLE, + INTEGER to LONG, + LONG to FLOAT, + LONG to DOUBLE, + LONG to INTEGER, + CLASS to MAP, + ) + } + } + + @CartesianTest + fun read(@CartesianTest.Enum shape1: ShapeTestCase, @CartesianTest.Enum shape2: ShapeTestCase) { + val jsonMapper = jsonMapper() + val json = jsonMapper.writeValueAsString(shape1.value) + + val e = catchThrowable { jsonMapper.readValue(json, shape2.kClass.java) } + + if (shape1 == shape2 || shape1 to shape2 in ShapeTestCase.VALID_CONVERSIONS) { + assertThat(e).isNull() + } else { + assertThat(e).isInstanceOf(MismatchedInputException::class.java) + } + } + + enum class LenientOffsetDateTimeTestCase( + val string: String, + val expectedOffsetDateTime: OffsetDateTime, + ) { + DATE( + "1998-04-21", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(0, 0), ZoneOffset.UTC), + ), + DATE_TIME( + "1998-04-21T04:00:00", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(4, 0), ZoneOffset.UTC), + ), + ZONED_DATE_TIME_1( + "1998-04-21T04:00:00+03:00", + expectedOffsetDateTime = + OffsetDateTime.of( + LocalDate.of(1998, 4, 21), + LocalTime.of(4, 0), + ZoneOffset.ofHours(3), + ), + ), + ZONED_DATE_TIME_2( + "1998-04-21T04:00:00Z", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(4, 0), ZoneOffset.UTC), + ), + } + + @ParameterizedTest + @EnumSource + fun readOffsetDateTime_lenient(testCase: LenientOffsetDateTimeTestCase) { + val jsonMapper = jsonMapper() + val json = jsonMapper.writeValueAsString(testCase.string) + + val offsetDateTime = jsonMapper().readValue(json) + + assertThat(offsetDateTime).isEqualTo(testCase.expectedOffsetDateTime) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableTest.kt new file mode 100644 index 0000000..1e9f4b4 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableTest.kt @@ -0,0 +1,27 @@ +package com.pioneer_intergration_app.api.core + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PhantomReachableTest { + + @Test + fun closeWhenPhantomReachable_whenObservedIsGarbageCollected_closesCloseable() { + var closed = false + val closeable = AutoCloseable { closed = true } + + closeWhenPhantomReachable( + // Pass an inline object for the object to observe so that it becomes immediately + // unreachable. + Any(), + closeable, + ) + + assertThat(closed).isFalse() + + System.gc() + Thread.sleep(100) + + assertThat(closed).isTrue() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/UtilsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/UtilsTest.kt new file mode 100644 index 0000000..84b042f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/UtilsTest.kt @@ -0,0 +1,33 @@ +package com.pioneer_intergration_app.api.core + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UtilsTest { + @Test + fun contentDeepEquals() { + assertThat(42 contentEquals 42).isTrue() + assertThat(42 contentEquals "Hello World!").isFalse() + assertThat(byteArrayOf(1, 2, 3) contentEquals byteArrayOf(1, 2, 3)).isTrue() + assertThat(byteArrayOf(1, 2, 3) contentEquals byteArrayOf(1, 2, 4)).isFalse() + assertThat( + arrayOf(byteArrayOf(1, 2), byteArrayOf(3)) contentEquals + arrayOf(byteArrayOf(1, 2), byteArrayOf(3)) + ) + .isTrue() + assertThat( + arrayOf(byteArrayOf(1, 2), byteArrayOf(3)) contentEquals + arrayOf(byteArrayOf(1), byteArrayOf(2, 3)) + ) + .isFalse() + } + + @Test + fun contentToString() { + assertThat((42).contentToString()).isEqualTo("42") + assertThat("Hello World!".contentToString()).isEqualTo("Hello World!") + assertThat(byteArrayOf(1, 2, 3).contentToString()).isEqualTo("[1, 2, 3]") + assertThat(arrayOf(byteArrayOf(1, 2), byteArrayOf(3)).contentToString()) + .isEqualTo("[[1, 2], [3]]") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ValuesTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ValuesTest.kt new file mode 100644 index 0000000..4fbcaec --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ValuesTest.kt @@ -0,0 +1,127 @@ +package com.pioneer_intergration_app.api.core + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class ValuesTest { + companion object { + private val NON_JSON = Any() + } + + enum class TestCase( + val value: JsonField<*>, + val expectedIsMissing: Boolean = false, + val expectedIsNull: Boolean = false, + val expectedAsKnown: Any? = null, + val expectedAsBoolean: Boolean? = null, + val expectedAsNumber: Number? = null, + val expectedAsString: String? = null, + val expectedAsArray: List? = null, + val expectedAsObject: Map? = null, + ) { + MISSING(JsonMissing.of(), expectedIsMissing = true), + NULL(JsonNull.of(), expectedIsNull = true), + KNOWN(KnownValue.of(NON_JSON), expectedAsKnown = NON_JSON), + KNOWN_BOOLEAN(KnownValue.of(true), expectedAsKnown = true, expectedAsBoolean = true), + BOOLEAN(JsonBoolean.of(true), expectedAsBoolean = true), + KNOWN_NUMBER(KnownValue.of(42), expectedAsKnown = 42, expectedAsNumber = 42), + NUMBER(JsonNumber.of(42), expectedAsNumber = 42), + KNOWN_STRING(KnownValue.of("hello"), expectedAsKnown = "hello", expectedAsString = "hello"), + STRING(JsonString.of("hello"), expectedAsString = "hello"), + KNOWN_ARRAY_NOT_ALL_JSON( + KnownValue.of(listOf("a", "b", NON_JSON)), + expectedAsKnown = listOf("a", "b", NON_JSON), + ), + KNOWN_ARRAY( + KnownValue.of(listOf("a", "b", "c")), + expectedAsKnown = listOf("a", "b", "c"), + expectedAsArray = listOf(JsonString.of("a"), JsonString.of("b"), JsonString.of("c")), + ), + ARRAY( + JsonArray.of(listOf(JsonString.of("a"), JsonString.of("b"), JsonString.of("c"))), + expectedAsArray = listOf(JsonString.of("a"), JsonString.of("b"), JsonString.of("c")), + ), + KNOWN_OBJECT_NOT_ALL_STRING_KEYS( + KnownValue.of(mapOf("a" to "b", 42 to "c")), + expectedAsKnown = mapOf("a" to "b", 42 to "c"), + ), + KNOWN_OBJECT_NOT_ALL_JSON( + KnownValue.of(mapOf("a" to "b", "b" to NON_JSON)), + expectedAsKnown = mapOf("a" to "b", "b" to NON_JSON), + ), + KNOWN_OBJECT( + KnownValue.of(mapOf("a" to "b", "b" to "c")), + expectedAsKnown = mapOf("a" to "b", "b" to "c"), + expectedAsObject = mapOf("a" to JsonString.of("b"), "b" to JsonString.of("c")), + ), + OBJECT( + JsonObject.of(mapOf("a" to JsonString.of("b"), "b" to JsonString.of("c"))), + expectedAsObject = mapOf("a" to JsonString.of("b"), "b" to JsonString.of("c")), + ), + } + + @ParameterizedTest + @EnumSource + fun isMissing(testCase: TestCase) { + val isMissing = testCase.value.isMissing() + + assertThat(isMissing).isEqualTo(testCase.expectedIsMissing) + } + + @ParameterizedTest + @EnumSource + fun isNull(testCase: TestCase) { + val isNull = testCase.value.isNull() + + assertThat(isNull).isEqualTo(testCase.expectedIsNull) + } + + @ParameterizedTest + @EnumSource + fun asKnown(testCase: TestCase) { + val known = testCase.value.asKnown() + + assertThat(known).isEqualTo(testCase.expectedAsKnown) + } + + @ParameterizedTest + @EnumSource + fun asBoolean(testCase: TestCase) { + val boolean = testCase.value.asBoolean() + + assertThat(boolean).isEqualTo(testCase.expectedAsBoolean) + } + + @ParameterizedTest + @EnumSource + fun asNumber(testCase: TestCase) { + val number = testCase.value.asNumber() + + assertThat(number).isEqualTo(testCase.expectedAsNumber) + } + + @ParameterizedTest + @EnumSource + fun asString(testCase: TestCase) { + val string = testCase.value.asString() + + assertThat(string).isEqualTo(testCase.expectedAsString) + } + + @ParameterizedTest + @EnumSource + fun asArray(testCase: TestCase) { + val array = testCase.value.asArray() + + assertThat(array).isEqualTo(testCase.expectedAsArray) + } + + @ParameterizedTest + @EnumSource + fun asObject(testCase: TestCase) { + val obj = testCase.value.asObject() + + assertThat(obj).isEqualTo(testCase.expectedAsObject) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HeadersTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HeadersTest.kt new file mode 100644 index 0000000..7385d36 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HeadersTest.kt @@ -0,0 +1,242 @@ +package com.pioneer_intergration_app.api.core.http + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class HeadersTest { + + enum class TestCase( + val headers: Headers, + val expectedMap: Map>, + val expectedSize: Int, + ) { + EMPTY(Headers.builder().build(), expectedMap = mapOf(), expectedSize = 0), + PUT_ONE( + Headers.builder().put("name", "value").build(), + expectedMap = mapOf("name" to listOf("value")), + expectedSize = 1, + ), + PUT_MULTIPLE( + Headers.builder().put("name", listOf("value1", "value2")).build(), + expectedMap = mapOf("name" to listOf("value1", "value2")), + expectedSize = 2, + ), + MULTIPLE_PUT( + Headers.builder().put("name1", "value").put("name2", "value").build(), + expectedMap = mapOf("name1" to listOf("value"), "name2" to listOf("value")), + expectedSize = 2, + ), + MULTIPLE_PUT_SAME_NAME( + Headers.builder().put("name", "value1").put("name", "value2").build(), + expectedMap = mapOf("name" to listOf("value1", "value2")), + expectedSize = 2, + ), + MULTIPLE_PUT_MULTIPLE( + Headers.builder() + .put("name", listOf("value1", "value2")) + .put("name", listOf("value1", "value2")) + .build(), + expectedMap = mapOf("name" to listOf("value1", "value2", "value1", "value2")), + expectedSize = 4, + ), + PUT_CASE_INSENSITIVE( + Headers.builder() + .put("name", "value1") + .put("NAME", "value2") + .put("nAmE", "value3") + .build(), + expectedMap = mapOf("name" to listOf("value1", "value2", "value3")), + expectedSize = 3, + ), + PUT_ALL_MAP( + Headers.builder() + .putAll( + mapOf( + "name1" to listOf("value1", "value2"), + "name2" to listOf("value1", "value2"), + ) + ) + .build(), + expectedMap = + mapOf("name1" to listOf("value1", "value2"), "name2" to listOf("value1", "value2")), + expectedSize = 4, + ), + PUT_ALL_HEADERS( + Headers.builder().putAll(Headers.builder().put("name", "value").build()).build(), + expectedMap = mapOf("name" to listOf("value")), + expectedSize = 1, + ), + PUT_ALL_CASE_INSENSITIVE( + Headers.builder() + .putAll( + mapOf( + "name" to listOf("value1"), + "NAME" to listOf("value2"), + "nAmE" to listOf("value3"), + ) + ) + .build(), + expectedMap = mapOf("name" to listOf("value1", "value2", "value3")), + expectedSize = 3, + ), + REMOVE_ABSENT( + Headers.builder().remove("name").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_PRESENT_ONE( + Headers.builder().put("name", "value").remove("name").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_PRESENT_MULTIPLE( + Headers.builder().put("name", listOf("value1", "value2")).remove("name").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_CASE_INSENSITIVE( + Headers.builder().put("name", listOf("value1", "value2")).remove("NAME").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_ALL( + Headers.builder() + .put("name1", "value") + .put("name3", "value") + .removeAll(setOf("name1", "name2", "name3")) + .build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_ALL_CASE_INSENSITIVE( + Headers.builder() + .put("name1", "value") + .put("name3", "value") + .removeAll(setOf("NAME1", "nAmE3")) + .build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + CLEAR( + Headers.builder().put("name1", "value").put("name2", "value").clear().build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REPLACE_ONE_ABSENT( + Headers.builder().replace("name", "value").build(), + expectedMap = mapOf("name" to listOf("value")), + expectedSize = 1, + ), + REPLACE_ONE_PRESENT_ONE( + Headers.builder().put("name", "value1").replace("name", "value2").build(), + expectedMap = mapOf("name" to listOf("value2")), + expectedSize = 1, + ), + REPLACE_ONE_PRESENT_MULTIPLE( + Headers.builder() + .put("name", listOf("value1", "value2")) + .replace("name", "value3") + .build(), + expectedMap = mapOf("name" to listOf("value3")), + expectedSize = 1, + ), + REPLACE_MULTIPLE_ABSENT( + Headers.builder().replace("name", listOf("value1", "value2")).build(), + expectedMap = mapOf("name" to listOf("value1", "value2")), + expectedSize = 2, + ), + REPLACE_MULTIPLE_PRESENT_ONE( + Headers.builder() + .put("name", "value1") + .replace("name", listOf("value2", "value3")) + .build(), + expectedMap = mapOf("name" to listOf("value2", "value3")), + expectedSize = 2, + ), + REPLACE_MULTIPLE_PRESENT_MULTIPLE( + Headers.builder() + .put("name", listOf("value1", "value2")) + .replace("name", listOf("value3", "value4")) + .build(), + expectedMap = mapOf("name" to listOf("value3", "value4")), + expectedSize = 2, + ), + REPLACE_CASE_INSENSITIVE( + Headers.builder() + .put("name", "value1") + .replace("NAME", listOf("value2", "value3")) + .build(), + expectedMap = mapOf("NAME" to listOf("value2", "value3")), + expectedSize = 2, + ), + REPLACE_ALL_MAP( + Headers.builder() + .put("name1", "value1") + .put("name2", "value1") + .put("name3", "value1") + .replaceAll(mapOf("name1" to listOf("value2"), "name3" to listOf("value2"))) + .build(), + expectedMap = + mapOf( + "name1" to listOf("value2"), + "name2" to listOf("value1"), + "name3" to listOf("value2"), + ), + expectedSize = 3, + ), + REPLACE_ALL_HEADERS( + Headers.builder() + .put("name1", "value1") + .put("name2", "value1") + .put("name3", "value1") + .replaceAll(Headers.builder().put("name1", "value2").put("name3", "value2").build()) + .build(), + expectedMap = + mapOf( + "name1" to listOf("value2"), + "name2" to listOf("value1"), + "name3" to listOf("value2"), + ), + expectedSize = 3, + ), + REPLACE_ALL_CASE_INSENSITIVE( + Headers.builder() + .put("name1", "value1") + .put("name2", "value1") + .replaceAll(mapOf("NAME1" to listOf("value2"), "nAmE2" to listOf("value2"))) + .build(), + expectedMap = mapOf("NAME1" to listOf("value2"), "nAmE2" to listOf("value2")), + expectedSize = 2, + ), + } + + @ParameterizedTest + @EnumSource + fun namesAndValues(testCase: TestCase) { + val map = mutableMapOf>() + val headers = testCase.headers + headers.names().forEach { name -> map[name] = headers.values(name) } + + assertThat(map).isEqualTo(testCase.expectedMap) + } + + @ParameterizedTest + @EnumSource + fun caseInsensitiveNames(testCase: TestCase) { + val headers = testCase.headers + + for (name in headers.names()) { + assertThat(headers.values(name)).isEqualTo(headers.values(name.lowercase())) + assertThat(headers.values(name)).isEqualTo(headers.values(name.uppercase())) + } + } + + @ParameterizedTest + @EnumSource + fun size(testCase: TestCase) { + val size = testCase.headers.size + + assertThat(size).isEqualTo(testCase.expectedSize) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestTest.kt new file mode 100644 index 0000000..6ca9b7f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestTest.kt @@ -0,0 +1,110 @@ +package com.pioneer_intergration_app.api.core.http + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class HttpRequestTest { + + enum class UrlTestCase(val request: HttpRequest, val expectedUrl: String) { + BASE_URL_ONLY( + HttpRequest.builder().method(HttpMethod.GET).baseUrl("https://api.example.com").build(), + expectedUrl = "https://api.example.com", + ), + BASE_URL_WITH_TRAILING_SLASH( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com/") + .build(), + expectedUrl = "https://api.example.com/", + ), + SINGLE_PATH_SEGMENT( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .build(), + expectedUrl = "https://api.example.com/users", + ), + MULTIPLE_PATH_SEGMENTS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegments("users", "123", "profile") + .build(), + expectedUrl = "https://api.example.com/users/123/profile", + ), + PATH_SEGMENT_WITH_SPECIAL_CHARS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("user name") + .build(), + expectedUrl = "https://api.example.com/user+name", + ), + SINGLE_QUERY_PARAM( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParam("limit", "10") + .build(), + expectedUrl = "https://api.example.com/users?limit=10", + ), + MULTIPLE_QUERY_PARAMS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParam("limit", "10") + .putQueryParam("offset", "20") + .build(), + expectedUrl = "https://api.example.com/users?limit=10&offset=20", + ), + QUERY_PARAM_WITH_SPECIAL_CHARS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("search") + .putQueryParam("q", "hello world") + .build(), + expectedUrl = "https://api.example.com/search?q=hello+world", + ), + MULTIPLE_VALUES_SAME_PARAM( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParams("tags", listOf("admin", "user")) + .build(), + expectedUrl = "https://api.example.com/users?tags=admin&tags=user", + ), + BASE_URL_WITH_TRAILING_SLASH_AND_PATH( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com/") + .addPathSegment("users") + .build(), + expectedUrl = "https://api.example.com/users", + ), + COMPLEX_URL( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl("https://api.example.com") + .addPathSegments("v1", "users", "123") + .putQueryParams("include", listOf("profile", "settings")) + .putQueryParam("format", "json") + .build(), + expectedUrl = + "https://api.example.com/v1/users/123?include=profile&include=settings&format=json", + ), + } + + @ParameterizedTest + @EnumSource + fun url(testCase: UrlTestCase) { + val actualUrl = testCase.request.url() + + assertThat(actualUrl).isEqualTo(testCase.expectedUrl) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/QueryParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/QueryParamsTest.kt new file mode 100644 index 0000000..6d0d584 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/QueryParamsTest.kt @@ -0,0 +1,180 @@ +package com.pioneer_intergration_app.api.core.http + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class QueryParamsTest { + + enum class TestCase( + val queryParams: QueryParams, + val expectedMap: Map>, + val expectedSize: Int, + ) { + EMPTY(QueryParams.builder().build(), expectedMap = mapOf(), expectedSize = 0), + PUT_ONE( + QueryParams.builder().put("key", "value").build(), + expectedMap = mapOf("key" to listOf("value")), + expectedSize = 1, + ), + PUT_MULTIPLE( + QueryParams.builder().put("key", listOf("value1", "value2")).build(), + expectedMap = mapOf("key" to listOf("value1", "value2")), + expectedSize = 2, + ), + MULTIPLE_PUT( + QueryParams.builder().put("key1", "value").put("key2", "value").build(), + expectedMap = mapOf("key1" to listOf("value"), "key2" to listOf("value")), + expectedSize = 2, + ), + MULTIPLE_PUT_SAME_NAME( + QueryParams.builder().put("key", "value1").put("key", "value2").build(), + expectedMap = mapOf("key" to listOf("value1", "value2")), + expectedSize = 2, + ), + MULTIPLE_PUT_MULTIPLE( + QueryParams.builder() + .put("key", listOf("value1", "value2")) + .put("key", listOf("value1", "value2")) + .build(), + expectedMap = mapOf("key" to listOf("value1", "value2", "value1", "value2")), + expectedSize = 4, + ), + PUT_ALL_MAP( + QueryParams.builder() + .putAll( + mapOf( + "key1" to listOf("value1", "value2"), + "key2" to listOf("value1", "value2"), + ) + ) + .build(), + expectedMap = + mapOf("key1" to listOf("value1", "value2"), "key2" to listOf("value1", "value2")), + expectedSize = 4, + ), + PUT_ALL_HEADERS( + QueryParams.builder().putAll(QueryParams.builder().put("key", "value").build()).build(), + expectedMap = mapOf("key" to listOf("value")), + expectedSize = 1, + ), + REMOVE_ABSENT( + QueryParams.builder().remove("key").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_PRESENT_ONE( + QueryParams.builder().put("key", "value").remove("key").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_PRESENT_MULTIPLE( + QueryParams.builder().put("key", listOf("value1", "value2")).remove("key").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_ALL( + QueryParams.builder() + .put("key1", "value") + .put("key3", "value") + .removeAll(setOf("key1", "key2", "key3")) + .build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + CLEAR( + QueryParams.builder().put("key1", "value").put("key2", "value").clear().build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REPLACE_ONE_ABSENT( + QueryParams.builder().replace("key", "value").build(), + expectedMap = mapOf("key" to listOf("value")), + expectedSize = 1, + ), + REPLACE_ONE_PRESENT_ONE( + QueryParams.builder().put("key", "value1").replace("key", "value2").build(), + expectedMap = mapOf("key" to listOf("value2")), + expectedSize = 1, + ), + REPLACE_ONE_PRESENT_MULTIPLE( + QueryParams.builder() + .put("key", listOf("value1", "value2")) + .replace("key", "value3") + .build(), + expectedMap = mapOf("key" to listOf("value3")), + expectedSize = 1, + ), + REPLACE_MULTIPLE_ABSENT( + QueryParams.builder().replace("key", listOf("value1", "value2")).build(), + expectedMap = mapOf("key" to listOf("value1", "value2")), + expectedSize = 2, + ), + REPLACE_MULTIPLE_PRESENT_ONE( + QueryParams.builder() + .put("key", "value1") + .replace("key", listOf("value2", "value3")) + .build(), + expectedMap = mapOf("key" to listOf("value2", "value3")), + expectedSize = 2, + ), + REPLACE_MULTIPLE_PRESENT_MULTIPLE( + QueryParams.builder() + .put("key", listOf("value1", "value2")) + .replace("key", listOf("value3", "value4")) + .build(), + expectedMap = mapOf("key" to listOf("value3", "value4")), + expectedSize = 2, + ), + REPLACE_ALL_MAP( + QueryParams.builder() + .put("key1", "value1") + .put("key2", "value1") + .put("key3", "value1") + .replaceAll(mapOf("key1" to listOf("value2"), "key3" to listOf("value2"))) + .build(), + expectedMap = + mapOf( + "key1" to listOf("value2"), + "key2" to listOf("value1"), + "key3" to listOf("value2"), + ), + expectedSize = 3, + ), + REPLACE_ALL_HEADERS( + QueryParams.builder() + .put("key1", "value1") + .put("key2", "value1") + .put("key3", "value1") + .replaceAll( + QueryParams.builder().put("key1", "value2").put("key3", "value2").build() + ) + .build(), + expectedMap = + mapOf( + "key1" to listOf("value2"), + "key2" to listOf("value1"), + "key3" to listOf("value2"), + ), + expectedSize = 3, + ), + } + + @ParameterizedTest + @EnumSource + fun keysAndValues(testCase: TestCase) { + val map = mutableMapOf>() + val queryParams = testCase.queryParams + queryParams.keys().forEach { key -> map[key] = queryParams.values(key) } + + assertThat(map).isEqualTo(testCase.expectedMap) + } + + @ParameterizedTest + @EnumSource + fun size(testCase: TestCase) { + val size = testCase.queryParams.size + + assertThat(size).isEqualTo(testCase.expectedSize) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClientTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClientTest.kt new file mode 100644 index 0000000..6de2c8b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClientTest.kt @@ -0,0 +1,353 @@ +package com.pioneer_intergration_app.api.core.http + +import com.github.tomakehurst.wiremock.client.WireMock.* +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo +import com.github.tomakehurst.wiremock.junit5.WireMockTest +import com.github.tomakehurst.wiremock.stubbing.Scenario +import com.pioneer_intergration_app.api.client.okhttp.OkHttpClient +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.Sleeper +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppRetryableException +import java.io.InputStream +import java.time.Duration +import kotlinx.coroutines.runBlocking +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.parallel.ResourceLock +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +@WireMockTest +@ResourceLock("https://github.com/wiremock/wiremock/issues/169") +internal class RetryingHttpClientTest { + + private var openResponseCount = 0 + private lateinit var baseUrl: String + private lateinit var httpClient: HttpClient + + @BeforeEach + fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) { + baseUrl = wmRuntimeInfo.httpBaseUrl + val okHttpClient = OkHttpClient.builder().build() + httpClient = + object : HttpClient { + + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse = trackClose(okHttpClient.execute(request, requestOptions)) + + override suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse = trackClose(okHttpClient.executeAsync(request, requestOptions)) + + override fun close() = okHttpClient.close() + + private fun trackClose(response: HttpResponse): HttpResponse { + openResponseCount++ + return object : HttpResponse { + + private var isClosed = false + + override fun statusCode(): Int = response.statusCode() + + override fun headers(): Headers = response.headers() + + override fun body(): InputStream = response.body() + + override fun close() { + response.close() + if (isClosed) { + return + } + openResponseCount-- + isClosed = true + } + } + } + } + resetAllScenarios() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute(async: Boolean) { + stubFor(post(urlPathEqualTo("/something")).willReturn(ok())) + val retryingClient = retryingHttpClientBuilder().build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify(1, postRequestedFor(urlPathEqualTo("/something"))) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withIdempotencyHeader(async: Boolean) { + stubFor( + post(urlPathEqualTo("/something")) + .withHeader("X-Some-Header", matching("stainless-java-retry-.+")) + .willReturn(ok()) + ) + val retryingClient = + retryingHttpClientBuilder().maxRetries(2).idempotencyHeader("X-Some-Header").build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify(1, postRequestedFor(urlPathEqualTo("/something"))) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withRetryAfterHeader(async: Boolean) { + stubFor( + post(urlPathEqualTo("/something")) + // First we fail with a retry after header given as a date + .inScenario("foo") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn( + serviceUnavailable().withHeader("Retry-After", "Wed, 21 Oct 2015 07:28:00 GMT") + ) + .willSetStateTo("RETRY_AFTER_DATE") + ) + stubFor( + post(urlPathEqualTo("/something")) + // Then we fail with a retry after header given as a delay + .inScenario("foo") + .whenScenarioStateIs("RETRY_AFTER_DATE") + .willReturn(serviceUnavailable().withHeader("Retry-After", "1.234")) + .willSetStateTo("RETRY_AFTER_DELAY") + ) + stubFor( + post(urlPathEqualTo("/something")) + // Then we return a success + .inScenario("foo") + .whenScenarioStateIs("RETRY_AFTER_DELAY") + .willReturn(ok()) + .willSetStateTo("COMPLETED") + ) + val retryingClient = retryingHttpClientBuilder().maxRetries(2).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify( + 1, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("0")), + ) + verify( + 1, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("1")), + ) + verify( + 1, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("2")), + ) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withOverwrittenRetryCountHeader(async: Boolean) { + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") // first we fail with a retry after header given as a date + .whenScenarioStateIs(Scenario.STARTED) + .willReturn( + serviceUnavailable().withHeader("Retry-After", "Wed, 21 Oct 2015 07:28:00 GMT") + ) + .willSetStateTo("RETRY_AFTER_DATE") + ) + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") // then we return a success + .whenScenarioStateIs("RETRY_AFTER_DATE") + .willReturn(ok()) + .willSetStateTo("COMPLETED") + ) + val retryingClient = retryingHttpClientBuilder().maxRetries(2).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .putHeader("x-stainless-retry-count", "42") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify( + 2, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("42")), + ) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withRetryAfterMsHeader(async: Boolean) { + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn(serviceUnavailable().withHeader("Retry-After-Ms", "10")) + .willSetStateTo("RETRY_AFTER_DELAY") + ) + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") // then we return a success + .whenScenarioStateIs("RETRY_AFTER_DELAY") + .willReturn(ok()) + .willSetStateTo("COMPLETED") + ) + val retryingClient = retryingHttpClientBuilder().maxRetries(1).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify(2, postRequestedFor(urlPathEqualTo("/something"))) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withRetryableException(async: Boolean) { + stubFor(post(urlPathEqualTo("/something")).willReturn(ok())) + + var callCount = 0 + val failingHttpClient = + object : HttpClient { + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + callCount++ + if (callCount == 1) { + throw PioneerIntergrationAppRetryableException( + "Simulated retryable failure" + ) + } + return httpClient.execute(request, requestOptions) + } + + override suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + callCount++ + if (callCount == 1) { + throw PioneerIntergrationAppRetryableException( + "Simulated retryable failure" + ) + } + return httpClient.executeAsync(request, requestOptions) + } + + override fun close() = httpClient.close() + } + + val retryingClient = + RetryingHttpClient.builder() + .httpClient(failingHttpClient) + .maxRetries(2) + .sleeper( + object : Sleeper { + + override fun sleep(duration: Duration) {} + + override suspend fun sleepAsync(duration: Duration) {} + + override fun close() {} + } + ) + .build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify( + 1, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("1")), + ) + verify( + 0, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("0")), + ) + assertNoResponseLeaks() + } + + private fun retryingHttpClientBuilder() = + RetryingHttpClient.builder() + .httpClient(httpClient) + // Use a no-op `Sleeper` to make the test fast. + .sleeper( + object : Sleeper { + + override fun sleep(duration: Duration) {} + + override suspend fun sleepAsync(duration: Duration) {} + + override fun close() {} + } + ) + + private fun HttpClient.execute(request: HttpRequest, async: Boolean): HttpResponse = + if (async) runBlocking { executeAsync(request) } else execute(request) + + // When retrying, all failed responses should be closed. Only the final returned response should + // be open. + private fun assertNoResponseLeaks() = assertThat(openResponseCount).isEqualTo(1) +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/OrderTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/OrderTest.kt new file mode 100644 index 0000000..9444dcd --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/OrderTest.kt @@ -0,0 +1,51 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.jsonMapper +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OrderTest { + + @Test + fun create() { + val order = + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + + assertThat(order.id()).isEqualTo(10L) + assertThat(order.complete()).isEqualTo(true) + assertThat(order.petId()).isEqualTo(198772L) + assertThat(order.quantity()).isEqualTo(7) + assertThat(order.shipDate()).isEqualTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(order.status()).isEqualTo(Order.Status.APPROVED) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val order = + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + + val roundtrippedOrder = + jsonMapper.readValue(jsonMapper.writeValueAsString(order), jacksonTypeRef()) + + assertThat(roundtrippedOrder).isEqualTo(order) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/CategoryTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/CategoryTest.kt new file mode 100644 index 0000000..1e1aaf7 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/CategoryTest.kt @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class CategoryTest { + + @Test + fun create() { + val category = Category.builder().id(1L).name("Dogs").build() + + assertThat(category.id()).isEqualTo(1L) + assertThat(category.name()).isEqualTo("Dogs") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val category = Category.builder().id(1L).name("Dogs").build() + + val roundtrippedCategory = + jsonMapper.readValue( + jsonMapper.writeValueAsString(category), + jacksonTypeRef(), + ) + + assertThat(roundtrippedCategory).isEqualTo(category) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParamsTest.kt new file mode 100644 index 0000000..ffb5ec2 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParamsTest.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetCreateParamsTest { + + @Test + fun create() { + PetCreateParams.builder() + .pet( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + PetCreateParams.builder() + .pet( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + PetCreateParams.builder() + .pet(Pet.builder().name("doggie").addPhotoUrl("string").build()) + .build() + + val body = params._body() + + assertThat(body).isEqualTo(Pet.builder().name("doggie").addPhotoUrl("string").build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParamsTest.kt new file mode 100644 index 0000000..0db30b9 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetDeleteParamsTest { + + @Test + fun create() { + PetDeleteParams.builder().petId(0L).build() + } + + @Test + fun pathParams() { + val params = PetDeleteParams.builder().petId(0L).build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParamsTest.kt new file mode 100644 index 0000000..d0433c0 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParamsTest.kt @@ -0,0 +1,34 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetFindByStatusParamsTest { + + @Test + fun create() { + PetFindByStatusParams.builder().status(PetFindByStatusParams.Status.AVAILABLE).build() + } + + @Test + fun queryParams() { + val params = + PetFindByStatusParams.builder().status(PetFindByStatusParams.Status.AVAILABLE).build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().put("status", "available").build()) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = PetFindByStatusParams.builder().build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParamsTest.kt new file mode 100644 index 0000000..1d87fe5 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParamsTest.kt @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetFindByTagsParamsTest { + + @Test + fun create() { + PetFindByTagsParams.builder().addTag("string").build() + } + + @Test + fun queryParams() { + val params = PetFindByTagsParams.builder().addTag("string").build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder().put("tags", listOf("string").joinToString(",")).build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = PetFindByTagsParams.builder().build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParamsTest.kt new file mode 100644 index 0000000..7e9e558 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetRetrieveParamsTest { + + @Test + fun create() { + PetRetrieveParams.builder().petId(0L).build() + } + + @Test + fun pathParams() { + val params = PetRetrieveParams.builder().petId(0L).build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetTest.kt new file mode 100644 index 0000000..e2da096 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetTest.kt @@ -0,0 +1,50 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetTest { + + @Test + fun create() { + val pet = + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + + assertThat(pet.name()).isEqualTo("doggie") + assertThat(pet.photoUrls()).containsExactly("string") + assertThat(pet.id()).isEqualTo(10L) + assertThat(pet.category()).isEqualTo(Category.builder().id(1L).name("Dogs").build()) + assertThat(pet.status()).isEqualTo(Pet.Status.AVAILABLE) + assertThat(pet.tags()).containsExactly(Pet.Tag.builder().id(0L).name("name").build()) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val pet = + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + + val roundtrippedPet = + jsonMapper.readValue(jsonMapper.writeValueAsString(pet), jacksonTypeRef()) + + assertThat(roundtrippedPet).isEqualTo(pet) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParamsTest.kt new file mode 100644 index 0000000..e9df453 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParamsTest.kt @@ -0,0 +1,43 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetUpdateByIdParamsTest { + + @Test + fun create() { + PetUpdateByIdParams.builder().petId(0L).name("name").status("status").build() + } + + @Test + fun pathParams() { + val params = PetUpdateByIdParams.builder().petId(0L).build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = PetUpdateByIdParams.builder().petId(0L).name("name").status("status").build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo(QueryParams.builder().put("name", "name").put("status", "status").build()) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = PetUpdateByIdParams.builder().petId(0L).build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParamsTest.kt new file mode 100644 index 0000000..57d2449 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParamsTest.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetUpdateParamsTest { + + @Test + fun create() { + PetUpdateParams.builder() + .pet( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + PetUpdateParams.builder() + .pet( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + PetUpdateParams.builder() + .pet(Pet.builder().name("doggie").addPhotoUrl("string").build()) + .build() + + val body = params._body() + + assertThat(body).isEqualTo(Pet.builder().name("doggie").addPhotoUrl("string").build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParamsTest.kt new file mode 100644 index 0000000..05542ba --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParamsTest.kt @@ -0,0 +1,77 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetUploadImageParamsTest { + + @Test + fun create() { + PetUploadImageParams.builder() + .petId(0L) + .additionalMetadata("additionalMetadata") + .image("some content") + .build() + } + + @Test + fun pathParams() { + val params = PetUploadImageParams.builder().petId(0L).image("some content").build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = + PetUploadImageParams.builder() + .petId(0L) + .additionalMetadata("additionalMetadata") + .image("some content") + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder().put("additionalMetadata", "additionalMetadata").build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = PetUploadImageParams.builder().petId(0L).image("some content").build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } + + @Test + fun body() { + val params = + PetUploadImageParams.builder() + .petId(0L) + .additionalMetadata("additionalMetadata") + .image("some content") + .build() + + val body = params._body() + + assertThat(body).isEqualTo("some content") + } + + @Test + fun bodyWithoutOptionalFields() { + val params = PetUploadImageParams.builder().petId(0L).image("some content").build() + + val body = params._body() + + assertThat(body).isEqualTo("some content") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponseTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponseTest.kt new file mode 100644 index 0000000..e3887f5 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponseTest.kt @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetUploadImageResponseTest { + + @Test + fun create() { + val petUploadImageResponse = + PetUploadImageResponse.builder().code(0).message("message").type("type").build() + + assertThat(petUploadImageResponse.code()).isEqualTo(0) + assertThat(petUploadImageResponse.message()).isEqualTo("message") + assertThat(petUploadImageResponse.type()).isEqualTo("type") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val petUploadImageResponse = + PetUploadImageResponse.builder().code(0).message("message").type("type").build() + + val roundtrippedPetUploadImageResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(petUploadImageResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedPetUploadImageResponse).isEqualTo(petUploadImageResponse) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParamsTest.kt new file mode 100644 index 0000000..34f9383 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParamsTest.kt @@ -0,0 +1,13 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store + +import org.junit.jupiter.api.Test + +internal class StoreListInventoryParamsTest { + + @Test + fun create() { + StoreListInventoryParams.builder().build() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponseTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponseTest.kt new file mode 100644 index 0000000..d27c18e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponseTest.kt @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class StoreListInventoryResponseTest { + + @Test + fun create() { + val storeListInventoryResponse = + StoreListInventoryResponse.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val storeListInventoryResponse = + StoreListInventoryResponse.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + + val roundtrippedStoreListInventoryResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(storeListInventoryResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedStoreListInventoryResponse).isEqualTo(storeListInventoryResponse) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParamsTest.kt new file mode 100644 index 0000000..9f13f41 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParamsTest.kt @@ -0,0 +1,65 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import com.pioneer_intergration_app.api.models.Order +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OrderCreateParamsTest { + + @Test + fun create() { + OrderCreateParams.builder() + .order( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + OrderCreateParams.builder() + .order( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = OrderCreateParams.builder().build() + + val body = params._body() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParamsTest.kt new file mode 100644 index 0000000..02c82b9 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OrderDeleteParamsTest { + + @Test + fun create() { + OrderDeleteParams.builder().orderId(0L).build() + } + + @Test + fun pathParams() { + val params = OrderDeleteParams.builder().orderId(0L).build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParamsTest.kt new file mode 100644 index 0000000..c7d569e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OrderRetrieveParamsTest { + + @Test + fun create() { + OrderRetrieveParams.builder().orderId(0L).build() + } + + @Test + fun pathParams() { + val params = OrderRetrieveParams.builder().orderId(0L).build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParamsTest.kt new file mode 100644 index 0000000..36afa09 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParamsTest.kt @@ -0,0 +1,69 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserCreateParamsTest { + + @Test + fun create() { + UserCreateParams.builder() + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + UserCreateParams.builder() + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = UserCreateParams.builder().build() + + val body = params._body() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParamsTest.kt new file mode 100644 index 0000000..f5a7cdc --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParamsTest.kt @@ -0,0 +1,69 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserCreateWithListParamsTest { + + @Test + fun create() { + UserCreateWithListParams.builder() + .addItem( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + UserCreateWithListParams.builder() + .addItem( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .containsExactly( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = UserCreateWithListParams.builder().build() + + val body = params._body() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParamsTest.kt new file mode 100644 index 0000000..5c6f200 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserDeleteParamsTest { + + @Test + fun create() { + UserDeleteParams.builder().username("username").build() + } + + @Test + fun pathParams() { + val params = UserDeleteParams.builder().username("username").build() + + assertThat(params._pathParam(0)).isEqualTo("username") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParamsTest.kt new file mode 100644 index 0000000..3863669 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParamsTest.kt @@ -0,0 +1,39 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserLoginParamsTest { + + @Test + fun create() { + UserLoginParams.builder().password("password").username("username").build() + } + + @Test + fun queryParams() { + val params = UserLoginParams.builder().password("password").username("username").build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder() + .put("password", "password") + .put("username", "username") + .build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = UserLoginParams.builder().build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParamsTest.kt new file mode 100644 index 0000000..bcbdd1c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParamsTest.kt @@ -0,0 +1,13 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.junit.jupiter.api.Test + +internal class UserLogoutParamsTest { + + @Test + fun create() { + UserLogoutParams.builder().build() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParamsTest.kt new file mode 100644 index 0000000..6ac07d9 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserRetrieveParamsTest { + + @Test + fun create() { + UserRetrieveParams.builder().username("username").build() + } + + @Test + fun pathParams() { + val params = UserRetrieveParams.builder().username("username").build() + + assertThat(params._pathParam(0)).isEqualTo("username") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserTest.kt new file mode 100644 index 0000000..9932c8a --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserTest.kt @@ -0,0 +1,56 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserTest { + + @Test + fun create() { + val user = + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + + assertThat(user.id()).isEqualTo(10L) + assertThat(user.email()).isEqualTo("john@email.com") + assertThat(user.firstName()).isEqualTo("John") + assertThat(user.lastName()).isEqualTo("James") + assertThat(user.password()).isEqualTo("12345") + assertThat(user.phone()).isEqualTo("12345") + assertThat(user.username()).isEqualTo("theUser") + assertThat(user.userStatus()).isEqualTo(1) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val user = + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + + val roundtrippedUser = + jsonMapper.readValue(jsonMapper.writeValueAsString(user), jacksonTypeRef()) + + assertThat(roundtrippedUser).isEqualTo(user) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParamsTest.kt new file mode 100644 index 0000000..52d4868 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParamsTest.kt @@ -0,0 +1,80 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserUpdateParamsTest { + + @Test + fun create() { + UserUpdateParams.builder() + .existingUsername("username") + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + } + + @Test + fun pathParams() { + val params = UserUpdateParams.builder().existingUsername("username").build() + + assertThat(params._pathParam(0)).isEqualTo("username") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun body() { + val params = + UserUpdateParams.builder() + .existingUsername("username") + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = UserUpdateParams.builder().existingUsername("username").build() + + val body = params._body() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ErrorHandlingTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ErrorHandlingTest.kt new file mode 100644 index 0000000..b1b41e6 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ErrorHandlingTest.kt @@ -0,0 +1,349 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services + +import com.github.tomakehurst.wiremock.client.WireMock.anyUrl +import com.github.tomakehurst.wiremock.client.WireMock.get +import com.github.tomakehurst.wiremock.client.WireMock.status +import com.github.tomakehurst.wiremock.client.WireMock.stubFor +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo +import com.github.tomakehurst.wiremock.junit5.WireMockTest +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.jsonMapper +import com.pioneer_intergration_app.api.errors.BadRequestException +import com.pioneer_intergration_app.api.errors.InternalServerException +import com.pioneer_intergration_app.api.errors.NotFoundException +import com.pioneer_intergration_app.api.errors.PermissionDeniedException +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppException +import com.pioneer_intergration_app.api.errors.RateLimitException +import com.pioneer_intergration_app.api.errors.UnauthorizedException +import com.pioneer_intergration_app.api.errors.UnexpectedStatusCodeException +import com.pioneer_intergration_app.api.errors.UnprocessableEntityException +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.entry +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.api.parallel.ResourceLock + +@WireMockTest +@ResourceLock("https://github.com/wiremock/wiremock/issues/169") +internal class ErrorHandlingTest { + + companion object { + + private val ERROR_JSON: JsonValue = JsonValue.from(mapOf("errorProperty" to "42")) + + private val ERROR_JSON_BYTES: ByteArray = jsonMapper().writeValueAsBytes(ERROR_JSON) + + private const val HEADER_NAME: String = "Error-Header" + + private const val HEADER_VALUE: String = "42" + + private const val NOT_JSON: String = "Not JSON" + } + + private lateinit var client: PioneerIntergrationAppClient + + @BeforeEach + fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) { + client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(wmRuntimeInfo.httpBaseUrl) + .apiKey("My API Key") + .build() + } + + @Test + fun storeListInventory400() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(400).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(400) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory400WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(400).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(400) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory401() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(401).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(401) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory401WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(401).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(401) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory403() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(403).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(403) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory403WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(403).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(403) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory404() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(404).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(404) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory404WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(404).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(404) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory422() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(422).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(422) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory422WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(422).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(422) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory429() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(429).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(429) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory429WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(429).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(429) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory500() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(500).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(500) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory500WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(500).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(500) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory999() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(999).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(999) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory999WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(999).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(999) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventoryInvalidJsonBody() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn(status(200).withHeader(HEADER_NAME, HEADER_VALUE).withBody(NOT_JSON)) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e).hasMessage("Error reading response") + } + + private fun Headers.toMap(): Map> = + mutableMapOf>().also { map -> + names().forEach { map[it] = values(it) } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt new file mode 100644 index 0000000..80d1c37 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt @@ -0,0 +1,91 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services + +import com.github.tomakehurst.wiremock.client.WireMock.anyUrl +import com.github.tomakehurst.wiremock.client.WireMock.equalTo +import com.github.tomakehurst.wiremock.client.WireMock.get +import com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor +import com.github.tomakehurst.wiremock.client.WireMock.ok +import com.github.tomakehurst.wiremock.client.WireMock.post +import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor +import com.github.tomakehurst.wiremock.client.WireMock.stubFor +import com.github.tomakehurst.wiremock.client.WireMock.verify +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo +import com.github.tomakehurst.wiremock.junit5.WireMockTest +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams +import java.time.OffsetDateTime +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.parallel.ResourceLock + +@WireMockTest +@ResourceLock("https://github.com/wiremock/wiremock/issues/169") +internal class ServiceParamsTest { + + private lateinit var client: PioneerIntergrationAppClient + + @BeforeEach + fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) { + client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(wmRuntimeInfo.httpBaseUrl) + .apiKey("My API Key") + .build() + } + + @Disabled("Prism tests are disabled") + @Test + fun listInventory() { + val storeService = client.store() + stubFor(get(anyUrl()).willReturn(ok("{}"))) + + storeService.listInventory( + StoreListInventoryParams.builder() + .putAdditionalHeader("Secret-Header", "42") + .putAdditionalQueryParam("secret_query_param", "42") + .build() + ) + + verify( + getRequestedFor(anyUrl()) + .withHeader("Secret-Header", equalTo("42")) + .withQueryParam("secret_query_param", equalTo("42")) + ) + } + + @Disabled("Prism tests are disabled") + @Test + fun create() { + val orderService = client.store().orders() + stubFor(post(anyUrl()).willReturn(ok("{}"))) + + orderService.create( + OrderCreateParams.builder() + .order( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + .putAdditionalHeader("Secret-Header", "42") + .putAdditionalQueryParam("secret_query_param", "42") + .build() + ) + + verify( + postRequestedFor(anyUrl()) + .withHeader("Secret-Header", equalTo("42")) + .withQueryParam("secret_query_param", equalTo("42")) + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncTest.kt new file mode 100644 index 0000000..e5b8172 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncTest.kt @@ -0,0 +1,170 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClientAsync +import com.pioneer_intergration_app.api.models.pets.Category +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class PetServiceAsyncTest { + + @Disabled("Prism tests are disabled") + @Test + suspend fun create() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val pet = + petServiceAsync.create( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val pet = petServiceAsync.retrieve(0L) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun update() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val pet = + petServiceAsync.update( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun delete() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + petServiceAsync.delete(0L) + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun findByStatus() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val pets = + petServiceAsync.findByStatus( + PetFindByStatusParams.builder() + .status(PetFindByStatusParams.Status.AVAILABLE) + .build() + ) + + pets.forEach { it.validate() } + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun findByTags() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val pets = + petServiceAsync.findByTags(PetFindByTagsParams.builder().addTag("string").build()) + + pets.forEach { it.validate() } + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun updateById() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + petServiceAsync.updateById( + PetUpdateByIdParams.builder().petId(0L).name("name").status("status").build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun uploadImage() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val response = + petServiceAsync.uploadImage( + PetUploadImageParams.builder() + .petId(0L) + .additionalMetadata("additionalMetadata") + .image("some content") + .build() + ) + + response.validate() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncTest.kt new file mode 100644 index 0000000..155b063 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncTest.kt @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClientAsync +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class StoreServiceAsyncTest { + + @Disabled("Prism tests are disabled") + @Test + suspend fun listInventory() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val storeServiceAsync = client.store() + + val response = storeServiceAsync.listInventory() + + response.validate() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncTest.kt new file mode 100644 index 0000000..a475abb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncTest.kt @@ -0,0 +1,160 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClientAsync +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class UserServiceAsyncTest { + + @Disabled("Prism tests are disabled") + @Test + suspend fun create() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + val user = + userServiceAsync.create( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + val user = userServiceAsync.retrieve("username") + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun update() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + userServiceAsync.update( + UserUpdateParams.builder() + .existingUsername("username") + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun delete() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + userServiceAsync.delete("username") + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun createWithList() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + val user = + userServiceAsync.createWithList( + UserCreateWithListParams.builder() + .addItem( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + ) + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun login() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + userServiceAsync.login( + UserLoginParams.builder().password("password").username("username").build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun logout() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + userServiceAsync.logout() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncTest.kt new file mode 100644 index 0000000..59b155c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncTest.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async.store + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClientAsync +import com.pioneer_intergration_app.api.models.Order +import java.time.OffsetDateTime +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class OrderServiceAsyncTest { + + @Disabled("Prism tests are disabled") + @Test + suspend fun create() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderServiceAsync = client.store().orders() + + val order = + orderServiceAsync.create( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + + order.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderServiceAsync = client.store().orders() + + val order = orderServiceAsync.retrieve(0L) + + order.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun delete() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderServiceAsync = client.store().orders() + + orderServiceAsync.delete(0L) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceTest.kt new file mode 100644 index 0000000..9fb4f5e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceTest.kt @@ -0,0 +1,169 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.pets.Category +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class PetServiceTest { + + @Disabled("Prism tests are disabled") + @Test + fun create() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val pet = + petService.create( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val pet = petService.retrieve(0L) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun update() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val pet = + petService.update( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun delete() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + petService.delete(0L) + } + + @Disabled("Prism tests are disabled") + @Test + fun findByStatus() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val pets = + petService.findByStatus( + PetFindByStatusParams.builder() + .status(PetFindByStatusParams.Status.AVAILABLE) + .build() + ) + + pets.forEach { it.validate() } + } + + @Disabled("Prism tests are disabled") + @Test + fun findByTags() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val pets = petService.findByTags(PetFindByTagsParams.builder().addTag("string").build()) + + pets.forEach { it.validate() } + } + + @Disabled("Prism tests are disabled") + @Test + fun updateById() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + petService.updateById( + PetUpdateByIdParams.builder().petId(0L).name("name").status("status").build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + fun uploadImage() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val response = + petService.uploadImage( + PetUploadImageParams.builder() + .petId(0L) + .additionalMetadata("additionalMetadata") + .image("some content") + .build() + ) + + response.validate() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceTest.kt new file mode 100644 index 0000000..b0acf06 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceTest.kt @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class StoreServiceTest { + + @Disabled("Prism tests are disabled") + @Test + fun listInventory() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val storeService = client.store() + + val response = storeService.listInventory() + + response.validate() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceTest.kt new file mode 100644 index 0000000..0e0ff55 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceTest.kt @@ -0,0 +1,160 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class UserServiceTest { + + @Disabled("Prism tests are disabled") + @Test + fun create() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + val user = + userService.create( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + val user = userService.retrieve("username") + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun update() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + userService.update( + UserUpdateParams.builder() + .existingUsername("username") + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + fun delete() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + userService.delete("username") + } + + @Disabled("Prism tests are disabled") + @Test + fun createWithList() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + val user = + userService.createWithList( + UserCreateWithListParams.builder() + .addItem( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + ) + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun login() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + userService.login( + UserLoginParams.builder().password("password").username("username").build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + fun logout() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + userService.logout() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceTest.kt new file mode 100644 index 0000000..b907022 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceTest.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking.store + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.Order +import java.time.OffsetDateTime +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class OrderServiceTest { + + @Disabled("Prism tests are disabled") + @Test + fun create() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderService = client.store().orders() + + val order = + orderService.create( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + + order.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderService = client.store().orders() + + val order = orderService.retrieve(0L) + + order.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun delete() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderService = client.store().orders() + + orderService.delete(0L) + } +} diff --git a/pioneer-intergration-app-kotlin-example/build.gradle.kts b/pioneer-intergration-app-kotlin-example/build.gradle.kts new file mode 100644 index 0000000..73d669e --- /dev/null +++ b/pioneer-intergration-app-kotlin-example/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + id("pioneer-intergration-app.kotlin") + application +} + +dependencies { + implementation(project(":pioneer-intergration-app-kotlin-core")) + implementation(project(":pioneer-intergration-app-kotlin-client-okhttp")) +} + +application { + // Use `./gradlew :pioneer-intergration-app-kotlin-example:run` to run `Main` + // Use `./gradlew :pioneer-intergration-app-kotlin-example:run -Pexample=Something` to run `SomethingExample` + mainClass = "com.pioneer_intergration_app.api.example.${ + if (project.hasProperty("example")) + "${project.property("example")}ExampleKt" + else + "MainKt" + }" +} diff --git a/pioneer-intergration-app-kotlin-lib/.keep b/pioneer-intergration-app-kotlin-lib/.keep new file mode 100644 index 0000000..5e2c99f --- /dev/null +++ b/pioneer-intergration-app-kotlin-lib/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store custom files to expand the SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts b/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts new file mode 100644 index 0000000..ca9b62f --- /dev/null +++ b/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts @@ -0,0 +1,101 @@ +plugins { + id("pioneer-intergration-app.kotlin") + id("com.gradleup.shadow") version "8.3.8" +} + +buildscript { + repositories { + google() + } + + dependencies { + classpath("com.guardsquare:proguard-gradle:7.4.2") + classpath("com.android.tools:r8:8.3.37") + } +} + +dependencies { + testImplementation(project(":pioneer-intergration-app-kotlin")) + testImplementation(kotlin("test")) + testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") + testImplementation("org.assertj:assertj-core:3.27.7") + testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") +} + +tasks.shadowJar { + from(sourceSets.test.get().output) + configurations = listOf(project.configurations.testRuntimeClasspath.get()) +} + +val proguardJarPath = "${layout.buildDirectory.get()}/libs/${project.name}-${project.version}-proguard.jar" +val proguardJar by tasks.registering(proguard.gradle.ProGuardTask::class) { + group = "verification" + dependsOn(tasks.shadowJar) + notCompatibleWithConfigurationCache("ProGuard") + + injars(tasks.shadowJar) + outjars(proguardJarPath) + printmapping("${layout.buildDirectory.get()}/proguard-mapping.txt") + + val javaHome = System.getProperty("java.home") + if (System.getProperty("java.version").startsWith("1.")) { + // Before Java 9, the runtime classes were packaged in a single jar file. + libraryjars("$javaHome/lib/rt.jar") + } else { + // As of Java 9, the runtime classes are packaged in modular jmod files. + libraryjars( + // Filters must be specified first, as a map. + mapOf("jarfilter" to "!**.jar", "filter" to "!module-info.class"), + "$javaHome/jmods/java.base.jmod" + ) + } + + configuration("./test.pro") + configuration("../pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro") +} + +val testProGuard by tasks.registering(JavaExec::class) { + group = "verification" + dependsOn(proguardJar) + notCompatibleWithConfigurationCache("ProGuard") + + mainClass.set("com.pioneer_intergration_app.api.proguard.ProGuardCompatibilityTest") + classpath = files(proguardJarPath) +} + +val r8JarPath = "${layout.buildDirectory.get()}/libs/${project.name}-${project.version}-r8.jar" +val r8Jar by tasks.registering(JavaExec::class) { + group = "verification" + dependsOn(tasks.shadowJar) + notCompatibleWithConfigurationCache("R8") + + mainClass.set("com.android.tools.r8.R8") + classpath = buildscript.configurations["classpath"] + + args = listOf( + "--release", + "--classfile", + "--output", r8JarPath, + "--lib", System.getProperty("java.home"), + "--pg-conf", "./test.pro", + "--pg-conf", "../pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro", + "--pg-map-output", "${layout.buildDirectory.get()}/r8-mapping.txt", + tasks.shadowJar.get().archiveFile.get().asFile.absolutePath, + ) +} + +val testR8 by tasks.registering(JavaExec::class) { + group = "verification" + dependsOn(r8Jar) + notCompatibleWithConfigurationCache("R8") + + mainClass.set("com.pioneer_intergration_app.api.proguard.ProGuardCompatibilityTest") + classpath = files(r8JarPath) +} + +tasks.test { + dependsOn(testProGuard) + dependsOn(testR8) + // We defer to the tests run via the ProGuard JAR. + enabled = false +} diff --git a/pioneer-intergration-app-kotlin-proguard-test/src/test/kotlin/com/pioneer_intergration_app/api/proguard/ProGuardCompatibilityTest.kt b/pioneer-intergration-app-kotlin-proguard-test/src/test/kotlin/com/pioneer_intergration_app/api/proguard/ProGuardCompatibilityTest.kt new file mode 100644 index 0000000..07d0682 --- /dev/null +++ b/pioneer-intergration-app-kotlin-proguard-test/src/test/kotlin/com/pioneer_intergration_app/api/proguard/ProGuardCompatibilityTest.kt @@ -0,0 +1,76 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.proguard + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.core.jsonMapper +import com.pioneer_intergration_app.api.models.Order +import java.time.OffsetDateTime +import kotlin.reflect.full.memberFunctions +import kotlin.reflect.jvm.javaMethod +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ProGuardCompatibilityTest { + + companion object { + + @JvmStatic + fun main(args: Array) { + // To debug that we're using the right JAR. + val jarPath = this::class.java.getProtectionDomain().codeSource.location + println("JAR being used: $jarPath") + + // We have to manually run the test methods instead of using the JUnit runner because it + // seems impossible to get working with R8. + val test = ProGuardCompatibilityTest() + test::class + .memberFunctions + .asSequence() + .filter { function -> + function.javaMethod?.isAnnotationPresent(Test::class.java) == true + } + .forEach { it.call(test) } + } + } + + @Test + fun proguardRules() { + val rulesFile = + javaClass.classLoader.getResourceAsStream( + "META-INF/proguard/pioneer-intergration-app-kotlin-core.pro" + ) + + assertThat(rulesFile).isNotNull() + } + + @Test + fun client() { + val client = PioneerIntergrationAppOkHttpClient.builder().apiKey("My API Key").build() + + assertThat(client).isNotNull() + assertThat(client.pets()).isNotNull() + assertThat(client.store()).isNotNull() + assertThat(client.users()).isNotNull() + } + + @Test + fun orderRoundtrip() { + val jsonMapper = jsonMapper() + val order = + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + + val roundtrippedOrder = + jsonMapper.readValue(jsonMapper.writeValueAsString(order), jacksonTypeRef()) + + assertThat(roundtrippedOrder).isEqualTo(order) + } +} diff --git a/pioneer-intergration-app-kotlin-proguard-test/test.pro b/pioneer-intergration-app-kotlin-proguard-test/test.pro new file mode 100644 index 0000000..ef5edfc --- /dev/null +++ b/pioneer-intergration-app-kotlin-proguard-test/test.pro @@ -0,0 +1,9 @@ +# Specify the entrypoint where ProGuard starts to determine what's reachable. +-keep class com.pioneer_intergration_app.api.proguard.** { *; } + +# For the testing framework. +-keep class org.junit.** { *; } + +# Many warnings don't apply for our testing purposes. +-dontnote +-dontwarn \ No newline at end of file diff --git a/pioneer-intergration-app-kotlin/build.gradle.kts b/pioneer-intergration-app-kotlin/build.gradle.kts new file mode 100644 index 0000000..9f7acb1 --- /dev/null +++ b/pioneer-intergration-app-kotlin/build.gradle.kts @@ -0,0 +1,29 @@ +plugins { + id("pioneer-intergration-app.kotlin") + id("pioneer-intergration-app.publish") +} + +dependencies { + api(project(":pioneer-intergration-app-kotlin-client-okhttp")) +} + +// Redefine `dokkaHtml` to: +// - Depend on the root project's task for merging the docs of all the projects +// - Forward that task's output to this task's output +tasks.named("dokkaHtml").configure { + actions.clear() + + val dokkaHtmlCollector = rootProject.tasks["dokkaHtmlCollector"] + dependsOn(dokkaHtmlCollector) + + val outputDirectory = project.layout.buildDirectory.dir("dokka/html") + doLast { + copy { + from(dokkaHtmlCollector.outputs.files) + into(outputDirectory) + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + } + + outputs.dir(outputDirectory) +} diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..8f98719 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,67 @@ +{ + "packages": { + ".": {} + }, + "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", + "include-v-in-tag": true, + "include-component-in-tag": false, + "versioning": "prerelease", + "prerelease": true, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": false, + "pull-request-header": "Automated Release PR", + "pull-request-title-pattern": "release: ${version}", + "changelog-sections": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "refactor", + "section": "Refactors" + }, + { + "type": "test", + "section": "Tests", + "hidden": true + }, + { + "type": "build", + "section": "Build System" + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": true + } + ], + "release-type": "simple", + "extra-files": [ + "README.md", + "build.gradle.kts" + ] +} \ No newline at end of file diff --git a/scripts/build b/scripts/build new file mode 100755 index 0000000..16a2b00 --- /dev/null +++ b/scripts/build @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Building classes" +./gradlew build testClasses "$@" -x test diff --git a/scripts/format b/scripts/format new file mode 100755 index 0000000..9e294b9 --- /dev/null +++ b/scripts/format @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if command -v ktfmt &> /dev/null; then + echo "==> Running ktfmt" + find . -name "*.kt" -not -path "./buildSrc/build/*" -print0 | xargs -0 -r ktfmt --kotlinlang-style "$@" +else + echo "==> Running gradlew format" + ./gradlew format +fi diff --git a/scripts/lint b/scripts/lint new file mode 100755 index 0000000..5837798 --- /dev/null +++ b/scripts/lint @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if command -v ktfmt &> /dev/null; then + echo "==> Checking ktfmt" + ./scripts/format --dry-run --set-exit-if-changed +else + echo "==> Running gradlew lint" + ./gradlew lint +fi diff --git a/scripts/mock b/scripts/mock new file mode 100755 index 0000000..0b28f6e --- /dev/null +++ b/scripts/mock @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if [[ -n "$1" && "$1" != '--'* ]]; then + URL="$1" + shift +else + URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" +fi + +# Check if the URL is empty +if [ -z "$URL" ]; then + echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" + exit 1 +fi + +echo "==> Starting mock server with URL ${URL}" + +# Run prism mock on the given spec +if [ "$1" == "--daemon" ]; then + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & + + # Wait for server to come online + echo -n "Waiting for server" + while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + echo -n "." + sleep 0.1 + done + + if grep -q "✖ fatal" ".prism.log"; then + cat .prism.log + exit 1 + fi + + echo +else + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" +fi diff --git a/scripts/test b/scripts/test new file mode 100755 index 0000000..047bc1d --- /dev/null +++ b/scripts/test @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +NC='\033[0m' # No Color + +function prism_is_running() { + curl --silent "http://localhost:4010" >/dev/null 2>&1 +} + +kill_server_on_port() { + pids=$(lsof -t -i tcp:"$1" || echo "") + if [ "$pids" != "" ]; then + kill "$pids" + echo "Stopped $pids." + fi +} + +function is_overriding_api_base_url() { + [ -n "$TEST_API_BASE_URL" ] +} + +if ! is_overriding_api_base_url && ! prism_is_running ; then + # When we exit this script, make sure to kill the background mock server process + trap 'kill_server_on_port 4010' EXIT + + # Start the dev server + ./scripts/mock --daemon +fi + +if is_overriding_api_base_url ; then + echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" + echo +elif ! prism_is_running ; then + echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" + echo -e "running against your OpenAPI spec." + echo + echo -e "To run the server, pass in the path or url of your OpenAPI" + echo -e "spec to the prism command:" + echo + echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" + echo + + exit 1 +else + echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo +fi + +echo "==> Running tests" +./gradlew test "$@" diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..6f6df7e --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,14 @@ +rootProject.name = "pioneer-intergration-app-kotlin-root" + +val projectNames = rootDir.listFiles() + ?.asSequence() + .orEmpty() + .filter { file -> + file.isDirectory && + file.name.startsWith("pioneer-intergration-app-kotlin") && + file.listFiles()?.asSequence().orEmpty().any { it.name == "build.gradle.kts" } + } + .map { it.name } + .toList() +println("projects: $projectNames") +projectNames.forEach { include(it) }